xref: /petsc/src/dm/impls/plex/plexrefine.c (revision 6d7c9049376a279694469be7d620afda16990bbf)
1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h>   /*I      "petscdmplex.h"   I*/
2412e9a14SMatthew G. Knepley #include <petsc/private/petscfeimpl.h>  /* For PetscFEInterpolate_Static() */
375d3a19aSMatthew G. Knepley #include <petscsf.h>
475d3a19aSMatthew G. Knepley 
53f2a96e3SMatthew G. Knepley PetscBool SBRcite = PETSC_FALSE;
63f2a96e3SMatthew G. Knepley const char SBRCitation[] = "@article{PlazaCarey2000,\n"
73f2a96e3SMatthew G. Knepley                           "  title   = {Local refinement of simplicial grids based on the skeleton},\n"
83f2a96e3SMatthew G. Knepley                           "  journal = {Applied Numerical Mathematics},\n"
93f2a96e3SMatthew G. Knepley                           "  author  = {A. Plaza and Graham F. Carey},\n"
103f2a96e3SMatthew G. Knepley                           "  volume  = {32},\n"
113f2a96e3SMatthew G. Knepley                           "  number  = {3},\n"
123f2a96e3SMatthew G. Knepley                           "  pages   = {195--218},\n"
133f2a96e3SMatthew G. Knepley                           "  doi     = {10.1016/S0168-9274(99)00022-7},\n"
143f2a96e3SMatthew G. Knepley                           "  year    = {2000}\n}\n";
153f2a96e3SMatthew G. Knepley 
163f2a96e3SMatthew G. Knepley const char * const DMPlexCellRefinerTypes[] = {"Regular", "ToBox", "ToSimplex", "Alfeld2D", "Alfeld3D", "PowellSabin", "BoundaryLayer", "SBR", "DMPlexCellRefinerTypes", "DM_REFINER_", NULL};
1775d3a19aSMatthew G. Knepley 
1809789c4cSMatthew G. Knepley /*
1909789c4cSMatthew G. Knepley   Note that j and invj are non-square:
2009789c4cSMatthew G. Knepley          v0 + j x_face = x_cell
2109789c4cSMatthew G. Knepley     invj (x_cell - v0) = x_face
2209789c4cSMatthew G. Knepley */
23412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerGetAffineFaceTransforms_Regular(DMPlexCellRefiner cr, DMPolytopeType ct, PetscInt *Nf, PetscReal *v0[], PetscReal *J[], PetscReal *invJ[], PetscReal *detJ[])
2409789c4cSMatthew G. Knepley {
2509789c4cSMatthew G. Knepley   /*
2609789c4cSMatthew G. Knepley    2
2709789c4cSMatthew G. Knepley    |\
2809789c4cSMatthew G. Knepley    | \
2909789c4cSMatthew G. Knepley    |  \
3009789c4cSMatthew G. Knepley    |   \
3109789c4cSMatthew G. Knepley    |    \
3209789c4cSMatthew G. Knepley    |     \
3309789c4cSMatthew G. Knepley    |      \
3409789c4cSMatthew G. Knepley    2       1
3509789c4cSMatthew G. Knepley    |        \
3609789c4cSMatthew G. Knepley    |         \
3709789c4cSMatthew G. Knepley    |          \
3809789c4cSMatthew G. Knepley    0---0-------1
39412e9a14SMatthew G. Knepley    v0[Nf][dc]:       3 x 2
40412e9a14SMatthew G. Knepley    J[Nf][df][dc]:    3 x 1 x 2
41412e9a14SMatthew G. Knepley    invJ[Nf][dc][df]: 3 x 2 x 1
42412e9a14SMatthew G. Knepley    detJ[Nf]:         3
4309789c4cSMatthew G. Knepley    */
44412e9a14SMatthew G. Knepley   static PetscReal tri_v0[]   = {0.0, -1.0,  0.0, 0.0,  -1.0,  0.0};
45412e9a14SMatthew G. Knepley   static PetscReal tri_J[]    = {1.0, 0.0,  -1.0, 1.0,   0.0, -1.0};
46412e9a14SMatthew G. Knepley   static PetscReal tri_invJ[] = {1.0, 0.0,  -0.5, 0.5,   0.0, -1.0};
47412e9a14SMatthew G. Knepley   static PetscReal tri_detJ[] = {1.0,  1.414213562373095,  1.0};
4809789c4cSMatthew G. Knepley   /*
4909789c4cSMatthew G. Knepley    3---------2---------2
5009789c4cSMatthew G. Knepley    |                   |
5109789c4cSMatthew G. Knepley    |                   |
5209789c4cSMatthew G. Knepley    |                   |
5309789c4cSMatthew G. Knepley    3                   1
5409789c4cSMatthew G. Knepley    |                   |
5509789c4cSMatthew G. Knepley    |                   |
5609789c4cSMatthew G. Knepley    |                   |
5709789c4cSMatthew G. Knepley    0---------0---------1
58412e9a14SMatthew G. Knepley 
59412e9a14SMatthew G. Knepley    v0[Nf][dc]:       4 x 2
60412e9a14SMatthew G. Knepley    J[Nf][df][dc]:    4 x 1 x 2
61412e9a14SMatthew G. Knepley    invJ[Nf][dc][df]: 4 x 2 x 1
62412e9a14SMatthew G. Knepley    detJ[Nf]:         4
6309789c4cSMatthew G. Knepley    */
64412e9a14SMatthew G. Knepley   static PetscReal quad_v0[]   = {0.0, -1.0,  1.0, 0.0,   0.0, 1.0  -1.0,  0.0};
65412e9a14SMatthew G. Knepley   static PetscReal quad_J[]    = {1.0, 0.0,   0.0, 1.0,  -1.0, 0.0,  0.0, -1.0};
66412e9a14SMatthew G. Knepley   static PetscReal quad_invJ[] = {1.0, 0.0,   0.0, 1.0,  -1.0, 0.0,  0.0, -1.0};
67412e9a14SMatthew G. Knepley   static PetscReal quad_detJ[] = {1.0,  1.0,  1.0,  1.0};
68412e9a14SMatthew G. Knepley 
69412e9a14SMatthew G. Knepley   PetscFunctionBegin;
70412e9a14SMatthew G. Knepley   switch (ct) {
71412e9a14SMatthew 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;
72412e9a14SMatthew 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;
7309789c4cSMatthew G. Knepley   default:
74412e9a14SMatthew G. Knepley     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unsupported polytope type %s", DMPolytopeTypes[ct]);
7509789c4cSMatthew G. Knepley   }
7609789c4cSMatthew G. Knepley   PetscFunctionReturn(0);
7709789c4cSMatthew G. Knepley }
7809789c4cSMatthew G. Knepley 
79bed052eaSMatthew G. Knepley /* Gets the affine map from the original cell to each subcell */
80412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerGetAffineTransforms_Regular(DMPlexCellRefiner cr, DMPolytopeType ct, PetscInt *Nc, PetscReal *v0[], PetscReal *J[], PetscReal *invJ[])
81bed052eaSMatthew G. Knepley {
82260b6d3fSMatthew G. Knepley   /*
83260b6d3fSMatthew G. Knepley    2
84260b6d3fSMatthew G. Knepley    |\
85260b6d3fSMatthew G. Knepley    | \
86260b6d3fSMatthew G. Knepley    |  \
87260b6d3fSMatthew G. Knepley    |   \
88260b6d3fSMatthew G. Knepley    | C  \
89260b6d3fSMatthew G. Knepley    |     \
90260b6d3fSMatthew G. Knepley    |      \
91260b6d3fSMatthew G. Knepley    2---1---1
92260b6d3fSMatthew G. Knepley    |\  D  / \
93260b6d3fSMatthew G. Knepley    | 2   0   \
94260b6d3fSMatthew G. Knepley    |A \ /  B  \
95260b6d3fSMatthew G. Knepley    0---0-------1
96260b6d3fSMatthew G. Knepley    */
97412e9a14SMatthew G. Knepley   static PetscReal tri_v0[]   = {-1.0, -1.0,  0.0, -1.0,  -1.0, 0.0,  0.0, -1.0};
98412e9a14SMatthew G. Knepley   static PetscReal tri_J[]    = {0.5, 0.0,
99412e9a14SMatthew G. Knepley                                  0.0, 0.5,
100412e9a14SMatthew G. Knepley 
101412e9a14SMatthew G. Knepley                                  0.5, 0.0,
102412e9a14SMatthew G. Knepley                                  0.0, 0.5,
103412e9a14SMatthew G. Knepley 
104412e9a14SMatthew G. Knepley                                  0.5, 0.0,
105412e9a14SMatthew G. Knepley                                  0.0, 0.5,
106412e9a14SMatthew G. Knepley 
107412e9a14SMatthew G. Knepley                                  0.0, -0.5,
108412e9a14SMatthew G. Knepley                                  0.5,  0.5};
109412e9a14SMatthew G. Knepley   static PetscReal tri_invJ[] = {2.0, 0.0,
110412e9a14SMatthew G. Knepley                                  0.0, 2.0,
111412e9a14SMatthew G. Knepley 
112412e9a14SMatthew G. Knepley                                  2.0, 0.0,
113412e9a14SMatthew G. Knepley                                  0.0, 2.0,
114412e9a14SMatthew G. Knepley 
115412e9a14SMatthew G. Knepley                                  2.0, 0.0,
116412e9a14SMatthew G. Knepley                                  0.0, 2.0,
117412e9a14SMatthew G. Knepley 
118412e9a14SMatthew G. Knepley                                  2.0,  2.0,
119412e9a14SMatthew G. Knepley                                 -2.0,  0.0};
120260b6d3fSMatthew G. Knepley     /*
121260b6d3fSMatthew G. Knepley      3---------2---------2
122260b6d3fSMatthew G. Knepley      |         |         |
123260b6d3fSMatthew G. Knepley      |    D    2    C    |
124260b6d3fSMatthew G. Knepley      |         |         |
125260b6d3fSMatthew G. Knepley      3----3----0----1----1
126260b6d3fSMatthew G. Knepley      |         |         |
127260b6d3fSMatthew G. Knepley      |    A    0    B    |
128260b6d3fSMatthew G. Knepley      |         |         |
129260b6d3fSMatthew G. Knepley      0---------0---------1
130260b6d3fSMatthew G. Knepley      */
131412e9a14SMatthew G. Knepley   static PetscReal quad_v0[]   = {-1.0, -1.0,  0.0, -1.0,  0.0, 0.0,  -1.0, 0.0};
132412e9a14SMatthew G. Knepley   static PetscReal quad_J[]    = {0.5, 0.0,
133412e9a14SMatthew G. Knepley                                   0.0, 0.5,
134412e9a14SMatthew G. Knepley 
135412e9a14SMatthew G. Knepley                                   0.5, 0.0,
136412e9a14SMatthew G. Knepley                                   0.0, 0.5,
137412e9a14SMatthew G. Knepley 
138412e9a14SMatthew G. Knepley                                   0.5, 0.0,
139412e9a14SMatthew G. Knepley                                   0.0, 0.5,
140412e9a14SMatthew G. Knepley 
141412e9a14SMatthew G. Knepley                                   0.5, 0.0,
142412e9a14SMatthew G. Knepley                                   0.0, 0.5};
143412e9a14SMatthew G. Knepley   static PetscReal quad_invJ[] = {2.0, 0.0,
144412e9a14SMatthew G. Knepley                                   0.0, 2.0,
145412e9a14SMatthew G. Knepley 
146412e9a14SMatthew G. Knepley                                   2.0, 0.0,
147412e9a14SMatthew G. Knepley                                   0.0, 2.0,
148412e9a14SMatthew G. Knepley 
149412e9a14SMatthew G. Knepley                                   2.0, 0.0,
150412e9a14SMatthew G. Knepley                                   0.0, 2.0,
151412e9a14SMatthew G. Knepley 
152412e9a14SMatthew G. Knepley                                   2.0, 0.0,
153412e9a14SMatthew G. Knepley                                   0.0, 2.0};
154c1879b55SMatthew G. Knepley     /*
155c1879b55SMatthew G. Knepley      Bottom (viewed from top)    Top
156c1879b55SMatthew G. Knepley      1---------2---------2       7---------2---------6
157c1879b55SMatthew G. Knepley      |         |         |       |         |         |
158c1879b55SMatthew G. Knepley      |    B    2    C    |       |    H    2    G    |
159c1879b55SMatthew G. Knepley      |         |         |       |         |         |
160c1879b55SMatthew G. Knepley      3----3----0----1----1       3----3----0----1----1
161c1879b55SMatthew G. Knepley      |         |         |       |         |         |
162c1879b55SMatthew G. Knepley      |    A    0    D    |       |    E    0    F    |
163c1879b55SMatthew G. Knepley      |         |         |       |         |         |
164c1879b55SMatthew G. Knepley      0---------0---------3       4---------0---------5
165c1879b55SMatthew G. Knepley      */
166412e9a14SMatthew 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,
167412e9a14SMatthew 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};
168412e9a14SMatthew G. Knepley   static PetscReal hex_J[]    = {0.5, 0.0, 0.0,
169412e9a14SMatthew G. Knepley                                  0.0, 0.5, 0.0,
170412e9a14SMatthew G. Knepley                                  0.0, 0.0, 0.5,
171bed052eaSMatthew G. Knepley 
172412e9a14SMatthew G. Knepley                                  0.5, 0.0, 0.0,
173412e9a14SMatthew G. Knepley                                  0.0, 0.5, 0.0,
174412e9a14SMatthew G. Knepley                                  0.0, 0.0, 0.5,
175412e9a14SMatthew G. Knepley 
176412e9a14SMatthew G. Knepley                                  0.5, 0.0, 0.0,
177412e9a14SMatthew G. Knepley                                  0.0, 0.5, 0.0,
178412e9a14SMatthew G. Knepley                                  0.0, 0.0, 0.5,
179412e9a14SMatthew G. Knepley 
180412e9a14SMatthew G. Knepley                                  0.5, 0.0, 0.0,
181412e9a14SMatthew G. Knepley                                  0.0, 0.5, 0.0,
182412e9a14SMatthew G. Knepley                                  0.0, 0.0, 0.5,
183412e9a14SMatthew G. Knepley 
184412e9a14SMatthew G. Knepley                                  0.5, 0.0, 0.0,
185412e9a14SMatthew G. Knepley                                  0.0, 0.5, 0.0,
186412e9a14SMatthew G. Knepley                                  0.0, 0.0, 0.5,
187412e9a14SMatthew G. Knepley 
188412e9a14SMatthew G. Knepley                                  0.5, 0.0, 0.0,
189412e9a14SMatthew G. Knepley                                  0.0, 0.5, 0.0,
190412e9a14SMatthew G. Knepley                                  0.0, 0.0, 0.5,
191412e9a14SMatthew G. Knepley 
192412e9a14SMatthew G. Knepley                                  0.5, 0.0, 0.0,
193412e9a14SMatthew G. Knepley                                  0.0, 0.5, 0.0,
194412e9a14SMatthew G. Knepley                                  0.0, 0.0, 0.5,
195412e9a14SMatthew G. Knepley 
196412e9a14SMatthew G. Knepley                                  0.5, 0.0, 0.0,
197412e9a14SMatthew G. Knepley                                  0.0, 0.5, 0.0,
198412e9a14SMatthew G. Knepley                                  0.0, 0.0, 0.5};
199412e9a14SMatthew G. Knepley   static PetscReal hex_invJ[] = {2.0, 0.0, 0.0,
200412e9a14SMatthew G. Knepley                                  0.0, 2.0, 0.0,
201412e9a14SMatthew G. Knepley                                  0.0, 0.0, 2.0,
202412e9a14SMatthew G. Knepley 
203412e9a14SMatthew G. Knepley                                  2.0, 0.0, 0.0,
204412e9a14SMatthew G. Knepley                                  0.0, 2.0, 0.0,
205412e9a14SMatthew G. Knepley                                  0.0, 0.0, 2.0,
206412e9a14SMatthew G. Knepley 
207412e9a14SMatthew G. Knepley                                  2.0, 0.0, 0.0,
208412e9a14SMatthew G. Knepley                                  0.0, 2.0, 0.0,
209412e9a14SMatthew G. Knepley                                  0.0, 0.0, 2.0,
210412e9a14SMatthew G. Knepley 
211412e9a14SMatthew G. Knepley                                  2.0, 0.0, 0.0,
212412e9a14SMatthew G. Knepley                                  0.0, 2.0, 0.0,
213412e9a14SMatthew G. Knepley                                  0.0, 0.0, 2.0,
214412e9a14SMatthew G. Knepley 
215412e9a14SMatthew G. Knepley                                  2.0, 0.0, 0.0,
216412e9a14SMatthew G. Knepley                                  0.0, 2.0, 0.0,
217412e9a14SMatthew G. Knepley                                  0.0, 0.0, 2.0,
218412e9a14SMatthew G. Knepley 
219412e9a14SMatthew G. Knepley                                  2.0, 0.0, 0.0,
220412e9a14SMatthew G. Knepley                                  0.0, 2.0, 0.0,
221412e9a14SMatthew G. Knepley                                  0.0, 0.0, 2.0,
222412e9a14SMatthew G. Knepley 
223412e9a14SMatthew G. Knepley                                  2.0, 0.0, 0.0,
224412e9a14SMatthew G. Knepley                                  0.0, 2.0, 0.0,
225412e9a14SMatthew G. Knepley                                  0.0, 0.0, 2.0,
226412e9a14SMatthew G. Knepley 
227412e9a14SMatthew G. Knepley                                  2.0, 0.0, 0.0,
228412e9a14SMatthew G. Knepley                                  0.0, 2.0, 0.0,
229412e9a14SMatthew G. Knepley                                  0.0, 0.0, 2.0};
230bed052eaSMatthew G. Knepley 
231bed052eaSMatthew G. Knepley   PetscFunctionBegin;
232412e9a14SMatthew G. Knepley   switch (ct) {
233412e9a14SMatthew 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;
234412e9a14SMatthew 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;
235412e9a14SMatthew 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;
236412e9a14SMatthew G. Knepley   default:
237412e9a14SMatthew G. Knepley     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unsupported polytope type %s", DMPolytopeTypes[ct]);
238412e9a14SMatthew G. Knepley   }
239bed052eaSMatthew G. Knepley   PetscFunctionReturn(0);
240bed052eaSMatthew G. Knepley }
241bed052eaSMatthew G. Knepley 
24280389061SMatthew G. Knepley /* Should this be here or in the DualSpace somehow? */
243412e9a14SMatthew G. Knepley PetscErrorCode CellRefinerInCellTest_Internal(DMPolytopeType ct, const PetscReal point[], PetscBool *inside)
24480389061SMatthew G. Knepley {
24580389061SMatthew G. Knepley   PetscReal sum = 0.0;
24680389061SMatthew G. Knepley   PetscInt  d;
24780389061SMatthew G. Knepley 
24880389061SMatthew G. Knepley   PetscFunctionBegin;
24980389061SMatthew G. Knepley   *inside = PETSC_TRUE;
250412e9a14SMatthew G. Knepley   switch (ct) {
251412e9a14SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
252412e9a14SMatthew G. Knepley   case DM_POLYTOPE_TETRAHEDRON:
253412e9a14SMatthew G. Knepley     for (d = 0; d < DMPolytopeTypeGetDim(ct); ++d) {
25480389061SMatthew G. Knepley       if (point[d] < -1.0) {*inside = PETSC_FALSE; break;}
25580389061SMatthew G. Knepley       sum += point[d];
25680389061SMatthew G. Knepley     }
257412e9a14SMatthew G. Knepley     if (sum > PETSC_SMALL) {*inside = PETSC_FALSE; break;}
25880389061SMatthew G. Knepley     break;
259412e9a14SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
260412e9a14SMatthew G. Knepley   case DM_POLYTOPE_HEXAHEDRON:
261412e9a14SMatthew G. Knepley     for (d = 0; d < DMPolytopeTypeGetDim(ct); ++d)
262412e9a14SMatthew G. Knepley       if (PetscAbsReal(point[d]) > 1.+PETSC_SMALL) {*inside = PETSC_FALSE; break;}
26394339e62SJed Brown     break;
26480389061SMatthew G. Knepley   default:
265412e9a14SMatthew G. Knepley     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unsupported polytope type %s", DMPolytopeTypes[ct]);
26680389061SMatthew G. Knepley   }
26780389061SMatthew G. Knepley   PetscFunctionReturn(0);
26880389061SMatthew G. Knepley }
26980389061SMatthew G. Knepley 
270412e9a14SMatthew G. Knepley /* Regular Refinment of Hybrid Meshes
27175d3a19aSMatthew G. Knepley 
272412e9a14SMatthew 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
273412e9a14SMatthew G. Knepley    to automatically generate a refined Plex. In fact, we would like these rules to be general enough to encompass other
274412e9a14SMatthew G. Knepley    transformations, such as changing from one type of cell to another, as simplex to hex.
27575d3a19aSMatthew G. Knepley 
276412e9a14SMatthew G. Knepley    To start, we can create a function that takes an original cell type and returns the number of new cells replacing it
277412e9a14SMatthew G. Knepley    and the types of the new cells.
278518a8359SMatthew G. Knepley 
279412e9a14SMatthew G. Knepley    We need the group multiplication table for group actions from the dihedral group for each cell type.
28042525629SMatthew G. Knepley 
281412e9a14SMatthew 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
282412e9a14SMatthew G. Knepley    we can just write this operator for faces with identity, and then compose the face orientation actions to get the actual
283412e9a14SMatthew G. Knepley    (face, orient) pairs for each subcell.
284412e9a14SMatthew G. Knepley */
2850314a74cSLawrence Mitchell 
28675d3a19aSMatthew G. Knepley /*
287412e9a14SMatthew G. Knepley   Input Parameters:
288412e9a14SMatthew G. Knepley + ct - The type of the input cell
289a5801f52SStefano Zampini . co - The orientation of this cell in its parent
290412e9a14SMatthew G. Knepley - cp - The requested cone point of this cell assuming orientation 0
291412e9a14SMatthew G. Knepley 
292412e9a14SMatthew G. Knepley   Output Parameters:
293a5801f52SStefano Zampini . cpnew - The new cone point, taking into account the orientation co
294412e9a14SMatthew G. Knepley */
295412e9a14SMatthew G. Knepley PETSC_STATIC_INLINE PetscErrorCode DMPolytopeMapCell(DMPolytopeType ct, PetscInt co, PetscInt cp, PetscInt *cpnew)
296412e9a14SMatthew G. Knepley {
297412e9a14SMatthew G. Knepley   const PetscInt csize = DMPolytopeTypeGetConeSize(ct);
298412e9a14SMatthew G. Knepley 
299412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
300412e9a14SMatthew G. Knepley   if (ct == DM_POLYTOPE_POINT) {*cpnew = cp;}
301412e9a14SMatthew G. Knepley   else                         {*cpnew = (co < 0 ? -(co+1)-cp+csize : co+cp)%csize;}
302412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
303412e9a14SMatthew G. Knepley }
304412e9a14SMatthew G. Knepley 
305412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerGetCellVertices_Regular(DMPlexCellRefiner cr, DMPolytopeType ct, PetscInt *Nv, PetscReal *subcellV[])
306412e9a14SMatthew G. Knepley {
307412e9a14SMatthew G. Knepley   static PetscReal seg_v[]  = {-1.0,  0.0,  1.0};
308412e9a14SMatthew 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};
309412e9a14SMatthew 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};
310412e9a14SMatthew G. Knepley   static PetscReal tet_v[]  = {-1.0, -1.0, -1.0,   0.0, -1.0, -1.0,   1.0, -1.0, -1.0,
311412e9a14SMatthew G. Knepley                                -1.0,  0.0, -1.0,   0.0,  0.0, -1.0,  -1.0,  1.0, -1.0,
312412e9a14SMatthew 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};
313412e9a14SMatthew G. Knepley   static PetscReal hex_v[]  = {-1.0, -1.0, -1.0,   0.0, -1.0, -1.0,   1.0, -1.0, -1.0,
314412e9a14SMatthew G. Knepley                                -1.0,  0.0, -1.0,   0.0,  0.0, -1.0,   1.0,  0.0, -1.0,
315412e9a14SMatthew G. Knepley                                -1.0,  1.0, -1.0,   0.0,  1.0, -1.0,   1.0,  1.0, -1.0,
316412e9a14SMatthew G. Knepley                                -1.0, -1.0,  0.0,   0.0, -1.0,  0.0,   1.0, -1.0,  0.0,
317412e9a14SMatthew G. Knepley                                -1.0,  0.0,  0.0,   0.0,  0.0,  0.0,   1.0,  0.0,  0.0,
318412e9a14SMatthew G. Knepley                                -1.0,  1.0,  0.0,   0.0,  1.0,  0.0,   1.0,  1.0,  0.0,
319412e9a14SMatthew G. Knepley                                -1.0, -1.0,  1.0,   0.0, -1.0,  1.0,   1.0, -1.0,  1.0,
320412e9a14SMatthew G. Knepley                                -1.0,  0.0,  1.0,   0.0,  0.0,  1.0,   1.0,  0.0,  1.0,
321412e9a14SMatthew G. Knepley                                -1.0,  1.0,  1.0,   0.0,  1.0,  1.0,   1.0,  1.0,  1.0};
322412e9a14SMatthew G. Knepley 
323412e9a14SMatthew G. Knepley   PetscFunctionBegin;
324412e9a14SMatthew G. Knepley   switch (ct) {
325412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:       *Nv =  3; *subcellV = seg_v;  break;
326412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:      *Nv =  6; *subcellV = tri_v;  break;
327412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL: *Nv =  9; *subcellV = quad_v; break;
328412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TETRAHEDRON:   *Nv = 10; *subcellV = tet_v;  break;
329412e9a14SMatthew G. Knepley     case DM_POLYTOPE_HEXAHEDRON:    *Nv = 27; *subcellV = hex_v;  break;
330412e9a14SMatthew G. Knepley     default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "No subcell vertices for cell type %s", DMPolytopeTypes[ct]);
331412e9a14SMatthew G. Knepley   }
332412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
333412e9a14SMatthew G. Knepley }
334412e9a14SMatthew G. Knepley 
33596ca5757SLisandro Dalcin static PetscErrorCode DMPlexCellRefinerGetCellVertices_ToBox(DMPlexCellRefiner cr, DMPolytopeType ct, PetscInt *Nv, PetscReal *subcellV[])
336412e9a14SMatthew G. Knepley {
337412e9a14SMatthew 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};
338412e9a14SMatthew G. Knepley   static PetscReal tet_v[] = {-1.0, -1.0, -1.0,   0.0, -1.0, -1.0,   1.0, -1.0, -1.0,
339412e9a14SMatthew 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,
340412e9a14SMatthew G. Knepley                               -1.0, -1.0,  0.0,  -1.0/3.0, -1.0, -1.0/3.0,   0.0, -1.0,  0.0,
341412e9a14SMatthew 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,
342412e9a14SMatthew G. Knepley                               -1.0, -1.0,  1.0,  -0.5, -0.5, -0.5};
343412e9a14SMatthew G. Knepley   PetscErrorCode   ierr;
344412e9a14SMatthew G. Knepley 
345412e9a14SMatthew G. Knepley   PetscFunctionBegin;
346412e9a14SMatthew G. Knepley   switch (ct) {
347412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:
348412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:
349412e9a14SMatthew G. Knepley     case DM_POLYTOPE_HEXAHEDRON:
350412e9a14SMatthew G. Knepley       ierr = DMPlexCellRefinerGetCellVertices_Regular(cr, ct, Nv, subcellV);CHKERRQ(ierr);break;
351412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:    *Nv =  7; *subcellV = tri_v; break;
352412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TETRAHEDRON: *Nv = 15; *subcellV = tet_v;  break;
353412e9a14SMatthew G. Knepley     default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "No subcell vertices for cell type %s", DMPolytopeTypes[ct]);
354412e9a14SMatthew G. Knepley   }
355412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
356412e9a14SMatthew G. Knepley }
357412e9a14SMatthew G. Knepley 
358412e9a14SMatthew G. Knepley /*
359412e9a14SMatthew G. Knepley   DMPlexCellRefinerGetCellVertices - Get the set of refined vertices lying in the closure of a reference cell of given type
360412e9a14SMatthew G. Knepley 
361412e9a14SMatthew G. Knepley   Input Parameters:
362412e9a14SMatthew G. Knepley + cr - The DMPlexCellRefiner object
363412e9a14SMatthew G. Knepley - ct - The cell type
364412e9a14SMatthew G. Knepley 
365412e9a14SMatthew G. Knepley   Output Parameters:
366412e9a14SMatthew G. Knepley + Nv       - The number of refined vertices in the closure of the reference cell of given type
367412e9a14SMatthew G. Knepley - subcellV - The coordinates of these vertices in the reference cell
368412e9a14SMatthew G. Knepley 
369412e9a14SMatthew G. Knepley   Level: developer
370412e9a14SMatthew G. Knepley 
371412e9a14SMatthew G. Knepley .seealso: DMPlexCellRefinerGetSubcellVertices()
372412e9a14SMatthew G. Knepley */
373412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerGetCellVertices(DMPlexCellRefiner cr, DMPolytopeType ct, PetscInt *Nv, PetscReal *subcellV[])
374412e9a14SMatthew G. Knepley {
375412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
376412e9a14SMatthew G. Knepley 
377412e9a14SMatthew G. Knepley   PetscFunctionBegin;
378a5801f52SStefano Zampini   if (!cr->ops->getcellvertices) SETERRQ1(PetscObjectComm((PetscObject)cr),PETSC_ERR_SUP,"Not for refiner type %s",DMPlexCellRefinerTypes[cr->type]);
379412e9a14SMatthew G. Knepley   ierr = (*cr->ops->getcellvertices)(cr, ct, Nv, subcellV);CHKERRQ(ierr);
380412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
381412e9a14SMatthew G. Knepley }
382412e9a14SMatthew G. Knepley 
383412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerGetSubcellVertices_Regular(DMPlexCellRefiner cr, DMPolytopeType ct, DMPolytopeType rct, PetscInt r, PetscInt *Nv, PetscInt *subcellV[])
384412e9a14SMatthew G. Knepley {
385412e9a14SMatthew G. Knepley   static PetscInt seg_v[]  = {0, 1, 1, 2};
386412e9a14SMatthew G. Knepley   static PetscInt tri_v[]  = {0, 3, 5,  3, 1, 4,  5, 4, 2,  3, 4, 5};
387412e9a14SMatthew G. Knepley   static PetscInt quad_v[] = {0, 4, 8, 7,  4, 1, 5, 8,  8, 5, 2, 6,  7, 8, 6, 3};
388412e9a14SMatthew G. Knepley   static PetscInt tet_v[]  = {0, 3, 1, 6,  3, 2, 4, 8,  1, 4, 5, 7,  6, 8, 7, 9,
389412e9a14SMatthew G. Knepley                               1, 6, 3, 7,  8, 4, 3, 7,  7, 3, 1, 4,  7, 3, 8, 6};
390412e9a14SMatthew 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,
391412e9a14SMatthew 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};
392412e9a14SMatthew G. Knepley 
393412e9a14SMatthew G. Knepley   PetscFunctionBegin;
394412e9a14SMatthew G. Knepley   if (ct != rct) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Cell type %s does not produce %s", DMPolytopeTypes[ct], DMPolytopeTypes[rct]);
395412e9a14SMatthew G. Knepley   switch (ct) {
396412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:       *Nv = 2; *subcellV = &seg_v[r*(*Nv)];  break;
397412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:      *Nv = 3; *subcellV = &tri_v[r*(*Nv)];  break;
398412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL: *Nv = 4; *subcellV = &quad_v[r*(*Nv)]; break;
399412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TETRAHEDRON:   *Nv = 4; *subcellV = &tet_v[r*(*Nv)];  break;
400412e9a14SMatthew G. Knepley     case DM_POLYTOPE_HEXAHEDRON:    *Nv = 8; *subcellV = &hex_v[r*(*Nv)];  break;
401412e9a14SMatthew G. Knepley     default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "No subcell vertices for cell type %s", DMPolytopeTypes[ct]);
402412e9a14SMatthew G. Knepley   }
403412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
404412e9a14SMatthew G. Knepley }
405412e9a14SMatthew G. Knepley 
40696ca5757SLisandro Dalcin static PetscErrorCode DMPlexCellRefinerGetSubcellVertices_ToBox(DMPlexCellRefiner cr, DMPolytopeType ct, DMPolytopeType rct, PetscInt r, PetscInt *Nv, PetscInt *subcellV[])
407412e9a14SMatthew G. Knepley {
408412e9a14SMatthew G. Knepley   static PetscInt tri_v[]  = {0, 3, 6, 5,  3, 1, 4, 6,  5, 6, 4, 2};
409412e9a14SMatthew 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};
410412e9a14SMatthew G. Knepley   PetscErrorCode  ierr;
411412e9a14SMatthew G. Knepley 
412412e9a14SMatthew G. Knepley   PetscFunctionBegin;
413412e9a14SMatthew G. Knepley   switch (ct) {
414412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:
415412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:
416412e9a14SMatthew G. Knepley     case DM_POLYTOPE_HEXAHEDRON:
417412e9a14SMatthew G. Knepley       ierr = DMPlexCellRefinerGetSubcellVertices_Regular(cr, ct, rct, r, Nv, subcellV);CHKERRQ(ierr);break;
418412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:
419412e9a14SMatthew 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]);
420412e9a14SMatthew G. Knepley       *Nv = 4; *subcellV = &tri_v[r*(*Nv)]; break;
421412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TETRAHEDRON:
422412e9a14SMatthew 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]);
423412e9a14SMatthew G. Knepley       *Nv = 8; *subcellV = &tet_v[r*(*Nv)]; break;
424412e9a14SMatthew G. Knepley     default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "No subcell vertices for cell type %s", DMPolytopeTypes[ct]);
425412e9a14SMatthew G. Knepley   }
426412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
427412e9a14SMatthew G. Knepley }
428412e9a14SMatthew G. Knepley 
429412e9a14SMatthew G. Knepley /*
430412e9a14SMatthew G. Knepley   DMPlexCellRefinerGetSubcellVertices - Get the set of refined vertices defining a subcell in the reference cell of given type
431412e9a14SMatthew G. Knepley 
432412e9a14SMatthew G. Knepley   Input Parameters:
433412e9a14SMatthew G. Knepley + cr  - The DMPlexCellRefiner object
434412e9a14SMatthew G. Knepley . ct  - The cell type
435412e9a14SMatthew G. Knepley . rct - The type of subcell
436412e9a14SMatthew G. Knepley - r   - The subcell index
437412e9a14SMatthew G. Knepley 
438412e9a14SMatthew G. Knepley   Output Parameters:
439412e9a14SMatthew G. Knepley + Nv       - The number of refined vertices in the subcell
440412e9a14SMatthew G. Knepley - subcellV - The indices of these vertices in the set of vertices returned by DMPlexCellRefinerGetCellVertices()
441412e9a14SMatthew G. Knepley 
442412e9a14SMatthew G. Knepley   Level: developer
443412e9a14SMatthew G. Knepley 
444412e9a14SMatthew G. Knepley .seealso: DMPlexCellRefinerGetCellVertices()
445412e9a14SMatthew G. Knepley */
446412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerGetSubcellVertices(DMPlexCellRefiner cr, DMPolytopeType ct, DMPolytopeType rct, PetscInt r, PetscInt *Nv, PetscInt *subcellV[])
447412e9a14SMatthew G. Knepley {
448412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
449412e9a14SMatthew G. Knepley 
450412e9a14SMatthew G. Knepley   PetscFunctionBegin;
451a5801f52SStefano Zampini   if (!cr->ops->getsubcellvertices) SETERRQ1(PetscObjectComm((PetscObject)cr),PETSC_ERR_SUP,"Not for refiner type %s",DMPlexCellRefinerTypes[cr->type]);
452412e9a14SMatthew G. Knepley   ierr = (*cr->ops->getsubcellvertices)(cr, ct, rct, r, Nv, subcellV);CHKERRQ(ierr);
453412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
454412e9a14SMatthew G. Knepley }
455412e9a14SMatthew G. Knepley 
456412e9a14SMatthew G. Knepley /*
457412e9a14SMatthew G. Knepley   Input Parameters:
458412e9a14SMatthew G. Knepley + cr   - The DMPlexCellRefiner
459412e9a14SMatthew G. Knepley . pct  - The cell type of the parent, from whom the new cell is being produced
460a5801f52SStefano Zampini . ct   - The type being produced
461a5801f52SStefano Zampini . r    - The replica number requested for the produced cell type
462a5801f52SStefano Zampini . Nv   - Number of vertices in the closure of the parent cell
463a5801f52SStefano Zampini . dE   - Spatial dimension
464a5801f52SStefano Zampini - in   - array of size Nv*dE, holding coordinates of the vertices in the closure of the parent cell
465a5801f52SStefano Zampini 
466a5801f52SStefano Zampini   Output Parameters:
467a5801f52SStefano Zampini . out - The coordinates of the new vertices
468a5801f52SStefano Zampini */
469a5801f52SStefano Zampini static PetscErrorCode DMPlexCellRefinerMapCoordinates(DMPlexCellRefiner cr, DMPolytopeType pct, DMPolytopeType ct, PetscInt r, PetscInt Nv, PetscInt dE, const PetscScalar in[], PetscScalar out[])
470a5801f52SStefano Zampini {
471a5801f52SStefano Zampini   PetscErrorCode ierr;
472a5801f52SStefano Zampini 
473a5801f52SStefano Zampini   PetscFunctionBeginHot;
474a5801f52SStefano Zampini   if (!cr->ops->mapcoords) SETERRQ1(PetscObjectComm((PetscObject)cr),PETSC_ERR_SUP,"Not for refiner type %s",DMPlexCellRefinerTypes[cr->type]);
475a5801f52SStefano Zampini   ierr = (*cr->ops->mapcoords)(cr, pct, ct, r, Nv, dE, in, out);CHKERRQ(ierr);
476a5801f52SStefano Zampini   PetscFunctionReturn(0);
477a5801f52SStefano Zampini }
478a5801f52SStefano Zampini 
479a5801f52SStefano Zampini /* Computes new vertex as the barycenter */
480a5801f52SStefano Zampini static PetscErrorCode DMPlexCellRefinerMapCoordinates_Barycenter(DMPlexCellRefiner cr, DMPolytopeType pct, DMPolytopeType ct, PetscInt r, PetscInt Nv, PetscInt dE, const PetscScalar in[], PetscScalar out[])
481a5801f52SStefano Zampini {
482a5801f52SStefano Zampini   PetscInt v,d;
483a5801f52SStefano Zampini 
484a5801f52SStefano Zampini   PetscFunctionBeginHot;
485a5801f52SStefano Zampini   if (ct != DM_POLYTOPE_POINT) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for refined point type %s",DMPolytopeTypes[ct]);
486a5801f52SStefano Zampini   for (d = 0; d < dE; ++d) out[d] = 0.0;
487a5801f52SStefano Zampini   for (v = 0; v < Nv; ++v) for (d = 0; d < dE; ++d) out[d] += in[v*dE+d];
488a5801f52SStefano Zampini   for (d = 0; d < dE; ++d) out[d] /= Nv;
489a5801f52SStefano Zampini   PetscFunctionReturn(0);
490a5801f52SStefano Zampini }
491a5801f52SStefano Zampini 
492a5801f52SStefano Zampini /*
493a5801f52SStefano Zampini   Input Parameters:
494a5801f52SStefano Zampini + cr  - The DMPlexCellRefiner
495a5801f52SStefano Zampini . pct - The cell type of the parent, from whom the new cell is being produced
4963f2a96e3SMatthew G. Knepley . pp  - The parent cell
497412e9a14SMatthew G. Knepley . po  - The orientation of the parent cell in its enclosing parent
498412e9a14SMatthew G. Knepley . ct  - The type being produced
499412e9a14SMatthew G. Knepley . r   - The replica number requested for the produced cell type
500412e9a14SMatthew G. Knepley - o   - The relative orientation of the replica
501412e9a14SMatthew G. Knepley 
502412e9a14SMatthew G. Knepley   Output Parameters:
503a5801f52SStefano Zampini + rnew - The replica number, given the orientation of the parent
504412e9a14SMatthew G. Knepley - onew - The replica orientation, given the orientation of the parent
505412e9a14SMatthew G. Knepley */
5063f2a96e3SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerMapSubcells(DMPlexCellRefiner cr, DMPolytopeType pct, PetscInt pp, PetscInt po, DMPolytopeType ct, PetscInt r, PetscInt o, PetscInt *rnew, PetscInt *onew)
507412e9a14SMatthew G. Knepley {
508412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
509412e9a14SMatthew G. Knepley 
510412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
511a5801f52SStefano Zampini   if (!cr->ops->mapsubcells) SETERRQ1(PetscObjectComm((PetscObject)cr),PETSC_ERR_SUP,"Not for refiner type %s",DMPlexCellRefinerTypes[cr->type]);
5123f2a96e3SMatthew G. Knepley   ierr = (*cr->ops->mapsubcells)(cr, pct, pp, po, ct, r, o, rnew, onew);CHKERRQ(ierr);
513412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
514412e9a14SMatthew G. Knepley }
515412e9a14SMatthew G. Knepley 
516cf4091a3SMatthew G. Knepley /*
517cf4091a3SMatthew G. Knepley   This is the group multiplication table for the dihedral group of the cell.
518cf4091a3SMatthew G. Knepley */
519cf4091a3SMatthew G. Knepley static PetscErrorCode ComposeOrientation_Private(PetscInt n, PetscInt o1, PetscInt o2, PetscInt *o)
520cf4091a3SMatthew G. Knepley {
521cf4091a3SMatthew G. Knepley   PetscFunctionBeginHot;
522cf4091a3SMatthew G. Knepley   if (!n)                      {*o = 0;}
523cf4091a3SMatthew G. Knepley   else if (o1 >= 0 && o2 >= 0) {*o = ( o1 + o2) % n;}
524cf4091a3SMatthew G. Knepley   else if (o1 <  0 && o2 <  0) {*o = (-o1 - o2) % n;}
525cf4091a3SMatthew G. Knepley   else if (o1 < 0)             {*o = -((-(o1+1) + o2) % n + 1);}
526cf4091a3SMatthew G. Knepley   else if (o2 < 0)             {*o = -((-(o2+1) + o1) % n + 1);}
527cf4091a3SMatthew G. Knepley   PetscFunctionReturn(0);
528cf4091a3SMatthew G. Knepley }
529cf4091a3SMatthew G. Knepley 
5303f2a96e3SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerMapSubcells_None(DMPlexCellRefiner cr, DMPolytopeType pct, PetscInt pp, PetscInt po, DMPolytopeType ct, PetscInt r, PetscInt o, PetscInt *rnew, PetscInt *onew)
531cf4091a3SMatthew G. Knepley {
532cf4091a3SMatthew G. Knepley   PetscErrorCode ierr;
533cf4091a3SMatthew G. Knepley 
534cf4091a3SMatthew G. Knepley   PetscFunctionBeginHot;
535cf4091a3SMatthew G. Knepley   *rnew = r;
536cf4091a3SMatthew G. Knepley   ierr  = ComposeOrientation_Private(DMPolytopeTypeGetConeSize(ct), po, o, onew);CHKERRQ(ierr);
537cf4091a3SMatthew G. Knepley   PetscFunctionReturn(0);
538cf4091a3SMatthew G. Knepley }
539cf4091a3SMatthew G. Knepley 
5403f2a96e3SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerMapSubcells_Regular(DMPlexCellRefiner cr, DMPolytopeType pct, PetscInt pp, PetscInt po, DMPolytopeType ct, PetscInt r, PetscInt o, PetscInt *rnew, PetscInt *onew)
541412e9a14SMatthew G. Knepley {
542412e9a14SMatthew G. Knepley   /* We shift any input orientation in order to make it non-negative
543412e9a14SMatthew 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)
544412e9a14SMatthew G. Knepley        The replica array r[po][r] gives the new replica number rnew given that the parent point has orientation po
545412e9a14SMatthew G. Knepley        Overall, replica (r, o) in a parent with orientation 0 matches replica (rnew, onew) in a parent with orientation po
546412e9a14SMatthew G. Knepley   */
547412e9a14SMatthew G. Knepley   PetscInt tri_seg_o[] = {-2, 0,
548412e9a14SMatthew G. Knepley                           -2, 0,
549412e9a14SMatthew G. Knepley                           -2, 0,
550412e9a14SMatthew G. Knepley                           0, -2,
551412e9a14SMatthew G. Knepley                           0, -2,
552412e9a14SMatthew G. Knepley                           0, -2};
553412e9a14SMatthew G. Knepley   PetscInt tri_seg_r[] = {1, 0, 2,
554412e9a14SMatthew G. Knepley                           0, 2, 1,
555412e9a14SMatthew G. Knepley                           2, 1, 0,
556412e9a14SMatthew G. Knepley                           0, 1, 2,
557412e9a14SMatthew G. Knepley                           1, 2, 0,
558412e9a14SMatthew G. Knepley                           2, 0, 1};
559412e9a14SMatthew G. Knepley   PetscInt tri_tri_o[] = {0,  1,  2, -3, -2, -1,
560412e9a14SMatthew G. Knepley                           2,  0,  1, -2, -1, -3,
561412e9a14SMatthew G. Knepley                           1,  2,  0, -1, -3, -2,
562412e9a14SMatthew G. Knepley                          -3, -2, -1,  0,  1,  2,
563412e9a14SMatthew G. Knepley                          -1, -3, -2,  1,  2,  0,
564412e9a14SMatthew G. Knepley                          -2, -1, -3,  2,  0,  1};
565412e9a14SMatthew G. Knepley   /* orientation if the replica is the center triangle */
566412e9a14SMatthew G. Knepley   PetscInt tri_tri_o_c[] = {2,  0,  1, -2, -1, -3,
567412e9a14SMatthew G. Knepley                             1,  2,  0, -1, -3, -2,
568412e9a14SMatthew G. Knepley                             0,  1,  2, -3, -2, -1,
569412e9a14SMatthew G. Knepley                            -3, -2, -1,  0,  1,  2,
570412e9a14SMatthew G. Knepley                            -1, -3, -2,  1,  2,  0,
571412e9a14SMatthew G. Knepley                            -2, -1, -3,  2,  0,  1};
572412e9a14SMatthew G. Knepley   PetscInt tri_tri_r[] = {0, 2, 1, 3,
573412e9a14SMatthew G. Knepley                           2, 1, 0, 3,
574412e9a14SMatthew G. Knepley                           1, 0, 2, 3,
575412e9a14SMatthew G. Knepley                           0, 1, 2, 3,
576412e9a14SMatthew G. Knepley                           1, 2, 0, 3,
577412e9a14SMatthew G. Knepley                           2, 0, 1, 3};
578412e9a14SMatthew G. Knepley   PetscInt quad_seg_r[] = {3, 2, 1, 0,
579412e9a14SMatthew G. Knepley                            2, 1, 0, 3,
580412e9a14SMatthew G. Knepley                            1, 0, 3, 2,
581412e9a14SMatthew G. Knepley                            0, 3, 2, 1,
582412e9a14SMatthew G. Knepley                            0, 1, 2, 3,
583412e9a14SMatthew G. Knepley                            1, 2, 3, 0,
584412e9a14SMatthew G. Knepley                            2, 3, 0, 1,
585412e9a14SMatthew G. Knepley                            3, 0, 1, 2};
586412e9a14SMatthew G. Knepley   PetscInt quad_quad_o[] = { 0,  1,  2,  3, -4, -3, -2, -1,
587412e9a14SMatthew G. Knepley                              4,  0,  1,  2, -3, -2, -1, -4,
588412e9a14SMatthew G. Knepley                              3,  4,  0,  1, -2, -1, -4, -3,
589412e9a14SMatthew G. Knepley                              2,  3,  4,  0, -1, -4, -3, -2,
590412e9a14SMatthew G. Knepley                             -4, -3, -2, -1,  0,  1,  2,  3,
591412e9a14SMatthew G. Knepley                             -1, -4, -3, -2,  1,  2,  3,  0,
592412e9a14SMatthew G. Knepley                             -2, -1, -4, -3,  2,  3,  0,  1,
593412e9a14SMatthew G. Knepley                             -3, -2, -1, -4,  3,  0,  1,  2};
594412e9a14SMatthew G. Knepley   PetscInt quad_quad_r[] = {0, 3, 2, 1,
595412e9a14SMatthew G. Knepley                             3, 2, 1, 0,
596412e9a14SMatthew G. Knepley                             2, 1, 0, 3,
597412e9a14SMatthew G. Knepley                             1, 0, 3, 2,
598412e9a14SMatthew G. Knepley                             0, 1, 2, 3,
599412e9a14SMatthew G. Knepley                             1, 2, 3, 0,
600412e9a14SMatthew G. Knepley                             2, 3, 0, 1,
601412e9a14SMatthew G. Knepley                             3, 0, 1, 2};
602412e9a14SMatthew G. Knepley   PetscInt tquad_tquad_o[] = { 0,  1, -2, -1,
603412e9a14SMatthew G. Knepley                                1,  0, -1, -2,
604412e9a14SMatthew G. Knepley                               -2, -1,  0,  1,
605412e9a14SMatthew G. Knepley                               -1, -2,  1,  0};
606412e9a14SMatthew G. Knepley   PetscInt tquad_tquad_r[] = {1, 0,
607412e9a14SMatthew G. Knepley                               1, 0,
608412e9a14SMatthew G. Knepley                               0, 1,
609412e9a14SMatthew G. Knepley                               0, 1};
610412e9a14SMatthew G. Knepley 
611412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
612412e9a14SMatthew G. Knepley   /* The default is no transformation */
613412e9a14SMatthew G. Knepley   *rnew = r;
614412e9a14SMatthew G. Knepley   *onew = o;
615412e9a14SMatthew G. Knepley   switch (pct) {
616412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:
617412e9a14SMatthew G. Knepley       if (ct == DM_POLYTOPE_SEGMENT) {
618412e9a14SMatthew G. Knepley         if      (po == 0 || po == -1) {*rnew = r;       *onew = o;}
619412e9a14SMatthew G. Knepley         else if (po == 1 || po == -2) {*rnew = (r+1)%2; *onew = (o == 0 || o == -1) ? -2 : 0;}
620412e9a14SMatthew G. Knepley         else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid orientation %D for segment", po);
621412e9a14SMatthew G. Knepley       }
622412e9a14SMatthew G. Knepley       break;
623412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:
624412e9a14SMatthew G. Knepley       switch (ct) {
625412e9a14SMatthew G. Knepley         case DM_POLYTOPE_SEGMENT:
626412e9a14SMatthew G. Knepley           if (o == -1) o = 0;
627412e9a14SMatthew G. Knepley           if (o == -2) o = 1;
628412e9a14SMatthew G. Knepley           *onew = tri_seg_o[(po+3)*2+o];
629412e9a14SMatthew G. Knepley           *rnew = tri_seg_r[(po+3)*3+r];
630412e9a14SMatthew G. Knepley           break;
631412e9a14SMatthew G. Knepley         case DM_POLYTOPE_TRIANGLE:
632412e9a14SMatthew 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];
633412e9a14SMatthew G. Knepley           *rnew = tri_tri_r[(po+3)*4+r];
634412e9a14SMatthew G. Knepley           break;
635412e9a14SMatthew G. Knepley         default: break;
636412e9a14SMatthew G. Knepley       }
637412e9a14SMatthew G. Knepley       break;
638412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:
639412e9a14SMatthew G. Knepley       switch (ct) {
640412e9a14SMatthew G. Knepley         case DM_POLYTOPE_SEGMENT:
641412e9a14SMatthew G. Knepley           *onew = o;
642412e9a14SMatthew G. Knepley           *rnew = quad_seg_r[(po+4)*4+r];
643412e9a14SMatthew G. Knepley           break;
644412e9a14SMatthew G. Knepley         case DM_POLYTOPE_QUADRILATERAL:
645412e9a14SMatthew G. Knepley           *onew = quad_quad_o[(po+4)*8+o+4];
646412e9a14SMatthew G. Knepley           *rnew = quad_quad_r[(po+4)*4+r];
647412e9a14SMatthew G. Knepley           break;
648412e9a14SMatthew G. Knepley         default: break;
649412e9a14SMatthew G. Knepley       }
650412e9a14SMatthew G. Knepley       break;
651412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEG_PRISM_TENSOR:
652412e9a14SMatthew G. Knepley       switch (ct) {
653412e9a14SMatthew G. Knepley         /* DM_POLYTOPE_POINT_PRISM_TENSOR does not change */
654412e9a14SMatthew G. Knepley         case DM_POLYTOPE_SEG_PRISM_TENSOR:
655412e9a14SMatthew G. Knepley           *onew = tquad_tquad_o[(po+2)*4+o+2];
656412e9a14SMatthew G. Knepley           *rnew = tquad_tquad_r[(po+2)*2+r];
657412e9a14SMatthew G. Knepley           break;
658412e9a14SMatthew G. Knepley         default: break;
659412e9a14SMatthew G. Knepley       }
660412e9a14SMatthew G. Knepley       break;
661412e9a14SMatthew G. Knepley     default: break;
662412e9a14SMatthew G. Knepley   }
663412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
664412e9a14SMatthew G. Knepley }
665412e9a14SMatthew G. Knepley 
6663f2a96e3SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerMapSubcells_ToBox(DMPlexCellRefiner cr, DMPolytopeType pct, PetscInt pp, PetscInt po, DMPolytopeType ct, PetscInt r, PetscInt o, PetscInt *rnew, PetscInt *onew)
667412e9a14SMatthew G. Knepley {
668412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
669412e9a14SMatthew G. Knepley   /* We shift any input orientation in order to make it non-negative
670412e9a14SMatthew 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)
671412e9a14SMatthew G. Knepley        The replica array r[po][r] gives the new replica number rnew given that the parent point has orientation po
672412e9a14SMatthew G. Knepley        Overall, replica (r, o) in a parent with orientation 0 matches replica (rnew, onew) in a parent with orientation po
673412e9a14SMatthew G. Knepley   */
674412e9a14SMatthew G. Knepley   PetscInt tri_seg_o[] = {0, -2,
675412e9a14SMatthew G. Knepley                           0, -2,
676412e9a14SMatthew G. Knepley                           0, -2,
677412e9a14SMatthew G. Knepley                           0, -2,
678412e9a14SMatthew G. Knepley                           0, -2,
679412e9a14SMatthew G. Knepley                           0, -2};
680412e9a14SMatthew G. Knepley   PetscInt tri_seg_r[] = {2, 1, 0,
681412e9a14SMatthew G. Knepley                           1, 0, 2,
682412e9a14SMatthew G. Knepley                           0, 2, 1,
683412e9a14SMatthew G. Knepley                           0, 1, 2,
684412e9a14SMatthew G. Knepley                           1, 2, 0,
685412e9a14SMatthew G. Knepley                           2, 0, 1};
686412e9a14SMatthew G. Knepley   PetscInt tri_tri_o[] = {0,  1,  2,  3, -4, -3, -2, -1,
687412e9a14SMatthew G. Knepley                           3,  0,  1,  2, -3, -2, -1, -4,
688412e9a14SMatthew G. Knepley                           1,  2,  3,  0, -1, -4, -3, -2,
689412e9a14SMatthew G. Knepley                          -4, -3, -2, -1,  0,  1,  2,  3,
690412e9a14SMatthew G. Knepley                          -1, -4, -3, -2,  1,  2,  3,  0,
691412e9a14SMatthew G. Knepley                          -3, -2, -1, -4,  3,  0,  1,  2};
692412e9a14SMatthew G. Knepley   PetscInt tri_tri_r[] = {0, 2, 1,
693412e9a14SMatthew G. Knepley                           2, 1, 0,
694412e9a14SMatthew G. Knepley                           1, 0, 2,
695412e9a14SMatthew G. Knepley                           0, 1, 2,
696412e9a14SMatthew G. Knepley                           1, 2, 0,
697412e9a14SMatthew G. Knepley                           2, 0, 1};
698412e9a14SMatthew G. Knepley   PetscInt tquad_tquad_o[] = { 0,  1, -2, -1,
699412e9a14SMatthew G. Knepley                                1,  0, -1, -2,
700412e9a14SMatthew G. Knepley                               -2, -1,  0,  1,
701412e9a14SMatthew G. Knepley                               -1, -2,  1,  0};
702412e9a14SMatthew G. Knepley   PetscInt tquad_tquad_r[] = {1, 0,
703412e9a14SMatthew G. Knepley                               1, 0,
704412e9a14SMatthew G. Knepley                               0, 1,
705412e9a14SMatthew G. Knepley                               0, 1};
706412e9a14SMatthew G. Knepley   PetscInt tquad_quad_o[] = {-2, -1, -4, -3,  2,  3,  0,  1,
707412e9a14SMatthew G. Knepley                               1,  2,  3,  0, -1, -4, -3, -2,
708412e9a14SMatthew G. Knepley                              -4, -3, -2, -1,  0,  1,  2,  3,
709412e9a14SMatthew G. Knepley                               1,  0,  3,  2, -3, -4, -1, -2};
710412e9a14SMatthew G. Knepley 
711412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
712412e9a14SMatthew G. Knepley   *rnew = r;
713412e9a14SMatthew G. Knepley   *onew = o;
714412e9a14SMatthew G. Knepley   switch (pct) {
715412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:
716412e9a14SMatthew G. Knepley       switch (ct) {
717412e9a14SMatthew G. Knepley         case DM_POLYTOPE_SEGMENT:
718412e9a14SMatthew G. Knepley           if (o == -1) o = 0;
719412e9a14SMatthew G. Knepley           if (o == -2) o = 1;
720412e9a14SMatthew G. Knepley           *onew = tri_seg_o[(po+3)*2+o];
721412e9a14SMatthew G. Knepley           *rnew = tri_seg_r[(po+3)*3+r];
722412e9a14SMatthew G. Knepley           break;
723412e9a14SMatthew G. Knepley         case DM_POLYTOPE_QUADRILATERAL:
724412e9a14SMatthew G. Knepley           *onew = tri_tri_o[(po+3)*8+o+4];
725412e9a14SMatthew G. Knepley           /* TODO See sheet, for fixing po == 1 and 2 */
726412e9a14SMatthew G. Knepley           if (po ==  2 && r == 2 && o >= 0) *onew = tri_tri_o[(po+3)*8+((o+3)%4)+4];
727412e9a14SMatthew G. Knepley           if (po ==  2 && r == 2 && o <  0) *onew = tri_tri_o[(po+3)*8+((o+5)%4)];
728412e9a14SMatthew G. Knepley           if (po ==  1 && r == 1 && o >= 0) *onew = tri_tri_o[(po+3)*8+((o+1)%4)+4];
729412e9a14SMatthew G. Knepley           if (po ==  1 && r == 1 && o <  0) *onew = tri_tri_o[(po+3)*8+((o+7)%4)];
730412e9a14SMatthew G. Knepley           if (po == -1 && r == 2 && o >= 0) *onew = tri_tri_o[(po+3)*8+((o+3)%4)+4];
731412e9a14SMatthew G. Knepley           if (po == -1 && r == 2 && o <  0) *onew = tri_tri_o[(po+3)*8+((o+5)%4)];
732412e9a14SMatthew G. Knepley           if (po == -2 && r == 1 && o >= 0) *onew = tri_tri_o[(po+3)*8+((o+1)%4)+4];
733412e9a14SMatthew G. Knepley           if (po == -2 && r == 1 && o <  0) *onew = tri_tri_o[(po+3)*8+((o+7)%4)];
734412e9a14SMatthew G. Knepley           *rnew = tri_tri_r[(po+3)*3+r];
735412e9a14SMatthew G. Knepley           break;
736412e9a14SMatthew G. Knepley         default: break;
737412e9a14SMatthew G. Knepley       }
738412e9a14SMatthew G. Knepley       break;
739412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEG_PRISM_TENSOR:
740412e9a14SMatthew G. Knepley       switch (ct) {
741412e9a14SMatthew G. Knepley         /* DM_POLYTOPE_POINT_PRISM_TENSOR does not change */
742412e9a14SMatthew G. Knepley         case DM_POLYTOPE_SEG_PRISM_TENSOR:
743412e9a14SMatthew G. Knepley           *onew = tquad_tquad_o[(po+2)*4+o+2];
744412e9a14SMatthew G. Knepley           *rnew = tquad_tquad_r[(po+2)*2+r];
745412e9a14SMatthew G. Knepley           break;
746412e9a14SMatthew G. Knepley         case DM_POLYTOPE_QUADRILATERAL:
747412e9a14SMatthew G. Knepley           *onew = tquad_quad_o[(po+2)*8+o+4];
748412e9a14SMatthew G. Knepley           *rnew = tquad_tquad_r[(po+2)*2+r];
749412e9a14SMatthew G. Knepley           break;
750412e9a14SMatthew G. Knepley         default: break;
751412e9a14SMatthew G. Knepley       }
752412e9a14SMatthew G. Knepley       break;
753412e9a14SMatthew G. Knepley     default:
7543f2a96e3SMatthew G. Knepley       ierr = DMPlexCellRefinerMapSubcells_Regular(cr, pct, pp, po, ct, r, o, rnew, onew);CHKERRQ(ierr);
755412e9a14SMatthew G. Knepley   }
756412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
757412e9a14SMatthew G. Knepley }
758412e9a14SMatthew G. Knepley 
7593f2a96e3SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerMapSubcells_ToSimplex(DMPlexCellRefiner cr, DMPolytopeType pct, PetscInt pp, PetscInt po, DMPolytopeType ct, PetscInt r, PetscInt o, PetscInt *rnew, PetscInt *onew)
760412e9a14SMatthew G. Knepley {
7613f2a96e3SMatthew G. Knepley   return DMPlexCellRefinerMapSubcells_Regular(cr, pct, pp, po, ct, r, o, rnew, onew);
762412e9a14SMatthew G. Knepley }
763412e9a14SMatthew G. Knepley 
764412e9a14SMatthew G. Knepley /*@
765412e9a14SMatthew G. Knepley   DMPlexCellRefinerRefine - Return a description of the refinement for a given cell type
766412e9a14SMatthew G. Knepley 
7673f2a96e3SMatthew G. Knepley   Input Parameters:
7683f2a96e3SMatthew G. Knepley + source - The cell type for a source point
7693f2a96e3SMatthew G. Knepley - p      - The source point, or PETSC_DETERMINE if the refine is homogeneous
770412e9a14SMatthew G. Knepley 
7713f2a96e3SMatthew G. Knepley   Output Parameters:
7723f2a96e3SMatthew G. Knepley + rt     - The refine type for this cell
7733f2a96e3SMatthew G. Knepley . Nt     - The number of cell types generated by refinement
774412e9a14SMatthew G. Knepley . target - The cell types generated
775412e9a14SMatthew G. Knepley . size   - The number of subcells of each type, ordered by dimension
776412e9a14SMatthew G. Knepley . cone   - A list of the faces for each subcell of the same type as source
777412e9a14SMatthew G. Knepley - ornt   - A list of the face orientations for each subcell of the same type as source
778412e9a14SMatthew G. Knepley 
779a5801f52SStefano Zampini   Note: The cone array gives the cone of each subcell listed by the first three outputs. For each cone point, we
780412e9a14SMatthew G. Knepley   need the cell type, point identifier, and orientation within the subcell. The orientation is with respect to the canonical
781412e9a14SMatthew G. Knepley   division (described in these outputs) of the cell in the original mesh. The point identifier is given by
782412e9a14SMatthew G. Knepley $   the number of cones to be taken, or 0 for the current cell
783412e9a14SMatthew G. Knepley $   the cell cone point number at each level from which it is subdivided
784412e9a14SMatthew G. Knepley $   the replica number r of the subdivision.
785412e9a14SMatthew G. Knepley   The orientation is with respect to the canonical cone orientation. For example, the prescription for edge division is
786412e9a14SMatthew G. Knepley $   Nt     = 2
787412e9a14SMatthew G. Knepley $   target = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT}
788412e9a14SMatthew G. Knepley $   size   = {1, 2}
789412e9a14SMatthew 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}
790412e9a14SMatthew G. Knepley $   ornt   = {                         0,                       0,                        0,                          0}
791412e9a14SMatthew G. Knepley 
792412e9a14SMatthew G. Knepley   Level: developer
793412e9a14SMatthew G. Knepley 
79496ca5757SLisandro Dalcin .seealso: DMPlexCellRefinerCreate(), DMPlexRefineUniform()
795412e9a14SMatthew G. Knepley @*/
7963f2a96e3SMatthew G. Knepley PetscErrorCode DMPlexCellRefinerRefine(DMPlexCellRefiner cr, DMPolytopeType source, PetscInt p, PetscInt *rt, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[])
797412e9a14SMatthew G. Knepley {
798412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
799412e9a14SMatthew G. Knepley 
800412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
801a5801f52SStefano Zampini   if (!cr->ops->refine) SETERRQ1(PetscObjectComm((PetscObject)cr),PETSC_ERR_SUP,"Not for refiner type %s",DMPlexCellRefinerTypes[cr->type]);
8023f2a96e3SMatthew G. Knepley   ierr = (*cr->ops->refine)(cr, source, p, rt, Nt, target, size, cone, ornt);CHKERRQ(ierr);
803412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
804412e9a14SMatthew G. Knepley }
805412e9a14SMatthew G. Knepley 
8063f2a96e3SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerRefine_None(DMPlexCellRefiner cr, DMPolytopeType source, PetscInt p, PetscInt *rt, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[])
807cf4091a3SMatthew G. Knepley {
808cf4091a3SMatthew G. Knepley   static DMPolytopeType vertexT[] = {DM_POLYTOPE_POINT};
809cf4091a3SMatthew G. Knepley   static PetscInt       vertexS[] = {1};
810cf4091a3SMatthew G. Knepley   static PetscInt       vertexC[] = {0};
811cf4091a3SMatthew G. Knepley   static PetscInt       vertexO[] = {0};
812cf4091a3SMatthew G. Knepley   static DMPolytopeType edgeT[]   = {DM_POLYTOPE_SEGMENT};
813cf4091a3SMatthew G. Knepley   static PetscInt       edgeS[]   = {1};
814cf4091a3SMatthew G. Knepley   static PetscInt       edgeC[]   = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0};
815cf4091a3SMatthew G. Knepley   static PetscInt       edgeO[]   = {0, 0};
816cf4091a3SMatthew G. Knepley   static DMPolytopeType tedgeT[]  = {DM_POLYTOPE_POINT_PRISM_TENSOR};
817cf4091a3SMatthew G. Knepley   static PetscInt       tedgeS[]  = {1};
818cf4091a3SMatthew G. Knepley   static PetscInt       tedgeC[]  = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0};
819cf4091a3SMatthew G. Knepley   static PetscInt       tedgeO[]  = {0, 0};
820cf4091a3SMatthew G. Knepley   static DMPolytopeType triT[]    = {DM_POLYTOPE_TRIANGLE};
821cf4091a3SMatthew G. Knepley   static PetscInt       triS[]    = {1};
822cf4091a3SMatthew G. Knepley   static PetscInt       triC[]    = {DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 2, 0};
823cf4091a3SMatthew G. Knepley   static PetscInt       triO[]    = {0, 0, 0};
824cf4091a3SMatthew G. Knepley   static DMPolytopeType quadT[]   = {DM_POLYTOPE_QUADRILATERAL};
825cf4091a3SMatthew G. Knepley   static PetscInt       quadS[]   = {1};
826cf4091a3SMatthew G. Knepley   static PetscInt       quadC[]   = {DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 1, 3, 0};
827cf4091a3SMatthew G. Knepley   static PetscInt       quadO[]   = {0, 0, 0, 0};
828cf4091a3SMatthew G. Knepley   static DMPolytopeType tquadT[]  = {DM_POLYTOPE_SEG_PRISM_TENSOR};
829cf4091a3SMatthew G. Knepley   static PetscInt       tquadS[]  = {1};
830cf4091a3SMatthew G. Knepley   static PetscInt       tquadC[]  = {DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 1, 2, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 1, 3, 0};
831cf4091a3SMatthew G. Knepley   static PetscInt       tquadO[]  = {0, 0, 0, 0};
832cf4091a3SMatthew G. Knepley   static DMPolytopeType tetT[]    = {DM_POLYTOPE_TETRAHEDRON};
833cf4091a3SMatthew G. Knepley   static PetscInt       tetS[]    = {1};
834cf4091a3SMatthew G. Knepley   static PetscInt       tetC[]    = {DM_POLYTOPE_TRIANGLE, 1, 0, 0, DM_POLYTOPE_TRIANGLE, 1, 1, 0, DM_POLYTOPE_TRIANGLE, 1, 2, 0, DM_POLYTOPE_TRIANGLE, 1, 3, 0};
835cf4091a3SMatthew G. Knepley   static PetscInt       tetO[]    = {0, 0, 0, 0};
836cf4091a3SMatthew G. Knepley   static DMPolytopeType hexT[]    = {DM_POLYTOPE_HEXAHEDRON};
837cf4091a3SMatthew G. Knepley   static PetscInt       hexS[]    = {1};
838cf4091a3SMatthew G. Knepley   static PetscInt       hexC[]    = {DM_POLYTOPE_QUADRILATERAL, 1, 0, 0, DM_POLYTOPE_QUADRILATERAL, 1, 1, 0, DM_POLYTOPE_QUADRILATERAL, 1, 2, 0,
839cf4091a3SMatthew G. Knepley                                      DM_POLYTOPE_QUADRILATERAL, 1, 3, 0, DM_POLYTOPE_QUADRILATERAL, 1, 4, 0, DM_POLYTOPE_QUADRILATERAL, 1, 5, 0};
840cf4091a3SMatthew G. Knepley   static PetscInt       hexO[]    = {0, 0, 0, 0, 0, 0};
841cf4091a3SMatthew G. Knepley   static DMPolytopeType tripT[]   = {DM_POLYTOPE_TRI_PRISM};
842cf4091a3SMatthew G. Knepley   static PetscInt       tripS[]   = {1};
843cf4091a3SMatthew G. Knepley   static PetscInt       tripC[]   = {DM_POLYTOPE_TRIANGLE, 1, 0, 0, DM_POLYTOPE_TRIANGLE, 1, 1, 0,
844cf4091a3SMatthew G. Knepley                                      DM_POLYTOPE_QUADRILATERAL, 1, 2, 0, DM_POLYTOPE_QUADRILATERAL, 1, 3, 0, DM_POLYTOPE_QUADRILATERAL, 1, 4, 0};
845cf4091a3SMatthew G. Knepley   static PetscInt       tripO[]   = {0, 0, 0, 0, 0};
846cf4091a3SMatthew G. Knepley   static DMPolytopeType ttripT[]  = {DM_POLYTOPE_TRI_PRISM_TENSOR};
847cf4091a3SMatthew G. Knepley   static PetscInt       ttripS[]  = {1};
848cf4091a3SMatthew G. Knepley   static PetscInt       ttripC[]  = {DM_POLYTOPE_TRIANGLE, 1, 0, 0, DM_POLYTOPE_TRIANGLE, 1, 1, 0,
849cf4091a3SMatthew G. Knepley                                      DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 2, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 3, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 4, 0};
850cf4091a3SMatthew G. Knepley   static PetscInt       ttripO[]  = {0, 0, 0, 0, 0};
851cf4091a3SMatthew G. Knepley   static DMPolytopeType tquadpT[] = {DM_POLYTOPE_QUAD_PRISM_TENSOR};
852cf4091a3SMatthew G. Knepley   static PetscInt       tquadpS[] = {1};
853cf4091a3SMatthew G. Knepley   static PetscInt       tquadpC[] = {DM_POLYTOPE_QUADRILATERAL, 1, 0, 0, DM_POLYTOPE_QUADRILATERAL, 1, 1, 0,
854cf4091a3SMatthew G. Knepley                                      DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 2, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 3, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 4, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 5, 0};
855cf4091a3SMatthew G. Knepley   static PetscInt       tquadpO[] = {0, 0, 0, 0, 0, 0};
856da9060c4SMatthew G. Knepley   static DMPolytopeType pyrT[]    = {DM_POLYTOPE_PYRAMID};
857da9060c4SMatthew G. Knepley   static PetscInt       pyrS[]    = {1};
858da9060c4SMatthew G. Knepley   static PetscInt       pyrC[]    = {DM_POLYTOPE_QUADRILATERAL, 1, 0, 0, DM_POLYTOPE_TRIANGLE, 1, 1, 0,
859da9060c4SMatthew G. Knepley                                      DM_POLYTOPE_TRIANGLE, 1, 2, 0, DM_POLYTOPE_TRIANGLE, 1, 3, 0, DM_POLYTOPE_TRIANGLE, 1, 4, 0};
860da9060c4SMatthew G. Knepley   static PetscInt       pyrO[]    = {0, 0, 0, 0, 0};
861cf4091a3SMatthew G. Knepley 
862cf4091a3SMatthew G. Knepley   PetscFunctionBegin;
8633f2a96e3SMatthew G. Knepley   if (rt) *rt = 0;
864cf4091a3SMatthew G. Knepley   switch (source) {
865cf4091a3SMatthew G. Knepley     case DM_POLYTOPE_POINT:              *Nt = 1; *target = vertexT; *size = vertexS; *cone = vertexC; *ornt = vertexO; break;
866cf4091a3SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:            *Nt = 1; *target = edgeT;   *size = edgeS;   *cone = edgeC;   *ornt = edgeO;   break;
867cf4091a3SMatthew G. Knepley     case DM_POLYTOPE_POINT_PRISM_TENSOR: *Nt = 1; *target = tedgeT;  *size = tedgeS;  *cone = tedgeC;  *ornt = tedgeO;  break;
868cf4091a3SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:           *Nt = 1; *target = triT;    *size = triS;    *cone = triC;    *ornt = triO;    break;
869cf4091a3SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:      *Nt = 1; *target = quadT;   *size = quadS;   *cone = quadC;   *ornt = quadO;   break;
870cf4091a3SMatthew G. Knepley     case DM_POLYTOPE_SEG_PRISM_TENSOR:   *Nt = 1; *target = tquadT;  *size = tquadS;  *cone = tquadC;  *ornt = tquadO;  break;
871cf4091a3SMatthew G. Knepley     case DM_POLYTOPE_TETRAHEDRON:        *Nt = 1; *target = tetT;    *size = tetS;    *cone = tetC;    *ornt = tetO;    break;
872cf4091a3SMatthew G. Knepley     case DM_POLYTOPE_HEXAHEDRON:         *Nt = 1; *target = hexT;    *size = hexS;    *cone = hexC;    *ornt = hexO;    break;
873cf4091a3SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM:          *Nt = 1; *target = tripT;   *size = tripS;   *cone = tripC;   *ornt = tripO;   break;
874cf4091a3SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:   *Nt = 1; *target = ttripT;  *size = ttripS;  *cone = ttripC;  *ornt = ttripO;  break;
875cf4091a3SMatthew G. Knepley     case DM_POLYTOPE_QUAD_PRISM_TENSOR:  *Nt = 1; *target = tquadpT; *size = tquadpS; *cone = tquadpC; *ornt = tquadpO; break;
876da9060c4SMatthew G. Knepley     case DM_POLYTOPE_PYRAMID:            *Nt = 1; *target = pyrT;    *size = pyrS;    *cone = pyrC;    *ornt = pyrO;    break;
877cf4091a3SMatthew G. Knepley     default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No refinement strategy for %s", DMPolytopeTypes[source]);
878cf4091a3SMatthew G. Knepley   }
879cf4091a3SMatthew G. Knepley   PetscFunctionReturn(0);
880cf4091a3SMatthew G. Knepley }
881cf4091a3SMatthew G. Knepley 
8823f2a96e3SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerRefine_Regular(DMPlexCellRefiner cr, DMPolytopeType source, PetscInt p, PetscInt *rt, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[])
883412e9a14SMatthew G. Knepley {
884412e9a14SMatthew G. Knepley   /* All vertices remain in the refined mesh */
885412e9a14SMatthew G. Knepley   static DMPolytopeType vertexT[] = {DM_POLYTOPE_POINT};
886412e9a14SMatthew G. Knepley   static PetscInt       vertexS[] = {1};
887412e9a14SMatthew G. Knepley   static PetscInt       vertexC[] = {0};
888412e9a14SMatthew G. Knepley   static PetscInt       vertexO[] = {0};
889412e9a14SMatthew G. Knepley   /* Split all edges with a new vertex, making two new 2 edges
890412e9a14SMatthew G. Knepley      0--0--0--1--1
891412e9a14SMatthew G. Knepley   */
892412e9a14SMatthew G. Knepley   static DMPolytopeType edgeT[]   = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT};
893412e9a14SMatthew G. Knepley   static PetscInt       edgeS[]   = {1, 2};
894412e9a14SMatthew 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};
895412e9a14SMatthew G. Knepley   static PetscInt       edgeO[]   = {                         0,                       0,                        0,                          0};
896412e9a14SMatthew G. Knepley   /* Do not split tensor edges */
897412e9a14SMatthew G. Knepley   static DMPolytopeType tedgeT[]  = {DM_POLYTOPE_POINT_PRISM_TENSOR};
898412e9a14SMatthew G. Knepley   static PetscInt       tedgeS[]  = {1};
899412e9a14SMatthew G. Knepley   static PetscInt       tedgeC[]  = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0};
900412e9a14SMatthew G. Knepley   static PetscInt       tedgeO[]  = {                         0,                          0};
901412e9a14SMatthew G. Knepley   /* Add 3 edges inside every triangle, making 4 new triangles.
90275d3a19aSMatthew G. Knepley    2
90375d3a19aSMatthew G. Knepley    |\
90475d3a19aSMatthew G. Knepley    | \
90575d3a19aSMatthew G. Knepley    |  \
906412e9a14SMatthew G. Knepley    0   1
90775d3a19aSMatthew G. Knepley    | C  \
90875d3a19aSMatthew G. Knepley    |     \
90975d3a19aSMatthew G. Knepley    |      \
91075d3a19aSMatthew G. Knepley    2---1---1
91175d3a19aSMatthew G. Knepley    |\  D  / \
912412e9a14SMatthew G. Knepley    1 2   0   0
91375d3a19aSMatthew G. Knepley    |A \ /  B  \
914412e9a14SMatthew G. Knepley    0-0-0---1---1
91575d3a19aSMatthew G. Knepley   */
916412e9a14SMatthew G. Knepley   static DMPolytopeType triT[]    = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_TRIANGLE};
917412e9a14SMatthew G. Knepley   static PetscInt       triS[]    = {3, 4};
918412e9a14SMatthew G. Knepley   static PetscInt       triC[]    = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
919412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 1, 2, 0,
920412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 1, 0, 0,
921412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 1, 2, 1,
922412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0,    0,
923412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 2, 0,
924412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,    2};
925412e9a14SMatthew G. Knepley   static PetscInt       triO[]    = {0, 0,
926412e9a14SMatthew G. Knepley                                      0, 0,
927412e9a14SMatthew G. Knepley                                      0, 0,
928412e9a14SMatthew G. Knepley                                      0, -2,  0,
929412e9a14SMatthew G. Knepley                                      0,  0, -2,
930412e9a14SMatthew G. Knepley                                     -2,  0,  0,
931412e9a14SMatthew G. Knepley                                      0,  0,  0};
932412e9a14SMatthew G. Knepley   /* Add a vertex in the center of each quadrilateral, and 4 edges inside, making 4 new quads.
933412e9a14SMatthew G. Knepley      3----1----2----0----2
934412e9a14SMatthew G. Knepley      |         |         |
935412e9a14SMatthew G. Knepley      0    D    2    C    1
936412e9a14SMatthew G. Knepley      |         |         |
937412e9a14SMatthew G. Knepley      3----3----0----1----1
938412e9a14SMatthew G. Knepley      |         |         |
939412e9a14SMatthew G. Knepley      1    A    0    B    0
940412e9a14SMatthew G. Knepley      |         |         |
941412e9a14SMatthew G. Knepley      0----0----0----1----1
942412e9a14SMatthew G. Knepley   */
943412e9a14SMatthew G. Knepley   static DMPolytopeType quadT[]   = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL};
944412e9a14SMatthew G. Knepley   static PetscInt       quadS[]   = {1, 4, 4};
945412e9a14SMatthew G. Knepley   static PetscInt       quadC[]   = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 0, 0,
946412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 0, 0,
947412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 0, 0,
948412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 3, 0, DM_POLYTOPE_POINT, 0, 0,
949412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 1, 3, 1,
950412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,    0,
951412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0,    2,
952412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 3, 0};
953412e9a14SMatthew G. Knepley   static PetscInt       quadO[]   = {0, 0,
954412e9a14SMatthew G. Knepley                                      0, 0,
955412e9a14SMatthew G. Knepley                                      0, 0,
956412e9a14SMatthew G. Knepley                                      0, 0,
957412e9a14SMatthew G. Knepley                                      0,  0, -2,  0,
958412e9a14SMatthew G. Knepley                                      0,  0,  0, -2,
959412e9a14SMatthew G. Knepley                                     -2,  0,  0,  0,
960412e9a14SMatthew G. Knepley                                      0, -2,  0,  0};
961412e9a14SMatthew G. Knepley   /* Add 1 edge inside every tensor quad, making 2 new tensor quads
962412e9a14SMatthew G. Knepley      2----2----1----3----3
963412e9a14SMatthew G. Knepley      |         |         |
964412e9a14SMatthew G. Knepley      |         |         |
965412e9a14SMatthew G. Knepley      |         |         |
966412e9a14SMatthew G. Knepley      4    A    6    B    5
967412e9a14SMatthew G. Knepley      |         |         |
968412e9a14SMatthew G. Knepley      |         |         |
969412e9a14SMatthew G. Knepley      |         |         |
970412e9a14SMatthew G. Knepley      0----0----0----1----1
971412e9a14SMatthew G. Knepley   */
972412e9a14SMatthew G. Knepley   static DMPolytopeType tquadT[]  = {DM_POLYTOPE_POINT_PRISM_TENSOR, DM_POLYTOPE_SEG_PRISM_TENSOR};
973412e9a14SMatthew G. Knepley   static PetscInt       tquadS[]  = {1, 2};
974412e9a14SMatthew G. Knepley   static PetscInt       tquadC[]  = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
975412e9a14SMatthew 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,
976412e9a14SMatthew 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};
977412e9a14SMatthew G. Knepley   static PetscInt       tquadO[]  = {0, 0,
978412e9a14SMatthew G. Knepley                                      0, 0, 0, 0,
979412e9a14SMatthew G. Knepley                                      0, 0, 0, 0};
980412e9a14SMatthew G. Knepley   /* Add 1 edge and 8 triangles inside every cell, making 8 new tets
981412e9a14SMatthew 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
982412e9a14SMatthew 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]
983412e9a14SMatthew G. Knepley      called e3, e4, and e5. The faces of a tet, given in DMPlexGetRawFaces_Internal() are
984412e9a14SMatthew G. Knepley        [v0, v1, v2], [v0, v3, v1], [v0, v2, v3], [v2, v1, v3]
985412e9a14SMatthew G. Knepley      The first four tets just cut off the corners, using the replica notation for new vertices,
986412e9a14SMatthew G. Knepley        [v0,      (e0, 0), (e2, 0), (e3, 0)]
987412e9a14SMatthew G. Knepley        [(e0, 0), v1,      (e1, 0), (e4, 0)]
988412e9a14SMatthew G. Knepley        [(e2, 0), (e1, 0), v2,      (e5, 0)]
989412e9a14SMatthew G. Knepley        [(e3, 0), (e4, 0), (e5, 0), v3     ]
990412e9a14SMatthew G. Knepley      The next four tets match a vertex to the newly created faces from cutting off those first tets.
991412e9a14SMatthew G. Knepley        [(e2, 0), (e3, 0), (e0, 0), (e5, 0)]
992412e9a14SMatthew G. Knepley        [(e4, 0), (e1, 0), (e0, 0), (e5, 0)]
993412e9a14SMatthew G. Knepley        [(e5, 0), (e0, 0), (e2, 0), (e1, 0)]
994412e9a14SMatthew G. Knepley        [(e5, 0), (e0, 0), (e4, 0), (e3, 0)]
995412e9a14SMatthew 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
996412e9a14SMatthew G. Knepley        [(e2, 0), (e0, 0), (e3, 0)]
997412e9a14SMatthew G. Knepley        [(e0, 0), (e1, 0), (e4, 0)]
998412e9a14SMatthew G. Knepley        [(e2, 0), (e5, 0), (e1, 0)]
999412e9a14SMatthew G. Knepley        [(e3, 0), (e4, 0), (e5, 0)]
1000412e9a14SMatthew G. Knepley      The next four, from the second group of tets, are
1001412e9a14SMatthew G. Knepley        [(e2, 0), (e0, 0), (e5, 0)]
1002412e9a14SMatthew G. Knepley        [(e4, 0), (e0, 0), (e5, 0)]
1003412e9a14SMatthew G. Knepley        [(e0, 0), (e1, 0), (e5, 0)]
1004412e9a14SMatthew G. Knepley        [(e5, 0), (e3, 0), (e0, 0)]
1005412e9a14SMatthew G. Knepley      I could write a program to generate these orientations by comparing the faces from GetRawFaces() with my existing table.
1006412e9a14SMatthew G. Knepley    */
1007412e9a14SMatthew G. Knepley   static DMPolytopeType tetT[]    = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_TRIANGLE, DM_POLYTOPE_TETRAHEDRON};
1008412e9a14SMatthew G. Knepley   static PetscInt       tetS[]    = {1, 8, 8};
1009412e9a14SMatthew G. Knepley   static PetscInt       tetC[]    = {DM_POLYTOPE_POINT, 2, 0, 0, 0, DM_POLYTOPE_POINT, 2, 2, 1, 0,
1010412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 1, 2, 2,
1011412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 3, 0, DM_POLYTOPE_SEGMENT, 1, 1, 1,
1012412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 1, 3, 2, DM_POLYTOPE_SEGMENT, 1, 0, 1,
1013412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 3, 1, DM_POLYTOPE_SEGMENT, 1, 2, 1,
1014412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 1, 2, 0,
1015412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 1, 3, 1,
1016412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 3, 2, DM_POLYTOPE_SEGMENT, 0,    0,
1017412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 0,    0,
1018412e9a14SMatthew 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,
1019412e9a14SMatthew 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,
1020412e9a14SMatthew 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,
1021412e9a14SMatthew 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,
1022412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_TRIANGLE, 0,    0, DM_POLYTOPE_TRIANGLE, 1, 2, 3, DM_POLYTOPE_TRIANGLE, 0,    4, DM_POLYTOPE_TRIANGLE, 0,    7,
1023412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_TRIANGLE, 0,    1, DM_POLYTOPE_TRIANGLE, 1, 3, 3, DM_POLYTOPE_TRIANGLE, 0,    5, DM_POLYTOPE_TRIANGLE, 0,    6,
1024412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_TRIANGLE, 0,    4, DM_POLYTOPE_TRIANGLE, 0,    6, DM_POLYTOPE_TRIANGLE, 0,    2, DM_POLYTOPE_TRIANGLE, 1, 0, 3,
1025412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_TRIANGLE, 0,    5, DM_POLYTOPE_TRIANGLE, 0,    7, DM_POLYTOPE_TRIANGLE, 0,    3, DM_POLYTOPE_TRIANGLE, 1, 1, 3};
1026412e9a14SMatthew G. Knepley   static PetscInt       tetO[]    = {0, 0,
1027412e9a14SMatthew G. Knepley                                      0,  0,  0,
1028412e9a14SMatthew G. Knepley                                      0,  0,  0,
1029412e9a14SMatthew G. Knepley                                      0,  0,  0,
1030412e9a14SMatthew G. Knepley                                      0,  0,  0,
1031412e9a14SMatthew G. Knepley                                      0,  0, -2,
1032412e9a14SMatthew G. Knepley                                      0,  0, -2,
1033412e9a14SMatthew G. Knepley                                      0, -2, -2,
1034412e9a14SMatthew G. Knepley                                      0, -2,  0,
1035412e9a14SMatthew G. Knepley                                      0,  0,  0,  0,
1036412e9a14SMatthew G. Knepley                                      0,  0,  0,  0,
1037412e9a14SMatthew G. Knepley                                      0,  0,  0,  0,
1038412e9a14SMatthew G. Knepley                                      0,  0,  0,  0,
1039412e9a14SMatthew G. Knepley                                     -3,  0,  0, -2,
1040412e9a14SMatthew G. Knepley                                     -2,  1,  0,  0,
1041412e9a14SMatthew G. Knepley                                     -2, -2, -1,  2,
1042412e9a14SMatthew G. Knepley                                     -2,  0, -2,  1};
1043412e9a14SMatthew G. Knepley   /* Add a vertex in the center of each cell, add 6 edges and 12 quads inside every cell, making 8 new hexes
1044412e9a14SMatthew 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
1045412e9a14SMatthew G. Knepley        [v0, v1, v2, v3] f0 bottom
1046412e9a14SMatthew G. Knepley        [v4, v5, v6, v7] f1 top
1047412e9a14SMatthew G. Knepley        [v0, v3, v5, v4] f2 front
1048412e9a14SMatthew G. Knepley        [v2, v1, v7, v6] f3 back
1049412e9a14SMatthew G. Knepley        [v3, v2, v6, v5] f4 right
1050412e9a14SMatthew G. Knepley        [v0, v4, v7, v1] f5 left
1051412e9a14SMatthew G. Knepley      The eight hexes are divided into four on the bottom, and four on the top,
1052412e9a14SMatthew G. Knepley        [v0,      (e0, 0),  (f0, 0),  (e3, 0),  (e9, 0), (f2, 0),  (c0, 0),  (f5, 0)]
1053412e9a14SMatthew G. Knepley        [(e0, 0), v1,       (e1, 0),  (f0, 0),  (f5, 0), (c0, 0),  (f3, 0),  (e10, 0)]
1054412e9a14SMatthew G. Knepley        [(f0, 0), (e1, 0),  v2,       (e2, 0),  (c0, 0), (f4, 0),  (e11, 0), (f3, 0)]
1055412e9a14SMatthew G. Knepley        [(e3, 0), (f0, 0),  (e2, 0),  v3,       (f2, 0), (e8, 0),  (f4, 0),  (c0, 0)]
1056412e9a14SMatthew G. Knepley        [(e9, 0), (f5, 0),  (c0, 0),  (f2, 0),  v4,      (e4, 0),  (f1, 0),  (e7, 0)]
1057412e9a14SMatthew G. Knepley        [(f2, 0), (c0, 0),  (f4, 0),  (e8, 0),  (e4, 0), v5,       (e5, 0),  (f1, 0)]
1058412e9a14SMatthew G. Knepley        [(c0, 0), (f3, 0),  (e11, 0), (f4, 0),  (f1, 0), (e5, 0),  v6,       (e6, 0)]
1059412e9a14SMatthew G. Knepley        [(f5, 0), (e10, 0), (f3, 0),  (c0, 0),  (e7, 0), (f1, 0),  (e6, 0),  v7]
1060412e9a14SMatthew 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,
1061412e9a14SMatthew G. Knepley        [(e9, 0), (f2, 0),  (c0, 0),  (f5, 0)]
1062412e9a14SMatthew G. Knepley        [(f5, 0), (c0, 0),  (f3, 0),  (e10, 0)]
1063412e9a14SMatthew G. Knepley        [(c0, 0), (f4, 0),  (e11, 0), (f3, 0)]
1064412e9a14SMatthew G. Knepley        [(f2, 0), (e8, 0),  (f4, 0),  (c0, 0)]
1065412e9a14SMatthew G. Knepley      and on the x-z plane,
1066412e9a14SMatthew G. Knepley        [(f0, 0), (e0, 0), (f5, 0), (c0, 0)]
1067412e9a14SMatthew G. Knepley        [(c0, 0), (f5, 0), (e7, 0), (f1, 0)]
1068412e9a14SMatthew G. Knepley        [(f4, 0), (c0, 0), (f1, 0), (e5, 0)]
1069412e9a14SMatthew G. Knepley        [(e2, 0), (f0, 0), (c0, 0), (f4, 0)]
1070412e9a14SMatthew G. Knepley      and on the y-z plane,
1071412e9a14SMatthew G. Knepley        [(e3, 0), (f2, 0), (c0, 0), (f0, 0)]
1072412e9a14SMatthew G. Knepley        [(f2, 0), (e4, 0), (f1, 0), (c0, 0)]
1073412e9a14SMatthew G. Knepley        [(c0, 0), (f1, 0), (e6, 0), (f3, 0)]
1074412e9a14SMatthew G. Knepley        [(f0, 0), (c0, 0), (f3, 0), (e1, 0)]
1075412e9a14SMatthew G. Knepley   */
1076412e9a14SMatthew G. Knepley   static DMPolytopeType hexT[]    = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL, DM_POLYTOPE_HEXAHEDRON};
1077412e9a14SMatthew G. Knepley   static PetscInt       hexS[]    = {1, 6, 12, 8};
1078412e9a14SMatthew G. Knepley   static PetscInt       hexC[]    = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 0, 0,
1079412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 0, 0,
1080412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 0, 0,
1081412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 3, 0, DM_POLYTOPE_POINT, 0, 0,
1082412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 4, 0, DM_POLYTOPE_POINT, 0, 0,
1083412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 5, 0, DM_POLYTOPE_POINT, 0, 0,
1084412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 3, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 0,    5, DM_POLYTOPE_SEGMENT, 1, 5, 0,
1085412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    5, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 1, 3, 1, DM_POLYTOPE_SEGMENT, 1, 5, 2,
1086412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    4, DM_POLYTOPE_SEGMENT, 1, 4, 1, DM_POLYTOPE_SEGMENT, 1, 3, 3, DM_POLYTOPE_SEGMENT, 0,    3,
1087412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 4, 3, DM_POLYTOPE_SEGMENT, 0,    4, DM_POLYTOPE_SEGMENT, 0,    2,
1088412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 5, 3, DM_POLYTOPE_SEGMENT, 0,    5, DM_POLYTOPE_SEGMENT, 0,    0,
1089412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    5, DM_POLYTOPE_SEGMENT, 1, 5, 1, DM_POLYTOPE_SEGMENT, 1, 1, 3, DM_POLYTOPE_SEGMENT, 0,    1,
1090412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    4, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 4, 2,
1091412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    4, DM_POLYTOPE_SEGMENT, 1, 4, 0,
1092412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 1, 0, 3,
1093412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 2, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,    2,
1094412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 1, 3, 2, DM_POLYTOPE_SEGMENT, 0,    3,
1095412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 1, 3, 0, DM_POLYTOPE_SEGMENT, 1, 0, 1,
1096412e9a14SMatthew 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,
1097412e9a14SMatthew 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,
1098412e9a14SMatthew 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,
1099412e9a14SMatthew 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,
1100412e9a14SMatthew 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,
1101412e9a14SMatthew 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,
1102412e9a14SMatthew 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,
1103412e9a14SMatthew 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};
1104412e9a14SMatthew G. Knepley   static PetscInt       hexO[]    = {0, 0,
1105412e9a14SMatthew G. Knepley                                      0, 0,
1106412e9a14SMatthew G. Knepley                                      0, 0,
1107412e9a14SMatthew G. Knepley                                      0, 0,
1108412e9a14SMatthew G. Knepley                                      0, 0,
1109412e9a14SMatthew G. Knepley                                      0, 0,
1110412e9a14SMatthew G. Knepley                                      0,  0, -2, -2,
1111412e9a14SMatthew G. Knepley                                      0, -2, -2,  0,
1112412e9a14SMatthew G. Knepley                                     -2, -2,  0,  0,
1113412e9a14SMatthew G. Knepley                                     -2,  0,  0, -2,
1114412e9a14SMatthew G. Knepley                                     -2,  0,  0, -2,
1115412e9a14SMatthew G. Knepley                                     -2, -2,  0,  0,
1116412e9a14SMatthew G. Knepley                                      0, -2, -2,  0,
1117412e9a14SMatthew G. Knepley                                      0,  0, -2, -2,
1118412e9a14SMatthew G. Knepley                                      0,  0, -2, -2,
1119412e9a14SMatthew G. Knepley                                     -2,  0,  0, -2,
1120412e9a14SMatthew G. Knepley                                     -2, -2,  0,  0,
1121412e9a14SMatthew G. Knepley                                      0, -2, -2,  0,
1122412e9a14SMatthew G. Knepley                                      0, 0,  0, 0, -4, 0,
1123412e9a14SMatthew G. Knepley                                      0, 0, -1, 0, -4, 0,
1124412e9a14SMatthew G. Knepley                                      0, 0, -1, 0,  0, 0,
1125412e9a14SMatthew G. Knepley                                      0, 0,  0, 0,  0, 0,
1126412e9a14SMatthew G. Knepley                                     -4, 0,  0, 0, -4, 0,
1127412e9a14SMatthew G. Knepley                                     -4, 0,  0, 0,  0, 0,
1128412e9a14SMatthew G. Knepley                                     -4, 0, -1, 0,  0, 0,
1129412e9a14SMatthew G. Knepley                                     -4, 0, -1, 0, -4, 0};
1130412e9a14SMatthew G. Knepley   /* Add 3 quads inside every triangular prism, making 4 new prisms. */
1131412e9a14SMatthew G. Knepley   static DMPolytopeType tripT[]   = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_TRIANGLE, DM_POLYTOPE_QUADRILATERAL, DM_POLYTOPE_TRI_PRISM};
1132412e9a14SMatthew G. Knepley   static PetscInt       tripS[]   = {3, 4, 6, 8};
1133412e9a14SMatthew G. Knepley   static PetscInt       tripC[]   = {DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 1, 3, 0,
1134412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 3, 0, DM_POLYTOPE_POINT, 1, 4, 0,
1135412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 4, 0, DM_POLYTOPE_POINT, 1, 2, 0,
1136412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 3, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 1, 4, 1,
1137412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 3, 3, DM_POLYTOPE_SEGMENT, 0,    0,
1138412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 3, 1, DM_POLYTOPE_SEGMENT, 1, 4, 3,
1139412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,    2,
1140412e9a14SMatthew 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,
1141412e9a14SMatthew 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,
1142412e9a14SMatthew 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,
1143412e9a14SMatthew 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,
1144412e9a14SMatthew 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,
1145412e9a14SMatthew 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,
1146412e9a14SMatthew 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,
1147412e9a14SMatthew 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,
1148412e9a14SMatthew 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,
1149412e9a14SMatthew 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,
1150412e9a14SMatthew 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,
1151412e9a14SMatthew 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,
1152412e9a14SMatthew 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,
1153412e9a14SMatthew 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};
1154412e9a14SMatthew G. Knepley   static PetscInt       tripO[]   = {0, 0,
1155412e9a14SMatthew G. Knepley                                      0, 0,
1156412e9a14SMatthew G. Knepley                                      0, 0,
1157412e9a14SMatthew G. Knepley                                      0, -2, -2,
1158412e9a14SMatthew G. Knepley                                     -2,  0, -2,
1159412e9a14SMatthew G. Knepley                                     -2, -2,  0,
1160412e9a14SMatthew G. Knepley                                      0,  0,  0,
1161412e9a14SMatthew G. Knepley                                     -2,  0, -2, -2,
1162412e9a14SMatthew G. Knepley                                     -2,  0, -2, -2,
1163412e9a14SMatthew G. Knepley                                     -2,  0, -2, -2,
1164412e9a14SMatthew G. Knepley                                      0, -2, -2,  0,
1165412e9a14SMatthew G. Knepley                                      0, -2, -2,  0,
1166412e9a14SMatthew G. Knepley                                      0, -2, -2,  0,
1167412e9a14SMatthew G. Knepley                                      0,  0,  0, -1,  0,
1168412e9a14SMatthew G. Knepley                                      0,  0,  0,  0, -1,
1169412e9a14SMatthew G. Knepley                                      0,  0, -1,  0,  0,
1170412e9a14SMatthew G. Knepley                                      2,  0,  0,  0,  0,
1171412e9a14SMatthew G. Knepley                                     -3,  0,  0, -1,  0,
1172412e9a14SMatthew G. Knepley                                     -3,  0,  0,  0, -1,
1173412e9a14SMatthew G. Knepley                                     -3,  0, -1,  0,  0,
1174412e9a14SMatthew G. Knepley                                     -3,  0,  0,  0,  0};
1175412e9a14SMatthew G. Knepley   /* Add 3 tensor quads inside every tensor triangular prism, making 4 new prisms.
1176412e9a14SMatthew G. Knepley       2
1177412e9a14SMatthew G. Knepley       |\
1178412e9a14SMatthew G. Knepley       | \
1179412e9a14SMatthew G. Knepley       |  \
1180412e9a14SMatthew G. Knepley       0---1
118175d3a19aSMatthew G. Knepley 
1182412e9a14SMatthew G. Knepley       2
118375d3a19aSMatthew G. Knepley 
1184412e9a14SMatthew G. Knepley       0   1
118575d3a19aSMatthew G. Knepley 
1186412e9a14SMatthew G. Knepley       2
1187412e9a14SMatthew G. Knepley       |\
1188412e9a14SMatthew G. Knepley       | \
1189412e9a14SMatthew G. Knepley       |  \
1190412e9a14SMatthew G. Knepley       0---1
1191412e9a14SMatthew G. Knepley   */
1192412e9a14SMatthew G. Knepley   static DMPolytopeType ttripT[]  = {DM_POLYTOPE_SEG_PRISM_TENSOR, DM_POLYTOPE_TRI_PRISM_TENSOR};
1193412e9a14SMatthew G. Knepley   static PetscInt       ttripS[]  = {3, 4};
1194412e9a14SMatthew 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,
1195412e9a14SMatthew 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,
1196412e9a14SMatthew 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,
1197412e9a14SMatthew 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,
1198412e9a14SMatthew 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,
1199412e9a14SMatthew 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,
1200412e9a14SMatthew 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};
1201412e9a14SMatthew G. Knepley   static PetscInt       ttripO[]  = {0, 0, 0, 0,
1202412e9a14SMatthew G. Knepley                                      0, 0, 0, 0,
1203412e9a14SMatthew G. Knepley                                      0, 0, 0, 0,
1204412e9a14SMatthew G. Knepley                                      0, 0,  0, -1,  0,
1205412e9a14SMatthew G. Knepley                                      0, 0,  0,  0, -1,
1206412e9a14SMatthew G. Knepley                                      0, 0, -1,  0,  0,
1207412e9a14SMatthew G. Knepley                                      0, 0,  0,  0,  0};
1208412e9a14SMatthew G. Knepley   /* Add 1 edge and 4 tensor quads inside every tensor quad prism, making 4 new prisms. */
1209412e9a14SMatthew G. Knepley   static DMPolytopeType tquadpT[]  = {DM_POLYTOPE_POINT_PRISM_TENSOR, DM_POLYTOPE_SEG_PRISM_TENSOR, DM_POLYTOPE_QUAD_PRISM_TENSOR};
1210412e9a14SMatthew G. Knepley   static PetscInt       tquadpS[]  = {1, 4, 4};
1211412e9a14SMatthew G. Knepley   static PetscInt       tquadpC[]  = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
1212412e9a14SMatthew 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,
1213412e9a14SMatthew 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,
1214412e9a14SMatthew 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,
1215412e9a14SMatthew 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,
1216412e9a14SMatthew 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,
1217412e9a14SMatthew 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,
1218412e9a14SMatthew 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,
1219412e9a14SMatthew 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};
1220412e9a14SMatthew G. Knepley   static PetscInt       tquadpO[]  = {0, 0,
1221412e9a14SMatthew G. Knepley                                       0, 0, 0, 0,
1222412e9a14SMatthew G. Knepley                                       0, 0, 0, 0,
1223412e9a14SMatthew G. Knepley                                       0, 0, 0, 0,
1224412e9a14SMatthew G. Knepley                                       0, 0, 0, 0,
1225412e9a14SMatthew G. Knepley                                       0, 0,  0,  0, -1,  0,
1226412e9a14SMatthew G. Knepley                                       0, 0,  0,  0,  0, -1,
1227412e9a14SMatthew G. Knepley                                       0, 0, -1,  0,  0,  0,
1228412e9a14SMatthew G. Knepley                                       0, 0,  0, -1,  0,  0};
1229da9060c4SMatthew G. Knepley   PetscErrorCode ierr;
123075d3a19aSMatthew G. Knepley 
1231412e9a14SMatthew G. Knepley   PetscFunctionBegin;
12323f2a96e3SMatthew G. Knepley   if (rt) *rt = 0;
1233412e9a14SMatthew G. Knepley   switch (source) {
1234412e9a14SMatthew G. Knepley     case DM_POLYTOPE_POINT:              *Nt = 1; *target = vertexT; *size = vertexS; *cone = vertexC; *ornt = vertexO; break;
1235412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:            *Nt = 2; *target = edgeT;   *size = edgeS;   *cone = edgeC;   *ornt = edgeO;   break;
1236412e9a14SMatthew G. Knepley     case DM_POLYTOPE_POINT_PRISM_TENSOR: *Nt = 1; *target = tedgeT;  *size = tedgeS;  *cone = tedgeC;  *ornt = tedgeO;  break;
1237412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:           *Nt = 2; *target = triT;    *size = triS;    *cone = triC;    *ornt = triO;    break;
1238412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:      *Nt = 3; *target = quadT;   *size = quadS;   *cone = quadC;   *ornt = quadO;   break;
1239412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEG_PRISM_TENSOR:   *Nt = 2; *target = tquadT;  *size = tquadS;  *cone = tquadC;  *ornt = tquadO;  break;
1240412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TETRAHEDRON:        *Nt = 3; *target = tetT;    *size = tetS;    *cone = tetC;    *ornt = tetO;    break;
1241412e9a14SMatthew G. Knepley     case DM_POLYTOPE_HEXAHEDRON:         *Nt = 4; *target = hexT;    *size = hexS;    *cone = hexC;    *ornt = hexO;    break;
1242412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM:          *Nt = 4; *target = tripT;   *size = tripS;   *cone = tripC;   *ornt = tripO;   break;
1243412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:   *Nt = 2; *target = ttripT;  *size = ttripS;  *cone = ttripC;  *ornt = ttripO;  break;
1244412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUAD_PRISM_TENSOR:  *Nt = 3; *target = tquadpT; *size = tquadpS; *cone = tquadpC; *ornt = tquadpO; break;
1245da9060c4SMatthew G. Knepley     /* TODO Fix pyramids: For now, we just ignore them */
1246da9060c4SMatthew G. Knepley     case DM_POLYTOPE_PYRAMID:
12473f2a96e3SMatthew G. Knepley       ierr = DMPlexCellRefinerRefine_None(cr, source, p, rt, Nt, target, size, cone, ornt);CHKERRQ(ierr);
1248da9060c4SMatthew G. Knepley       break;
1249412e9a14SMatthew G. Knepley     default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No refinement strategy for %s", DMPolytopeTypes[source]);
1250412e9a14SMatthew G. Knepley   }
1251412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1252412e9a14SMatthew G. Knepley }
125375d3a19aSMatthew G. Knepley 
12543f2a96e3SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerRefine_ToBox(DMPlexCellRefiner cr, DMPolytopeType source, PetscInt p, PetscInt *rt, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[])
1255412e9a14SMatthew G. Knepley {
1256412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
1257412e9a14SMatthew G. Knepley   /* Change tensor edges to segments */
1258412e9a14SMatthew G. Knepley   static DMPolytopeType tedgeT[]  = {DM_POLYTOPE_SEGMENT};
1259412e9a14SMatthew G. Knepley   static PetscInt       tedgeS[]  = {1};
1260412e9a14SMatthew G. Knepley   static PetscInt       tedgeC[]  = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0};
1261412e9a14SMatthew G. Knepley   static PetscInt       tedgeO[]  = {                         0,                          0};
1262412e9a14SMatthew G. Knepley   /* Add 1 vertex, 3 edges inside every triangle, making 3 new quadrilaterals.
1263e5337592SStefano Zampini    2
1264e5337592SStefano Zampini    |\
1265e5337592SStefano Zampini    | \
1266e5337592SStefano Zampini    |  \
1267e5337592SStefano Zampini    |   \
1268412e9a14SMatthew G. Knepley    0    1
1269412e9a14SMatthew G. Knepley    |     \
1270e5337592SStefano Zampini    |      \
1271e5337592SStefano Zampini    2       1
1272e5337592SStefano Zampini    |\     / \
1273e5337592SStefano Zampini    | 2   1   \
1274e5337592SStefano Zampini    |  \ /     \
1275412e9a14SMatthew G. Knepley    1   |       0
1276e5337592SStefano Zampini    |   0        \
1277e5337592SStefano Zampini    |   |         \
1278412e9a14SMatthew G. Knepley    |   |          \
1279412e9a14SMatthew G. Knepley    0-0-0-----1-----1
1280e5337592SStefano Zampini   */
1281412e9a14SMatthew G. Knepley   static DMPolytopeType triT[]    = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL};
1282412e9a14SMatthew G. Knepley   static PetscInt       triS[]    = {1, 3, 3};
1283412e9a14SMatthew G. Knepley   static PetscInt       triC[]    = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 0,    0,
1284412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 0,    0,
1285412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 0,    0,
1286412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 1, 2, 1,
1287412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,    0,
1288412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 2, 0};
1289412e9a14SMatthew G. Knepley   static PetscInt       triO[]    = {0, 0,
1290412e9a14SMatthew G. Knepley                                      0, 0,
1291412e9a14SMatthew G. Knepley                                      0, 0,
1292412e9a14SMatthew G. Knepley                                      0,  0, -2,  0,
1293412e9a14SMatthew G. Knepley                                      0,  0,  0, -2,
1294412e9a14SMatthew G. Knepley                                      0, -2,  0,  0};
1295412e9a14SMatthew G. Knepley   /* Add 1 edge inside every tensor quad, making 2 new quadrilaterals
1296412e9a14SMatthew G. Knepley      2----2----1----3----3
12974330a3fcSStefano Zampini      |         |         |
12984330a3fcSStefano Zampini      |         |         |
12994330a3fcSStefano Zampini      |         |         |
1300412e9a14SMatthew G. Knepley      4    A    6    B    5
13014330a3fcSStefano Zampini      |         |         |
1302412e9a14SMatthew G. Knepley      |         |         |
1303412e9a14SMatthew G. Knepley      |         |         |
1304412e9a14SMatthew G. Knepley      0----0----0----1----1
13054330a3fcSStefano Zampini   */
1306412e9a14SMatthew G. Knepley   static DMPolytopeType tquadT[]  = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL};
1307412e9a14SMatthew G. Knepley   static PetscInt       tquadS[]  = {1, 2};
1308412e9a14SMatthew G. Knepley   static PetscInt       tquadC[]  = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
1309412e9a14SMatthew G. Knepley                                      /* TODO  Fix these */
1310412e9a14SMatthew 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,
1311412e9a14SMatthew 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};
1312412e9a14SMatthew G. Knepley   static PetscInt       tquadO[]  = {0, 0,
1313412e9a14SMatthew G. Knepley                                      0, 0, -2, -2,
1314412e9a14SMatthew G. Knepley                                      0, 0, -2, -2};
1315412e9a14SMatthew G. Knepley   /* Add 6 triangles inside every cell, making 4 new hexs
1316412e9a14SMatthew G. Knepley      TODO: Need different SubcellMap(). Need to make a struct with the function pointers in it
1317412e9a14SMatthew 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
1318412e9a14SMatthew 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]
1319412e9a14SMatthew G. Knepley      called e3, e4, and e5. The faces of a tet, given in DMPlexGetRawFaces_Internal() are
1320412e9a14SMatthew G. Knepley        [v0, v1, v2], [v0, v3, v1], [v0, v2, v3], [v2, v1, v3]
1321412e9a14SMatthew G. Knepley      We make a new hex in each corner
1322412e9a14SMatthew G. Knepley        [v0, (e0, 0), (f0, 0), (e2, 0), (e3, 0), (f2, 0), (c0, 0), (f1, 0)]
1323412e9a14SMatthew G. Knepley        [v1, (e4, 0), (f3, 0), (e1, 0), (e0, 0), (f0, 0), (c0, 0), (f1, 0)]
1324412e9a14SMatthew G. Knepley        [v2, (e1, 0), (f3, 0), (e5, 0), (e2, 0), (f2, 0), (c0, 0), (f0, 0)]
1325412e9a14SMatthew G. Knepley        [v3, (e4, 0), (f1, 0), (e3, 0), (e5, 0), (f2, 0), (c0, 0), (f3, 0)]
1326412e9a14SMatthew G. Knepley      We create a new face for each edge
1327412e9a14SMatthew G. Knepley        [(e3, 0), (f2, 0), (c0, 0), (f1, 0)]
1328412e9a14SMatthew G. Knepley        [(f0, 0), (e0, 0), (f1, 0), (c0, 0)]
1329412e9a14SMatthew G. Knepley        [(e2, 0), (f0, 0), (c0, 0), (f2, 0)]
1330412e9a14SMatthew G. Knepley        [(f3, 0), (e4, 0), (f1, 0), (c0, 0)]
1331412e9a14SMatthew G. Knepley        [(e1, 0), (f3, 0), (c0, 0), (f0, 0)]
1332412e9a14SMatthew G. Knepley        [(e5, 0), (f3, 0), (c0, 0), (f2, 0)]
1333412e9a14SMatthew 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.
133475d3a19aSMatthew G. Knepley    */
1335412e9a14SMatthew G. Knepley   static DMPolytopeType tetT[]    = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL, DM_POLYTOPE_HEXAHEDRON};
1336412e9a14SMatthew G. Knepley   static PetscInt       tetS[]    = {1, 4, 6, 4};
1337412e9a14SMatthew G. Knepley   static PetscInt       tetC[]    = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 0, 0,
1338412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 0, 0,
1339412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 0, 0,
1340412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 3, 0, DM_POLYTOPE_POINT, 0, 0,
1341412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 2, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 0,
1342412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,    0,
1343412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 1, 2, 0,
1344412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 3, 1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,    3,
1345412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 3, 0, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 1, 0, 1,
1346412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 3, 2, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 1, 2, 1,
1347412e9a14SMatthew 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,
1348412e9a14SMatthew 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,
1349412e9a14SMatthew 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,
1350412e9a14SMatthew 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};
1351412e9a14SMatthew G. Knepley   static PetscInt       tetO[]    = {0, 0,
1352412e9a14SMatthew G. Knepley                                      0, 0,
1353412e9a14SMatthew G. Knepley                                      0, 0,
1354412e9a14SMatthew G. Knepley                                      0, 0,
1355412e9a14SMatthew G. Knepley                                      0,  0, -2, -2,
1356412e9a14SMatthew G. Knepley                                     -2,  0,  0, -2,
1357412e9a14SMatthew G. Knepley                                      0,  0, -2, -2,
1358412e9a14SMatthew G. Knepley                                     -2,  0,  0, -2,
1359412e9a14SMatthew G. Knepley                                      0,  0, -2, -2,
1360412e9a14SMatthew G. Knepley                                      0,  0, -2, -2,
1361412e9a14SMatthew G. Knepley                                      0,  0,  0,  0,  0,  0,
1362412e9a14SMatthew G. Knepley                                      1, -1,  1,  0,  0,  3,
1363412e9a14SMatthew G. Knepley                                      0, -4,  1, -1,  0,  3,
1364412e9a14SMatthew G. Knepley                                      1, -4,  3, -2, -4,  3};
1365412e9a14SMatthew G. Knepley   /* Add 3 quads inside every triangular prism, making 4 new prisms. */
1366412e9a14SMatthew G. Knepley   static DMPolytopeType tripT[]   = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL, DM_POLYTOPE_HEXAHEDRON};
1367412e9a14SMatthew G. Knepley   static PetscInt       tripS[]   = {1, 5, 9, 6};
1368412e9a14SMatthew G. Knepley   static PetscInt       tripC[]   = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 0, 0,
1369412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 0, 0,
1370412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 0, 0,
1371412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 3, 0, DM_POLYTOPE_POINT, 0, 0,
1372412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 4, 0, DM_POLYTOPE_POINT, 0, 0,
1373412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 3, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 0,    4, DM_POLYTOPE_SEGMENT, 1, 4, 1,
1374412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 3, 3, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 0,    2,
1375412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    4, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 1, 3, 1, DM_POLYTOPE_SEGMENT, 1, 4, 3,
1376412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 1, 2, 0,
1377412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 1, 3, 0,
1378412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    4, DM_POLYTOPE_SEGMENT, 1, 4, 0,
1379412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 2, 2,
1380412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 3, 2,
1381412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    4, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 1, 4, 2,
1382412e9a14SMatthew 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,
1383412e9a14SMatthew 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,
1384412e9a14SMatthew 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,
1385412e9a14SMatthew 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,
1386412e9a14SMatthew 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,
1387412e9a14SMatthew 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};
1388412e9a14SMatthew G. Knepley   static PetscInt       tripO[]   = {0, 0,
1389412e9a14SMatthew G. Knepley                                      0, 0,
1390412e9a14SMatthew G. Knepley                                      0, 0,
1391412e9a14SMatthew G. Knepley                                      0, 0,
1392412e9a14SMatthew G. Knepley                                      0, 0,
1393412e9a14SMatthew G. Knepley                                      0,  0, -2, -2,
1394412e9a14SMatthew G. Knepley                                     -2,  0,  0, -2,
1395412e9a14SMatthew G. Knepley                                      0, -2, -2,  0,
1396412e9a14SMatthew G. Knepley                                      0,  0, -2, -2,
1397412e9a14SMatthew G. Knepley                                      0,  0, -2, -2,
1398412e9a14SMatthew G. Knepley                                      0,  0, -2, -2,
1399412e9a14SMatthew G. Knepley                                      0, -2, -2,  0,
1400412e9a14SMatthew G. Knepley                                      0, -2, -2,  0,
1401412e9a14SMatthew G. Knepley                                      0, -2, -2,  0,
1402412e9a14SMatthew G. Knepley                                      0,  0,  0, -1,  0,  1,
1403412e9a14SMatthew G. Knepley                                      0,  0,  0,  0,  0, -4,
1404412e9a14SMatthew G. Knepley                                      0,  0,  0,  0, -1,  1,
1405412e9a14SMatthew G. Knepley                                     -4,  0,  0, -1,  0,  1,
1406412e9a14SMatthew G. Knepley                                     -4,  0,  0,  0,  0, -4,
1407412e9a14SMatthew G. Knepley                                     -4,  0,  0,  0, -1,  1};
1408412e9a14SMatthew G. Knepley   /* Add 3 tensor quads inside every tensor triangular prism, making 4 new tensor triangular prisms.
1409412e9a14SMatthew G. Knepley       2
1410412e9a14SMatthew G. Knepley       |\
1411412e9a14SMatthew G. Knepley       | \
1412412e9a14SMatthew G. Knepley       |  \
1413412e9a14SMatthew G. Knepley       0---1
141475d3a19aSMatthew G. Knepley 
1415412e9a14SMatthew G. Knepley       2
141675d3a19aSMatthew G. Knepley 
1417412e9a14SMatthew G. Knepley       0   1
141875d3a19aSMatthew G. Knepley 
1419412e9a14SMatthew G. Knepley       2
1420412e9a14SMatthew G. Knepley       |\
1421412e9a14SMatthew G. Knepley       | \
1422412e9a14SMatthew G. Knepley       |  \
1423412e9a14SMatthew G. Knepley       0---1
142475d3a19aSMatthew G. Knepley   */
1425412e9a14SMatthew G. Knepley   static DMPolytopeType ttripT[]  = {DM_POLYTOPE_POINT_PRISM_TENSOR, DM_POLYTOPE_SEG_PRISM_TENSOR, DM_POLYTOPE_QUAD_PRISM_TENSOR};
1426412e9a14SMatthew G. Knepley   static PetscInt       ttripS[]  = {1, 3, 3};
1427412e9a14SMatthew G. Knepley   static PetscInt       ttripC[]  = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
1428412e9a14SMatthew 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,
1429412e9a14SMatthew 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,
1430412e9a14SMatthew 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,
1431412e9a14SMatthew 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,
1432412e9a14SMatthew 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,
1433412e9a14SMatthew 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};
1434412e9a14SMatthew G. Knepley   static PetscInt       ttripO[]  = {0, 0,
1435412e9a14SMatthew G. Knepley                                      0, 0, 0, 0,
1436412e9a14SMatthew G. Knepley                                      0, 0, 0, 0,
1437412e9a14SMatthew G. Knepley                                      0, 0, 0, 0,
1438412e9a14SMatthew G. Knepley                                      0, 0, 0,  0, -1, 0,
1439412e9a14SMatthew G. Knepley                                      0, 0, 0,  0,  0, -1,
1440412e9a14SMatthew G. Knepley                                      0, 0, 0, -1,  0, 0};
1441412e9a14SMatthew G. Knepley   /* TODO Add 3 quads inside every tensor triangular prism, making 4 new triangular prisms.
1442412e9a14SMatthew G. Knepley       2
1443412e9a14SMatthew G. Knepley       |\
1444412e9a14SMatthew G. Knepley       | \
1445412e9a14SMatthew G. Knepley       |  \
1446412e9a14SMatthew G. Knepley       0---1
144775d3a19aSMatthew G. Knepley 
1448412e9a14SMatthew G. Knepley       2
144975d3a19aSMatthew G. Knepley 
1450412e9a14SMatthew G. Knepley       0   1
145175d3a19aSMatthew G. Knepley 
1452412e9a14SMatthew G. Knepley       2
1453412e9a14SMatthew G. Knepley       |\
1454412e9a14SMatthew G. Knepley       | \
1455412e9a14SMatthew G. Knepley       |  \
1456412e9a14SMatthew G. Knepley       0---1
1457a97b51b8SMatthew G. Knepley   */
1458412e9a14SMatthew G. Knepley   static DMPolytopeType ctripT[]  = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL, DM_POLYTOPE_HEXAHEDRON};
1459412e9a14SMatthew G. Knepley   static PetscInt       ctripS[]  = {1, 3, 3};
1460412e9a14SMatthew G. Knepley   static PetscInt       ctripC[]  = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
1461412e9a14SMatthew 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,
1462412e9a14SMatthew 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,
1463412e9a14SMatthew 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,
1464412e9a14SMatthew 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,
1465412e9a14SMatthew 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,
1466412e9a14SMatthew 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};
1467412e9a14SMatthew G. Knepley   static PetscInt       ctripO[]  = {0, 0,
1468412e9a14SMatthew G. Knepley                                      0, 0, -2, -2,
1469412e9a14SMatthew G. Knepley                                      0, 0, -2, -2,
1470412e9a14SMatthew G. Knepley                                      0, 0, -2, -2,
1471412e9a14SMatthew G. Knepley                                     -4, 0, 0, -1,  0,  1,
1472412e9a14SMatthew G. Knepley                                     -4, 0, 0,  0,  0, -4,
1473412e9a14SMatthew G. Knepley                                     -4, 0, 0,  0, -1,  1};
1474412e9a14SMatthew G. Knepley   /* Add 1 edge and 4 quads inside every tensor quad prism, making 4 new hexahedra. */
1475412e9a14SMatthew G. Knepley   static DMPolytopeType tquadpT[]  = {DM_POLYTOPE_POINT_PRISM_TENSOR, DM_POLYTOPE_SEG_PRISM_TENSOR, DM_POLYTOPE_QUAD_PRISM_TENSOR};
1476412e9a14SMatthew G. Knepley   static PetscInt       tquadpS[]  = {1, 4, 4};
1477412e9a14SMatthew G. Knepley   static PetscInt       tquadpC[]  = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
1478412e9a14SMatthew 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,
1479412e9a14SMatthew 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,
1480412e9a14SMatthew 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,
1481412e9a14SMatthew 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,
1482412e9a14SMatthew 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,
1483412e9a14SMatthew 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,
1484412e9a14SMatthew 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,
1485412e9a14SMatthew 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};
1486412e9a14SMatthew G. Knepley   static PetscInt       tquadpO[]  = {0, 0,
1487412e9a14SMatthew G. Knepley                                       0, 0, 0, 0,
1488412e9a14SMatthew G. Knepley                                       0, 0, 0, 0,
1489412e9a14SMatthew G. Knepley                                       0, 0, 0, 0,
1490412e9a14SMatthew G. Knepley                                       0, 0, 0, 0,
1491412e9a14SMatthew G. Knepley                                       0, 0,  0,  0, -1,  0,
1492412e9a14SMatthew G. Knepley                                       0, 0,  0,  0,  0, -1,
1493412e9a14SMatthew G. Knepley                                       0, 0, -1,  0,  0,  0,
1494412e9a14SMatthew G. Knepley                                       0, 0,  0, -1,  0,  0};
1495412e9a14SMatthew G. Knepley   PetscBool convertTensor = PETSC_TRUE;
1496a97b51b8SMatthew G. Knepley 
1497412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
14983f2a96e3SMatthew G. Knepley   if (rt) *rt = 0;
1499412e9a14SMatthew G. Knepley   if (convertTensor) {
1500412e9a14SMatthew G. Knepley     switch (source) {
1501412e9a14SMatthew G. Knepley       case DM_POLYTOPE_POINT:
1502412e9a14SMatthew G. Knepley       case DM_POLYTOPE_SEGMENT:
1503412e9a14SMatthew G. Knepley       case DM_POLYTOPE_QUADRILATERAL:
1504412e9a14SMatthew G. Knepley       case DM_POLYTOPE_HEXAHEDRON:
15053f2a96e3SMatthew G. Knepley         ierr = DMPlexCellRefinerRefine_Regular(cr, source, p, rt, Nt, target, size, cone, ornt);CHKERRQ(ierr);
1506a97b51b8SMatthew G. Knepley         break;
1507412e9a14SMatthew G. Knepley       case DM_POLYTOPE_POINT_PRISM_TENSOR: *Nt = 1; *target = tedgeT;  *size = tedgeS;  *cone = tedgeC;  *ornt = tedgeO;  break;
1508412e9a14SMatthew G. Knepley       case DM_POLYTOPE_SEG_PRISM_TENSOR:   *Nt = 2; *target = tquadT;  *size = tquadS;  *cone = tquadC;  *ornt = tquadO;  break;
1509412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM_TENSOR:   *Nt = 3; *target = ctripT;  *size = ctripS;  *cone = ctripC;  *ornt = ctripO;  break;
1510412e9a14SMatthew G. Knepley       case DM_POLYTOPE_QUAD_PRISM_TENSOR:  *Nt = 3; *target = tquadpT; *size = tquadpS; *cone = tquadpC; *ornt = tquadpO; break;
1511412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRIANGLE:           *Nt = 3; *target = triT;    *size = triS;    *cone = triC;    *ornt = triO;    break;
1512412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TETRAHEDRON:        *Nt = 4; *target = tetT;    *size = tetS;    *cone = tetC;    *ornt = tetO;    break;
1513412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM:          *Nt = 4; *target = tripT;   *size = tripS;   *cone = tripC;   *ornt = tripO;   break;
1514da9060c4SMatthew G. Knepley       /* TODO Fix pyramids: For now, we just ignore them */
1515da9060c4SMatthew G. Knepley       case DM_POLYTOPE_PYRAMID:
15163f2a96e3SMatthew G. Knepley         ierr = DMPlexCellRefinerRefine_None(cr, source, p, rt, Nt, target, size, cone, ornt);CHKERRQ(ierr);
1517da9060c4SMatthew G. Knepley         break;
1518412e9a14SMatthew G. Knepley       default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No refinement strategy for %s", DMPolytopeTypes[source]);
1519b5da9499SMatthew G. Knepley     }
1520b5da9499SMatthew G. Knepley   } else {
1521412e9a14SMatthew G. Knepley     switch (source) {
1522412e9a14SMatthew G. Knepley       case DM_POLYTOPE_POINT:
1523412e9a14SMatthew G. Knepley       case DM_POLYTOPE_POINT_PRISM_TENSOR:
1524412e9a14SMatthew G. Knepley       case DM_POLYTOPE_SEGMENT:
1525412e9a14SMatthew G. Knepley       case DM_POLYTOPE_QUADRILATERAL:
1526412e9a14SMatthew G. Knepley       case DM_POLYTOPE_SEG_PRISM_TENSOR:
1527412e9a14SMatthew G. Knepley       case DM_POLYTOPE_HEXAHEDRON:
1528412e9a14SMatthew G. Knepley       case DM_POLYTOPE_QUAD_PRISM_TENSOR:
15293f2a96e3SMatthew G. Knepley         ierr = DMPlexCellRefinerRefine_Regular(cr, source, p, rt, Nt, target, size, cone, ornt);CHKERRQ(ierr);
1530b5da9499SMatthew G. Knepley         break;
1531412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRIANGLE:           *Nt = 3; *target = triT;    *size = triS;    *cone = triC;    *ornt = triO;    break;
1532412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TETRAHEDRON:        *Nt = 4; *target = tetT;    *size = tetS;    *cone = tetC;    *ornt = tetO;    break;
1533412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM:          *Nt = 4; *target = tripT;   *size = tripS;   *cone = tripC;   *ornt = tripO;   break;
1534412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM_TENSOR:   *Nt = 3; *target = ttripT;  *size = ttripS;  *cone = ttripC;  *ornt = ttripO;  break;
1535da9060c4SMatthew G. Knepley       /* TODO Fix pyramids: For now, we just ignore them */
1536da9060c4SMatthew G. Knepley       case DM_POLYTOPE_PYRAMID:
15373f2a96e3SMatthew G. Knepley         ierr = DMPlexCellRefinerRefine_None(cr, source, p, rt, Nt, target, size, cone, ornt);CHKERRQ(ierr);
1538da9060c4SMatthew G. Knepley         break;
1539412e9a14SMatthew G. Knepley       default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No refinement strategy for %s", DMPolytopeTypes[source]);
154027fcede3SMatthew G. Knepley     }
154175d3a19aSMatthew G. Knepley   }
154275d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
154375d3a19aSMatthew G. Knepley }
154475d3a19aSMatthew G. Knepley 
15453f2a96e3SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerRefine_ToSimplex(DMPlexCellRefiner cr, DMPolytopeType source, PetscInt p, PetscInt *rt, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[])
154675d3a19aSMatthew G. Knepley {
1547412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
1548412e9a14SMatthew G. Knepley 
1549412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
15503f2a96e3SMatthew G. Knepley   if (rt) *rt = 0;
1551412e9a14SMatthew G. Knepley   switch (source) {
1552412e9a14SMatthew G. Knepley     case DM_POLYTOPE_POINT:
1553412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:
1554412e9a14SMatthew G. Knepley     case DM_POLYTOPE_POINT_PRISM_TENSOR:
1555412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:
1556412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TETRAHEDRON:
1557412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM:
1558412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:
1559412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:
1560412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEG_PRISM_TENSOR:
1561412e9a14SMatthew G. Knepley     case DM_POLYTOPE_HEXAHEDRON:
1562412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
15633f2a96e3SMatthew G. Knepley       ierr = DMPlexCellRefinerRefine_Regular(cr, source, p, rt, Nt, target, size, cone, ornt);CHKERRQ(ierr);
1564412e9a14SMatthew G. Knepley       break;
1565da9060c4SMatthew G. Knepley     /* TODO Fix pyramids: For now, we just ignore them */
1566da9060c4SMatthew G. Knepley     case DM_POLYTOPE_PYRAMID:
15673f2a96e3SMatthew G. Knepley       ierr = DMPlexCellRefinerRefine_None(cr, source, p, rt, Nt, target, size, cone, ornt);CHKERRQ(ierr);
1568da9060c4SMatthew G. Knepley       break;
1569412e9a14SMatthew G. Knepley     default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No refinement strategy for %s", DMPolytopeTypes[source]);
1570412e9a14SMatthew G. Knepley   }
1571412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1572412e9a14SMatthew G. Knepley }
1573412e9a14SMatthew G. Knepley 
15743f2a96e3SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerRefine_Alfeld2D(DMPlexCellRefiner cr, DMPolytopeType source, PetscInt p, PetscInt *rt, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[])
1575cf4091a3SMatthew G. Knepley {
1576cf4091a3SMatthew G. Knepley   PetscErrorCode ierr;
1577cf4091a3SMatthew G. Knepley   /* Add 1 vertex, 3 edges inside every triangle, making 3 new triangles.
1578cf4091a3SMatthew G. Knepley    2
1579cf4091a3SMatthew G. Knepley    |\
1580cf4091a3SMatthew G. Knepley    |\\
1581cf4091a3SMatthew G. Knepley    | |\
1582cf4091a3SMatthew G. Knepley    | \ \
1583cf4091a3SMatthew G. Knepley    | |  \
1584cf4091a3SMatthew G. Knepley    |  \  \
1585cf4091a3SMatthew G. Knepley    |   |  \
1586cf4091a3SMatthew G. Knepley    2   \   \
1587cf4091a3SMatthew G. Knepley    |   |    1
1588cf4091a3SMatthew G. Knepley    |   2    \
1589cf4091a3SMatthew G. Knepley    |   |    \
1590cf4091a3SMatthew G. Knepley    |   /\   \
1591cf4091a3SMatthew G. Knepley    |  0  1  |
1592cf4091a3SMatthew G. Knepley    | /    \ |
1593cf4091a3SMatthew G. Knepley    |/      \|
1594cf4091a3SMatthew G. Knepley    0---0----1
1595cf4091a3SMatthew G. Knepley   */
1596cf4091a3SMatthew G. Knepley   static DMPolytopeType triT[]    = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT, DM_POLYTOPE_TRIANGLE};
1597cf4091a3SMatthew G. Knepley   static PetscInt       triS[]    = {1, 3, 3};
1598cf4091a3SMatthew G. Knepley   static PetscInt       triC[]    = {DM_POLYTOPE_POINT, 2, 0, 0, 0, DM_POLYTOPE_POINT, 0, 0,
1599cf4091a3SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 2, 1, 0, 0, DM_POLYTOPE_POINT, 0, 0,
1600cf4091a3SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 2, 2, 0, 0, DM_POLYTOPE_POINT, 0, 0,
1601cf4091a3SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0, 1, DM_POLYTOPE_SEGMENT, 0, 0,
1602cf4091a3SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0, 2, DM_POLYTOPE_SEGMENT, 0, 1,
1603cf4091a3SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0, 0, DM_POLYTOPE_SEGMENT, 0, 2};
1604cf4091a3SMatthew G. Knepley   static PetscInt       triO[]    = {0, 0,
1605cf4091a3SMatthew G. Knepley                                      0, 0,
1606cf4091a3SMatthew G. Knepley                                      0, 0,
1607cf4091a3SMatthew G. Knepley                                      0,  0, -2,
1608cf4091a3SMatthew G. Knepley                                      0,  0, -2,
1609cf4091a3SMatthew G. Knepley                                      0,  0, -2};
1610cf4091a3SMatthew G. Knepley 
1611cf4091a3SMatthew G. Knepley   PetscFunctionBeginHot;
16123f2a96e3SMatthew G. Knepley   if (rt) *rt = 0;
1613cf4091a3SMatthew G. Knepley   switch (source) {
1614cf4091a3SMatthew G. Knepley     case DM_POLYTOPE_POINT:
1615cf4091a3SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:
1616cf4091a3SMatthew G. Knepley     case DM_POLYTOPE_POINT_PRISM_TENSOR:
1617cf4091a3SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:
1618cf4091a3SMatthew G. Knepley     case DM_POLYTOPE_SEG_PRISM_TENSOR:
1619cf4091a3SMatthew G. Knepley     case DM_POLYTOPE_TETRAHEDRON:
1620cf4091a3SMatthew G. Knepley     case DM_POLYTOPE_HEXAHEDRON:
1621cf4091a3SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM:
1622cf4091a3SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:
1623cf4091a3SMatthew G. Knepley     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
1624da9060c4SMatthew G. Knepley     case DM_POLYTOPE_PYRAMID:
16253f2a96e3SMatthew G. Knepley       ierr = DMPlexCellRefinerRefine_None(cr, source, p, rt, Nt, target, size, cone, ornt);CHKERRQ(ierr);
1626cf4091a3SMatthew G. Knepley       break;
1627cf4091a3SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:           *Nt = 3; *target = triT;    *size = triS;    *cone = triC;    *ornt = triO;    break;
1628cf4091a3SMatthew G. Knepley     default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No refinement strategy for %s", DMPolytopeTypes[source]);
1629cf4091a3SMatthew G. Knepley   }
1630cf4091a3SMatthew G. Knepley   PetscFunctionReturn(0);
1631cf4091a3SMatthew G. Knepley }
1632cf4091a3SMatthew G. Knepley 
16333f2a96e3SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerRefine_Alfeld3D(DMPlexCellRefiner cr, DMPolytopeType source, PetscInt p, PetscInt *rt, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[])
1634cf4091a3SMatthew G. Knepley {
1635cf4091a3SMatthew G. Knepley   PetscErrorCode ierr;
1636cf4091a3SMatthew G. Knepley   /* Add 6 triangles inside every cell, making 4 new tets
1637cf4091a3SMatthew 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
1638cf4091a3SMatthew 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]
1639cf4091a3SMatthew G. Knepley      called e3, e4, and e5. The faces of a tet, given in DMPlexGetRawFaces_Internal() are
1640cf4091a3SMatthew G. Knepley        [v0, v1, v2], [v0, v3, v1], [v0, v2, v3], [v2, v1, v3]
1641cf4091a3SMatthew G. Knepley      We make a new tet on each face
1642cf4091a3SMatthew G. Knepley        [v0, v1, v2, (c0, 0)]
1643cf4091a3SMatthew G. Knepley        [v0, v3, v1, (c0, 0)]
1644cf4091a3SMatthew G. Knepley        [v0, v2, v3, (c0, 0)]
1645cf4091a3SMatthew G. Knepley        [v2, v1, v3, (c0, 0)]
1646cf4091a3SMatthew G. Knepley      We create a new face for each edge
1647cf4091a3SMatthew G. Knepley        [v0, (c0, 0), v1     ]
1648cf4091a3SMatthew G. Knepley        [v0, v2,      (c0, 0)]
1649cf4091a3SMatthew G. Knepley        [v2, v1,      (c0, 0)]
1650cf4091a3SMatthew G. Knepley        [v0, (c0, 0), v3     ]
1651cf4091a3SMatthew G. Knepley        [v1, v3,      (c0, 0)]
1652cf4091a3SMatthew G. Knepley        [v3, v2,      (c0, 0)]
1653cf4091a3SMatthew G. Knepley    */
1654cf4091a3SMatthew G. Knepley   static DMPolytopeType tetT[]    = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT, DM_POLYTOPE_TRIANGLE, DM_POLYTOPE_TETRAHEDRON};
1655cf4091a3SMatthew G. Knepley   static PetscInt       tetS[]    = {1, 4, 6, 4};
1656cf4091a3SMatthew G. Knepley   static PetscInt       tetC[]    = {DM_POLYTOPE_POINT, 3, 0, 0, 0, 0, DM_POLYTOPE_POINT, 0, 0,
1657cf4091a3SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 3, 0, 1, 0, 0, DM_POLYTOPE_POINT, 0, 0,
1658cf4091a3SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 3, 0, 2, 0, 0, DM_POLYTOPE_POINT, 0, 0,
1659cf4091a3SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 3, 1, 0, 1, 0, DM_POLYTOPE_POINT, 0, 0,
1660cf4091a3SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,       0, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 2, 0, 0, 0,
1661cf4091a3SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 2, 0, 2, 0, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 0,       0,
1662cf4091a3SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 2, 0, 1, 0, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,       2,
1663cf4091a3SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,       0, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 2, 1, 0, 0,
1664cf4091a3SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 2, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 0,       1,
1665cf4091a3SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 2, 2, 1, 0, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 0,       3,
1666cf4091a3SMatthew G. Knepley                                      DM_POLYTOPE_TRIANGLE, 1, 0, 0, DM_POLYTOPE_TRIANGLE, 0, 0, DM_POLYTOPE_TRIANGLE, 0, 1, DM_POLYTOPE_TRIANGLE, 0, 2,
1667cf4091a3SMatthew G. Knepley                                      DM_POLYTOPE_TRIANGLE, 1, 1, 0, DM_POLYTOPE_TRIANGLE, 0, 3, DM_POLYTOPE_TRIANGLE, 0, 0, DM_POLYTOPE_TRIANGLE, 0, 4,
1668cf4091a3SMatthew G. Knepley                                      DM_POLYTOPE_TRIANGLE, 1, 2, 0, DM_POLYTOPE_TRIANGLE, 0, 1, DM_POLYTOPE_TRIANGLE, 0, 3, DM_POLYTOPE_TRIANGLE, 0, 5,
1669cf4091a3SMatthew G. Knepley                                      DM_POLYTOPE_TRIANGLE, 1, 3, 0, DM_POLYTOPE_TRIANGLE, 0, 2, DM_POLYTOPE_TRIANGLE, 0, 5, DM_POLYTOPE_TRIANGLE, 0, 4};
1670cf4091a3SMatthew G. Knepley   static PetscInt       tetO[]    = {0, 0,
1671cf4091a3SMatthew G. Knepley                                      0, 0,
1672cf4091a3SMatthew G. Knepley                                      0, 0,
1673cf4091a3SMatthew G. Knepley                                      0, 0,
1674cf4091a3SMatthew G. Knepley                                      0, -2, -2,
1675cf4091a3SMatthew G. Knepley                                     -2,  0, -2,
1676cf4091a3SMatthew G. Knepley                                     -2,  0, -2,
1677cf4091a3SMatthew G. Knepley                                      0, -2, -2,
1678cf4091a3SMatthew G. Knepley                                     -2,  0, -2,
1679cf4091a3SMatthew G. Knepley                                     -2,  0, -2,
1680cf4091a3SMatthew G. Knepley                                      0,  0,  0,  0,
1681cf4091a3SMatthew G. Knepley                                      0,  0, -3,  0,
1682cf4091a3SMatthew G. Knepley                                      0, -3, -3,  0,
1683cf4091a3SMatthew G. Knepley                                      0, -3, -1, -1};
1684cf4091a3SMatthew G. Knepley 
1685cf4091a3SMatthew G. Knepley   PetscFunctionBeginHot;
16863f2a96e3SMatthew G. Knepley   if (rt) *rt = 0;
1687cf4091a3SMatthew G. Knepley   switch (source) {
1688cf4091a3SMatthew G. Knepley     case DM_POLYTOPE_POINT:
1689cf4091a3SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:
1690cf4091a3SMatthew G. Knepley     case DM_POLYTOPE_POINT_PRISM_TENSOR:
1691cf4091a3SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:
1692cf4091a3SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:
1693cf4091a3SMatthew G. Knepley     case DM_POLYTOPE_SEG_PRISM_TENSOR:
1694cf4091a3SMatthew G. Knepley     case DM_POLYTOPE_HEXAHEDRON:
1695cf4091a3SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM:
1696cf4091a3SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:
1697cf4091a3SMatthew G. Knepley     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
1698da9060c4SMatthew G. Knepley     case DM_POLYTOPE_PYRAMID:
16993f2a96e3SMatthew G. Knepley       ierr = DMPlexCellRefinerRefine_None(cr, source, p, rt, Nt, target, size, cone, ornt);CHKERRQ(ierr);
1700cf4091a3SMatthew G. Knepley       break;
1701cf4091a3SMatthew G. Knepley     case DM_POLYTOPE_TETRAHEDRON:        *Nt = 4; *target = tetT;    *size = tetS;    *cone = tetC;    *ornt = tetO;    break;
1702cf4091a3SMatthew G. Knepley     default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No refinement strategy for %s", DMPolytopeTypes[source]);
1703cf4091a3SMatthew G. Knepley   }
1704cf4091a3SMatthew G. Knepley   PetscFunctionReturn(0);
1705cf4091a3SMatthew G. Knepley }
1706cf4091a3SMatthew G. Knepley 
1707a5801f52SStefano Zampini typedef struct {
1708a5801f52SStefano Zampini   PetscInt       n;
1709a5801f52SStefano Zampini   PetscReal      r;
1710a5801f52SStefano Zampini   PetscScalar    *h;
1711a5801f52SStefano Zampini   PetscInt       *Nt;
1712a5801f52SStefano Zampini   DMPolytopeType **target;
1713a5801f52SStefano Zampini   PetscInt       **size;
1714a5801f52SStefano Zampini   PetscInt       **cone;
1715a5801f52SStefano Zampini   PetscInt       **ornt;
1716a5801f52SStefano Zampini } PlexRefiner_BL;
1717a5801f52SStefano Zampini 
1718a5801f52SStefano Zampini static PetscErrorCode DMPlexCellRefinerSetUp_BL(DMPlexCellRefiner cr)
1719a5801f52SStefano Zampini {
1720a5801f52SStefano Zampini   PlexRefiner_BL *crbl;
1721a5801f52SStefano Zampini   PetscErrorCode ierr;
1722a5801f52SStefano Zampini   PetscInt       i,n;
1723a5801f52SStefano Zampini   PetscReal      r;
1724a5801f52SStefano Zampini   PetscInt       c1,c2,o1,o2;
1725a5801f52SStefano Zampini 
1726a5801f52SStefano Zampini   PetscFunctionBegin;
1727a5801f52SStefano Zampini   ierr = PetscNew(&crbl);CHKERRQ(ierr);
1728a5801f52SStefano Zampini   cr->data = crbl;
1729a5801f52SStefano Zampini   crbl->n = 1; /* 1 split -> 2 new cells */
1730a5801f52SStefano Zampini   crbl->r = 1; /* linear progression */
1731a5801f52SStefano Zampini 
1732a5801f52SStefano Zampini   /* TODO: add setfromoptions to the refiners? */
1733a5801f52SStefano Zampini   ierr = PetscOptionsGetInt(((PetscObject) cr->dm)->options,((PetscObject) cr->dm)->prefix, "-dm_plex_refine_boundarylayer_splits", &crbl->n, NULL);CHKERRQ(ierr);
1734a5801f52SStefano Zampini   if (crbl->n < 1) SETERRQ1(PetscObjectComm((PetscObject)cr),PETSC_ERR_SUP,"Number of splits %D must be positive",crbl->n);
1735a5801f52SStefano Zampini   ierr = PetscOptionsGetReal(((PetscObject) cr->dm)->options,((PetscObject) cr->dm)->prefix, "-dm_plex_refine_boundarylayer_progression", &crbl->r, NULL);CHKERRQ(ierr);
1736a5801f52SStefano Zampini   n = crbl->n;
1737a5801f52SStefano Zampini   r = crbl->r;
1738a5801f52SStefano Zampini 
1739a5801f52SStefano Zampini   /* we only split DM_POLYTOPE_POINT_PRISM_TENSOR, DM_POLYTOPE_SEG_PRISM_TENSOR, DM_POLYTOPE_TRI_PRISM_TENSOR and DM_POLYTOPE_QUAD_PRISM_TENSOR */
1740a5801f52SStefano Zampini   ierr = PetscMalloc5(4,&crbl->Nt,4,&crbl->target,4,&crbl->size,4,&crbl->cone,4,&crbl->ornt);CHKERRQ(ierr);
1741a5801f52SStefano Zampini 
1742a5801f52SStefano Zampini   /* progression */
1743a5801f52SStefano Zampini   ierr = PetscMalloc1(n,&crbl->h);CHKERRQ(ierr);
1744a5801f52SStefano Zampini   if (r > 1) {
1745a5801f52SStefano Zampini     PetscReal d = (r-1.)/(PetscPowRealInt(r,n+1)-1.);
1746a5801f52SStefano Zampini 
1747a5801f52SStefano Zampini     crbl->h[0] = d;
1748a5801f52SStefano Zampini     for (i = 1; i < n; i++) {
1749a5801f52SStefano Zampini       d *= r;
1750a5801f52SStefano Zampini       crbl->h[i] = crbl->h[i-1] + d;
1751a5801f52SStefano Zampini     }
1752a5801f52SStefano Zampini   } else { /* linear */
1753a5801f52SStefano Zampini     for (i = 0; i < n; i++) crbl->h[i] = (i + 1.)/(n+1); /* linear */
1754a5801f52SStefano Zampini   }
1755a5801f52SStefano Zampini 
1756a5801f52SStefano Zampini   /* DM_POLYTOPE_POINT_PRISM_TENSOR produces n points and n+1 tensor segments */
1757a5801f52SStefano Zampini   c1 = 14+6*(n-1);
1758a5801f52SStefano Zampini   o1 = 2*(n+1);
1759a5801f52SStefano Zampini   crbl->Nt[0] = 2;
1760a5801f52SStefano Zampini 
1761a5801f52SStefano Zampini   ierr = PetscMalloc4(crbl->Nt[0],&crbl->target[0],crbl->Nt[0],&crbl->size[0],c1,&crbl->cone[0],o1,&crbl->ornt[0]);CHKERRQ(ierr);
1762a5801f52SStefano Zampini 
1763a5801f52SStefano Zampini   crbl->target[0][0] = DM_POLYTOPE_POINT;
1764a5801f52SStefano Zampini   crbl->target[0][1] = DM_POLYTOPE_POINT_PRISM_TENSOR;
1765a5801f52SStefano Zampini 
1766a5801f52SStefano Zampini   crbl->size[0][0] = n;
1767a5801f52SStefano Zampini   crbl->size[0][1] = n+1;
1768a5801f52SStefano Zampini 
1769a5801f52SStefano Zampini   /* the tensor segments */
1770a5801f52SStefano Zampini   crbl->cone[0][0] = DM_POLYTOPE_POINT;
1771a5801f52SStefano Zampini   crbl->cone[0][1] = 1;
1772a5801f52SStefano Zampini   crbl->cone[0][2] = 0;
1773a5801f52SStefano Zampini   crbl->cone[0][3] = 0;
1774a5801f52SStefano Zampini   crbl->cone[0][4] = DM_POLYTOPE_POINT;
1775a5801f52SStefano Zampini   crbl->cone[0][5] = 0;
1776a5801f52SStefano Zampini   crbl->cone[0][6] = 0;
1777a5801f52SStefano Zampini   for (i = 0; i < n-1; i++) {
1778a5801f52SStefano Zampini     crbl->cone[0][7+6*i+0] = DM_POLYTOPE_POINT;
1779a5801f52SStefano Zampini     crbl->cone[0][7+6*i+1] = 0;
1780a5801f52SStefano Zampini     crbl->cone[0][7+6*i+2] = i;
1781a5801f52SStefano Zampini     crbl->cone[0][7+6*i+3] = DM_POLYTOPE_POINT;
1782a5801f52SStefano Zampini     crbl->cone[0][7+6*i+4] = 0;
1783a5801f52SStefano Zampini     crbl->cone[0][7+6*i+5] = i+1;
1784a5801f52SStefano Zampini   }
1785a5801f52SStefano Zampini   crbl->cone[0][7+6*(n-1)+0] = DM_POLYTOPE_POINT;
1786a5801f52SStefano Zampini   crbl->cone[0][7+6*(n-1)+1] = 0;
1787a5801f52SStefano Zampini   crbl->cone[0][7+6*(n-1)+2] = n-1;
1788a5801f52SStefano Zampini   crbl->cone[0][7+6*(n-1)+3] = DM_POLYTOPE_POINT;
1789a5801f52SStefano Zampini   crbl->cone[0][7+6*(n-1)+4] = 1;
1790a5801f52SStefano Zampini   crbl->cone[0][7+6*(n-1)+5] = 1;
1791a5801f52SStefano Zampini   crbl->cone[0][7+6*(n-1)+6] = 0;
1792a5801f52SStefano Zampini   for (i = 0; i < o1; i++) crbl->ornt[0][i] = 0;
1793a5801f52SStefano Zampini 
1794a5801f52SStefano Zampini   /* DM_POLYTOPE_SEG_PRISM_TENSOR produces n segments and n+1 tensor quads */
1795a5801f52SStefano Zampini   c1 = 8*n;
1796a5801f52SStefano Zampini   c2 = 30+14*(n-1);
1797a5801f52SStefano Zampini   o1 = 2*n;
1798a5801f52SStefano Zampini   o2 = 4*(n+1);
1799a5801f52SStefano Zampini   crbl->Nt[1] = 2;
1800a5801f52SStefano Zampini 
1801a5801f52SStefano Zampini   ierr = PetscMalloc4(crbl->Nt[1],&crbl->target[1],crbl->Nt[1],&crbl->size[1],c1+c2,&crbl->cone[1],o1+o2,&crbl->ornt[1]);CHKERRQ(ierr);
1802a5801f52SStefano Zampini 
1803a5801f52SStefano Zampini   crbl->target[1][0] = DM_POLYTOPE_SEGMENT;
1804a5801f52SStefano Zampini   crbl->target[1][1] = DM_POLYTOPE_SEG_PRISM_TENSOR;
1805a5801f52SStefano Zampini 
1806a5801f52SStefano Zampini   crbl->size[1][0] = n;
1807a5801f52SStefano Zampini   crbl->size[1][1] = n+1;
1808a5801f52SStefano Zampini 
1809a5801f52SStefano Zampini   /* the segments */
1810a5801f52SStefano Zampini   for (i = 0; i < n; i++) {
1811a5801f52SStefano Zampini     crbl->cone[1][8*i+0] = DM_POLYTOPE_POINT;
1812a5801f52SStefano Zampini     crbl->cone[1][8*i+1] = 1;
1813a5801f52SStefano Zampini     crbl->cone[1][8*i+2] = 2;
1814a5801f52SStefano Zampini     crbl->cone[1][8*i+3] = i;
1815a5801f52SStefano Zampini     crbl->cone[1][8*i+4] = DM_POLYTOPE_POINT;
1816a5801f52SStefano Zampini     crbl->cone[1][8*i+5] = 1;
1817a5801f52SStefano Zampini     crbl->cone[1][8*i+6] = 3;
1818a5801f52SStefano Zampini     crbl->cone[1][8*i+7] = i;
1819a5801f52SStefano Zampini   }
1820a5801f52SStefano Zampini 
1821a5801f52SStefano Zampini   /* the tensor quads */
1822a5801f52SStefano Zampini   crbl->cone[1][c1+ 0] = DM_POLYTOPE_SEGMENT;
1823a5801f52SStefano Zampini   crbl->cone[1][c1+ 1] = 1;
1824a5801f52SStefano Zampini   crbl->cone[1][c1+ 2] = 0;
1825a5801f52SStefano Zampini   crbl->cone[1][c1+ 3] = 0;
1826a5801f52SStefano Zampini   crbl->cone[1][c1+ 4] = DM_POLYTOPE_SEGMENT;
1827a5801f52SStefano Zampini   crbl->cone[1][c1+ 5] = 0;
1828a5801f52SStefano Zampini   crbl->cone[1][c1+ 6] = 0;
1829a5801f52SStefano Zampini   crbl->cone[1][c1+ 7] = DM_POLYTOPE_POINT_PRISM_TENSOR;
1830a5801f52SStefano Zampini   crbl->cone[1][c1+ 8] = 1;
1831a5801f52SStefano Zampini   crbl->cone[1][c1+ 9] = 2;
1832a5801f52SStefano Zampini   crbl->cone[1][c1+10] = 0;
1833a5801f52SStefano Zampini   crbl->cone[1][c1+11] = DM_POLYTOPE_POINT_PRISM_TENSOR;
1834a5801f52SStefano Zampini   crbl->cone[1][c1+12] = 1;
1835a5801f52SStefano Zampini   crbl->cone[1][c1+13] = 3;
1836a5801f52SStefano Zampini   crbl->cone[1][c1+14] = 0;
1837a5801f52SStefano Zampini   for (i = 0; i < n-1; i++) {
1838a5801f52SStefano Zampini     crbl->cone[1][c1+15+14*i+ 0] = DM_POLYTOPE_SEGMENT;
1839a5801f52SStefano Zampini     crbl->cone[1][c1+15+14*i+ 1] = 0;
1840a5801f52SStefano Zampini     crbl->cone[1][c1+15+14*i+ 2] = i;
1841a5801f52SStefano Zampini     crbl->cone[1][c1+15+14*i+ 3] = DM_POLYTOPE_SEGMENT;
1842a5801f52SStefano Zampini     crbl->cone[1][c1+15+14*i+ 4] = 0;
1843a5801f52SStefano Zampini     crbl->cone[1][c1+15+14*i+ 5] = i+1;
1844a5801f52SStefano Zampini     crbl->cone[1][c1+15+14*i+ 6] = DM_POLYTOPE_POINT_PRISM_TENSOR;
1845a5801f52SStefano Zampini     crbl->cone[1][c1+15+14*i+ 7] = 1;
1846a5801f52SStefano Zampini     crbl->cone[1][c1+15+14*i+ 8] = 2;
1847a5801f52SStefano Zampini     crbl->cone[1][c1+15+14*i+ 9] = i+1;
1848a5801f52SStefano Zampini     crbl->cone[1][c1+15+14*i+10] = DM_POLYTOPE_POINT_PRISM_TENSOR;
1849a5801f52SStefano Zampini     crbl->cone[1][c1+15+14*i+11] = 1;
1850a5801f52SStefano Zampini     crbl->cone[1][c1+15+14*i+12] = 3;
1851a5801f52SStefano Zampini     crbl->cone[1][c1+15+14*i+13] = i+1;
1852a5801f52SStefano Zampini   }
1853a5801f52SStefano Zampini   crbl->cone[1][c1+15+14*(n-1)+ 0] = DM_POLYTOPE_SEGMENT;
1854a5801f52SStefano Zampini   crbl->cone[1][c1+15+14*(n-1)+ 1] = 0;
1855a5801f52SStefano Zampini   crbl->cone[1][c1+15+14*(n-1)+ 2] = n-1;
1856a5801f52SStefano Zampini   crbl->cone[1][c1+15+14*(n-1)+ 3] = DM_POLYTOPE_SEGMENT;
1857a5801f52SStefano Zampini   crbl->cone[1][c1+15+14*(n-1)+ 4] = 1;
1858a5801f52SStefano Zampini   crbl->cone[1][c1+15+14*(n-1)+ 5] = 1;
1859a5801f52SStefano Zampini   crbl->cone[1][c1+15+14*(n-1)+ 6] = 0;
1860a5801f52SStefano Zampini   crbl->cone[1][c1+15+14*(n-1)+ 7] = DM_POLYTOPE_POINT_PRISM_TENSOR;
1861a5801f52SStefano Zampini   crbl->cone[1][c1+15+14*(n-1)+ 8] = 1;
1862a5801f52SStefano Zampini   crbl->cone[1][c1+15+14*(n-1)+ 9] = 2;
1863a5801f52SStefano Zampini   crbl->cone[1][c1+15+14*(n-1)+10] = n;
1864a5801f52SStefano Zampini   crbl->cone[1][c1+15+14*(n-1)+11] = DM_POLYTOPE_POINT_PRISM_TENSOR;
1865a5801f52SStefano Zampini   crbl->cone[1][c1+15+14*(n-1)+12] = 1;
1866a5801f52SStefano Zampini   crbl->cone[1][c1+15+14*(n-1)+13] = 3;
1867a5801f52SStefano Zampini   crbl->cone[1][c1+15+14*(n-1)+14] = n;
1868a5801f52SStefano Zampini   for (i = 0; i < o1+o2; i++) crbl->ornt[1][i] = 0;
1869a5801f52SStefano Zampini 
1870a5801f52SStefano Zampini   /* DM_POLYTOPE_TRI_PRISM_TENSOR produces n triangles and n+1 tensor triangular prisms */
1871a5801f52SStefano Zampini   c1 = 12*n;
1872a5801f52SStefano Zampini   c2 = 38+18*(n-1);
1873a5801f52SStefano Zampini   o1 = 3*n;
1874a5801f52SStefano Zampini   o2 = 5*(n+1);
1875a5801f52SStefano Zampini   crbl->Nt[2] = 2;
1876a5801f52SStefano Zampini 
1877a5801f52SStefano Zampini   ierr = PetscMalloc4(crbl->Nt[2],&crbl->target[2],crbl->Nt[2],&crbl->size[2],c1+c2,&crbl->cone[2],o1+o2,&crbl->ornt[2]);CHKERRQ(ierr);
1878a5801f52SStefano Zampini 
1879a5801f52SStefano Zampini   crbl->target[2][0] = DM_POLYTOPE_TRIANGLE;
1880a5801f52SStefano Zampini   crbl->target[2][1] = DM_POLYTOPE_TRI_PRISM_TENSOR;
1881a5801f52SStefano Zampini 
1882a5801f52SStefano Zampini   crbl->size[2][0] = n;
1883a5801f52SStefano Zampini   crbl->size[2][1] = n+1;
1884a5801f52SStefano Zampini 
1885a5801f52SStefano Zampini   /* the triangles */
1886a5801f52SStefano Zampini   for (i = 0; i < n; i++) {
1887a5801f52SStefano Zampini     crbl->cone[2][12*i+ 0] = DM_POLYTOPE_SEGMENT;
1888a5801f52SStefano Zampini     crbl->cone[2][12*i+ 1] = 1;
1889a5801f52SStefano Zampini     crbl->cone[2][12*i+ 2] = 2;
1890a5801f52SStefano Zampini     crbl->cone[2][12*i+ 3] = i;
1891a5801f52SStefano Zampini     crbl->cone[2][12*i+ 4] = DM_POLYTOPE_SEGMENT;
1892a5801f52SStefano Zampini     crbl->cone[2][12*i+ 5] = 1;
1893a5801f52SStefano Zampini     crbl->cone[2][12*i+ 6] = 3;
1894a5801f52SStefano Zampini     crbl->cone[2][12*i+ 7] = i;
1895a5801f52SStefano Zampini     crbl->cone[2][12*i+ 8] = DM_POLYTOPE_SEGMENT;
1896a5801f52SStefano Zampini     crbl->cone[2][12*i+ 9] = 1;
1897a5801f52SStefano Zampini     crbl->cone[2][12*i+10] = 4;
1898a5801f52SStefano Zampini     crbl->cone[2][12*i+11] = i;
1899a5801f52SStefano Zampini   }
1900a5801f52SStefano Zampini 
1901a5801f52SStefano Zampini   /* the triangular prisms */
1902a5801f52SStefano Zampini   crbl->cone[2][c1+ 0] = DM_POLYTOPE_TRIANGLE;
1903a5801f52SStefano Zampini   crbl->cone[2][c1+ 1] = 1;
1904a5801f52SStefano Zampini   crbl->cone[2][c1+ 2] = 0;
1905a5801f52SStefano Zampini   crbl->cone[2][c1+ 3] = 0;
1906a5801f52SStefano Zampini   crbl->cone[2][c1+ 4] = DM_POLYTOPE_TRIANGLE;
1907a5801f52SStefano Zampini   crbl->cone[2][c1+ 5] = 0;
1908a5801f52SStefano Zampini   crbl->cone[2][c1+ 6] = 0;
1909a5801f52SStefano Zampini   crbl->cone[2][c1+ 7] = DM_POLYTOPE_SEG_PRISM_TENSOR;
1910a5801f52SStefano Zampini   crbl->cone[2][c1+ 8] = 1;
1911a5801f52SStefano Zampini   crbl->cone[2][c1+ 9] = 2;
1912a5801f52SStefano Zampini   crbl->cone[2][c1+10] = 0;
1913a5801f52SStefano Zampini   crbl->cone[2][c1+11] = DM_POLYTOPE_SEG_PRISM_TENSOR;
1914a5801f52SStefano Zampini   crbl->cone[2][c1+12] = 1;
1915a5801f52SStefano Zampini   crbl->cone[2][c1+13] = 3;
1916a5801f52SStefano Zampini   crbl->cone[2][c1+14] = 0;
1917a5801f52SStefano Zampini   crbl->cone[2][c1+15] = DM_POLYTOPE_SEG_PRISM_TENSOR;
1918a5801f52SStefano Zampini   crbl->cone[2][c1+16] = 1;
1919a5801f52SStefano Zampini   crbl->cone[2][c1+17] = 4;
1920a5801f52SStefano Zampini   crbl->cone[2][c1+18] = 0;
1921a5801f52SStefano Zampini   for (i = 0; i < n-1; i++) {
1922a5801f52SStefano Zampini     crbl->cone[2][c1+19+18*i+ 0] = DM_POLYTOPE_TRIANGLE;
1923a5801f52SStefano Zampini     crbl->cone[2][c1+19+18*i+ 1] = 0;
1924a5801f52SStefano Zampini     crbl->cone[2][c1+19+18*i+ 2] = i;
1925a5801f52SStefano Zampini     crbl->cone[2][c1+19+18*i+ 3] = DM_POLYTOPE_TRIANGLE;
1926a5801f52SStefano Zampini     crbl->cone[2][c1+19+18*i+ 4] = 0;
1927a5801f52SStefano Zampini     crbl->cone[2][c1+19+18*i+ 5] = i+1;
1928a5801f52SStefano Zampini     crbl->cone[2][c1+19+18*i+ 6] = DM_POLYTOPE_SEG_PRISM_TENSOR;
1929a5801f52SStefano Zampini     crbl->cone[2][c1+19+18*i+ 7] = 1;
1930a5801f52SStefano Zampini     crbl->cone[2][c1+19+18*i+ 8] = 2;
1931a5801f52SStefano Zampini     crbl->cone[2][c1+19+18*i+ 9] = i+1;
1932a5801f52SStefano Zampini     crbl->cone[2][c1+19+18*i+10] = DM_POLYTOPE_SEG_PRISM_TENSOR;
1933a5801f52SStefano Zampini     crbl->cone[2][c1+19+18*i+11] = 1;
1934a5801f52SStefano Zampini     crbl->cone[2][c1+19+18*i+12] = 3;
1935a5801f52SStefano Zampini     crbl->cone[2][c1+19+18*i+13] = i+1;
1936a5801f52SStefano Zampini     crbl->cone[2][c1+19+18*i+14] = DM_POLYTOPE_SEG_PRISM_TENSOR;
1937a5801f52SStefano Zampini     crbl->cone[2][c1+19+18*i+15] = 1;
1938a5801f52SStefano Zampini     crbl->cone[2][c1+19+18*i+16] = 4;
1939a5801f52SStefano Zampini     crbl->cone[2][c1+19+18*i+17] = i+1;
1940a5801f52SStefano Zampini   }
1941a5801f52SStefano Zampini   crbl->cone[2][c1+19+18*(n-1)+ 0] = DM_POLYTOPE_TRIANGLE;
1942a5801f52SStefano Zampini   crbl->cone[2][c1+19+18*(n-1)+ 1] = 0;
1943a5801f52SStefano Zampini   crbl->cone[2][c1+19+18*(n-1)+ 2] = n-1;
1944a5801f52SStefano Zampini   crbl->cone[2][c1+19+18*(n-1)+ 3] = DM_POLYTOPE_TRIANGLE;
1945a5801f52SStefano Zampini   crbl->cone[2][c1+19+18*(n-1)+ 4] = 1;
1946a5801f52SStefano Zampini   crbl->cone[2][c1+19+18*(n-1)+ 5] = 1;
1947a5801f52SStefano Zampini   crbl->cone[2][c1+19+18*(n-1)+ 6] = 0;
1948a5801f52SStefano Zampini   crbl->cone[2][c1+19+18*(n-1)+ 7] = DM_POLYTOPE_SEG_PRISM_TENSOR;
1949a5801f52SStefano Zampini   crbl->cone[2][c1+19+18*(n-1)+ 8] = 1;
1950a5801f52SStefano Zampini   crbl->cone[2][c1+19+18*(n-1)+ 9] = 2;
1951a5801f52SStefano Zampini   crbl->cone[2][c1+19+18*(n-1)+10] = n;
1952a5801f52SStefano Zampini   crbl->cone[2][c1+19+18*(n-1)+11] = DM_POLYTOPE_SEG_PRISM_TENSOR;
1953a5801f52SStefano Zampini   crbl->cone[2][c1+19+18*(n-1)+12] = 1;
1954a5801f52SStefano Zampini   crbl->cone[2][c1+19+18*(n-1)+13] = 3;
1955a5801f52SStefano Zampini   crbl->cone[2][c1+19+18*(n-1)+14] = n;
1956a5801f52SStefano Zampini   crbl->cone[2][c1+19+18*(n-1)+15] = DM_POLYTOPE_SEG_PRISM_TENSOR;
1957a5801f52SStefano Zampini   crbl->cone[2][c1+19+18*(n-1)+16] = 1;
1958a5801f52SStefano Zampini   crbl->cone[2][c1+19+18*(n-1)+17] = 4;
1959a5801f52SStefano Zampini   crbl->cone[2][c1+19+18*(n-1)+18] = n;
1960a5801f52SStefano Zampini   for (i = 0; i < o1+o2; i++) crbl->ornt[2][i] = 0;
1961a5801f52SStefano Zampini 
1962a5801f52SStefano Zampini   /* DM_POLYTOPE_QUAD_PRISM_TENSOR produces n quads and n+1 tensor quad prisms */
1963a5801f52SStefano Zampini   c1 = 16*n;
1964a5801f52SStefano Zampini   c2 = 46+22*(n-1);
1965a5801f52SStefano Zampini   o1 = 4*n;
1966a5801f52SStefano Zampini   o2 = 6*(n+1);
1967a5801f52SStefano Zampini   crbl->Nt[3] = 2;
1968a5801f52SStefano Zampini 
1969a5801f52SStefano Zampini   ierr = PetscMalloc4(crbl->Nt[3],&crbl->target[3],crbl->Nt[3],&crbl->size[3],c1+c2,&crbl->cone[3],o1+o2,&crbl->ornt[3]);CHKERRQ(ierr);
1970a5801f52SStefano Zampini 
1971a5801f52SStefano Zampini   crbl->target[3][0] = DM_POLYTOPE_QUADRILATERAL;
1972a5801f52SStefano Zampini   crbl->target[3][1] = DM_POLYTOPE_QUAD_PRISM_TENSOR;
1973a5801f52SStefano Zampini 
1974a5801f52SStefano Zampini   crbl->size[3][0] = n;
1975a5801f52SStefano Zampini   crbl->size[3][1] = n+1;
1976a5801f52SStefano Zampini 
1977a5801f52SStefano Zampini   /* the quads */
1978a5801f52SStefano Zampini   for (i = 0; i < n; i++) {
1979a5801f52SStefano Zampini     crbl->cone[3][16*i+ 0] = DM_POLYTOPE_SEGMENT;
1980a5801f52SStefano Zampini     crbl->cone[3][16*i+ 1] = 1;
1981a5801f52SStefano Zampini     crbl->cone[3][16*i+ 2] = 2;
1982a5801f52SStefano Zampini     crbl->cone[3][16*i+ 3] = i;
1983a5801f52SStefano Zampini     crbl->cone[3][16*i+ 4] = DM_POLYTOPE_SEGMENT;
1984a5801f52SStefano Zampini     crbl->cone[3][16*i+ 5] = 1;
1985a5801f52SStefano Zampini     crbl->cone[3][16*i+ 6] = 3;
1986a5801f52SStefano Zampini     crbl->cone[3][16*i+ 7] = i;
1987a5801f52SStefano Zampini     crbl->cone[3][16*i+ 8] = DM_POLYTOPE_SEGMENT;
1988a5801f52SStefano Zampini     crbl->cone[3][16*i+ 9] = 1;
1989a5801f52SStefano Zampini     crbl->cone[3][16*i+10] = 4;
1990a5801f52SStefano Zampini     crbl->cone[3][16*i+11] = i;
1991a5801f52SStefano Zampini     crbl->cone[3][16*i+12] = DM_POLYTOPE_SEGMENT;
1992a5801f52SStefano Zampini     crbl->cone[3][16*i+13] = 1;
1993a5801f52SStefano Zampini     crbl->cone[3][16*i+14] = 5;
1994a5801f52SStefano Zampini     crbl->cone[3][16*i+15] = i;
1995a5801f52SStefano Zampini   }
1996a5801f52SStefano Zampini 
1997a5801f52SStefano Zampini   /* the quad prisms */
1998a5801f52SStefano Zampini   crbl->cone[3][c1+ 0] = DM_POLYTOPE_QUADRILATERAL;
1999a5801f52SStefano Zampini   crbl->cone[3][c1+ 1] = 1;
2000a5801f52SStefano Zampini   crbl->cone[3][c1+ 2] = 0;
2001a5801f52SStefano Zampini   crbl->cone[3][c1+ 3] = 0;
2002a5801f52SStefano Zampini   crbl->cone[3][c1+ 4] = DM_POLYTOPE_QUADRILATERAL;
2003a5801f52SStefano Zampini   crbl->cone[3][c1+ 5] = 0;
2004a5801f52SStefano Zampini   crbl->cone[3][c1+ 6] = 0;
2005a5801f52SStefano Zampini   crbl->cone[3][c1+ 7] = DM_POLYTOPE_SEG_PRISM_TENSOR;
2006a5801f52SStefano Zampini   crbl->cone[3][c1+ 8] = 1;
2007a5801f52SStefano Zampini   crbl->cone[3][c1+ 9] = 2;
2008a5801f52SStefano Zampini   crbl->cone[3][c1+10] = 0;
2009a5801f52SStefano Zampini   crbl->cone[3][c1+11] = DM_POLYTOPE_SEG_PRISM_TENSOR;
2010a5801f52SStefano Zampini   crbl->cone[3][c1+12] = 1;
2011a5801f52SStefano Zampini   crbl->cone[3][c1+13] = 3;
2012a5801f52SStefano Zampini   crbl->cone[3][c1+14] = 0;
2013a5801f52SStefano Zampini   crbl->cone[3][c1+15] = DM_POLYTOPE_SEG_PRISM_TENSOR;
2014a5801f52SStefano Zampini   crbl->cone[3][c1+16] = 1;
2015a5801f52SStefano Zampini   crbl->cone[3][c1+17] = 4;
2016a5801f52SStefano Zampini   crbl->cone[3][c1+18] = 0;
2017a5801f52SStefano Zampini   crbl->cone[3][c1+19] = DM_POLYTOPE_SEG_PRISM_TENSOR;
2018a5801f52SStefano Zampini   crbl->cone[3][c1+20] = 1;
2019a5801f52SStefano Zampini   crbl->cone[3][c1+21] = 5;
2020a5801f52SStefano Zampini   crbl->cone[3][c1+22] = 0;
2021a5801f52SStefano Zampini   for (i = 0; i < n-1; i++) {
2022a5801f52SStefano Zampini     crbl->cone[3][c1+23+22*i+ 0] = DM_POLYTOPE_QUADRILATERAL;
2023a5801f52SStefano Zampini     crbl->cone[3][c1+23+22*i+ 1] = 0;
2024a5801f52SStefano Zampini     crbl->cone[3][c1+23+22*i+ 2] = i;
2025a5801f52SStefano Zampini     crbl->cone[3][c1+23+22*i+ 3] = DM_POLYTOPE_QUADRILATERAL;
2026a5801f52SStefano Zampini     crbl->cone[3][c1+23+22*i+ 4] = 0;
2027a5801f52SStefano Zampini     crbl->cone[3][c1+23+22*i+ 5] = i+1;
2028a5801f52SStefano Zampini     crbl->cone[3][c1+23+22*i+ 6] = DM_POLYTOPE_SEG_PRISM_TENSOR;
2029a5801f52SStefano Zampini     crbl->cone[3][c1+23+22*i+ 7] = 1;
2030a5801f52SStefano Zampini     crbl->cone[3][c1+23+22*i+ 8] = 2;
2031a5801f52SStefano Zampini     crbl->cone[3][c1+23+22*i+ 9] = i+1;
2032a5801f52SStefano Zampini     crbl->cone[3][c1+23+22*i+10] = DM_POLYTOPE_SEG_PRISM_TENSOR;
2033a5801f52SStefano Zampini     crbl->cone[3][c1+23+22*i+11] = 1;
2034a5801f52SStefano Zampini     crbl->cone[3][c1+23+22*i+12] = 3;
2035a5801f52SStefano Zampini     crbl->cone[3][c1+23+22*i+13] = i+1;
2036a5801f52SStefano Zampini     crbl->cone[3][c1+23+22*i+14] = DM_POLYTOPE_SEG_PRISM_TENSOR;
2037a5801f52SStefano Zampini     crbl->cone[3][c1+23+22*i+15] = 1;
2038a5801f52SStefano Zampini     crbl->cone[3][c1+23+22*i+16] = 4;
2039a5801f52SStefano Zampini     crbl->cone[3][c1+23+22*i+17] = i+1;
2040a5801f52SStefano Zampini     crbl->cone[3][c1+23+22*i+18] = DM_POLYTOPE_SEG_PRISM_TENSOR;
2041a5801f52SStefano Zampini     crbl->cone[3][c1+23+22*i+19] = 1;
2042a5801f52SStefano Zampini     crbl->cone[3][c1+23+22*i+20] = 5;
2043a5801f52SStefano Zampini     crbl->cone[3][c1+23+22*i+21] = i+1;
2044a5801f52SStefano Zampini   }
2045a5801f52SStefano Zampini   crbl->cone[3][c1+23+22*(n-1)+ 0] = DM_POLYTOPE_QUADRILATERAL;
2046a5801f52SStefano Zampini   crbl->cone[3][c1+23+22*(n-1)+ 1] = 0;
2047a5801f52SStefano Zampini   crbl->cone[3][c1+23+22*(n-1)+ 2] = n-1;
2048a5801f52SStefano Zampini   crbl->cone[3][c1+23+22*(n-1)+ 3] = DM_POLYTOPE_QUADRILATERAL;
2049a5801f52SStefano Zampini   crbl->cone[3][c1+23+22*(n-1)+ 4] = 1;
2050a5801f52SStefano Zampini   crbl->cone[3][c1+23+22*(n-1)+ 5] = 1;
2051a5801f52SStefano Zampini   crbl->cone[3][c1+23+22*(n-1)+ 6] = 0;
2052a5801f52SStefano Zampini   crbl->cone[3][c1+23+22*(n-1)+ 7] = DM_POLYTOPE_SEG_PRISM_TENSOR;
2053a5801f52SStefano Zampini   crbl->cone[3][c1+23+22*(n-1)+ 8] = 1;
2054a5801f52SStefano Zampini   crbl->cone[3][c1+23+22*(n-1)+ 9] = 2;
2055a5801f52SStefano Zampini   crbl->cone[3][c1+23+22*(n-1)+10] = n;
2056a5801f52SStefano Zampini   crbl->cone[3][c1+23+22*(n-1)+11] = DM_POLYTOPE_SEG_PRISM_TENSOR;
2057a5801f52SStefano Zampini   crbl->cone[3][c1+23+22*(n-1)+12] = 1;
2058a5801f52SStefano Zampini   crbl->cone[3][c1+23+22*(n-1)+13] = 3;
2059a5801f52SStefano Zampini   crbl->cone[3][c1+23+22*(n-1)+14] = n;
2060a5801f52SStefano Zampini   crbl->cone[3][c1+23+22*(n-1)+15] = DM_POLYTOPE_SEG_PRISM_TENSOR;
2061a5801f52SStefano Zampini   crbl->cone[3][c1+23+22*(n-1)+16] = 1;
2062a5801f52SStefano Zampini   crbl->cone[3][c1+23+22*(n-1)+17] = 4;
2063a5801f52SStefano Zampini   crbl->cone[3][c1+23+22*(n-1)+18] = n;
2064a5801f52SStefano Zampini   crbl->cone[3][c1+23+22*(n-1)+19] = DM_POLYTOPE_SEG_PRISM_TENSOR;
2065a5801f52SStefano Zampini   crbl->cone[3][c1+23+22*(n-1)+20] = 1;
2066a5801f52SStefano Zampini   crbl->cone[3][c1+23+22*(n-1)+21] = 5;
2067a5801f52SStefano Zampini   crbl->cone[3][c1+23+22*(n-1)+22] = n;
2068a5801f52SStefano Zampini   for (i = 0; i < o1+o2; i++) crbl->ornt[3][i] = 0;
2069a5801f52SStefano Zampini   PetscFunctionReturn(0);
2070a5801f52SStefano Zampini }
2071a5801f52SStefano Zampini 
2072a5801f52SStefano Zampini static PetscErrorCode DMPlexCellRefinerDestroy_BL(DMPlexCellRefiner cr)
2073a5801f52SStefano Zampini {
2074a5801f52SStefano Zampini   PlexRefiner_BL *crbl = (PlexRefiner_BL *)cr->data;
2075a5801f52SStefano Zampini   PetscErrorCode ierr;
2076a5801f52SStefano Zampini 
2077a5801f52SStefano Zampini   PetscFunctionBegin;
2078a5801f52SStefano Zampini   ierr = PetscFree4(crbl->target[0],crbl->size[0],crbl->cone[0],crbl->ornt[0]);CHKERRQ(ierr);
2079a5801f52SStefano Zampini   ierr = PetscFree4(crbl->target[1],crbl->size[1],crbl->cone[1],crbl->ornt[1]);CHKERRQ(ierr);
2080a5801f52SStefano Zampini   ierr = PetscFree4(crbl->target[2],crbl->size[2],crbl->cone[2],crbl->ornt[2]);CHKERRQ(ierr);
2081a5801f52SStefano Zampini   ierr = PetscFree4(crbl->target[3],crbl->size[3],crbl->cone[3],crbl->ornt[3]);CHKERRQ(ierr);
2082a5801f52SStefano Zampini   ierr = PetscFree5(crbl->Nt,crbl->target,crbl->size,crbl->cone,crbl->ornt);CHKERRQ(ierr);
2083a5801f52SStefano Zampini   ierr = PetscFree(crbl->h);CHKERRQ(ierr);
2084a5801f52SStefano Zampini   ierr = PetscFree(cr->data);CHKERRQ(ierr);
2085a5801f52SStefano Zampini   PetscFunctionReturn(0);
2086a5801f52SStefano Zampini }
2087a5801f52SStefano Zampini 
20883f2a96e3SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerRefine_BL(DMPlexCellRefiner cr, DMPolytopeType source, PetscInt p, PetscInt *rt, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[])
2089cf4091a3SMatthew G. Knepley {
2090a5801f52SStefano Zampini   PlexRefiner_BL  *crbl = (PlexRefiner_BL *)cr->data;
2091cf4091a3SMatthew G. Knepley   PetscErrorCode  ierr;
2092cf4091a3SMatthew G. Knepley 
2093cf4091a3SMatthew G. Knepley   PetscFunctionBeginHot;
20943f2a96e3SMatthew G. Knepley   if (rt) *rt = 0;
2095cf4091a3SMatthew G. Knepley   switch (source) {
2096a5801f52SStefano Zampini   case DM_POLYTOPE_POINT_PRISM_TENSOR:
2097a5801f52SStefano Zampini     *Nt     = crbl->Nt[0];
2098a5801f52SStefano Zampini     *target = crbl->target[0];
2099a5801f52SStefano Zampini     *size   = crbl->size[0];
2100a5801f52SStefano Zampini     *cone   = crbl->cone[0];
2101a5801f52SStefano Zampini     *ornt   = crbl->ornt[0];
2102cf4091a3SMatthew G. Knepley     break;
2103a5801f52SStefano Zampini   case DM_POLYTOPE_SEG_PRISM_TENSOR:
2104a5801f52SStefano Zampini     *Nt     = crbl->Nt[1];
2105a5801f52SStefano Zampini     *target = crbl->target[1];
2106a5801f52SStefano Zampini     *size   = crbl->size[1];
2107a5801f52SStefano Zampini     *cone   = crbl->cone[1];
2108a5801f52SStefano Zampini     *ornt   = crbl->ornt[1];
2109a5801f52SStefano Zampini     break;
2110a5801f52SStefano Zampini   case DM_POLYTOPE_TRI_PRISM_TENSOR:
2111a5801f52SStefano Zampini     *Nt     = crbl->Nt[2];
2112a5801f52SStefano Zampini     *target = crbl->target[2];
2113a5801f52SStefano Zampini     *size   = crbl->size[2];
2114a5801f52SStefano Zampini     *cone   = crbl->cone[2];
2115a5801f52SStefano Zampini     *ornt   = crbl->ornt[2];
2116a5801f52SStefano Zampini     break;
2117a5801f52SStefano Zampini   case DM_POLYTOPE_QUAD_PRISM_TENSOR:
2118a5801f52SStefano Zampini     *Nt     = crbl->Nt[3];
2119a5801f52SStefano Zampini     *target = crbl->target[3];
2120a5801f52SStefano Zampini     *size   = crbl->size[3];
2121a5801f52SStefano Zampini     *cone   = crbl->cone[3];
2122a5801f52SStefano Zampini     *ornt   = crbl->ornt[3];
2123a5801f52SStefano Zampini     break;
2124a5801f52SStefano Zampini   default:
21253f2a96e3SMatthew G. Knepley     ierr = DMPlexCellRefinerRefine_None(cr,source,p,rt,Nt,target,size,cone,ornt);CHKERRQ(ierr);
2126a5801f52SStefano Zampini   }
2127a5801f52SStefano Zampini   PetscFunctionReturn(0);
2128a5801f52SStefano Zampini }
2129a5801f52SStefano Zampini 
21303f2a96e3SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerMapSubcells_BL(DMPlexCellRefiner cr, DMPolytopeType pct, PetscInt pp, PetscInt po, DMPolytopeType ct, PetscInt r, PetscInt o, PetscInt *rnew, PetscInt *onew)
2131a5801f52SStefano Zampini {
2132a5801f52SStefano Zampini   /* We shift any input orientation in order to make it non-negative
2133a5801f52SStefano Zampini        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)
2134a5801f52SStefano Zampini        The replica array r[po][r] gives the new replica number rnew given that the parent point has orientation po
2135a5801f52SStefano Zampini        Overall, replica (r, o) in a parent with orientation 0 matches replica (rnew, onew) in a parent with orientation po
2136a5801f52SStefano Zampini   */
2137a5801f52SStefano Zampini   PetscInt       tquad_seg_o[]   = { 0,  1, -2, -1,
2138a5801f52SStefano Zampini                                      0,  1, -2, -1,
2139a5801f52SStefano Zampini                                     -2, -1,  0,  1,
2140a5801f52SStefano Zampini                                     -2, -1,  0,  1};
2141a5801f52SStefano Zampini   PetscInt       tquad_tquad_o[] = { 0,  1, -2, -1,
2142a5801f52SStefano Zampini                                      1,  0, -1, -2,
2143a5801f52SStefano Zampini                                     -2, -1,  0,  1,
2144a5801f52SStefano Zampini                                     -1, -2,  1,  0};
2145a5801f52SStefano Zampini   PlexRefiner_BL *crbl = (PlexRefiner_BL *)cr->data;
2146a5801f52SStefano Zampini   const PetscInt n = crbl->n;
2147a5801f52SStefano Zampini   PetscErrorCode ierr;
2148a5801f52SStefano Zampini 
2149a5801f52SStefano Zampini   PetscFunctionBeginHot;
2150a5801f52SStefano Zampini   *rnew = r;
2151a5801f52SStefano Zampini   *onew = o;
2152a5801f52SStefano Zampini   switch (pct) {
2153a5801f52SStefano Zampini     case DM_POLYTOPE_POINT_PRISM_TENSOR:
2154a5801f52SStefano Zampini       if (ct == DM_POLYTOPE_POINT_PRISM_TENSOR) {
2155a5801f52SStefano Zampini         if      (po == 0 || po == -1) {*rnew = r;     *onew = o;}
2156a5801f52SStefano Zampini         else if (po == 1 || po == -2) {*rnew = n - r; *onew = (o == 0 || o == -1) ? -2 : 0;}
2157a5801f52SStefano Zampini         else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid orientation %D for tensor segment", po);
2158a5801f52SStefano Zampini       }
2159a5801f52SStefano Zampini       break;
2160a5801f52SStefano Zampini     case DM_POLYTOPE_SEG_PRISM_TENSOR:
2161a5801f52SStefano Zampini       switch (ct) {
2162a5801f52SStefano Zampini         case DM_POLYTOPE_SEGMENT:
2163a5801f52SStefano Zampini           *onew = tquad_seg_o[(po+2)*4+o+2];
2164a5801f52SStefano Zampini           *rnew = r;
2165a5801f52SStefano Zampini           break;
2166a5801f52SStefano Zampini         case DM_POLYTOPE_SEG_PRISM_TENSOR:
2167a5801f52SStefano Zampini           *onew = tquad_tquad_o[(po+2)*4+o+2];
2168a5801f52SStefano Zampini           *rnew = r;
2169a5801f52SStefano Zampini           break;
2170a5801f52SStefano Zampini         default: break;
2171a5801f52SStefano Zampini       }
2172a5801f52SStefano Zampini       break;
2173a5801f52SStefano Zampini     default:
21743f2a96e3SMatthew G. Knepley       ierr = DMPlexCellRefinerMapSubcells_None(cr, pct, pp, po, ct, r, o, rnew, onew);CHKERRQ(ierr);
2175a5801f52SStefano Zampini   }
2176a5801f52SStefano Zampini   PetscFunctionReturn(0);
2177a5801f52SStefano Zampini }
2178a5801f52SStefano Zampini 
2179a5801f52SStefano Zampini static PetscErrorCode DMPlexCellRefinerMapCoordinates_BL(DMPlexCellRefiner cr, DMPolytopeType pct, DMPolytopeType ct, PetscInt r, PetscInt Nv, PetscInt dE, const PetscScalar in[], PetscScalar out[])
2180a5801f52SStefano Zampini {
2181a5801f52SStefano Zampini   PlexRefiner_BL  *crbl = (PlexRefiner_BL *)cr->data;
2182a5801f52SStefano Zampini   PetscInt        d;
2183a5801f52SStefano Zampini   PetscErrorCode  ierr;
2184a5801f52SStefano Zampini 
2185a5801f52SStefano Zampini   PetscFunctionBeginHot;
2186a5801f52SStefano Zampini   switch (pct) {
2187a5801f52SStefano Zampini   case DM_POLYTOPE_POINT_PRISM_TENSOR:
2188a5801f52SStefano Zampini     if (ct != DM_POLYTOPE_POINT) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for refined point type %s",DMPolytopeTypes[ct]);
2189a5801f52SStefano Zampini     if (Nv != 2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for parent vertices %D",Nv);
2190a5801f52SStefano Zampini     if (r >= crbl->n || r < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Invalid replica %D, must be in [0,%D)",r,crbl->n);
2191a5801f52SStefano Zampini     for (d = 0; d < dE; d++) out[d] = in[d] + crbl->h[r] * (in[d + dE] - in[d]);
2192a5801f52SStefano Zampini     break;
2193a5801f52SStefano Zampini   default:
2194a5801f52SStefano Zampini     ierr = DMPlexCellRefinerMapCoordinates_Barycenter(cr,pct,ct,r,Nv,dE,in,out);CHKERRQ(ierr);
2195cf4091a3SMatthew G. Knepley   }
2196cf4091a3SMatthew G. Knepley   PetscFunctionReturn(0);
2197cf4091a3SMatthew G. Knepley }
2198cf4091a3SMatthew G. Knepley 
21993f2a96e3SMatthew G. Knepley typedef struct {
22003f2a96e3SMatthew G. Knepley   DMLabel      splitPoints; /* List of edges to be bisected (1) and cells to be divided (2) */
22013f2a96e3SMatthew G. Knepley   PetscSection secEdgeLen;  /* Section for edge length field */
22023f2a96e3SMatthew G. Knepley   PetscReal   *edgeLen;     /* Storage for edge length field */
22033f2a96e3SMatthew G. Knepley   PetscInt    *splitArray;  /* Array for communication of split points label */
22043f2a96e3SMatthew G. Knepley } PlexRefiner_SBR;
22053f2a96e3SMatthew G. Knepley 
22063f2a96e3SMatthew G. Knepley typedef struct _p_PointQueue *PointQueue;
22073f2a96e3SMatthew G. Knepley struct _p_PointQueue {
22083f2a96e3SMatthew G. Knepley   PetscInt  size;   /* Size of the storage array */
22093f2a96e3SMatthew G. Knepley   PetscInt *points; /* Array of mesh points */
22103f2a96e3SMatthew G. Knepley   PetscInt  front;  /* Index of the front of the queue */
22113f2a96e3SMatthew G. Knepley   PetscInt  back;   /* Index of the back of the queue */
22123f2a96e3SMatthew G. Knepley   PetscInt  num;    /* Number of enqueued points */
22133f2a96e3SMatthew G. Knepley };
22143f2a96e3SMatthew G. Knepley 
22153f2a96e3SMatthew G. Knepley static PetscErrorCode PointQueueCreate(PetscInt size, PointQueue *queue)
22163f2a96e3SMatthew G. Knepley {
22173f2a96e3SMatthew G. Knepley   PointQueue     q;
22183f2a96e3SMatthew G. Knepley   PetscErrorCode ierr;
22193f2a96e3SMatthew G. Knepley 
22203f2a96e3SMatthew G. Knepley   PetscFunctionBegin;
22213f2a96e3SMatthew G. Knepley   if (size < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Queue size %D must be non-negative", size);
22223f2a96e3SMatthew G. Knepley   ierr = PetscCalloc1(1, &q);CHKERRQ(ierr);
22233f2a96e3SMatthew G. Knepley   q->size = size;
22243f2a96e3SMatthew G. Knepley   ierr = PetscMalloc1(q->size, &q->points);CHKERRQ(ierr);
22253f2a96e3SMatthew G. Knepley   q->num   = 0;
22263f2a96e3SMatthew G. Knepley   q->front = 0;
22273f2a96e3SMatthew G. Knepley   q->back  = q->size-1;
22283f2a96e3SMatthew G. Knepley   *queue = q;
22293f2a96e3SMatthew G. Knepley   PetscFunctionReturn(0);
22303f2a96e3SMatthew G. Knepley }
22313f2a96e3SMatthew G. Knepley 
22323f2a96e3SMatthew G. Knepley static PetscErrorCode PointQueueDestroy(PointQueue *queue)
22333f2a96e3SMatthew G. Knepley {
22343f2a96e3SMatthew G. Knepley   PointQueue     q = *queue;
22353f2a96e3SMatthew G. Knepley   PetscErrorCode ierr;
22363f2a96e3SMatthew G. Knepley 
22373f2a96e3SMatthew G. Knepley   PetscFunctionBegin;
22383f2a96e3SMatthew G. Knepley   ierr = PetscFree(q->points);CHKERRQ(ierr);
22393f2a96e3SMatthew G. Knepley   ierr = PetscFree(q);CHKERRQ(ierr);
22403f2a96e3SMatthew G. Knepley   *queue = NULL;
22413f2a96e3SMatthew G. Knepley   PetscFunctionReturn(0);
22423f2a96e3SMatthew G. Knepley }
22433f2a96e3SMatthew G. Knepley 
22443f2a96e3SMatthew G. Knepley static PetscErrorCode PointQueueEnsureSize(PointQueue queue)
22453f2a96e3SMatthew G. Knepley {
22463f2a96e3SMatthew G. Knepley   PetscErrorCode ierr;
22473f2a96e3SMatthew G. Knepley 
22483f2a96e3SMatthew G. Knepley   PetscFunctionBegin;
22493f2a96e3SMatthew G. Knepley   if (queue->num < queue->size) PetscFunctionReturn(0);
22503f2a96e3SMatthew G. Knepley   queue->size *= 2;
22513f2a96e3SMatthew G. Knepley   ierr = PetscRealloc(queue->size * sizeof(PetscInt), &queue->points);CHKERRQ(ierr);
22523f2a96e3SMatthew G. Knepley   PetscFunctionReturn(0);
22533f2a96e3SMatthew G. Knepley }
22543f2a96e3SMatthew G. Knepley 
22553f2a96e3SMatthew G. Knepley static PetscErrorCode PointQueueEnqueue(PointQueue queue, PetscInt p)
22563f2a96e3SMatthew G. Knepley {
22573f2a96e3SMatthew G. Knepley   PetscErrorCode ierr;
22583f2a96e3SMatthew G. Knepley 
22593f2a96e3SMatthew G. Knepley   PetscFunctionBegin;
22603f2a96e3SMatthew G. Knepley   ierr = PointQueueEnsureSize(queue);CHKERRQ(ierr);
22613f2a96e3SMatthew G. Knepley   queue->back = (queue->back + 1) % queue->size;
22623f2a96e3SMatthew G. Knepley   queue->points[queue->back] = p;
22633f2a96e3SMatthew G. Knepley   ++queue->num;
22643f2a96e3SMatthew G. Knepley   PetscFunctionReturn(0);
22653f2a96e3SMatthew G. Knepley }
22663f2a96e3SMatthew G. Knepley 
22673f2a96e3SMatthew G. Knepley static PetscErrorCode PointQueueDequeue(PointQueue queue, PetscInt *p)
22683f2a96e3SMatthew G. Knepley {
22693f2a96e3SMatthew G. Knepley   PetscFunctionBegin;
22703f2a96e3SMatthew G. Knepley   if (!queue->num) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot dequeue from an empty queue");
22713f2a96e3SMatthew G. Knepley   *p = queue->points[queue->front];
22723f2a96e3SMatthew G. Knepley   queue->front = (queue->front + 1) % queue->size;
22733f2a96e3SMatthew G. Knepley   --queue->num;
22743f2a96e3SMatthew G. Knepley   PetscFunctionReturn(0);
22753f2a96e3SMatthew G. Knepley }
22763f2a96e3SMatthew G. Knepley 
22773f2a96e3SMatthew G. Knepley #if 0
22783f2a96e3SMatthew G. Knepley static PetscErrorCode PointQueueFront(PointQueue queue, PetscInt *p)
22793f2a96e3SMatthew G. Knepley {
22803f2a96e3SMatthew G. Knepley   PetscFunctionBegin;
22813f2a96e3SMatthew G. Knepley   if (!queue->num) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot get the front of an empty queue");
22823f2a96e3SMatthew G. Knepley   *p = queue->points[queue->front];
22833f2a96e3SMatthew G. Knepley   PetscFunctionReturn(0);
22843f2a96e3SMatthew G. Knepley }
22853f2a96e3SMatthew G. Knepley 
22863f2a96e3SMatthew G. Knepley static PetscErrorCode PointQueueBack(PointQueue queue, PetscInt *p)
22873f2a96e3SMatthew G. Knepley {
22883f2a96e3SMatthew G. Knepley   PetscFunctionBegin;
22893f2a96e3SMatthew G. Knepley   if (!queue->num) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot get the back of an empty queue");
22903f2a96e3SMatthew G. Knepley   *p = queue->points[queue->back];
22913f2a96e3SMatthew G. Knepley   PetscFunctionReturn(0);
22923f2a96e3SMatthew G. Knepley }
22933f2a96e3SMatthew G. Knepley #endif
22943f2a96e3SMatthew G. Knepley 
22953f2a96e3SMatthew G. Knepley PETSC_STATIC_INLINE PetscBool PointQueueEmpty(PointQueue queue)
22963f2a96e3SMatthew G. Knepley {
22973f2a96e3SMatthew G. Knepley   if (!queue->num) return PETSC_TRUE;
22983f2a96e3SMatthew G. Knepley   return PETSC_FALSE;
22993f2a96e3SMatthew G. Knepley }
23003f2a96e3SMatthew G. Knepley 
23013f2a96e3SMatthew G. Knepley static PetscErrorCode SBRGetEdgeLen_Private(DMPlexCellRefiner cr, PetscInt edge, PetscReal *len)
23023f2a96e3SMatthew G. Knepley {
23033f2a96e3SMatthew G. Knepley   PlexRefiner_SBR *sbr = (PlexRefiner_SBR *) cr->data;
23043f2a96e3SMatthew G. Knepley   DM               dm  = cr->dm;
23053f2a96e3SMatthew G. Knepley   PetscInt         off;
23063f2a96e3SMatthew G. Knepley   PetscErrorCode   ierr;
23073f2a96e3SMatthew G. Knepley 
23083f2a96e3SMatthew G. Knepley   PetscFunctionBeginHot;
23093f2a96e3SMatthew G. Knepley   ierr = PetscSectionGetOffset(sbr->secEdgeLen, edge, &off);CHKERRQ(ierr);
23103f2a96e3SMatthew G. Knepley   if (sbr->edgeLen[off] <= 0.0) {
23113f2a96e3SMatthew G. Knepley     DM                 cdm;
23123f2a96e3SMatthew G. Knepley     Vec                coordsLocal;
23133f2a96e3SMatthew G. Knepley     const PetscScalar *coords;
23143f2a96e3SMatthew G. Knepley     const PetscInt    *cone;
23153f2a96e3SMatthew G. Knepley     PetscScalar       *cA, *cB;
23163f2a96e3SMatthew G. Knepley     PetscInt           coneSize, cdim;
23173f2a96e3SMatthew G. Knepley 
23183f2a96e3SMatthew G. Knepley     ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
23193f2a96e3SMatthew G. Knepley     ierr = DMPlexGetCone(dm, edge, &cone);CHKERRQ(ierr);
23203f2a96e3SMatthew G. Knepley     ierr = DMPlexGetConeSize(dm, edge, &coneSize);CHKERRQ(ierr);
23213f2a96e3SMatthew G. Knepley     if (coneSize != 2) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Edge %D cone size must be 2, not %D", edge, coneSize);
23223f2a96e3SMatthew G. Knepley     ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr);
23233f2a96e3SMatthew G. Knepley     ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr);
23243f2a96e3SMatthew G. Knepley     ierr = VecGetArrayRead(coordsLocal, &coords);CHKERRQ(ierr);
23253f2a96e3SMatthew G. Knepley     ierr = DMPlexPointLocalRead(cdm, cone[0], coords, &cA);CHKERRQ(ierr);
23263f2a96e3SMatthew G. Knepley     ierr = DMPlexPointLocalRead(cdm, cone[1], coords, &cB);CHKERRQ(ierr);
23273f2a96e3SMatthew G. Knepley     sbr->edgeLen[off] = DMPlex_DistD_Internal(cdim, cA, cB);
23283f2a96e3SMatthew G. Knepley     ierr = VecRestoreArrayRead(coordsLocal, &coords);CHKERRQ(ierr);
23293f2a96e3SMatthew G. Knepley   }
23303f2a96e3SMatthew G. Knepley   *len = sbr->edgeLen[off];
23313f2a96e3SMatthew G. Knepley   PetscFunctionReturn(0);
23323f2a96e3SMatthew G. Knepley }
23333f2a96e3SMatthew G. Knepley 
23343f2a96e3SMatthew G. Knepley /* Mark local edges that should be split */
23353f2a96e3SMatthew G. Knepley /* TODO This will not work in 3D */
23363f2a96e3SMatthew G. Knepley static PetscErrorCode SBRSplitLocalEdges_Private(DMPlexCellRefiner cr, PointQueue queue)
23373f2a96e3SMatthew G. Knepley {
23383f2a96e3SMatthew G. Knepley   PlexRefiner_SBR *sbr = (PlexRefiner_SBR *) cr->data;
23393f2a96e3SMatthew G. Knepley   DM               dm  = cr->dm;
23403f2a96e3SMatthew G. Knepley   PetscErrorCode   ierr;
23413f2a96e3SMatthew G. Knepley 
23423f2a96e3SMatthew G. Knepley   PetscFunctionBegin;
23433f2a96e3SMatthew G. Knepley   while (!PointQueueEmpty(queue)) {
23443f2a96e3SMatthew G. Knepley     PetscInt        p = -1;
23453f2a96e3SMatthew G. Knepley     const PetscInt *support;
23463f2a96e3SMatthew G. Knepley     PetscInt        supportSize, s;
23473f2a96e3SMatthew G. Knepley 
23483f2a96e3SMatthew G. Knepley     ierr = PointQueueDequeue(queue, &p);CHKERRQ(ierr);
23493f2a96e3SMatthew G. Knepley     ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr);
23503f2a96e3SMatthew G. Knepley     ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr);
23513f2a96e3SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
23523f2a96e3SMatthew G. Knepley       const PetscInt  cell = support[s];
23533f2a96e3SMatthew G. Knepley       const PetscInt *cone;
23543f2a96e3SMatthew G. Knepley       PetscInt        coneSize, c;
23553f2a96e3SMatthew G. Knepley       PetscInt        cval, eval, maxedge;
23563f2a96e3SMatthew G. Knepley       PetscReal       len, maxlen;
23573f2a96e3SMatthew G. Knepley 
23583f2a96e3SMatthew G. Knepley       ierr = DMLabelGetValue(sbr->splitPoints, cell, &cval);CHKERRQ(ierr);
23593f2a96e3SMatthew G. Knepley       if (cval == 2) continue;
23603f2a96e3SMatthew G. Knepley       ierr = DMPlexGetCone(dm, cell, &cone);CHKERRQ(ierr);
23613f2a96e3SMatthew G. Knepley       ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr);
23623f2a96e3SMatthew G. Knepley       ierr = SBRGetEdgeLen_Private(cr, cone[0], &maxlen);CHKERRQ(ierr);
23633f2a96e3SMatthew G. Knepley       maxedge = cone[0];
23643f2a96e3SMatthew G. Knepley       for (c = 1; c < coneSize; ++c) {
23653f2a96e3SMatthew G. Knepley         ierr = SBRGetEdgeLen_Private(cr, cone[c], &len);CHKERRQ(ierr);
23663f2a96e3SMatthew G. Knepley         if (len > maxlen) {maxlen = len; maxedge = cone[c];}
23673f2a96e3SMatthew G. Knepley       }
23683f2a96e3SMatthew G. Knepley       ierr = DMLabelGetValue(sbr->splitPoints, maxedge, &eval);CHKERRQ(ierr);
23693f2a96e3SMatthew G. Knepley       if (eval != 1) {
23703f2a96e3SMatthew G. Knepley         ierr = DMLabelSetValue(sbr->splitPoints, maxedge, 1);CHKERRQ(ierr);
23713f2a96e3SMatthew G. Knepley         ierr = PointQueueEnqueue(queue, maxedge);CHKERRQ(ierr);
23723f2a96e3SMatthew G. Knepley       }
23733f2a96e3SMatthew G. Knepley       ierr = DMLabelSetValue(sbr->splitPoints, cell, 2);CHKERRQ(ierr);
23743f2a96e3SMatthew G. Knepley     }
23753f2a96e3SMatthew G. Knepley   }
23763f2a96e3SMatthew G. Knepley   PetscFunctionReturn(0);
23773f2a96e3SMatthew G. Knepley }
23783f2a96e3SMatthew G. Knepley 
23793f2a96e3SMatthew G. Knepley static PetscErrorCode SBRInitializeComm(DMPlexCellRefiner cr, PetscSF pointSF)
23803f2a96e3SMatthew G. Knepley {
23813f2a96e3SMatthew G. Knepley   PlexRefiner_SBR *sbr = (PlexRefiner_SBR *) cr->data;
23823f2a96e3SMatthew G. Knepley   DMLabel          splitPoints = sbr->splitPoints;
23833f2a96e3SMatthew G. Knepley   PetscInt        *splitArray  = sbr->splitArray;
23843f2a96e3SMatthew G. Knepley   const PetscInt  *degree;
23853f2a96e3SMatthew G. Knepley   const PetscInt  *points;
23863f2a96e3SMatthew G. Knepley   PetscInt         Nl, l, pStart, pEnd, p, val;
23873f2a96e3SMatthew G. Knepley   PetscErrorCode   ierr;
23883f2a96e3SMatthew G. Knepley 
23893f2a96e3SMatthew G. Knepley   PetscFunctionBegin;
23903f2a96e3SMatthew G. Knepley   /* Add in leaves */
23913f2a96e3SMatthew G. Knepley   ierr = PetscSFGetGraph(pointSF, NULL, &Nl, &points, NULL);CHKERRQ(ierr);
23923f2a96e3SMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
23933f2a96e3SMatthew G. Knepley     ierr = DMLabelGetValue(splitPoints, points[l], &val);CHKERRQ(ierr);
23943f2a96e3SMatthew G. Knepley     if (val > 0) splitArray[points[l]] = val;
23953f2a96e3SMatthew G. Knepley   }
23963f2a96e3SMatthew G. Knepley   /* Add in shared roots */
23973f2a96e3SMatthew G. Knepley   ierr = PetscSFComputeDegreeBegin(pointSF, &degree);CHKERRQ(ierr);
23983f2a96e3SMatthew G. Knepley   ierr = PetscSFComputeDegreeEnd(pointSF, &degree);CHKERRQ(ierr);
23993f2a96e3SMatthew G. Knepley   ierr = DMPlexGetChart(cr->dm, &pStart, &pEnd);CHKERRQ(ierr);
24003f2a96e3SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
24013f2a96e3SMatthew G. Knepley     if (degree[p]) {
24023f2a96e3SMatthew G. Knepley       ierr = DMLabelGetValue(splitPoints, p, &val);CHKERRQ(ierr);
24033f2a96e3SMatthew G. Knepley       if (val > 0) splitArray[p] = val;
24043f2a96e3SMatthew G. Knepley     }
24053f2a96e3SMatthew G. Knepley   }
24063f2a96e3SMatthew G. Knepley   PetscFunctionReturn(0);
24073f2a96e3SMatthew G. Knepley }
24083f2a96e3SMatthew G. Knepley 
24093f2a96e3SMatthew G. Knepley static PetscErrorCode SBRFinalizeComm(DMPlexCellRefiner cr, PetscSF pointSF, PointQueue queue)
24103f2a96e3SMatthew G. Knepley {
24113f2a96e3SMatthew G. Knepley   PlexRefiner_SBR *sbr = (PlexRefiner_SBR *) cr->data;
24123f2a96e3SMatthew G. Knepley   DMLabel          splitPoints = sbr->splitPoints;
24133f2a96e3SMatthew G. Knepley   PetscInt        *splitArray  = sbr->splitArray;
24143f2a96e3SMatthew G. Knepley   const PetscInt  *degree;
24153f2a96e3SMatthew G. Knepley   const PetscInt  *points;
24163f2a96e3SMatthew G. Knepley   PetscInt         Nl, l, pStart, pEnd, p, val;
24173f2a96e3SMatthew G. Knepley   PetscErrorCode   ierr;
24183f2a96e3SMatthew G. Knepley 
24193f2a96e3SMatthew G. Knepley   PetscFunctionBegin;
24203f2a96e3SMatthew G. Knepley   /* Read out leaves */
24213f2a96e3SMatthew G. Knepley   ierr = PetscSFGetGraph(pointSF, NULL, &Nl, &points, NULL);CHKERRQ(ierr);
24223f2a96e3SMatthew G. Knepley   for (l = 0; l < Nl; ++l) {
24233f2a96e3SMatthew G. Knepley     const PetscInt p    = points[l];
24243f2a96e3SMatthew G. Knepley     const PetscInt cval = splitArray[p];
24253f2a96e3SMatthew G. Knepley 
24263f2a96e3SMatthew G. Knepley     if (cval) {
24273f2a96e3SMatthew G. Knepley       ierr = DMLabelGetValue(splitPoints, p, &val);CHKERRQ(ierr);
24283f2a96e3SMatthew G. Knepley       if (val <= 0) {
24293f2a96e3SMatthew G. Knepley         ierr = DMLabelSetValue(splitPoints, p, cval);CHKERRQ(ierr);
24303f2a96e3SMatthew G. Knepley         ierr = PointQueueEnqueue(queue, p);CHKERRQ(ierr);
24313f2a96e3SMatthew G. Knepley       }
24323f2a96e3SMatthew G. Knepley     }
24333f2a96e3SMatthew G. Knepley   }
24343f2a96e3SMatthew G. Knepley   /* Read out shared roots */
24353f2a96e3SMatthew G. Knepley   ierr = PetscSFComputeDegreeBegin(pointSF, &degree);CHKERRQ(ierr);
24363f2a96e3SMatthew G. Knepley   ierr = PetscSFComputeDegreeEnd(pointSF, &degree);CHKERRQ(ierr);
24373f2a96e3SMatthew G. Knepley   ierr = DMPlexGetChart(cr->dm, &pStart, &pEnd);CHKERRQ(ierr);
24383f2a96e3SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
24393f2a96e3SMatthew G. Knepley     if (degree[p]) {
24403f2a96e3SMatthew G. Knepley       const PetscInt cval = splitArray[p];
24413f2a96e3SMatthew G. Knepley 
24423f2a96e3SMatthew G. Knepley       if (cval) {
24433f2a96e3SMatthew G. Knepley         ierr = DMLabelGetValue(splitPoints, p, &val);CHKERRQ(ierr);
24443f2a96e3SMatthew G. Knepley         if (val <= 0) {
24453f2a96e3SMatthew G. Knepley           ierr = DMLabelSetValue(splitPoints, p, cval);CHKERRQ(ierr);
24463f2a96e3SMatthew G. Knepley           ierr = PointQueueEnqueue(queue, p);CHKERRQ(ierr);
24473f2a96e3SMatthew G. Knepley         }
24483f2a96e3SMatthew G. Knepley       }
24493f2a96e3SMatthew G. Knepley     }
24503f2a96e3SMatthew G. Knepley   }
24513f2a96e3SMatthew G. Knepley   PetscFunctionReturn(0);
24523f2a96e3SMatthew G. Knepley }
24533f2a96e3SMatthew G. Knepley 
24543f2a96e3SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerSetUp_SBR(DMPlexCellRefiner cr)
24553f2a96e3SMatthew G. Knepley {
24563f2a96e3SMatthew G. Knepley   PlexRefiner_SBR *sbr;
24573f2a96e3SMatthew G. Knepley   PetscSF          pointSF;
24583f2a96e3SMatthew G. Knepley   PointQueue       queue = NULL;
24593f2a96e3SMatthew G. Knepley   IS               refineIS;
24603f2a96e3SMatthew G. Knepley   const PetscInt  *refineCells;
24613f2a96e3SMatthew G. Knepley   PetscMPIInt      size;
24623f2a96e3SMatthew G. Knepley   PetscInt         pStart, pEnd, p, eStart, eEnd, e, edgeLenSize, Nc, c;
24633f2a96e3SMatthew G. Knepley   PetscBool        empty;
24643f2a96e3SMatthew G. Knepley   PetscErrorCode   ierr;
24653f2a96e3SMatthew G. Knepley 
24663f2a96e3SMatthew G. Knepley   PetscFunctionBegin;
24673f2a96e3SMatthew G. Knepley   ierr = PetscCitationsRegister(SBRCitation, &SBRcite);CHKERRQ(ierr);
24683f2a96e3SMatthew G. Knepley   ierr = PetscNew(&sbr);CHKERRQ(ierr);
24693f2a96e3SMatthew G. Knepley   cr->data = sbr;
24703f2a96e3SMatthew G. Knepley   ierr = DMLabelCreate(PETSC_COMM_SELF, "Split Points", &sbr->splitPoints);CHKERRQ(ierr);
24713f2a96e3SMatthew G. Knepley   /* Create edge lengths */
24723f2a96e3SMatthew G. Knepley   ierr = DMPlexGetDepthStratum(cr->dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
24733f2a96e3SMatthew G. Knepley   ierr = PetscSectionCreate(PETSC_COMM_SELF, &sbr->secEdgeLen);CHKERRQ(ierr);
24743f2a96e3SMatthew G. Knepley   ierr = PetscSectionSetChart(sbr->secEdgeLen, eStart, eEnd);CHKERRQ(ierr);
24753f2a96e3SMatthew G. Knepley   for (e = eStart; e < eEnd; ++e) {
24763f2a96e3SMatthew G. Knepley     ierr = PetscSectionSetDof(sbr->secEdgeLen, e, 1);CHKERRQ(ierr);
24773f2a96e3SMatthew G. Knepley   }
24783f2a96e3SMatthew G. Knepley   ierr = PetscSectionSetUp(sbr->secEdgeLen);CHKERRQ(ierr);
24793f2a96e3SMatthew G. Knepley   ierr = PetscSectionGetStorageSize(sbr->secEdgeLen, &edgeLenSize);CHKERRQ(ierr);
24803f2a96e3SMatthew G. Knepley   ierr = PetscCalloc1(edgeLenSize, &sbr->edgeLen);CHKERRQ(ierr);
24813f2a96e3SMatthew G. Knepley   /* Add edges of cells that are marked for refinement to edge queue */
24823f2a96e3SMatthew G. Knepley   if (!cr->adaptLabel) SETERRQ(PetscObjectComm((PetscObject) cr), PETSC_ERR_ARG_WRONGSTATE, "CellRefiner must have an adaptation label in order to use SBR algorithm");
24833f2a96e3SMatthew G. Knepley   ierr = PointQueueCreate(1024, &queue);CHKERRQ(ierr);
24843f2a96e3SMatthew G. Knepley   ierr = DMLabelGetStratumIS(cr->adaptLabel, DM_ADAPT_REFINE, &refineIS);CHKERRQ(ierr);
24853f2a96e3SMatthew G. Knepley   ierr = DMLabelGetStratumSize(cr->adaptLabel, DM_ADAPT_REFINE, &Nc);CHKERRQ(ierr);
24863f2a96e3SMatthew G. Knepley   if (refineIS) {ierr = ISGetIndices(refineIS, &refineCells);CHKERRQ(ierr);}
24873f2a96e3SMatthew G. Knepley   for (c = 0; c < Nc; ++c) {
24883f2a96e3SMatthew G. Knepley     PetscInt *closure = NULL;
24893f2a96e3SMatthew G. Knepley     PetscInt  Ncl, cl;
24903f2a96e3SMatthew G. Knepley 
24913f2a96e3SMatthew G. Knepley     ierr = DMLabelSetValue(sbr->splitPoints, refineCells[c], 2);CHKERRQ(ierr);
24923f2a96e3SMatthew G. Knepley     ierr = DMPlexGetTransitiveClosure(cr->dm, refineCells[c], PETSC_TRUE, &Ncl, &closure);CHKERRQ(ierr);
24933f2a96e3SMatthew G. Knepley     for (cl = 0; cl < Ncl; cl += 2) {
24943f2a96e3SMatthew G. Knepley       const PetscInt edge = closure[cl];
24953f2a96e3SMatthew G. Knepley 
24963f2a96e3SMatthew G. Knepley       if (edge >= eStart && edge < eEnd) {
24973f2a96e3SMatthew G. Knepley         ierr = DMLabelSetValue(sbr->splitPoints, edge, 1);CHKERRQ(ierr);
24983f2a96e3SMatthew G. Knepley         ierr = PointQueueEnqueue(queue, edge);CHKERRQ(ierr);
24993f2a96e3SMatthew G. Knepley       }
25003f2a96e3SMatthew G. Knepley     }
25013f2a96e3SMatthew G. Knepley     ierr = DMPlexRestoreTransitiveClosure(cr->dm, refineCells[c], PETSC_TRUE, &Ncl, &closure);CHKERRQ(ierr);
25023f2a96e3SMatthew G. Knepley   }
25033f2a96e3SMatthew G. Knepley   if (refineIS) {ierr = ISRestoreIndices(refineIS, &refineCells);CHKERRQ(ierr);}
25043f2a96e3SMatthew G. Knepley   ierr = ISDestroy(&refineIS);CHKERRQ(ierr);
25053f2a96e3SMatthew G. Knepley   /* Setup communication */
25063f2a96e3SMatthew G. Knepley   ierr = MPI_Comm_size(PetscObjectComm((PetscObject) cr->dm), &size);CHKERRQ(ierr);
25073f2a96e3SMatthew G. Knepley   ierr = DMGetPointSF(cr->dm, &pointSF);CHKERRQ(ierr);
25083f2a96e3SMatthew G. Knepley   if (size > 1) {
25093f2a96e3SMatthew G. Knepley     PetscInt pStart, pEnd;
25103f2a96e3SMatthew G. Knepley 
25113f2a96e3SMatthew G. Knepley     ierr = DMPlexGetChart(cr->dm, &pStart, &pEnd);CHKERRQ(ierr);
25123f2a96e3SMatthew G. Knepley     ierr = PetscCalloc1(pEnd-pStart, &sbr->splitArray);CHKERRQ(ierr);
25133f2a96e3SMatthew G. Knepley   }
25143f2a96e3SMatthew G. Knepley   /* While edge queue is not empty: */
25153f2a96e3SMatthew G. Knepley   empty = PointQueueEmpty(queue);
25163f2a96e3SMatthew G. Knepley   ierr = MPI_Allreduce(MPI_IN_PLACE, &empty, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject) cr->dm));CHKERRQ(ierr);
25173f2a96e3SMatthew G. Knepley   while (!empty) {
25183f2a96e3SMatthew G. Knepley     ierr = SBRSplitLocalEdges_Private(cr, queue);CHKERRQ(ierr);
25193f2a96e3SMatthew G. Knepley     /* Communicate marked edges
25203f2a96e3SMatthew G. Knepley          An easy implementation is to allocate an array the size of the number of points. We put the splitPoints marks into the
25213f2a96e3SMatthew G. Knepley          array, and then call PetscSFReduce()+PetscSFBcast() to make the marks consistent.
25223f2a96e3SMatthew G. Knepley 
25233f2a96e3SMatthew G. Knepley          TODO: We could use in-place communication with a different SF
25243f2a96e3SMatthew G. Knepley            We use MPI_SUM for the Reduce, and check the result against the rootdegree. If sum >= rootdegree+1, then the edge has
25253f2a96e3SMatthew G. Knepley            already been marked. If not, it might have been handled on the process in this round, but we add it anyway.
25263f2a96e3SMatthew G. Knepley 
25273f2a96e3SMatthew G. Knepley            In order to update the queue with the new edges from the label communication, we use BcastAnOp(MPI_SUM), so that new
25283f2a96e3SMatthew G. Knepley            values will have 1+0=1 and old values will have 1+1=2. Loop over these, resetting the values to 1, and adding any new
25293f2a96e3SMatthew G. Knepley            edge to the queue.
25303f2a96e3SMatthew G. Knepley     */
25313f2a96e3SMatthew G. Knepley     if (size > 1) {
25323f2a96e3SMatthew G. Knepley       ierr = SBRInitializeComm(cr, pointSF);CHKERRQ(ierr);
25333f2a96e3SMatthew G. Knepley       ierr = PetscSFReduceBegin(pointSF, MPIU_INT, sbr->splitArray, sbr->splitArray, MPI_MAX);CHKERRQ(ierr);
25343f2a96e3SMatthew G. Knepley       ierr = PetscSFReduceEnd(pointSF, MPIU_INT, sbr->splitArray, sbr->splitArray, MPI_MAX);CHKERRQ(ierr);
25353f2a96e3SMatthew G. Knepley       ierr = PetscSFBcastBegin(pointSF, MPIU_INT, sbr->splitArray, sbr->splitArray);CHKERRQ(ierr);
25363f2a96e3SMatthew G. Knepley       ierr = PetscSFBcastEnd(pointSF, MPIU_INT, sbr->splitArray, sbr->splitArray);CHKERRQ(ierr);
25373f2a96e3SMatthew G. Knepley       ierr = SBRFinalizeComm(cr, pointSF, queue);CHKERRQ(ierr);
25383f2a96e3SMatthew G. Knepley     }
25393f2a96e3SMatthew G. Knepley     empty = PointQueueEmpty(queue);
25403f2a96e3SMatthew G. Knepley     ierr = MPI_Allreduce(MPI_IN_PLACE, &empty, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject) cr->dm));CHKERRQ(ierr);
25413f2a96e3SMatthew G. Knepley   }
25423f2a96e3SMatthew G. Knepley   ierr = PetscFree(sbr->splitArray);CHKERRQ(ierr);
25433f2a96e3SMatthew G. Knepley   /* Calculate refineType for each cell */
25443f2a96e3SMatthew G. Knepley   ierr = DMLabelCreate(PETSC_COMM_SELF, "Refine Type", &cr->refineType);CHKERRQ(ierr);
25453f2a96e3SMatthew G. Knepley   ierr = DMPlexGetChart(cr->dm, &pStart, &pEnd);CHKERRQ(ierr);
25463f2a96e3SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
25473f2a96e3SMatthew G. Knepley     DMPolytopeType ct;
25483f2a96e3SMatthew G. Knepley     PetscInt       val;
25493f2a96e3SMatthew G. Knepley 
25503f2a96e3SMatthew G. Knepley     ierr = DMPlexGetCellType(cr->dm, p, &ct);CHKERRQ(ierr);
25513f2a96e3SMatthew G. Knepley     switch (ct) {
25523f2a96e3SMatthew G. Knepley       case DM_POLYTOPE_POINT:
25533f2a96e3SMatthew G. Knepley         ierr = DMLabelSetValue(cr->refineType, p, 0);CHKERRQ(ierr);break;
25543f2a96e3SMatthew G. Knepley       case DM_POLYTOPE_SEGMENT:
25553f2a96e3SMatthew G. Knepley         ierr = DMLabelGetValue(sbr->splitPoints, p, &val);CHKERRQ(ierr);
25563f2a96e3SMatthew G. Knepley         if (val == 1) {ierr = DMLabelSetValue(cr->refineType, p, 2);CHKERRQ(ierr);}
25573f2a96e3SMatthew G. Knepley         else          {ierr = DMLabelSetValue(cr->refineType, p, 1);CHKERRQ(ierr);}
25583f2a96e3SMatthew G. Knepley         break;
25593f2a96e3SMatthew G. Knepley       case DM_POLYTOPE_TRIANGLE:
25603f2a96e3SMatthew G. Knepley         ierr = DMLabelGetValue(sbr->splitPoints, p, &val);CHKERRQ(ierr);
25613f2a96e3SMatthew G. Knepley         if (val == 2) {
25623f2a96e3SMatthew G. Knepley           const PetscInt *cone;
25633f2a96e3SMatthew G. Knepley           PetscReal       lens[3];
25643f2a96e3SMatthew G. Knepley           PetscInt        vals[3], i;
25653f2a96e3SMatthew G. Knepley 
25663f2a96e3SMatthew G. Knepley           ierr = DMPlexGetCone(cr->dm, p, &cone);CHKERRQ(ierr);
25673f2a96e3SMatthew G. Knepley           for (i = 0; i < 3; ++i) {
25683f2a96e3SMatthew G. Knepley             ierr = DMLabelGetValue(sbr->splitPoints, cone[i], &vals[i]);CHKERRQ(ierr);
25693f2a96e3SMatthew G. Knepley             vals[i] = vals[i] < 0 ? 0 : vals[i];
25703f2a96e3SMatthew G. Knepley             ierr = SBRGetEdgeLen_Private(cr, cone[i], &lens[i]);CHKERRQ(ierr);
25713f2a96e3SMatthew G. Knepley           }
25723f2a96e3SMatthew G. Knepley           if (vals[0] && vals[1] && vals[2]) {ierr = DMLabelSetValue(cr->refineType, p, 4);CHKERRQ(ierr);}
25733f2a96e3SMatthew G. Knepley           else if (vals[0] && vals[1])       {ierr = DMLabelSetValue(cr->refineType, p, lens[0] > lens[1] ? 5 : 6);CHKERRQ(ierr);}
25743f2a96e3SMatthew G. Knepley           else if (vals[1] && vals[2])       {ierr = DMLabelSetValue(cr->refineType, p, lens[1] > lens[2] ? 7 : 8);CHKERRQ(ierr);}
25753f2a96e3SMatthew G. Knepley           else if (vals[2] && vals[0])       {ierr = DMLabelSetValue(cr->refineType, p, lens[2] > lens[0] ? 9: 10);CHKERRQ(ierr);}
25763f2a96e3SMatthew G. Knepley           else if (vals[0])                  {ierr = DMLabelSetValue(cr->refineType, p, 11);CHKERRQ(ierr);}
25773f2a96e3SMatthew G. Knepley           else if (vals[1])                  {ierr = DMLabelSetValue(cr->refineType, p, 12);CHKERRQ(ierr);}
25783f2a96e3SMatthew G. Knepley           else if (vals[2])                  {ierr = DMLabelSetValue(cr->refineType, p, 13);CHKERRQ(ierr);}
25793f2a96e3SMatthew G. Knepley           else SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Cell %D does not fit any refinement type (%D, %D, %D)", p, vals[0], vals[1], vals[2]);
25803f2a96e3SMatthew G. Knepley         } else {ierr = DMLabelSetValue(cr->refineType, p, 3);CHKERRQ(ierr);}
25813f2a96e3SMatthew G. Knepley         break;
25823f2a96e3SMatthew G. Knepley       default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot handle points of type %s", DMPolytopeTypes[ct]);
25833f2a96e3SMatthew G. Knepley     }
25843f2a96e3SMatthew G. Knepley     ierr = DMLabelGetValue(sbr->splitPoints, p, &val);CHKERRQ(ierr);
25853f2a96e3SMatthew G. Knepley   }
25863f2a96e3SMatthew G. Knepley   /* Cleanup */
25873f2a96e3SMatthew G. Knepley   ierr = PointQueueDestroy(&queue);CHKERRQ(ierr);
25883f2a96e3SMatthew G. Knepley   PetscFunctionReturn(0);
25893f2a96e3SMatthew G. Knepley }
25903f2a96e3SMatthew G. Knepley 
25913f2a96e3SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerDestroy_SBR(DMPlexCellRefiner cr)
25923f2a96e3SMatthew G. Knepley {
25933f2a96e3SMatthew G. Knepley   PlexRefiner_SBR *sbr = (PlexRefiner_SBR *) cr->data;
25943f2a96e3SMatthew G. Knepley   PetscErrorCode   ierr;
25953f2a96e3SMatthew G. Knepley 
25963f2a96e3SMatthew G. Knepley   PetscFunctionBegin;
25973f2a96e3SMatthew G. Knepley   ierr = PetscFree(sbr->edgeLen);CHKERRQ(ierr);
25983f2a96e3SMatthew G. Knepley   ierr = PetscSectionDestroy(&sbr->secEdgeLen);CHKERRQ(ierr);
25993f2a96e3SMatthew G. Knepley   ierr = DMLabelDestroy(&sbr->splitPoints);CHKERRQ(ierr);
26003f2a96e3SMatthew G. Knepley   ierr = PetscFree(cr->data);CHKERRQ(ierr);
26013f2a96e3SMatthew G. Knepley   PetscFunctionReturn(0);
26023f2a96e3SMatthew G. Knepley }
26033f2a96e3SMatthew G. Knepley 
26043f2a96e3SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerRefine_SBR(DMPlexCellRefiner cr, DMPolytopeType source, PetscInt p, PetscInt *rt, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[])
26053f2a96e3SMatthew G. Knepley {
26063f2a96e3SMatthew G. Knepley   /* Add 1 edge inside this triangle, making 2 new triangles.
26073f2a96e3SMatthew G. Knepley    2
26083f2a96e3SMatthew G. Knepley    |\
26093f2a96e3SMatthew G. Knepley    | \
26103f2a96e3SMatthew G. Knepley    |  \
26113f2a96e3SMatthew G. Knepley    |   \
26123f2a96e3SMatthew G. Knepley    |    1
26133f2a96e3SMatthew G. Knepley    |     \
26143f2a96e3SMatthew G. Knepley    |  B   \
26153f2a96e3SMatthew G. Knepley    2       1
26163f2a96e3SMatthew G. Knepley    |      / \
26173f2a96e3SMatthew G. Knepley    | ____/   0
26183f2a96e3SMatthew G. Knepley    |/    A    \
26193f2a96e3SMatthew G. Knepley    0-----0-----1
26203f2a96e3SMatthew G. Knepley   */
26213f2a96e3SMatthew G. Knepley   static DMPolytopeType triT10[]  = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_TRIANGLE};
26223f2a96e3SMatthew G. Knepley   static PetscInt       triS10[]  = {1, 2};
26233f2a96e3SMatthew G. Knepley   static PetscInt       triC10[]  = {DM_POLYTOPE_POINT, 2, 0, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
26243f2a96e3SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0,    0,
26253f2a96e3SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0,    0};
26263f2a96e3SMatthew G. Knepley   static PetscInt       triO10[]  = {0, 0,
26273f2a96e3SMatthew G. Knepley                                      0,  0, -2,
26283f2a96e3SMatthew G. Knepley                                      0,  0,  0};
26293f2a96e3SMatthew G. Knepley   /* Add 1 edge inside this triangle, making 2 new triangles.
26303f2a96e3SMatthew G. Knepley    2
26313f2a96e3SMatthew G. Knepley    |\
26323f2a96e3SMatthew G. Knepley    | \
26333f2a96e3SMatthew G. Knepley    |  \
26343f2a96e3SMatthew G. Knepley    0   \
26353f2a96e3SMatthew G. Knepley    |    \
26363f2a96e3SMatthew G. Knepley    |     \
26373f2a96e3SMatthew G. Knepley    |      \
26383f2a96e3SMatthew G. Knepley    2   A   1
26393f2a96e3SMatthew G. Knepley    |\       \
26403f2a96e3SMatthew G. Knepley    1 ---\    \
26413f2a96e3SMatthew G. Knepley    |  B  ----\\
26423f2a96e3SMatthew G. Knepley    0-----0-----1
26433f2a96e3SMatthew G. Knepley   */
26443f2a96e3SMatthew G. Knepley   static PetscInt       triC11[]  = {DM_POLYTOPE_POINT, 2, 1, 0, 0, DM_POLYTOPE_POINT, 1, 2, 0,
26453f2a96e3SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0,    0,
26463f2a96e3SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0,    0};
26473f2a96e3SMatthew G. Knepley   static PetscInt       triO11[]  = {0, 0,
26483f2a96e3SMatthew G. Knepley                                      0,  0, -2,
26493f2a96e3SMatthew G. Knepley                                      0,  0,  0};
26503f2a96e3SMatthew G. Knepley   /* Add 1 edge inside this triangle, making 2 new triangles.
26513f2a96e3SMatthew G. Knepley    2
26523f2a96e3SMatthew G. Knepley    |\
26533f2a96e3SMatthew G. Knepley    |\\
26543f2a96e3SMatthew G. Knepley    || \
26553f2a96e3SMatthew G. Knepley    | \ \
26563f2a96e3SMatthew G. Knepley    |  | \
26573f2a96e3SMatthew G. Knepley    |  |  \
26583f2a96e3SMatthew G. Knepley    |  |   \
26593f2a96e3SMatthew G. Knepley    2   \   1
26603f2a96e3SMatthew G. Knepley    |  A |   \
26613f2a96e3SMatthew G. Knepley    |    |  B \
26623f2a96e3SMatthew G. Knepley    |     \    \
26633f2a96e3SMatthew G. Knepley    0-----0-----1
26643f2a96e3SMatthew G. Knepley   */
26653f2a96e3SMatthew G. Knepley   static PetscInt       triC12[]  = {DM_POLYTOPE_POINT, 2, 2, 0, 0, DM_POLYTOPE_POINT, 1, 0, 0,
26663f2a96e3SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0,    0,
26673f2a96e3SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0,    0};
26683f2a96e3SMatthew G. Knepley   static PetscInt       triO12[]  = {0, 0,
26693f2a96e3SMatthew G. Knepley                                      0,  0, -2,
26703f2a96e3SMatthew G. Knepley                                      0,  0,  0};
26713f2a96e3SMatthew G. Knepley   /* Add 2 edges inside this triangle, making 3 new triangles.
26723f2a96e3SMatthew G. Knepley    2
26733f2a96e3SMatthew G. Knepley    |\
26743f2a96e3SMatthew G. Knepley    | \
26753f2a96e3SMatthew G. Knepley    |  \
26763f2a96e3SMatthew G. Knepley    0   \
26773f2a96e3SMatthew G. Knepley    |    1
26783f2a96e3SMatthew G. Knepley    |     \
26793f2a96e3SMatthew G. Knepley    |  B   \
26803f2a96e3SMatthew G. Knepley    2-------1
26813f2a96e3SMatthew G. Knepley    |   C  / \
26823f2a96e3SMatthew G. Knepley    1 ____/   0
26833f2a96e3SMatthew G. Knepley    |/    A    \
26843f2a96e3SMatthew G. Knepley    0-----0-----1
26853f2a96e3SMatthew G. Knepley   */
26863f2a96e3SMatthew G. Knepley   static DMPolytopeType triT20[]  = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_TRIANGLE};
26873f2a96e3SMatthew G. Knepley   static PetscInt       triS20[]  = {2, 3};
26883f2a96e3SMatthew G. Knepley   static PetscInt       triC20[]  = {DM_POLYTOPE_POINT, 2, 0, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
26893f2a96e3SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 1, 2, 0,
26903f2a96e3SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0,    0,
26913f2a96e3SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0,    1,
26923f2a96e3SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    1};
26933f2a96e3SMatthew G. Knepley   static PetscInt       triO20[]  = {0, 0,
26943f2a96e3SMatthew G. Knepley                                      0, 0,
26953f2a96e3SMatthew G. Knepley                                      0,  0, -2,
26963f2a96e3SMatthew G. Knepley                                      0,  0, -2,
26973f2a96e3SMatthew G. Knepley                                      0,  0,  0};
26983f2a96e3SMatthew G. Knepley   /* Add 1 edge inside this triangle, making 2 new triangles.
26993f2a96e3SMatthew G. Knepley    2
27003f2a96e3SMatthew G. Knepley    |\
27013f2a96e3SMatthew G. Knepley    | \
27023f2a96e3SMatthew G. Knepley    |  \
27033f2a96e3SMatthew G. Knepley    0   \
27043f2a96e3SMatthew G. Knepley    |    1
27053f2a96e3SMatthew G. Knepley    |     \
27063f2a96e3SMatthew G. Knepley    |  B   \
27073f2a96e3SMatthew G. Knepley    2       1
27083f2a96e3SMatthew G. Knepley    |      /|\
27093f2a96e3SMatthew G. Knepley    1 ____/ / 0
27103f2a96e3SMatthew G. Knepley    |/ A   / C \
27113f2a96e3SMatthew G. Knepley    0-----0-----1
27123f2a96e3SMatthew G. Knepley   */
27133f2a96e3SMatthew G. Knepley   static PetscInt       triC21[]  = {DM_POLYTOPE_POINT, 2, 0, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
27143f2a96e3SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 1, 0, 0,
27153f2a96e3SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,    0,
27163f2a96e3SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0,    0,
27173f2a96e3SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0,    1};
27183f2a96e3SMatthew G. Knepley   static PetscInt       triO21[]  = {0, 0,
27193f2a96e3SMatthew G. Knepley                                      0, 0,
27203f2a96e3SMatthew G. Knepley                                      0, -2, -2,
27213f2a96e3SMatthew G. Knepley                                      0,  0,  0,
27223f2a96e3SMatthew G. Knepley                                      0,  0,  0};
27233f2a96e3SMatthew G. Knepley   /* Add 2 edges inside this triangle, making 3 new triangles.
27243f2a96e3SMatthew G. Knepley    2
27253f2a96e3SMatthew G. Knepley    |\
27263f2a96e3SMatthew G. Knepley    | \
27273f2a96e3SMatthew G. Knepley    |  \
27283f2a96e3SMatthew G. Knepley    0   \
27293f2a96e3SMatthew G. Knepley    |    \
27303f2a96e3SMatthew G. Knepley    |     \
27313f2a96e3SMatthew G. Knepley    |      \
27323f2a96e3SMatthew G. Knepley    2   A   1
27333f2a96e3SMatthew G. Knepley    |\       \
27343f2a96e3SMatthew G. Knepley    1 ---\    \
27353f2a96e3SMatthew G. Knepley    |B \_C----\\
27363f2a96e3SMatthew G. Knepley    0-----0-----1
27373f2a96e3SMatthew G. Knepley   */
27383f2a96e3SMatthew G. Knepley   static PetscInt       triC22[]  = {DM_POLYTOPE_POINT, 2, 1, 0, 0, DM_POLYTOPE_POINT, 1, 2, 0,
27393f2a96e3SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 1, 0, 0,
27403f2a96e3SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0,    0,
27413f2a96e3SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0,    1,
27423f2a96e3SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    1};
27433f2a96e3SMatthew G. Knepley   static PetscInt       triO22[]  = {0, 0,
27443f2a96e3SMatthew G. Knepley                                      0, 0,
27453f2a96e3SMatthew G. Knepley                                      0,  0, -2,
27463f2a96e3SMatthew G. Knepley                                      0,  0, -2,
27473f2a96e3SMatthew G. Knepley                                      0,  0,  0};
27483f2a96e3SMatthew G. Knepley   /* Add 1 edge inside this triangle, making 2 new triangles.
27493f2a96e3SMatthew G. Knepley    2
27503f2a96e3SMatthew G. Knepley    |\
27513f2a96e3SMatthew G. Knepley    | \
27523f2a96e3SMatthew G. Knepley    |  \
27533f2a96e3SMatthew G. Knepley    0   \
27543f2a96e3SMatthew G. Knepley    |    \
27553f2a96e3SMatthew G. Knepley    |  C  \
27563f2a96e3SMatthew G. Knepley    |      \
27573f2a96e3SMatthew G. Knepley    2-------1
27583f2a96e3SMatthew G. Knepley    |\     A \
27593f2a96e3SMatthew G. Knepley    1 ---\    \
27603f2a96e3SMatthew G. Knepley    |  B  ----\\
27613f2a96e3SMatthew G. Knepley    0-----0-----1
27623f2a96e3SMatthew G. Knepley   */
27633f2a96e3SMatthew G. Knepley   static PetscInt       triC23[]  = {DM_POLYTOPE_POINT, 2, 1, 0, 0, DM_POLYTOPE_POINT, 1, 2, 0,
27643f2a96e3SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 1, 1, 0,
27653f2a96e3SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,    0,
27663f2a96e3SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0,    0,
27673f2a96e3SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0,    1};
27683f2a96e3SMatthew G. Knepley   static PetscInt       triO23[]  = {0, 0,
27693f2a96e3SMatthew G. Knepley                                      0, 0,
27703f2a96e3SMatthew G. Knepley                                      0, -2, -2,
27713f2a96e3SMatthew G. Knepley                                      0,  0,  0,
27723f2a96e3SMatthew G. Knepley                                      0,  0,  0};
27733f2a96e3SMatthew G. Knepley   /* Add 2 edges inside this triangle, making 3 new triangles.
27743f2a96e3SMatthew G. Knepley    2
27753f2a96e3SMatthew G. Knepley    |\
27763f2a96e3SMatthew G. Knepley    |\\
27773f2a96e3SMatthew G. Knepley    || \
27783f2a96e3SMatthew G. Knepley    | \ \
27793f2a96e3SMatthew G. Knepley    |  | \
27803f2a96e3SMatthew G. Knepley    |  |  \
27813f2a96e3SMatthew G. Knepley    |  |   \
27823f2a96e3SMatthew G. Knepley    2   \ C 1
27833f2a96e3SMatthew G. Knepley    |  A | / \
27843f2a96e3SMatthew G. Knepley    |    | |B \
27853f2a96e3SMatthew G. Knepley    |     \/   \
27863f2a96e3SMatthew G. Knepley    0-----0-----1
27873f2a96e3SMatthew G. Knepley   */
27883f2a96e3SMatthew G. Knepley   static PetscInt       triC24[]  = {DM_POLYTOPE_POINT, 2, 2, 0, 0, DM_POLYTOPE_POINT, 1, 0, 0,
27893f2a96e3SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
27903f2a96e3SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0,    0,
27913f2a96e3SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0,    1,
27923f2a96e3SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    1};
27933f2a96e3SMatthew G. Knepley   static PetscInt       triO24[]  = {0, 0,
27943f2a96e3SMatthew G. Knepley                                      0, 0,
27953f2a96e3SMatthew G. Knepley                                      0,  0, -2,
27963f2a96e3SMatthew G. Knepley                                      0,  0, -2,
27973f2a96e3SMatthew G. Knepley                                      0,  0,  0};
27983f2a96e3SMatthew G. Knepley   /* Add 1 edge inside this triangle, making 2 new triangles.
27993f2a96e3SMatthew G. Knepley    2
28003f2a96e3SMatthew G. Knepley    |\
28013f2a96e3SMatthew G. Knepley    |\\
28023f2a96e3SMatthew G. Knepley    || \
28033f2a96e3SMatthew G. Knepley    | \ \
28043f2a96e3SMatthew G. Knepley    |  | \
28053f2a96e3SMatthew G. Knepley    |  |  \
28063f2a96e3SMatthew G. Knepley    |  |   \
28073f2a96e3SMatthew G. Knepley    2 A \   1
28083f2a96e3SMatthew G. Knepley    |\   |   \
28093f2a96e3SMatthew G. Knepley    | \__|  B \
28103f2a96e3SMatthew G. Knepley    | C  \\    \
28113f2a96e3SMatthew G. Knepley    0-----0-----1
28123f2a96e3SMatthew G. Knepley   */
28133f2a96e3SMatthew G. Knepley   static PetscInt       triC25[]  = {DM_POLYTOPE_POINT, 2, 2, 0, 0, DM_POLYTOPE_POINT, 1, 0, 0,
28143f2a96e3SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 2, 0,
28153f2a96e3SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,    0,
28163f2a96e3SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0,    0,
28173f2a96e3SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0,    1};
28183f2a96e3SMatthew G. Knepley   static PetscInt       triO25[]  = {0, 0,
28193f2a96e3SMatthew G. Knepley                                      0, 0,
28203f2a96e3SMatthew G. Knepley                                      0, -2, -2,
28213f2a96e3SMatthew G. Knepley                                      0,  0,  0,
28223f2a96e3SMatthew G. Knepley                                      0,  0,  0};
28233f2a96e3SMatthew G. Knepley   DMLabel        rtype = cr->refineType;
28243f2a96e3SMatthew G. Knepley   PetscInt       val;
28253f2a96e3SMatthew G. Knepley   PetscErrorCode ierr;
28263f2a96e3SMatthew G. Knepley 
28273f2a96e3SMatthew G. Knepley 
28283f2a96e3SMatthew G. Knepley   PetscFunctionBeginHot;
28293f2a96e3SMatthew G. Knepley   if (p < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point argument is invalid");
28303f2a96e3SMatthew G. Knepley   ierr = DMLabelGetValue(rtype, p, &val);CHKERRQ(ierr);
28313f2a96e3SMatthew G. Knepley   if (rt) *rt = val;
28323f2a96e3SMatthew G. Knepley   switch (source) {
28333f2a96e3SMatthew G. Knepley     case DM_POLYTOPE_POINT:
28343f2a96e3SMatthew G. Knepley     case DM_POLYTOPE_POINT_PRISM_TENSOR:
28353f2a96e3SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:
28363f2a96e3SMatthew G. Knepley     case DM_POLYTOPE_SEG_PRISM_TENSOR:
28373f2a96e3SMatthew G. Knepley     case DM_POLYTOPE_TETRAHEDRON:
28383f2a96e3SMatthew G. Knepley     case DM_POLYTOPE_HEXAHEDRON:
28393f2a96e3SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM:
28403f2a96e3SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:
28413f2a96e3SMatthew G. Knepley     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
28423f2a96e3SMatthew G. Knepley     case DM_POLYTOPE_PYRAMID:
28433f2a96e3SMatthew G. Knepley       ierr = DMPlexCellRefinerRefine_None(cr, source, p, NULL, Nt, target, size, cone, ornt);CHKERRQ(ierr);
28443f2a96e3SMatthew G. Knepley       break;
28453f2a96e3SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:
28463f2a96e3SMatthew G. Knepley       if (val == 1) {ierr = DMPlexCellRefinerRefine_None(cr, source, p, NULL, Nt, target, size, cone, ornt);CHKERRQ(ierr);}
28473f2a96e3SMatthew G. Knepley       else          {ierr = DMPlexCellRefinerRefine_Regular(cr, source, p, NULL, Nt, target, size, cone, ornt);CHKERRQ(ierr);}
28483f2a96e3SMatthew G. Knepley       break;
28493f2a96e3SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:
28503f2a96e3SMatthew G. Knepley       switch (val) {
28513f2a96e3SMatthew G. Knepley         case 12: *Nt = 2; *target = triT10; *size = triS10; *cone = triC10; *ornt = triO10; break;
28523f2a96e3SMatthew G. Knepley         case 13: *Nt = 2; *target = triT10; *size = triS10; *cone = triC11; *ornt = triO11; break;
28533f2a96e3SMatthew G. Knepley         case 11: *Nt = 2; *target = triT10; *size = triS10; *cone = triC12; *ornt = triO12; break;
28543f2a96e3SMatthew G. Knepley         case  5: *Nt = 2; *target = triT20; *size = triS20; *cone = triC24; *ornt = triO24; break;
28553f2a96e3SMatthew G. Knepley         case  6: *Nt = 2; *target = triT20; *size = triS20; *cone = triC21; *ornt = triO21; break;
28563f2a96e3SMatthew G. Knepley         case  7: *Nt = 2; *target = triT20; *size = triS20; *cone = triC20; *ornt = triO20; break;
28573f2a96e3SMatthew G. Knepley         case  8: *Nt = 2; *target = triT20; *size = triS20; *cone = triC23; *ornt = triO23; break;
28583f2a96e3SMatthew G. Knepley         case  9: *Nt = 2; *target = triT20; *size = triS20; *cone = triC22; *ornt = triO22; break;
28593f2a96e3SMatthew G. Knepley         case 10: *Nt = 2; *target = triT20; *size = triS20; *cone = triC25; *ornt = triO25; break;
28603f2a96e3SMatthew G. Knepley         case  4: ierr = DMPlexCellRefinerRefine_Regular(cr, source, p, NULL, Nt, target, size, cone, ornt);CHKERRQ(ierr); break;
28613f2a96e3SMatthew G. Knepley         default: ierr = DMPlexCellRefinerRefine_None(cr, source, p, NULL, Nt, target, size, cone, ornt);CHKERRQ(ierr);
28623f2a96e3SMatthew G. Knepley       }
28633f2a96e3SMatthew G. Knepley       break;
28643f2a96e3SMatthew G. Knepley     default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No refinement strategy for %s", DMPolytopeTypes[source]);
28653f2a96e3SMatthew G. Knepley   }
28663f2a96e3SMatthew G. Knepley   PetscFunctionReturn(0);
28673f2a96e3SMatthew G. Knepley }
28683f2a96e3SMatthew G. Knepley 
28693f2a96e3SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerMapSubcells_SBR(DMPlexCellRefiner cr, DMPolytopeType pct, PetscInt pp, PetscInt po, DMPolytopeType ct, PetscInt r, PetscInt o, PetscInt *rnew, PetscInt *onew)
28703f2a96e3SMatthew G. Knepley {
28713f2a96e3SMatthew G. Knepley   /* We shift any input orientation in order to make it non-negative
28723f2a96e3SMatthew 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)
28733f2a96e3SMatthew G. Knepley        The replica array r[po][r] gives the new replica number rnew given that the parent point has orientation po
28743f2a96e3SMatthew G. Knepley        Overall, replica (r, o) in a parent with orientation 0 matches replica (rnew, onew) in a parent with orientation po
28753f2a96e3SMatthew G. Knepley   */
28763f2a96e3SMatthew G. Knepley   PetscInt         rt;
28773f2a96e3SMatthew G. Knepley   PetscErrorCode   ierr;
28783f2a96e3SMatthew G. Knepley 
28793f2a96e3SMatthew G. Knepley   PetscFunctionBeginHot;
28803f2a96e3SMatthew G. Knepley   ierr = DMLabelGetValue(cr->refineType, pp, &rt);CHKERRQ(ierr);
28813f2a96e3SMatthew G. Knepley   *rnew = r;
28823f2a96e3SMatthew G. Knepley   *onew = o;
28833f2a96e3SMatthew G. Knepley   switch (rt) {
28843f2a96e3SMatthew G. Knepley     case 5:
28853f2a96e3SMatthew G. Knepley     case 6:
28863f2a96e3SMatthew G. Knepley     case 7:
28873f2a96e3SMatthew G. Knepley     case 8:
28883f2a96e3SMatthew G. Knepley     case 9:
28893f2a96e3SMatthew G. Knepley     case 10:
28903f2a96e3SMatthew G. Knepley       switch (ct) {
28913f2a96e3SMatthew G. Knepley         case DM_POLYTOPE_SEGMENT:
28923f2a96e3SMatthew G. Knepley           break;
28933f2a96e3SMatthew G. Knepley         case DM_POLYTOPE_TRIANGLE:
28943f2a96e3SMatthew G. Knepley           break;
28953f2a96e3SMatthew G. Knepley         default: break;
28963f2a96e3SMatthew G. Knepley       }
28973f2a96e3SMatthew G. Knepley       break;
28983f2a96e3SMatthew G. Knepley     case 11:
28993f2a96e3SMatthew G. Knepley     case 12:
29003f2a96e3SMatthew G. Knepley     case 13:
29013f2a96e3SMatthew G. Knepley       switch (ct) {
29023f2a96e3SMatthew G. Knepley         case DM_POLYTOPE_SEGMENT:
29033f2a96e3SMatthew G. Knepley           break;
29043f2a96e3SMatthew G. Knepley         case DM_POLYTOPE_TRIANGLE:
29053f2a96e3SMatthew G. Knepley           *onew = po < 0 ? -(o+1)  : o;
29063f2a96e3SMatthew G. Knepley           *rnew = po < 0 ? (r+1)%2 : r;
29073f2a96e3SMatthew G. Knepley           break;
29083f2a96e3SMatthew G. Knepley         default: break;
29093f2a96e3SMatthew G. Knepley       }
29103f2a96e3SMatthew G. Knepley       break;
29113f2a96e3SMatthew G. Knepley     case 2:
29123f2a96e3SMatthew G. Knepley     case 4:
29133f2a96e3SMatthew G. Knepley       ierr = DMPlexCellRefinerMapSubcells_Regular(cr, pct, pp, po, ct, r, o, rnew, onew);CHKERRQ(ierr);
29143f2a96e3SMatthew G. Knepley       break;
29153f2a96e3SMatthew G. Knepley     default: ierr = DMPlexCellRefinerMapSubcells_None(cr, pct, pp, po, ct, r, o, rnew, onew);CHKERRQ(ierr);
29163f2a96e3SMatthew G. Knepley   }
29173f2a96e3SMatthew G. Knepley   PetscFunctionReturn(0);
29183f2a96e3SMatthew G. Knepley }
29193f2a96e3SMatthew G. Knepley 
2920412e9a14SMatthew G. Knepley static PetscErrorCode CellRefinerCreateOffset_Internal(DMPlexCellRefiner cr, PetscInt ctOrder[], PetscInt ctStart[], PetscInt **offset)
2921412e9a14SMatthew G. Knepley {
2922412e9a14SMatthew G. Knepley   PetscInt       c, cN, *off;
292375d3a19aSMatthew G. Knepley   PetscErrorCode ierr;
292475d3a19aSMatthew G. Knepley 
292575d3a19aSMatthew G. Knepley   PetscFunctionBegin;
29263f2a96e3SMatthew G. Knepley   if (cr->refineType) {
29273f2a96e3SMatthew G. Knepley     IS              rtIS;
29283f2a96e3SMatthew G. Knepley     const PetscInt *reftypes;
29293f2a96e3SMatthew G. Knepley     PetscInt        Nrt, r;
29303f2a96e3SMatthew G. Knepley 
29313f2a96e3SMatthew G. Knepley     ierr = DMLabelGetNumValues(cr->refineType, &Nrt);CHKERRQ(ierr);
29323f2a96e3SMatthew G. Knepley     ierr = DMLabelGetValueIS(cr->refineType, &rtIS);CHKERRQ(ierr);
29333f2a96e3SMatthew G. Knepley     ierr = ISGetIndices(rtIS, &reftypes);CHKERRQ(ierr);
29343f2a96e3SMatthew G. Knepley     ierr = PetscCalloc1(Nrt*DM_NUM_POLYTOPES, &off);CHKERRQ(ierr);
29353f2a96e3SMatthew G. Knepley     for (r = 0; r < Nrt; ++r) {
29363f2a96e3SMatthew G. Knepley       const PetscInt  rt = reftypes[r];
29373f2a96e3SMatthew G. Knepley       IS              rtIS;
29383f2a96e3SMatthew G. Knepley       const PetscInt *points;
29393f2a96e3SMatthew G. Knepley       DMPolytopeType  ct;
29403f2a96e3SMatthew G. Knepley       PetscInt        p;
29413f2a96e3SMatthew G. Knepley 
29423f2a96e3SMatthew G. Knepley       ierr = DMLabelGetStratumIS(cr->refineType, rt, &rtIS);CHKERRQ(ierr);
29433f2a96e3SMatthew G. Knepley       ierr = ISGetIndices(rtIS, &points);CHKERRQ(ierr);
29443f2a96e3SMatthew G. Knepley       p    = points[0];
29453f2a96e3SMatthew G. Knepley       ierr = ISRestoreIndices(rtIS, &points);CHKERRQ(ierr);
29463f2a96e3SMatthew G. Knepley       ierr = ISDestroy(&rtIS);CHKERRQ(ierr);
29473f2a96e3SMatthew G. Knepley       ierr = DMPlexGetCellType(cr->dm, p, &ct);CHKERRQ(ierr);
29483f2a96e3SMatthew G. Knepley       for (cN = DM_POLYTOPE_POINT; cN < DM_NUM_POLYTOPES; ++cN) {
29493f2a96e3SMatthew G. Knepley         const DMPolytopeType ctNew = (DMPolytopeType) cN;
29503f2a96e3SMatthew G. Knepley         DMPolytopeType      *rct;
29513f2a96e3SMatthew G. Knepley         PetscInt            *rsize, *cone, *ornt;
29523f2a96e3SMatthew G. Knepley         PetscInt             Nct, n, s;
29533f2a96e3SMatthew G. Knepley 
29543f2a96e3SMatthew G. Knepley         if (DMPolytopeTypeGetDim(ct) < 0 || DMPolytopeTypeGetDim(ctNew) < 0) {off[r*DM_NUM_POLYTOPES+ctNew] = -1; break;}
29553f2a96e3SMatthew G. Knepley         off[r*DM_NUM_POLYTOPES+ctNew] = 0;
29563f2a96e3SMatthew G. Knepley         for (s = 0; s <= r; ++s) {
29573f2a96e3SMatthew G. Knepley           const PetscInt st = reftypes[s];
29583f2a96e3SMatthew G. Knepley           DMPolytopeType sct;
29593f2a96e3SMatthew G. Knepley           PetscInt       q, qrt;
29603f2a96e3SMatthew G. Knepley 
29613f2a96e3SMatthew G. Knepley           ierr = DMLabelGetStratumIS(cr->refineType, st, &rtIS);CHKERRQ(ierr);
29623f2a96e3SMatthew G. Knepley           ierr = ISGetIndices(rtIS, &points);CHKERRQ(ierr);
29633f2a96e3SMatthew G. Knepley           q    = points[0];
29643f2a96e3SMatthew G. Knepley           ierr = ISRestoreIndices(rtIS, &points);CHKERRQ(ierr);
29653f2a96e3SMatthew G. Knepley           ierr = ISDestroy(&rtIS);CHKERRQ(ierr);
29663f2a96e3SMatthew G. Knepley           ierr = DMPlexGetCellType(cr->dm, q, &sct);CHKERRQ(ierr);
29673f2a96e3SMatthew G. Knepley           ierr = DMPlexCellRefinerRefine(cr, sct, q, &qrt, &Nct, &rct, &rsize, &cone, &ornt);CHKERRQ(ierr);
29683f2a96e3SMatthew G. Knepley           if (st != qrt) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Refine type %D of point %D does not match predicted type %D", qrt, q, st);
29693f2a96e3SMatthew G. Knepley           if (st == rt) {
29703f2a96e3SMatthew G. Knepley             for (n = 0; n < Nct; ++n) if (rct[n] == ctNew) break;
29713f2a96e3SMatthew G. Knepley             if (n == Nct) off[r*DM_NUM_POLYTOPES+ctNew] = -1;
29723f2a96e3SMatthew G. Knepley             break;
29733f2a96e3SMatthew G. Knepley           }
29743f2a96e3SMatthew G. Knepley           for (n = 0; n < Nct; ++n) {
29753f2a96e3SMatthew G. Knepley             if (rct[n] == ctNew) {
29763f2a96e3SMatthew G. Knepley               PetscInt sn;
29773f2a96e3SMatthew G. Knepley 
29783f2a96e3SMatthew G. Knepley               ierr = DMLabelGetStratumSize(cr->refineType, st, &sn);CHKERRQ(ierr);
29793f2a96e3SMatthew G. Knepley               off[r*DM_NUM_POLYTOPES+ctNew] += sn * rsize[n];
29803f2a96e3SMatthew G. Knepley             }
29813f2a96e3SMatthew G. Knepley           }
29823f2a96e3SMatthew G. Knepley         }
29833f2a96e3SMatthew G. Knepley       }
29843f2a96e3SMatthew G. Knepley     }
29853f2a96e3SMatthew G. Knepley #if 0
29863f2a96e3SMatthew G. Knepley     {
29873f2a96e3SMatthew G. Knepley       PetscInt cols = 8;
29883f2a96e3SMatthew G. Knepley       PetscInt f, g;
29893f2a96e3SMatthew G. Knepley       ierr = PetscPrintf(PETSC_COMM_SELF, "Offsets\n");CHKERRQ(ierr);
29903f2a96e3SMatthew G. Knepley       ierr = PetscPrintf(PETSC_COMM_SELF, "     ");CHKERRQ(ierr);
29913f2a96e3SMatthew G. Knepley       for (g = 0; g < cols; ++g) {
29923f2a96e3SMatthew G. Knepley         ierr = PetscPrintf(PETSC_COMM_SELF, " % 14s", DMPolytopeTypes[g]);CHKERRQ(ierr);
29933f2a96e3SMatthew G. Knepley       }
29943f2a96e3SMatthew G. Knepley       ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr);
29953f2a96e3SMatthew G. Knepley       for (f = 0; f < Nrt; ++f) {
29963f2a96e3SMatthew G. Knepley         ierr = PetscPrintf(PETSC_COMM_SELF, "%2d  |", reftypes[f]);CHKERRQ(ierr);
29973f2a96e3SMatthew G. Knepley         for (g = 0; g < cols; ++g) {
29983f2a96e3SMatthew G. Knepley           ierr = PetscPrintf(PETSC_COMM_SELF, " % 14d", PetscRealPart(off[f*DM_NUM_POLYTOPES+g]));CHKERRQ(ierr);
29993f2a96e3SMatthew G. Knepley         }
30003f2a96e3SMatthew G. Knepley         ierr = PetscPrintf(PETSC_COMM_SELF, " |\n");CHKERRQ(ierr);
30013f2a96e3SMatthew G. Knepley       }
30023f2a96e3SMatthew G. Knepley     }
30033f2a96e3SMatthew G. Knepley #endif
30043f2a96e3SMatthew G. Knepley     ierr = ISRestoreIndices(rtIS, &reftypes);CHKERRQ(ierr);
30053f2a96e3SMatthew G. Knepley     ierr = ISDestroy(&rtIS);CHKERRQ(ierr);
30063f2a96e3SMatthew G. Knepley   } else {
3007412e9a14SMatthew G. Knepley     ierr = PetscCalloc1(DM_NUM_POLYTOPES*DM_NUM_POLYTOPES, &off);CHKERRQ(ierr);
3008412e9a14SMatthew G. Knepley     for (c = DM_POLYTOPE_POINT; c < DM_NUM_POLYTOPES; ++c) {
3009412e9a14SMatthew G. Knepley       const DMPolytopeType ct = (DMPolytopeType) c;
3010412e9a14SMatthew G. Knepley       for (cN = DM_POLYTOPE_POINT; cN < DM_NUM_POLYTOPES; ++cN) {
3011412e9a14SMatthew G. Knepley         const DMPolytopeType ctNew = (DMPolytopeType) cN;
3012412e9a14SMatthew G. Knepley         DMPolytopeType      *rct;
3013412e9a14SMatthew G. Knepley         PetscInt            *rsize, *cone, *ornt;
3014412e9a14SMatthew G. Knepley         PetscInt             Nct, n, i;
3015412e9a14SMatthew G. Knepley 
3016412e9a14SMatthew G. Knepley         if (DMPolytopeTypeGetDim(ct) < 0 || DMPolytopeTypeGetDim(ctNew) < 0) {off[ct*DM_NUM_POLYTOPES+ctNew] = -1; break;}
3017412e9a14SMatthew G. Knepley         off[ct*DM_NUM_POLYTOPES+ctNew] = 0;
3018412e9a14SMatthew G. Knepley         for (i = DM_POLYTOPE_POINT; i < DM_NUM_POLYTOPES; ++i) {
3019412e9a14SMatthew G. Knepley           const DMPolytopeType ict  = (DMPolytopeType) ctOrder[i];
3020412e9a14SMatthew G. Knepley           const DMPolytopeType ictn = (DMPolytopeType) ctOrder[i+1];
3021412e9a14SMatthew G. Knepley 
30223f2a96e3SMatthew G. Knepley           ierr = DMPlexCellRefinerRefine(cr, ict, PETSC_DETERMINE, NULL, &Nct, &rct, &rsize, &cone, &ornt);CHKERRQ(ierr);
3023412e9a14SMatthew G. Knepley           if (ict == ct) {
3024412e9a14SMatthew G. Knepley             for (n = 0; n < Nct; ++n) if (rct[n] == ctNew) break;
3025412e9a14SMatthew G. Knepley             if (n == Nct) off[ct*DM_NUM_POLYTOPES+ctNew] = -1;
3026412e9a14SMatthew G. Knepley             break;
3027412e9a14SMatthew G. Knepley           }
3028412e9a14SMatthew G. Knepley           for (n = 0; n < Nct; ++n) if (rct[n] == ctNew) off[ct*DM_NUM_POLYTOPES+ctNew] += (ctStart[ictn]-ctStart[ict]) * rsize[n];
3029412e9a14SMatthew G. Knepley         }
3030412e9a14SMatthew G. Knepley       }
3031412e9a14SMatthew G. Knepley     }
30323f2a96e3SMatthew G. Knepley   }
3033412e9a14SMatthew G. Knepley   *offset = off;
3034412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
3035412e9a14SMatthew G. Knepley }
3036412e9a14SMatthew G. Knepley 
3037412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerSetStarts(DMPlexCellRefiner cr, const PetscInt ctStart[], const PetscInt ctStartNew[])
3038412e9a14SMatthew G. Knepley {
3039412e9a14SMatthew G. Knepley   const PetscInt ctSize = DM_NUM_POLYTOPES+1;
3040412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
3041412e9a14SMatthew G. Knepley 
3042412e9a14SMatthew G. Knepley   PetscFunctionBegin;
3043412e9a14SMatthew G. Knepley   if (cr->setupcalled) SETERRQ(PetscObjectComm((PetscObject) cr), PETSC_ERR_ARG_WRONGSTATE, "Must call this function before DMPlexCellRefinerSetUp()");
3044412e9a14SMatthew G. Knepley   ierr = PetscCalloc2(ctSize, &cr->ctStart, ctSize, &cr->ctStartNew);CHKERRQ(ierr);
3045412e9a14SMatthew G. Knepley   ierr = PetscArraycpy(cr->ctStart,    ctStart,    ctSize);CHKERRQ(ierr);
3046412e9a14SMatthew G. Knepley   ierr = PetscArraycpy(cr->ctStartNew, ctStartNew, ctSize);CHKERRQ(ierr);
3047412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
3048412e9a14SMatthew G. Knepley }
3049412e9a14SMatthew G. Knepley 
3050412e9a14SMatthew G. Knepley /* Construct cell type order since we must loop over cell types in depth order */
3051412e9a14SMatthew G. Knepley PetscErrorCode DMPlexCreateCellTypeOrder_Internal(DMPolytopeType ctCell, PetscInt *ctOrder[], PetscInt *ctOrderInv[])
3052412e9a14SMatthew G. Knepley {
3053412e9a14SMatthew G. Knepley   PetscInt      *ctO, *ctOInv;
3054412e9a14SMatthew G. Knepley   PetscInt       c, d, off = 0;
3055412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
3056412e9a14SMatthew G. Knepley 
3057412e9a14SMatthew G. Knepley   PetscFunctionBegin;
3058412e9a14SMatthew G. Knepley   ierr = PetscCalloc2(DM_NUM_POLYTOPES+1, &ctO, DM_NUM_POLYTOPES+1, &ctOInv);CHKERRQ(ierr);
3059412e9a14SMatthew G. Knepley   for (d = 3; d >= DMPolytopeTypeGetDim(ctCell); --d) {
3060412e9a14SMatthew G. Knepley     for (c = 0; c <= DM_NUM_POLYTOPES; ++c) {
3061412e9a14SMatthew G. Knepley       if (DMPolytopeTypeGetDim((DMPolytopeType) c) != d) continue;
3062412e9a14SMatthew G. Knepley       ctO[off++] = c;
3063412e9a14SMatthew G. Knepley     }
3064412e9a14SMatthew G. Knepley   }
3065412e9a14SMatthew G. Knepley   if (DMPolytopeTypeGetDim(ctCell) != 0) {
3066412e9a14SMatthew G. Knepley     for (c = 0; c <= DM_NUM_POLYTOPES; ++c) {
3067412e9a14SMatthew G. Knepley       if (DMPolytopeTypeGetDim((DMPolytopeType) c) != 0) continue;
3068412e9a14SMatthew G. Knepley       ctO[off++] = c;
3069412e9a14SMatthew G. Knepley     }
3070412e9a14SMatthew G. Knepley   }
3071412e9a14SMatthew G. Knepley   for (d = DMPolytopeTypeGetDim(ctCell)-1; d > 0; --d) {
3072412e9a14SMatthew G. Knepley     for (c = 0; c <= DM_NUM_POLYTOPES; ++c) {
3073412e9a14SMatthew G. Knepley       if (DMPolytopeTypeGetDim((DMPolytopeType) c) != d) continue;
3074412e9a14SMatthew G. Knepley       ctO[off++] = c;
3075412e9a14SMatthew G. Knepley     }
3076412e9a14SMatthew G. Knepley   }
3077412e9a14SMatthew G. Knepley   for (c = 0; c <= DM_NUM_POLYTOPES; ++c) {
3078412e9a14SMatthew G. Knepley     if (DMPolytopeTypeGetDim((DMPolytopeType) c) >= 0) continue;
3079412e9a14SMatthew G. Knepley     ctO[off++] = c;
3080412e9a14SMatthew G. Knepley   }
3081412e9a14SMatthew G. Knepley   if (off != DM_NUM_POLYTOPES+1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid offset %D for cell type order", off);
3082412e9a14SMatthew G. Knepley   for (c = 0; c <= DM_NUM_POLYTOPES; ++c) {
3083412e9a14SMatthew G. Knepley     ctOInv[ctO[c]] = c;
3084412e9a14SMatthew G. Knepley   }
3085412e9a14SMatthew G. Knepley   *ctOrder    = ctO;
3086412e9a14SMatthew G. Knepley   *ctOrderInv = ctOInv;
3087412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
3088412e9a14SMatthew G. Knepley }
3089412e9a14SMatthew G. Knepley 
3090412e9a14SMatthew G. Knepley PetscErrorCode DMPlexCellRefinerSetUp(DMPlexCellRefiner cr)
3091412e9a14SMatthew G. Knepley {
3092412e9a14SMatthew G. Knepley   DM             dm = cr->dm;
3093412e9a14SMatthew G. Knepley   DMPolytopeType ctCell;
3094412e9a14SMatthew G. Knepley   PetscInt       pStart, pEnd, p, c;
3095412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
3096412e9a14SMatthew G. Knepley 
3097412e9a14SMatthew G. Knepley   PetscFunctionBegin;
3098412e9a14SMatthew G. Knepley   PetscValidHeader(cr, 1);
3099412e9a14SMatthew G. Knepley   if (cr->setupcalled) PetscFunctionReturn(0);
3100a5801f52SStefano Zampini   if (cr->ops->setup) {
3101a5801f52SStefano Zampini     ierr = (*cr->ops->setup)(cr);CHKERRQ(ierr);
3102a5801f52SStefano Zampini   }
3103412e9a14SMatthew G. Knepley   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
3104a5801f52SStefano Zampini   if (pEnd > pStart) {
3105a5801f52SStefano Zampini     ierr = DMPlexGetCellType(dm, 0, &ctCell);CHKERRQ(ierr);
3106a5801f52SStefano Zampini   } else {
3107412e9a14SMatthew G. Knepley     PetscInt dim;
3108a57030b0SMatthew G. Knepley     ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
3109412e9a14SMatthew G. Knepley     switch (dim) {
3110412e9a14SMatthew G. Knepley     case 0: ctCell = DM_POLYTOPE_POINT;break;
3111412e9a14SMatthew G. Knepley     case 1: ctCell = DM_POLYTOPE_SEGMENT;break;
3112412e9a14SMatthew G. Knepley     case 2: ctCell = DM_POLYTOPE_TRIANGLE;break;
3113412e9a14SMatthew G. Knepley     case 3: ctCell = DM_POLYTOPE_TETRAHEDRON;break;
3114a5801f52SStefano Zampini     default: ctCell = DM_POLYTOPE_UNKNOWN;
3115412e9a14SMatthew G. Knepley     }
3116412e9a14SMatthew G. Knepley   }
3117412e9a14SMatthew G. Knepley   ierr = DMPlexCreateCellTypeOrder_Internal(ctCell, &cr->ctOrder, &cr->ctOrderInv);CHKERRQ(ierr);
3118412e9a14SMatthew G. Knepley   /* Construct sizes and offsets for each cell type */
3119412e9a14SMatthew G. Knepley   if (!cr->ctStart) {
3120412e9a14SMatthew G. Knepley     PetscInt *ctS, *ctSN, *ctC, *ctCN;
3121412e9a14SMatthew G. Knepley 
3122412e9a14SMatthew G. Knepley     ierr = PetscCalloc2(DM_NUM_POLYTOPES+1, &ctS, DM_NUM_POLYTOPES+1, &ctSN);CHKERRQ(ierr);
3123412e9a14SMatthew G. Knepley     ierr = PetscCalloc2(DM_NUM_POLYTOPES+1, &ctC, DM_NUM_POLYTOPES+1, &ctCN);CHKERRQ(ierr);
3124412e9a14SMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
3125412e9a14SMatthew G. Knepley       DMPolytopeType  ct;
3126412e9a14SMatthew G. Knepley       DMPolytopeType *rct;
3127412e9a14SMatthew G. Knepley       PetscInt       *rsize, *cone, *ornt;
3128412e9a14SMatthew G. Knepley       PetscInt        Nct, n;
3129412e9a14SMatthew G. Knepley 
3130412e9a14SMatthew G. Knepley       ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
3131412e9a14SMatthew G. Knepley       if ((PetscInt) ct < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No cell type for point %D", p);
3132412e9a14SMatthew G. Knepley       ++ctC[ct];
31333f2a96e3SMatthew G. Knepley       ierr = DMPlexCellRefinerRefine(cr, ct, p, NULL, &Nct, &rct, &rsize, &cone, &ornt);CHKERRQ(ierr);
3134412e9a14SMatthew G. Knepley       for (n = 0; n < Nct; ++n) ctCN[rct[n]] += rsize[n];
3135412e9a14SMatthew G. Knepley     }
3136412e9a14SMatthew G. Knepley     for (c = 0; c < DM_NUM_POLYTOPES; ++c) {
3137412e9a14SMatthew G. Knepley       const PetscInt ct  = cr->ctOrder[c];
3138412e9a14SMatthew G. Knepley       const PetscInt ctn = cr->ctOrder[c+1];
3139412e9a14SMatthew G. Knepley 
3140412e9a14SMatthew G. Knepley       ctS[ctn]  = ctS[ct]  + ctC[ct];
3141412e9a14SMatthew G. Knepley       ctSN[ctn] = ctSN[ct] + ctCN[ct];
3142412e9a14SMatthew G. Knepley     }
3143412e9a14SMatthew G. Knepley     ierr = PetscFree2(ctC, ctCN);CHKERRQ(ierr);
3144412e9a14SMatthew G. Knepley     cr->ctStart    = ctS;
3145412e9a14SMatthew G. Knepley     cr->ctStartNew = ctSN;
3146412e9a14SMatthew G. Knepley   }
3147412e9a14SMatthew G. Knepley   ierr = CellRefinerCreateOffset_Internal(cr, cr->ctOrder, cr->ctStart, &cr->offset);CHKERRQ(ierr);
3148412e9a14SMatthew G. Knepley   cr->setupcalled = PETSC_TRUE;
3149412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
3150412e9a14SMatthew G. Knepley }
3151412e9a14SMatthew G. Knepley 
3152412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerView_Ascii(DMPlexCellRefiner cr, PetscViewer v)
3153412e9a14SMatthew G. Knepley {
3154412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
3155412e9a14SMatthew G. Knepley 
3156412e9a14SMatthew G. Knepley   PetscFunctionBegin;
3157412e9a14SMatthew G. Knepley   ierr = PetscViewerASCIIPrintf(v, "Cell Refiner: %s\n", DMPlexCellRefinerTypes[cr->type]);CHKERRQ(ierr);
3158412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
3159412e9a14SMatthew G. Knepley }
3160412e9a14SMatthew G. Knepley 
3161412e9a14SMatthew G. Knepley /*
3162412e9a14SMatthew G. Knepley   DMPlexCellRefinerView - Views a DMPlexCellRefiner object
3163412e9a14SMatthew G. Knepley 
3164412e9a14SMatthew G. Knepley   Collective on cr
3165412e9a14SMatthew G. Knepley 
3166412e9a14SMatthew G. Knepley   Input Parameters:
3167412e9a14SMatthew G. Knepley + cr     - The DMPlexCellRefiner object
3168412e9a14SMatthew G. Knepley - viewer - The PetscViewer object
3169412e9a14SMatthew G. Knepley 
3170412e9a14SMatthew G. Knepley   Level: beginner
3171412e9a14SMatthew G. Knepley 
3172412e9a14SMatthew G. Knepley .seealso: DMPlexCellRefinerCreate()
3173412e9a14SMatthew G. Knepley */
3174412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerView(DMPlexCellRefiner cr, PetscViewer viewer)
3175412e9a14SMatthew G. Knepley {
3176412e9a14SMatthew G. Knepley   PetscBool      iascii;
3177412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
3178412e9a14SMatthew G. Knepley 
3179412e9a14SMatthew G. Knepley   PetscFunctionBegin;
3180412e9a14SMatthew G. Knepley   PetscValidHeader(cr, 1);
3181412e9a14SMatthew G. Knepley   if (viewer) PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
3182412e9a14SMatthew G. Knepley   if (!viewer) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject) cr), &viewer);CHKERRQ(ierr);}
3183412e9a14SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
3184412e9a14SMatthew G. Knepley   ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
3185412e9a14SMatthew G. Knepley   if (iascii) {ierr = DMPlexCellRefinerView_Ascii(cr, viewer);CHKERRQ(ierr);}
3186412e9a14SMatthew G. Knepley   ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
3187412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
3188412e9a14SMatthew G. Knepley }
3189412e9a14SMatthew G. Knepley 
3190412e9a14SMatthew G. Knepley PetscErrorCode DMPlexCellRefinerDestroy(DMPlexCellRefiner *cr)
3191412e9a14SMatthew G. Knepley {
3192412e9a14SMatthew G. Knepley   PetscInt       c;
3193412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
3194412e9a14SMatthew G. Knepley 
3195412e9a14SMatthew G. Knepley   PetscFunctionBegin;
3196412e9a14SMatthew G. Knepley   if (!*cr) PetscFunctionReturn(0);
3197412e9a14SMatthew G. Knepley   PetscValidHeaderSpecific(*cr, DM_CLASSID, 1);
3198a5801f52SStefano Zampini   if ((*cr)->ops->destroy) {
3199a5801f52SStefano Zampini     ierr = ((*cr)->ops->destroy)(*cr);CHKERRQ(ierr);
3200a5801f52SStefano Zampini   }
3201412e9a14SMatthew G. Knepley   ierr = PetscObjectDereference((PetscObject) (*cr)->dm);CHKERRQ(ierr);
32023f2a96e3SMatthew G. Knepley   ierr = DMLabelDestroy(&(*cr)->refineType);CHKERRQ(ierr);
3203412e9a14SMatthew G. Knepley   ierr = PetscFree2((*cr)->ctOrder, (*cr)->ctOrderInv);CHKERRQ(ierr);
3204412e9a14SMatthew G. Knepley   ierr = PetscFree2((*cr)->ctStart, (*cr)->ctStartNew);CHKERRQ(ierr);
3205412e9a14SMatthew G. Knepley   ierr = PetscFree((*cr)->offset);CHKERRQ(ierr);
3206412e9a14SMatthew G. Knepley   for (c = 0; c < DM_NUM_POLYTOPES; ++c) {
3207412e9a14SMatthew G. Knepley     ierr = PetscFEDestroy(&(*cr)->coordFE[c]);CHKERRQ(ierr);
3208412e9a14SMatthew G. Knepley     ierr = PetscFEGeomDestroy(&(*cr)->refGeom[c]);CHKERRQ(ierr);
3209412e9a14SMatthew G. Knepley   }
3210412e9a14SMatthew G. Knepley   ierr = PetscFree2((*cr)->coordFE, (*cr)->refGeom);CHKERRQ(ierr);
3211412e9a14SMatthew G. Knepley   ierr = PetscHeaderDestroy(cr);CHKERRQ(ierr);
3212412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
3213412e9a14SMatthew G. Knepley }
3214412e9a14SMatthew G. Knepley 
3215412e9a14SMatthew G. Knepley PetscErrorCode DMPlexCellRefinerCreate(DM dm, DMPlexCellRefiner *cr)
3216412e9a14SMatthew G. Knepley {
3217412e9a14SMatthew G. Knepley   DMPlexCellRefiner tmp;
3218412e9a14SMatthew G. Knepley   PetscErrorCode    ierr;
3219412e9a14SMatthew G. Knepley 
3220412e9a14SMatthew G. Knepley   PetscFunctionBegin;
3221412e9a14SMatthew G. Knepley   PetscValidPointer(cr, 2);
3222412e9a14SMatthew G. Knepley   *cr  = NULL;
3223412e9a14SMatthew G. Knepley   ierr = PetscHeaderCreate(tmp, DM_CLASSID, "DMPlexCellRefiner", "Cell Refiner", "DMPlexCellRefiner", PETSC_COMM_SELF, DMPlexCellRefinerDestroy, DMPlexCellRefinerView);CHKERRQ(ierr);
3224412e9a14SMatthew G. Knepley   tmp->setupcalled = PETSC_FALSE;
3225412e9a14SMatthew G. Knepley 
3226412e9a14SMatthew G. Knepley   tmp->dm = dm;
3227412e9a14SMatthew G. Knepley   ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr);
3228412e9a14SMatthew G. Knepley   ierr = DMPlexGetCellRefinerType(dm, &tmp->type);CHKERRQ(ierr);
3229412e9a14SMatthew G. Knepley   switch (tmp->type) {
323096ca5757SLisandro Dalcin   case DM_REFINER_REGULAR:
3231412e9a14SMatthew G. Knepley     tmp->ops->refine                  = DMPlexCellRefinerRefine_Regular;
3232412e9a14SMatthew G. Knepley     tmp->ops->mapsubcells             = DMPlexCellRefinerMapSubcells_Regular;
3233412e9a14SMatthew G. Knepley     tmp->ops->getcellvertices         = DMPlexCellRefinerGetCellVertices_Regular;
3234412e9a14SMatthew G. Knepley     tmp->ops->getsubcellvertices      = DMPlexCellRefinerGetSubcellVertices_Regular;
3235a5801f52SStefano Zampini     tmp->ops->mapcoords               = DMPlexCellRefinerMapCoordinates_Barycenter;
3236412e9a14SMatthew G. Knepley     tmp->ops->getaffinetransforms     = DMPlexCellRefinerGetAffineTransforms_Regular;
3237412e9a14SMatthew G. Knepley     tmp->ops->getaffinefacetransforms = DMPlexCellRefinerGetAffineFaceTransforms_Regular;
3238412e9a14SMatthew G. Knepley     break;
323996ca5757SLisandro Dalcin   case DM_REFINER_TO_BOX:
324096ca5757SLisandro Dalcin     tmp->ops->refine             = DMPlexCellRefinerRefine_ToBox;
324196ca5757SLisandro Dalcin     tmp->ops->mapsubcells        = DMPlexCellRefinerMapSubcells_ToBox;
324296ca5757SLisandro Dalcin     tmp->ops->getcellvertices    = DMPlexCellRefinerGetCellVertices_ToBox;
324396ca5757SLisandro Dalcin     tmp->ops->getsubcellvertices = DMPlexCellRefinerGetSubcellVertices_ToBox;
3244a5801f52SStefano Zampini     tmp->ops->mapcoords          = DMPlexCellRefinerMapCoordinates_Barycenter;
3245412e9a14SMatthew G. Knepley     break;
324696ca5757SLisandro Dalcin   case DM_REFINER_TO_SIMPLEX:
3247412e9a14SMatthew G. Knepley     tmp->ops->refine      = DMPlexCellRefinerRefine_ToSimplex;
3248412e9a14SMatthew G. Knepley     tmp->ops->mapsubcells = DMPlexCellRefinerMapSubcells_ToSimplex;
3249a5801f52SStefano Zampini     tmp->ops->mapcoords   = DMPlexCellRefinerMapCoordinates_Barycenter;
3250412e9a14SMatthew G. Knepley     break;
3251cf4091a3SMatthew G. Knepley   case DM_REFINER_ALFELD2D:
3252cf4091a3SMatthew G. Knepley     tmp->ops->refine      = DMPlexCellRefinerRefine_Alfeld2D;
3253cf4091a3SMatthew G. Knepley     tmp->ops->mapsubcells = DMPlexCellRefinerMapSubcells_None;
3254a5801f52SStefano Zampini     tmp->ops->mapcoords   = DMPlexCellRefinerMapCoordinates_Barycenter;
3255cf4091a3SMatthew G. Knepley     break;
3256cf4091a3SMatthew G. Knepley   case DM_REFINER_ALFELD3D:
3257cf4091a3SMatthew G. Knepley     tmp->ops->refine      = DMPlexCellRefinerRefine_Alfeld3D;
3258cf4091a3SMatthew G. Knepley     tmp->ops->mapsubcells = DMPlexCellRefinerMapSubcells_None;
3259a5801f52SStefano Zampini     tmp->ops->mapcoords   = DMPlexCellRefinerMapCoordinates_Barycenter;
3260cf4091a3SMatthew G. Knepley     break;
3261a5801f52SStefano Zampini   case DM_REFINER_BOUNDARYLAYER:
3262a5801f52SStefano Zampini     tmp->ops->setup       = DMPlexCellRefinerSetUp_BL;
3263a5801f52SStefano Zampini     tmp->ops->destroy     = DMPlexCellRefinerDestroy_BL;
3264cf4091a3SMatthew G. Knepley     tmp->ops->refine      = DMPlexCellRefinerRefine_BL;
3265cf4091a3SMatthew G. Knepley     tmp->ops->mapsubcells = DMPlexCellRefinerMapSubcells_BL;
3266a5801f52SStefano Zampini     tmp->ops->mapcoords   = DMPlexCellRefinerMapCoordinates_BL;
3267cf4091a3SMatthew G. Knepley     break;
32683f2a96e3SMatthew G. Knepley   case DM_REFINER_SBR:
32693f2a96e3SMatthew G. Knepley     tmp->ops->setup       = DMPlexCellRefinerSetUp_SBR;
32703f2a96e3SMatthew G. Knepley     tmp->ops->destroy     = DMPlexCellRefinerDestroy_SBR;
32713f2a96e3SMatthew G. Knepley     tmp->ops->refine      = DMPlexCellRefinerRefine_SBR;
32723f2a96e3SMatthew G. Knepley     tmp->ops->mapsubcells = DMPlexCellRefinerMapSubcells_SBR;
32733f2a96e3SMatthew G. Knepley     tmp->ops->mapcoords   = DMPlexCellRefinerMapCoordinates_Barycenter;
32743f2a96e3SMatthew G. Knepley     break;
3275412e9a14SMatthew G. Knepley   default: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Invalid cell refiner type %s", DMPlexCellRefinerTypes[tmp->type]);
3276412e9a14SMatthew G. Knepley   }
3277412e9a14SMatthew G. Knepley   ierr = PetscCalloc2(DM_NUM_POLYTOPES, &tmp->coordFE, DM_NUM_POLYTOPES, &tmp->refGeom);CHKERRQ(ierr);
3278412e9a14SMatthew G. Knepley   *cr = tmp;
3279412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
3280412e9a14SMatthew G. Knepley }
3281412e9a14SMatthew G. Knepley 
3282412e9a14SMatthew G. Knepley /*@
3283412e9a14SMatthew G. Knepley   DMPlexCellRefinerGetAffineTransforms - Gets the affine map from the reference cell to each subcell
3284412e9a14SMatthew G. Knepley 
3285412e9a14SMatthew G. Knepley   Input Parameters:
3286412e9a14SMatthew G. Knepley + cr - The DMPlexCellRefiner object
3287412e9a14SMatthew G. Knepley - ct - The cell type
3288412e9a14SMatthew G. Knepley 
3289412e9a14SMatthew G. Knepley   Output Parameters:
3290412e9a14SMatthew G. Knepley + Nc   - The number of subcells produced from this cell type
3291412e9a14SMatthew G. Knepley . v0   - The translation of the first vertex for each subcell
3292412e9a14SMatthew G. Knepley . J    - The Jacobian for each subcell (map from reference cell to subcell)
3293412e9a14SMatthew G. Knepley - invJ - The inverse Jacobian for each subcell
3294412e9a14SMatthew G. Knepley 
3295412e9a14SMatthew G. Knepley   Level: developer
3296412e9a14SMatthew G. Knepley 
3297412e9a14SMatthew G. Knepley .seealso: DMPlexCellRefinerGetAffineFaceTransforms(), Create()
3298412e9a14SMatthew G. Knepley @*/
3299412e9a14SMatthew G. Knepley PetscErrorCode DMPlexCellRefinerGetAffineTransforms(DMPlexCellRefiner cr, DMPolytopeType ct, PetscInt *Nc, PetscReal *v0[], PetscReal *J[], PetscReal *invJ[])
3300412e9a14SMatthew G. Knepley {
3301412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
3302412e9a14SMatthew G. Knepley 
3303412e9a14SMatthew G. Knepley   PetscFunctionBegin;
3304412e9a14SMatthew G. Knepley   if (!cr->ops->getaffinetransforms) SETERRQ(PetscObjectComm((PetscObject) cr), PETSC_ERR_SUP, "No support for affine transforms from this refiner");
3305412e9a14SMatthew G. Knepley   ierr = (*cr->ops->getaffinetransforms)(cr, ct, Nc, v0, J, invJ);CHKERRQ(ierr);
3306412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
3307412e9a14SMatthew G. Knepley }
3308412e9a14SMatthew G. Knepley 
3309412e9a14SMatthew G. Knepley /*@
3310412e9a14SMatthew G. Knepley   DMPlexCellRefinerGetAffineFaceTransforms - Gets the affine map from the reference face cell to each face in the given cell
3311412e9a14SMatthew G. Knepley 
3312412e9a14SMatthew G. Knepley   Input Parameters:
3313412e9a14SMatthew G. Knepley + cr - The DMPlexCellRefiner object
3314412e9a14SMatthew G. Knepley - ct - The cell type
3315412e9a14SMatthew G. Knepley 
3316412e9a14SMatthew G. Knepley   Output Parameters:
3317412e9a14SMatthew G. Knepley + Nf   - The number of faces for this cell type
3318412e9a14SMatthew G. Knepley . v0   - The translation of the first vertex for each face
3319412e9a14SMatthew G. Knepley . J    - The Jacobian for each face (map from original cell to subcell)
3320412e9a14SMatthew G. Knepley . invJ - The inverse Jacobian for each face
3321412e9a14SMatthew G. Knepley - detJ - The determinant of the Jacobian for each face
3322412e9a14SMatthew G. Knepley 
3323412e9a14SMatthew G. Knepley   Note: The Jacobian and inverse Jacboian will be rectangular, and the inverse is really a generalized inverse.
3324412e9a14SMatthew G. Knepley 
3325412e9a14SMatthew G. Knepley   Level: developer
3326412e9a14SMatthew G. Knepley 
3327412e9a14SMatthew G. Knepley .seealso: DMPlexCellRefinerGetAffineTransforms(), Create()
3328412e9a14SMatthew G. Knepley @*/
3329412e9a14SMatthew G. Knepley PetscErrorCode DMPlexCellRefinerGetAffineFaceTransforms(DMPlexCellRefiner cr, DMPolytopeType ct, PetscInt *Nf, PetscReal *v0[], PetscReal *J[], PetscReal *invJ[], PetscReal *detJ[])
3330412e9a14SMatthew G. Knepley {
3331412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
3332412e9a14SMatthew G. Knepley 
3333412e9a14SMatthew G. Knepley   PetscFunctionBegin;
3334412e9a14SMatthew G. Knepley   if (!cr->ops->getaffinefacetransforms) SETERRQ(PetscObjectComm((PetscObject) cr), PETSC_ERR_SUP, "No support for affine face transforms from this refiner");
3335412e9a14SMatthew G. Knepley   ierr = (*cr->ops->getaffinefacetransforms)(cr, ct, Nf, v0, J, invJ, detJ);CHKERRQ(ierr);
3336412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
3337412e9a14SMatthew G. Knepley }
3338412e9a14SMatthew G. Knepley 
3339412e9a14SMatthew G. Knepley /* Numbering regularly refined meshes
3340412e9a14SMatthew G. Knepley 
3341412e9a14SMatthew G. Knepley    We want the numbering of the new mesh to respect the same depth stratification as the old mesh. We first compute
3342412e9a14SMatthew G. Knepley    the number of new points at each depth. This means that offsets for each depth can be computed, making no assumptions
3343412e9a14SMatthew G. Knepley    about the order of different cell types.
3344412e9a14SMatthew G. Knepley 
3345412e9a14SMatthew G. Knepley    However, when we want to order different depth strata, it will be very useful to make assumptions about contiguous
3346412e9a14SMatthew G. Knepley    numbering of different cell types, especially if we want to compute new numberings without communication. Therefore, we
3347412e9a14SMatthew G. Knepley    will require that cells are numbering contiguously for each cell type, and that those blocks come in the same order as
3348412e9a14SMatthew G. Knepley    the cell type enumeration within a given depth stratum.
3349412e9a14SMatthew G. Knepley 
3350412e9a14SMatthew 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
3351412e9a14SMatthew G. Knepley    start at the new depth offset, run through all prior cell types incrementing by the total addition from that type, then
3352412e9a14SMatthew G. Knepley    offset by the old cell type number and replica number for the insertion.
3353412e9a14SMatthew G. Knepley */
33543f2a96e3SMatthew G. Knepley 
33553f2a96e3SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerGetReducedPointNumber(DMPlexCellRefiner cr, PetscInt rt, PetscInt p, PetscInt *rp)
33563f2a96e3SMatthew G. Knepley {
33573f2a96e3SMatthew G. Knepley   IS              rtIS;
33583f2a96e3SMatthew G. Knepley   const PetscInt *points;
33593f2a96e3SMatthew G. Knepley   PetscInt        n;
33603f2a96e3SMatthew G. Knepley   PetscErrorCode  ierr;
33613f2a96e3SMatthew G. Knepley 
33623f2a96e3SMatthew G. Knepley   PetscFunctionBegin;
33633f2a96e3SMatthew G. Knepley   /* TODO Move this inside the DMLabel so that I do not have to create the IS */
33643f2a96e3SMatthew G. Knepley   ierr = DMLabelGetStratumIS(cr->refineType, rt, &rtIS);CHKERRQ(ierr);
33653f2a96e3SMatthew G. Knepley   ierr = ISGetLocalSize(rtIS, &n);CHKERRQ(ierr);
33663f2a96e3SMatthew G. Knepley   ierr = ISGetIndices(rtIS, &points);CHKERRQ(ierr);
33673f2a96e3SMatthew G. Knepley   ierr = PetscFindInt(p, n, points, rp);CHKERRQ(ierr);
33683f2a96e3SMatthew G. Knepley   ierr = ISRestoreIndices(rtIS, &points);CHKERRQ(ierr);
33693f2a96e3SMatthew G. Knepley   ierr = ISDestroy(&rtIS);CHKERRQ(ierr);
33703f2a96e3SMatthew G. Knepley   PetscFunctionReturn(0);
33713f2a96e3SMatthew G. Knepley }
33723f2a96e3SMatthew G. Knepley 
33733f2a96e3SMatthew G. Knepley /*
33743f2a96e3SMatthew G. Knepley   DMPlexCellRefinerGetNewPoint - Get the number of a point in the refined mesh based on information from the original mesh.
33753f2a96e3SMatthew G. Knepley 
33763f2a96e3SMatthew G. Knepley   Not collective
33773f2a96e3SMatthew G. Knepley 
33783f2a96e3SMatthew G. Knepley   Input Parameters:
33793f2a96e3SMatthew G. Knepley + cr    - The cell refiner
33803f2a96e3SMatthew G. Knepley . ct    - The type of the original point which produces the new point
33813f2a96e3SMatthew G. Knepley . ctNew - The type of the new point
33823f2a96e3SMatthew G. Knepley . p     - The original point which produces the new point
33833f2a96e3SMatthew G. Knepley - r     - The replica number of the new point, meaning it is the rth point of type ctNew produced from p
33843f2a96e3SMatthew G. Knepley 
33853f2a96e3SMatthew G. Knepley   Output Parameters:
33863f2a96e3SMatthew G. Knepley . pNew  - The new point number
33873f2a96e3SMatthew G. Knepley 
33883f2a96e3SMatthew G. Knepley   Level: developer
33893f2a96e3SMatthew G. Knepley 
33903f2a96e3SMatthew G. Knepley .seealso: DMPlexCellRefinerRefine()
33913f2a96e3SMatthew G. Knepley */
3392412e9a14SMatthew G. Knepley PetscErrorCode DMPlexCellRefinerGetNewPoint(DMPlexCellRefiner cr, DMPolytopeType ct, DMPolytopeType ctNew, PetscInt p, PetscInt r, PetscInt *pNew)
3393412e9a14SMatthew G. Knepley {
3394412e9a14SMatthew G. Knepley   DMPolytopeType *rct;
3395412e9a14SMatthew G. Knepley   PetscInt       *rsize, *cone, *ornt;
33963f2a96e3SMatthew G. Knepley   PetscInt       rt, Nct, n, off, rp;
3397412e9a14SMatthew G. Knepley   PetscInt       ctS  = cr->ctStart[ct],       ctE  = cr->ctStart[cr->ctOrder[cr->ctOrderInv[ct]+1]];
3398412e9a14SMatthew G. Knepley   PetscInt       ctSN = cr->ctStartNew[ctNew], ctEN = cr->ctStartNew[cr->ctOrder[cr->ctOrderInv[ctNew]+1]];
33993f2a96e3SMatthew G. Knepley   PetscInt       newp = ctSN, cind;
3400412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
3401412e9a14SMatthew G. Knepley 
3402412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
3403412e9a14SMatthew 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);
34043f2a96e3SMatthew G. Knepley   ierr = DMPlexCellRefinerRefine(cr, ct, p, &rt, &Nct, &rct, &rsize, &cone, &ornt);CHKERRQ(ierr);
34053f2a96e3SMatthew G. Knepley   if (cr->refineType) {
34063f2a96e3SMatthew G. Knepley     /* TODO Make this a function in DMLabel */
34073f2a96e3SMatthew G. Knepley     {
34083f2a96e3SMatthew G. Knepley       IS              rtIS;
34093f2a96e3SMatthew G. Knepley       const PetscInt *reftypes;
34103f2a96e3SMatthew G. Knepley       PetscInt        Nrt;
3411412e9a14SMatthew G. Knepley 
34123f2a96e3SMatthew G. Knepley       ierr = DMLabelGetNumValues(cr->refineType, &Nrt);CHKERRQ(ierr);
34133f2a96e3SMatthew G. Knepley       ierr = DMLabelGetValueIS(cr->refineType, &rtIS);CHKERRQ(ierr);
34143f2a96e3SMatthew G. Knepley       ierr = ISGetIndices(rtIS, &reftypes);CHKERRQ(ierr);
34153f2a96e3SMatthew G. Knepley       for (cind = 0; cind < Nrt; ++cind) if (reftypes[cind] == rt) break;
34163f2a96e3SMatthew G. Knepley       if (cind >= Nrt) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Unable to locate refine type %D", rt);
34173f2a96e3SMatthew G. Knepley       ierr = ISRestoreIndices(rtIS, &reftypes);CHKERRQ(ierr);
34183f2a96e3SMatthew G. Knepley       ierr = ISDestroy(&rtIS);CHKERRQ(ierr);
34193f2a96e3SMatthew G. Knepley     }
34203f2a96e3SMatthew G. Knepley     ierr = DMPlexCellRefinerGetReducedPointNumber(cr, rt, p, &rp);CHKERRQ(ierr);
34213f2a96e3SMatthew G. Knepley     if (rp < 0) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell type %s point %D does not have refine type %D", DMPolytopeTypes[ct], p, rt);
34223f2a96e3SMatthew G. Knepley   } else {
34233f2a96e3SMatthew G. Knepley     cind = ct;
34243f2a96e3SMatthew G. Knepley     rp   = p - ctS;
34253f2a96e3SMatthew G. Knepley   }
34263f2a96e3SMatthew G. Knepley   off = cr->offset[cind*DM_NUM_POLYTOPES + ctNew];
34273f2a96e3SMatthew G. Knepley   if (off < 0) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell type %s (%D) of point %D does not produce type %s", DMPolytopeTypes[ct], rt, p, DMPolytopeTypes[ctNew]);
3428412e9a14SMatthew G. Knepley   newp += off;
3429412e9a14SMatthew G. Knepley   for (n = 0; n < Nct; ++n) {
3430412e9a14SMatthew G. Knepley     if (rct[n] == ctNew) {
3431412e9a14SMatthew G. Knepley       if (rsize[n] && r >= rsize[n])
3432412e9a14SMatthew 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]);
34333f2a96e3SMatthew G. Knepley       newp += rp * rsize[n] + r;
3434412e9a14SMatthew G. Knepley       break;
3435412e9a14SMatthew G. Knepley     }
3436412e9a14SMatthew G. Knepley   }
3437412e9a14SMatthew G. Knepley 
3438412e9a14SMatthew 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);
3439412e9a14SMatthew G. Knepley   *pNew = newp;
3440412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
3441412e9a14SMatthew G. Knepley }
3442412e9a14SMatthew G. Knepley 
3443412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerSetConeSizes(DMPlexCellRefiner cr, DM rdm)
3444412e9a14SMatthew G. Knepley {
3445412e9a14SMatthew G. Knepley   DM              dm = cr->dm;
3446412e9a14SMatthew G. Knepley   PetscInt        pStart, pEnd, p, pNew;
3447412e9a14SMatthew G. Knepley   PetscErrorCode  ierr;
3448412e9a14SMatthew G. Knepley 
3449412e9a14SMatthew G. Knepley   PetscFunctionBegin;
3450412e9a14SMatthew G. Knepley   /* Must create the celltype label here so that we do not automatically try to compute the types */
3451412e9a14SMatthew G. Knepley   ierr = DMCreateLabel(rdm, "celltype");CHKERRQ(ierr);
3452412e9a14SMatthew G. Knepley   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
3453412e9a14SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
3454412e9a14SMatthew G. Knepley     DMPolytopeType  ct;
3455412e9a14SMatthew G. Knepley     DMPolytopeType *rct;
3456412e9a14SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt;
3457412e9a14SMatthew G. Knepley     PetscInt        Nct, n, r;
3458412e9a14SMatthew G. Knepley 
3459412e9a14SMatthew G. Knepley     ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
34603f2a96e3SMatthew G. Knepley     ierr = DMPlexCellRefinerRefine(cr, ct, p, NULL, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
3461412e9a14SMatthew G. Knepley     for (n = 0; n < Nct; ++n) {
3462412e9a14SMatthew G. Knepley       for (r = 0; r < rsize[n]; ++r) {
3463412e9a14SMatthew G. Knepley         ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], p, r, &pNew);CHKERRQ(ierr);
3464412e9a14SMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, pNew, DMPolytopeTypeGetConeSize(rct[n]));CHKERRQ(ierr);
3465412e9a14SMatthew G. Knepley         ierr = DMPlexSetCellType(rdm, pNew, rct[n]);CHKERRQ(ierr);
3466412e9a14SMatthew G. Knepley       }
3467412e9a14SMatthew G. Knepley     }
3468412e9a14SMatthew G. Knepley   }
3469412e9a14SMatthew G. Knepley   {
3470412e9a14SMatthew G. Knepley     DMLabel  ctLabel;
3471412e9a14SMatthew G. Knepley     DM_Plex *plex = (DM_Plex *) rdm->data;
3472412e9a14SMatthew G. Knepley 
3473412e9a14SMatthew G. Knepley     ierr = DMPlexGetCellTypeLabel(rdm, &ctLabel);CHKERRQ(ierr);
3474412e9a14SMatthew G. Knepley     ierr = PetscObjectStateGet((PetscObject) ctLabel, &plex->celltypeState);CHKERRQ(ierr);
3475412e9a14SMatthew G. Knepley   }
3476412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
3477412e9a14SMatthew G. Knepley }
3478412e9a14SMatthew G. Knepley 
3479412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerSetCones(DMPlexCellRefiner cr, DM rdm)
3480412e9a14SMatthew G. Knepley {
3481412e9a14SMatthew G. Knepley   DM             dm = cr->dm;
3482412e9a14SMatthew G. Knepley   DMPolytopeType ct;
3483412e9a14SMatthew G. Knepley   PetscInt      *coneNew, *orntNew;
3484412e9a14SMatthew G. Knepley   PetscInt       maxConeSize = 0, pStart, pEnd, p, pNew;
3485412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
3486412e9a14SMatthew G. Knepley 
3487412e9a14SMatthew G. Knepley   PetscFunctionBegin;
3488412e9a14SMatthew G. Knepley   for (p = 0; p < DM_NUM_POLYTOPES; ++p) maxConeSize = PetscMax(maxConeSize, DMPolytopeTypeGetConeSize((DMPolytopeType) p));
3489412e9a14SMatthew G. Knepley   ierr = PetscMalloc2(maxConeSize, &coneNew, maxConeSize, &orntNew);CHKERRQ(ierr);
3490412e9a14SMatthew G. Knepley   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
3491412e9a14SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
3492412e9a14SMatthew G. Knepley     const PetscInt *cone, *ornt;
3493412e9a14SMatthew G. Knepley     PetscInt        coff, ooff, c;
3494412e9a14SMatthew G. Knepley     DMPolytopeType *rct;
3495412e9a14SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt;
3496412e9a14SMatthew G. Knepley     PetscInt        Nct, n, r;
3497412e9a14SMatthew G. Knepley     ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
3498412e9a14SMatthew G. Knepley     ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr);
3499412e9a14SMatthew G. Knepley     ierr = DMPlexGetConeOrientation(dm, p, &ornt);CHKERRQ(ierr);
35003f2a96e3SMatthew G. Knepley     ierr = DMPlexCellRefinerRefine(cr, ct, p, NULL, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
3501412e9a14SMatthew G. Knepley     for (n = 0, coff = 0, ooff = 0; n < Nct; ++n) {
3502412e9a14SMatthew G. Knepley       const DMPolytopeType ctNew    = rct[n];
3503412e9a14SMatthew G. Knepley       const PetscInt       csizeNew = DMPolytopeTypeGetConeSize(ctNew);
3504412e9a14SMatthew G. Knepley 
3505412e9a14SMatthew G. Knepley       for (r = 0; r < rsize[n]; ++r) {
3506412e9a14SMatthew G. Knepley         /* pNew is a subcell produced by subdividing p */
3507412e9a14SMatthew G. Knepley         ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], p, r, &pNew);CHKERRQ(ierr);
3508412e9a14SMatthew G. Knepley         for (c = 0; c < csizeNew; ++c) {
3509412e9a14SMatthew G. Knepley           PetscInt             ppp   = -1;                             /* Parent Parent point: Parent of point pp */
3510412e9a14SMatthew G. Knepley           PetscInt             pp    = p;                              /* Parent point: Point in the original mesh producing new cone point */
3511412e9a14SMatthew G. Knepley           PetscInt             po    = 0;                              /* Orientation of parent point pp in parent parent point ppp */
3512412e9a14SMatthew G. Knepley           DMPolytopeType       pct   = ct;                             /* Parent type: Cell type for parent of new cone point */
3513412e9a14SMatthew G. Knepley           const PetscInt      *pcone = cone;                           /* Parent cone: Cone of parent point pp */
3514412e9a14SMatthew G. Knepley           PetscInt             pr    = -1;                             /* Replica number of pp that produces new cone point  */
3515412e9a14SMatthew G. Knepley           const DMPolytopeType ft    = (DMPolytopeType) rcone[coff++]; /* Cell type for new cone point of pNew */
3516412e9a14SMatthew G. Knepley           const PetscInt       fn    = rcone[coff++];                  /* Number of cones of p that need to be taken when producing new cone point */
3517412e9a14SMatthew G. Knepley           PetscInt             fo    = rornt[ooff++];                  /* Orientation of new cone point in pNew */
3518412e9a14SMatthew G. Knepley           PetscInt             lc;
3519412e9a14SMatthew G. Knepley 
3520412e9a14SMatthew G. Knepley           /* Get the type (pct) and point number (pp) of the parent point in the original mesh which produces this cone point */
3521412e9a14SMatthew G. Knepley           for (lc = 0; lc < fn; ++lc) {
3522412e9a14SMatthew G. Knepley             const PetscInt *ppornt;
3523412e9a14SMatthew G. Knepley             PetscInt        pcp;
3524412e9a14SMatthew G. Knepley 
3525412e9a14SMatthew G. Knepley             ierr = DMPolytopeMapCell(pct, po, rcone[coff++], &pcp);CHKERRQ(ierr);
3526412e9a14SMatthew G. Knepley             ppp  = pp;
3527412e9a14SMatthew G. Knepley             pp   = pcone[pcp];
3528412e9a14SMatthew G. Knepley             ierr = DMPlexGetCellType(dm, pp, &pct);CHKERRQ(ierr);
3529412e9a14SMatthew G. Knepley             ierr = DMPlexGetCone(dm, pp, &pcone);CHKERRQ(ierr);
3530412e9a14SMatthew G. Knepley             ierr = DMPlexGetConeOrientation(dm, ppp, &ppornt);CHKERRQ(ierr);
3531cf4091a3SMatthew G. Knepley             if (po <  0 && pct != DM_POLYTOPE_POINT) {
3532cf4091a3SMatthew G. Knepley               const PetscInt pornt   = ppornt[pcp];
3533cf4091a3SMatthew G. Knepley               const PetscInt pcsize  = DMPolytopeTypeGetConeSize(pct);
3534cf4091a3SMatthew G. Knepley               const PetscInt pcstart = pornt < 0 ? -(pornt+1) : pornt;
3535cf4091a3SMatthew G. Knepley               const PetscInt rcstart = (pcstart+pcsize-1)%pcsize;
3536cf4091a3SMatthew G. Knepley               po = pornt < 0 ? -(rcstart+1) : rcstart;
3537cf4091a3SMatthew G. Knepley             } else {
3538412e9a14SMatthew G. Knepley               po = ppornt[pcp];
3539412e9a14SMatthew G. Knepley             }
3540cf4091a3SMatthew G. Knepley           }
3541412e9a14SMatthew G. Knepley           pr = rcone[coff++];
3542412e9a14SMatthew G. Knepley           /* Orientation po of pp maps (pr, fo) -> (pr', fo') */
35433f2a96e3SMatthew G. Knepley           ierr = DMPlexCellRefinerMapSubcells(cr, pct, pp, po, ft, pr, fo, &pr, &fo);CHKERRQ(ierr);
3544412e9a14SMatthew G. Knepley           ierr = DMPlexCellRefinerGetNewPoint(cr, pct, ft, pp, pr, &coneNew[c]);CHKERRQ(ierr);
3545412e9a14SMatthew G. Knepley           orntNew[c] = fo;
3546412e9a14SMatthew G. Knepley         }
3547412e9a14SMatthew G. Knepley         ierr = DMPlexSetCone(rdm, pNew, coneNew);CHKERRQ(ierr);
3548412e9a14SMatthew G. Knepley         ierr = DMPlexSetConeOrientation(rdm, pNew, orntNew);CHKERRQ(ierr);
3549412e9a14SMatthew G. Knepley       }
3550412e9a14SMatthew G. Knepley     }
3551412e9a14SMatthew G. Knepley   }
3552412e9a14SMatthew G. Knepley   ierr = PetscFree2(coneNew, orntNew);CHKERRQ(ierr);
35533f2a96e3SMatthew G. Knepley   ierr = DMViewFromOptions(rdm, NULL, "-rdm_view");CHKERRQ(ierr);
3554412e9a14SMatthew G. Knepley   ierr = DMPlexSymmetrize(rdm);CHKERRQ(ierr);
3555412e9a14SMatthew G. Knepley   ierr = DMPlexStratify(rdm);CHKERRQ(ierr);
3556412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
3557412e9a14SMatthew G. Knepley }
3558412e9a14SMatthew G. Knepley 
3559412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerGetCoordinateFE(DMPlexCellRefiner cr, DMPolytopeType ct, PetscFE *fe)
3560412e9a14SMatthew G. Knepley {
3561412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
3562412e9a14SMatthew G. Knepley 
3563412e9a14SMatthew G. Knepley   PetscFunctionBegin;
3564412e9a14SMatthew G. Knepley   if (!cr->coordFE[ct]) {
3565412e9a14SMatthew G. Knepley     PetscInt  dim, cdim;
3566412e9a14SMatthew G. Knepley     PetscBool isSimplex;
3567412e9a14SMatthew G. Knepley 
3568412e9a14SMatthew G. Knepley     switch (ct) {
3569412e9a14SMatthew G. Knepley       case DM_POLYTOPE_SEGMENT:       dim = 1; isSimplex = PETSC_TRUE;  break;
3570412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRIANGLE:      dim = 2; isSimplex = PETSC_TRUE;  break;
3571412e9a14SMatthew G. Knepley       case DM_POLYTOPE_QUADRILATERAL: dim = 2; isSimplex = PETSC_FALSE; break;
3572412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TETRAHEDRON:   dim = 3; isSimplex = PETSC_TRUE;  break;
3573412e9a14SMatthew G. Knepley       case DM_POLYTOPE_HEXAHEDRON:    dim = 3; isSimplex = PETSC_FALSE; break;
3574412e9a14SMatthew G. Knepley       default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "No coordinate FE for cell type %s", DMPolytopeTypes[ct]);
3575412e9a14SMatthew G. Knepley     }
3576412e9a14SMatthew G. Knepley     ierr = DMGetCoordinateDim(cr->dm, &cdim);CHKERRQ(ierr);
3577412e9a14SMatthew G. Knepley     ierr = PetscFECreateLagrange(PETSC_COMM_SELF, dim, cdim, isSimplex, 1, PETSC_DETERMINE, &cr->coordFE[ct]);CHKERRQ(ierr);
3578412e9a14SMatthew G. Knepley     {
3579412e9a14SMatthew G. Knepley       PetscDualSpace  dsp;
3580412e9a14SMatthew G. Knepley       PetscQuadrature quad;
3581412e9a14SMatthew G. Knepley       DM              K;
3582412e9a14SMatthew G. Knepley       PetscFEGeom    *cg;
3583412e9a14SMatthew G. Knepley       PetscReal      *Xq, *xq, *wq;
3584412e9a14SMatthew G. Knepley       PetscInt        Nq, q;
3585412e9a14SMatthew G. Knepley 
3586412e9a14SMatthew G. Knepley       ierr = DMPlexCellRefinerGetCellVertices(cr, ct, &Nq, &Xq);CHKERRQ(ierr);
3587412e9a14SMatthew G. Knepley       ierr = PetscMalloc1(Nq*cdim, &xq);CHKERRQ(ierr);
3588412e9a14SMatthew G. Knepley       for (q = 0; q < Nq*cdim; ++q) xq[q] = Xq[q];
3589412e9a14SMatthew G. Knepley       ierr = PetscMalloc1(Nq, &wq);CHKERRQ(ierr);
3590412e9a14SMatthew G. Knepley       for (q = 0; q < Nq; ++q) wq[q] = 1.0;
3591412e9a14SMatthew G. Knepley       ierr = PetscQuadratureCreate(PETSC_COMM_SELF, &quad);CHKERRQ(ierr);
3592412e9a14SMatthew G. Knepley       ierr = PetscQuadratureSetData(quad, dim, 1, Nq, xq, wq);CHKERRQ(ierr);
3593412e9a14SMatthew G. Knepley       ierr = PetscFESetQuadrature(cr->coordFE[ct], quad);CHKERRQ(ierr);
3594412e9a14SMatthew G. Knepley 
3595412e9a14SMatthew G. Knepley       ierr = PetscFEGetDualSpace(cr->coordFE[ct], &dsp);CHKERRQ(ierr);
3596412e9a14SMatthew G. Knepley       ierr = PetscDualSpaceGetDM(dsp, &K);CHKERRQ(ierr);
3597412e9a14SMatthew G. Knepley       ierr = PetscFEGeomCreate(quad, 1, cdim, PETSC_FALSE, &cr->refGeom[ct]);CHKERRQ(ierr);
3598412e9a14SMatthew G. Knepley       cg   = cr->refGeom[ct];
3599412e9a14SMatthew G. Knepley       ierr = DMPlexComputeCellGeometryFEM(K, 0, NULL, cg->v, cg->J, cg->invJ, cg->detJ);CHKERRQ(ierr);
3600412e9a14SMatthew G. Knepley       ierr = PetscQuadratureDestroy(&quad);CHKERRQ(ierr);
3601412e9a14SMatthew G. Knepley     }
3602412e9a14SMatthew G. Knepley   }
3603412e9a14SMatthew G. Knepley   *fe = cr->coordFE[ct];
3604412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
3605412e9a14SMatthew G. Knepley }
3606412e9a14SMatthew G. Knepley 
3607412e9a14SMatthew G. Knepley /*
3608412e9a14SMatthew G. Knepley   DMPlexCellRefinerMapLocalizedCoordinates - Given a cell of type ct with localized coordinates x, we generate localized coordinates xr for subcell r of type rct.
3609412e9a14SMatthew G. Knepley 
3610412e9a14SMatthew G. Knepley   Not collective
3611412e9a14SMatthew G. Knepley 
3612412e9a14SMatthew G. Knepley   Input Parameters:
3613412e9a14SMatthew G. Knepley + cr  - The DMPlexCellRefiner
3614412e9a14SMatthew G. Knepley . ct  - The type of the parent cell
3615412e9a14SMatthew G. Knepley . rct - The type of the produced cell
3616412e9a14SMatthew G. Knepley . r   - The index of the produced cell
3617412e9a14SMatthew G. Knepley - x   - The localized coordinates for the parent cell
3618412e9a14SMatthew G. Knepley 
3619412e9a14SMatthew G. Knepley   Output Parameter:
3620412e9a14SMatthew G. Knepley . xr  - The localized coordinates for the produced cell
3621412e9a14SMatthew G. Knepley 
3622412e9a14SMatthew G. Knepley   Level: developer
3623412e9a14SMatthew G. Knepley 
3624412e9a14SMatthew G. Knepley .seealso: DMPlexCellRefinerSetCoordinates()
3625412e9a14SMatthew G. Knepley */
3626412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerMapLocalizedCoordinates(DMPlexCellRefiner cr, DMPolytopeType ct, DMPolytopeType rct, PetscInt r, const PetscScalar x[], PetscScalar xr[])
3627412e9a14SMatthew G. Knepley {
3628412e9a14SMatthew G. Knepley   PetscFE        fe = NULL;
3629412e9a14SMatthew G. Knepley   PetscInt       cdim, Nv, v, *subcellV;
3630412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
3631412e9a14SMatthew G. Knepley 
3632412e9a14SMatthew G. Knepley   PetscFunctionBegin;
3633412e9a14SMatthew G. Knepley   ierr = DMPlexCellRefinerGetCoordinateFE(cr, ct, &fe);CHKERRQ(ierr);
3634412e9a14SMatthew G. Knepley   ierr = DMPlexCellRefinerGetSubcellVertices(cr, ct, rct, r, &Nv, &subcellV);CHKERRQ(ierr);
3635412e9a14SMatthew G. Knepley   ierr = PetscFEGetNumComponents(fe, &cdim);CHKERRQ(ierr);
3636412e9a14SMatthew G. Knepley   for (v = 0; v < Nv; ++v) {
3637412e9a14SMatthew G. Knepley     ierr = PetscFEInterpolate_Static(fe, x, cr->refGeom[ct], subcellV[v], &xr[v*cdim]);CHKERRQ(ierr);
3638412e9a14SMatthew G. Knepley   }
3639412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
3640412e9a14SMatthew G. Knepley }
3641412e9a14SMatthew G. Knepley 
3642412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerSetCoordinates(DMPlexCellRefiner cr, DM rdm)
3643412e9a14SMatthew G. Knepley {
3644412e9a14SMatthew G. Knepley   DM                    dm = cr->dm, cdm;
3645412e9a14SMatthew G. Knepley   PetscSection          coordSection, coordSectionNew;
3646412e9a14SMatthew G. Knepley   Vec                   coordsLocal, coordsLocalNew;
3647412e9a14SMatthew G. Knepley   const PetscScalar    *coords;
3648412e9a14SMatthew G. Knepley   PetscScalar          *coordsNew;
3649412e9a14SMatthew G. Knepley   const DMBoundaryType *bd;
3650412e9a14SMatthew G. Knepley   const PetscReal      *maxCell, *L;
3651412e9a14SMatthew G. Knepley   PetscBool             isperiodic, localizeVertices = PETSC_FALSE, localizeCells = PETSC_FALSE;
3652412e9a14SMatthew G. Knepley   PetscInt              dE, d, cStart, cEnd, c, vStartNew, vEndNew, v, pStart, pEnd, p, ocStart, ocEnd;
3653412e9a14SMatthew G. Knepley   PetscErrorCode        ierr;
3654412e9a14SMatthew G. Knepley 
3655412e9a14SMatthew G. Knepley   PetscFunctionBegin;
3656412e9a14SMatthew G. Knepley   ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
365790b157c4SStefano Zampini   ierr = DMGetPeriodicity(dm, &isperiodic, &maxCell, &L, &bd);CHKERRQ(ierr);
365890b157c4SStefano Zampini   /* Determine if we need to localize coordinates when generating them */
3659b9ccc978SStefano Zampini   if (isperiodic) {
3660412e9a14SMatthew G. Knepley     localizeVertices = PETSC_TRUE;
3661412e9a14SMatthew G. Knepley     if (!maxCell) {
3662412e9a14SMatthew G. Knepley       PetscBool localized;
3663412e9a14SMatthew G. Knepley       ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr);
3664412e9a14SMatthew G. Knepley       if (!localized) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_USER, "Cannot refine a periodic mesh if coordinates have not been localized");
3665412e9a14SMatthew G. Knepley       localizeCells = PETSC_TRUE;
3666b9ccc978SStefano Zampini     }
3667b9ccc978SStefano Zampini   }
3668b9ccc978SStefano Zampini 
3669b9ccc978SStefano Zampini   ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr);
3670412e9a14SMatthew G. Knepley   ierr = PetscSectionGetFieldComponents(coordSection, 0, &dE);CHKERRQ(ierr);
3671412e9a14SMatthew G. Knepley   if (maxCell) {
3672412e9a14SMatthew G. Knepley     PetscReal maxCellNew[3];
3673412e9a14SMatthew G. Knepley 
3674412e9a14SMatthew G. Knepley     for (d = 0; d < dE; ++d) maxCellNew[d] = maxCell[d]/2.0;
3675412e9a14SMatthew G. Knepley     ierr = DMSetPeriodicity(rdm, isperiodic, maxCellNew, L, bd);CHKERRQ(ierr);
3676412e9a14SMatthew G. Knepley   } else {
3677412e9a14SMatthew G. Knepley     ierr = DMSetPeriodicity(rdm, isperiodic, maxCell, L, bd);CHKERRQ(ierr);
3678412e9a14SMatthew G. Knepley   }
3679b9ccc978SStefano Zampini   ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &coordSectionNew);CHKERRQ(ierr);
3680b9ccc978SStefano Zampini   ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr);
3681412e9a14SMatthew G. Knepley   ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dE);CHKERRQ(ierr);
3682412e9a14SMatthew G. Knepley   ierr = DMPlexGetDepthStratum(rdm, 0, &vStartNew, &vEndNew);CHKERRQ(ierr);
3683412e9a14SMatthew G. Knepley   if (localizeCells) {ierr = PetscSectionSetChart(coordSectionNew, 0,         vEndNew);CHKERRQ(ierr);}
3684412e9a14SMatthew G. Knepley   else               {ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vEndNew);CHKERRQ(ierr);}
3685b9ccc978SStefano Zampini 
3686412e9a14SMatthew G. Knepley   /* Localization should be inherited */
3687412e9a14SMatthew G. Knepley   /*   Stefano calculates parent cells for each new cell for localization */
3688412e9a14SMatthew G. Knepley   /*   Localized cells need coordinates of closure */
3689412e9a14SMatthew G. Knepley   for (v = vStartNew; v < vEndNew; ++v) {
3690412e9a14SMatthew G. Knepley     ierr = PetscSectionSetDof(coordSectionNew, v, dE);CHKERRQ(ierr);
3691412e9a14SMatthew G. Knepley     ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dE);CHKERRQ(ierr);
3692412e9a14SMatthew G. Knepley   }
3693412e9a14SMatthew G. Knepley   if (localizeCells) {
3694412e9a14SMatthew G. Knepley     ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
3695412e9a14SMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
3696412e9a14SMatthew G. Knepley       PetscInt dof;
369790b157c4SStefano Zampini 
3698412e9a14SMatthew G. Knepley       ierr = PetscSectionGetDof(coordSection, c, &dof);CHKERRQ(ierr);
3699412e9a14SMatthew G. Knepley       if (dof) {
3700412e9a14SMatthew G. Knepley         DMPolytopeType  ct;
3701412e9a14SMatthew G. Knepley         DMPolytopeType *rct;
3702412e9a14SMatthew G. Knepley         PetscInt       *rsize, *rcone, *rornt;
3703412e9a14SMatthew G. Knepley         PetscInt        dim, cNew, Nct, n, r;
370490b157c4SStefano Zampini 
3705412e9a14SMatthew G. Knepley         ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr);
3706412e9a14SMatthew G. Knepley         dim  = DMPolytopeTypeGetDim(ct);
37073f2a96e3SMatthew G. Knepley         ierr = DMPlexCellRefinerRefine(cr, ct, c, NULL, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
3708412e9a14SMatthew G. Knepley         /* This allows for different cell types */
3709412e9a14SMatthew G. Knepley         for (n = 0; n < Nct; ++n) {
3710412e9a14SMatthew G. Knepley           if (dim != DMPolytopeTypeGetDim(rct[n])) continue;
3711412e9a14SMatthew G. Knepley           for (r = 0; r < rsize[n]; ++r) {
3712412e9a14SMatthew G. Knepley             PetscInt *closure = NULL;
3713412e9a14SMatthew G. Knepley             PetscInt  clSize, cl, Nv = 0;
371490b157c4SStefano Zampini 
3715412e9a14SMatthew G. Knepley             ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], c, r, &cNew);CHKERRQ(ierr);
3716412e9a14SMatthew G. Knepley             ierr = DMPlexGetTransitiveClosure(rdm, cNew, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr);
3717412e9a14SMatthew G. Knepley             for (cl = 0; cl < clSize*2; cl += 2) {if ((closure[cl] >= vStartNew) && (closure[cl] < vEndNew)) ++Nv;}
3718412e9a14SMatthew G. Knepley             ierr = DMPlexRestoreTransitiveClosure(rdm, cNew, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr);
3719412e9a14SMatthew G. Knepley             ierr = PetscSectionSetDof(coordSectionNew, cNew, Nv * dE);CHKERRQ(ierr);
3720412e9a14SMatthew G. Knepley             ierr = PetscSectionSetFieldDof(coordSectionNew, cNew, 0, Nv * dE);CHKERRQ(ierr);
37219fc2a3f3SStefano Zampini           }
372290b157c4SStefano Zampini         }
372390b157c4SStefano Zampini       }
3724412e9a14SMatthew G. Knepley     }
372575d3a19aSMatthew G. Knepley   }
372675d3a19aSMatthew G. Knepley   ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr);
3727412e9a14SMatthew G. Knepley   ierr = DMViewFromOptions(dm, NULL, "-coarse_dm_view");CHKERRQ(ierr);
372846e270d4SMatthew G. Knepley   ierr = DMSetCoordinateSection(rdm, PETSC_DETERMINE, coordSectionNew);CHKERRQ(ierr);
3729412e9a14SMatthew G. Knepley   {
3730412e9a14SMatthew G. Knepley     VecType     vtype;
3731412e9a14SMatthew G. Knepley     PetscInt    coordSizeNew, bs;
3732412e9a14SMatthew G. Knepley     const char *name;
3733412e9a14SMatthew G. Knepley 
3734412e9a14SMatthew G. Knepley     ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr);
3735412e9a14SMatthew G. Knepley     ierr = VecCreate(PETSC_COMM_SELF, &coordsLocalNew);CHKERRQ(ierr);
373675d3a19aSMatthew G. Knepley     ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr);
3737412e9a14SMatthew G. Knepley     ierr = VecSetSizes(coordsLocalNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr);
3738412e9a14SMatthew G. Knepley     ierr = PetscObjectGetName((PetscObject) coordsLocal, &name);CHKERRQ(ierr);
3739412e9a14SMatthew G. Knepley     ierr = PetscObjectSetName((PetscObject) coordsLocalNew, name);CHKERRQ(ierr);
3740412e9a14SMatthew G. Knepley     ierr = VecGetBlockSize(coordsLocal, &bs);CHKERRQ(ierr);
3741412e9a14SMatthew G. Knepley     ierr = VecSetBlockSize(coordsLocalNew, bs);CHKERRQ(ierr);
3742412e9a14SMatthew G. Knepley     ierr = VecGetType(coordsLocal, &vtype);CHKERRQ(ierr);
3743412e9a14SMatthew G. Knepley     ierr = VecSetType(coordsLocalNew, vtype);CHKERRQ(ierr);
3744b5da9499SMatthew G. Knepley   }
3745412e9a14SMatthew G. Knepley   ierr = VecGetArrayRead(coordsLocal, &coords);CHKERRQ(ierr);
3746412e9a14SMatthew G. Knepley   ierr = VecGetArray(coordsLocalNew, &coordsNew);CHKERRQ(ierr);
3747412e9a14SMatthew G. Knepley   ierr = PetscSectionGetChart(coordSection, &ocStart, &ocEnd);CHKERRQ(ierr);
3748412e9a14SMatthew G. Knepley   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
3749412e9a14SMatthew G. Knepley   /* First set coordinates for vertices*/
3750412e9a14SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
3751412e9a14SMatthew G. Knepley     DMPolytopeType  ct;
3752412e9a14SMatthew G. Knepley     DMPolytopeType *rct;
3753412e9a14SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt;
3754412e9a14SMatthew G. Knepley     PetscInt        Nct, n, r;
3755412e9a14SMatthew G. Knepley     PetscBool       hasVertex = PETSC_FALSE, isLocalized = PETSC_FALSE;
375690b157c4SStefano Zampini 
3757412e9a14SMatthew G. Knepley     ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
37583f2a96e3SMatthew G. Knepley     ierr = DMPlexCellRefinerRefine(cr, ct, p, NULL, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
3759412e9a14SMatthew G. Knepley     for (n = 0; n < Nct; ++n) {
3760412e9a14SMatthew G. Knepley       if (rct[n] == DM_POLYTOPE_POINT) {hasVertex = PETSC_TRUE; break;}
3761412e9a14SMatthew G. Knepley     }
3762412e9a14SMatthew G. Knepley     if (localizeVertices && ct != DM_POLYTOPE_POINT && (p >= ocStart) && (p < ocEnd)) {
3763412e9a14SMatthew G. Knepley       PetscInt dof;
3764412e9a14SMatthew G. Knepley       ierr = PetscSectionGetDof(coordSection, p, &dof);CHKERRQ(ierr);
3765412e9a14SMatthew G. Knepley       if (dof) isLocalized = PETSC_TRUE;
3766412e9a14SMatthew G. Knepley     }
3767412e9a14SMatthew G. Knepley     if (hasVertex) {
3768a5801f52SStefano Zampini       const PetscScalar *icoords = NULL;
3769412e9a14SMatthew G. Knepley       PetscScalar       *pcoords = NULL;
3770412e9a14SMatthew G. Knepley       PetscInt          Nc, Nv, v, d;
377190b157c4SStefano Zampini 
3772412e9a14SMatthew G. Knepley       ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, p, &Nc, &pcoords);CHKERRQ(ierr);
3773a5801f52SStefano Zampini 
3774a5801f52SStefano Zampini       icoords = pcoords;
3775a5801f52SStefano Zampini       Nv      = Nc/dE;
3776a5801f52SStefano Zampini       if (ct != DM_POLYTOPE_POINT) {
3777412e9a14SMatthew G. Knepley         if (localizeVertices) {
3778412e9a14SMatthew G. Knepley           PetscScalar anchor[3];
377990b157c4SStefano Zampini 
3780412e9a14SMatthew G. Knepley           for (d = 0; d < dE; ++d) anchor[d] = pcoords[d];
3781412e9a14SMatthew G. Knepley           if (!isLocalized) {
3782a5801f52SStefano Zampini             for (v = 0; v < Nv; ++v) {ierr = DMLocalizeCoordinate_Internal(dm, dE, anchor, &pcoords[v*dE], &pcoords[v*dE]);CHKERRQ(ierr);}
3783412e9a14SMatthew G. Knepley           } else {
3784412e9a14SMatthew G. Knepley             Nv = Nc/(2*dE);
3785a5801f52SStefano Zampini             icoords = pcoords + Nv*dE;
3786a5801f52SStefano Zampini             for (v = Nv; v < Nv*2; ++v) {ierr = DMLocalizeCoordinate_Internal(dm, dE, anchor, &pcoords[v*dE], &pcoords[v*dE]);CHKERRQ(ierr);}
378790b157c4SStefano Zampini           }
3788b5da9499SMatthew G. Knepley         }
378990b157c4SStefano Zampini       }
3790412e9a14SMatthew G. Knepley       for (n = 0; n < Nct; ++n) {
3791412e9a14SMatthew G. Knepley         if (rct[n] != DM_POLYTOPE_POINT) continue;
3792412e9a14SMatthew G. Knepley         for (r = 0; r < rsize[n]; ++r) {
3793a5801f52SStefano Zampini           PetscScalar vcoords[3];
3794412e9a14SMatthew G. Knepley           PetscInt    vNew, off;
3795b5da9499SMatthew G. Knepley 
3796412e9a14SMatthew G. Knepley           ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], p, r, &vNew);CHKERRQ(ierr);
3797412e9a14SMatthew G. Knepley           ierr = PetscSectionGetOffset(coordSectionNew, vNew, &off);CHKERRQ(ierr);
3798a5801f52SStefano Zampini           ierr = DMPlexCellRefinerMapCoordinates(cr, ct, rct[n], r, Nv, dE, icoords, vcoords);CHKERRQ(ierr);
3799eac51794SMatthew G. Knepley           ierr = DMPlexSnapToGeomModel(dm, p, vcoords, &coordsNew[off]);CHKERRQ(ierr);
3800b5da9499SMatthew G. Knepley         }
38019fc2a3f3SStefano Zampini       }
3802a5801f52SStefano Zampini       ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, p, &Nc, &pcoords);CHKERRQ(ierr);
3803412e9a14SMatthew G. Knepley     }
3804412e9a14SMatthew G. Knepley   }
3805412e9a14SMatthew G. Knepley   /* Then set coordinates for cells by localizing */
3806412e9a14SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
3807412e9a14SMatthew G. Knepley     DMPolytopeType  ct;
3808412e9a14SMatthew G. Knepley     DMPolytopeType *rct;
3809412e9a14SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt;
3810412e9a14SMatthew G. Knepley     PetscInt        Nct, n, r;
3811412e9a14SMatthew G. Knepley     PetscBool       isLocalized = PETSC_FALSE;
381290b157c4SStefano Zampini 
3813412e9a14SMatthew G. Knepley     ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
38143f2a96e3SMatthew G. Knepley     ierr = DMPlexCellRefinerRefine(cr, ct, p, NULL, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
3815412e9a14SMatthew G. Knepley     if (localizeCells && ct != DM_POLYTOPE_POINT && (p >= ocStart) && (p < ocEnd)) {
3816412e9a14SMatthew G. Knepley       PetscInt dof;
3817412e9a14SMatthew G. Knepley       ierr = PetscSectionGetDof(coordSection, p, &dof);CHKERRQ(ierr);
3818412e9a14SMatthew G. Knepley       if (dof) isLocalized = PETSC_TRUE;
3819b5da9499SMatthew G. Knepley     }
3820412e9a14SMatthew G. Knepley     if (isLocalized) {
3821412e9a14SMatthew G. Knepley       const PetscScalar *pcoords;
38229fc2a3f3SStefano Zampini 
3823412e9a14SMatthew G. Knepley       ierr = DMPlexPointLocalRead(cdm, p, coords, &pcoords);CHKERRQ(ierr);
3824412e9a14SMatthew G. Knepley       for (n = 0; n < Nct; ++n) {
3825412e9a14SMatthew G. Knepley         const PetscInt Nr = rsize[n];
382690b157c4SStefano Zampini 
3827412e9a14SMatthew G. Knepley         if (DMPolytopeTypeGetDim(ct) != DMPolytopeTypeGetDim(rct[n])) continue;
3828412e9a14SMatthew G. Knepley         for (r = 0; r < Nr; ++r) {
3829412e9a14SMatthew G. Knepley           PetscInt pNew, offNew;
383090b157c4SStefano Zampini 
3831412e9a14SMatthew G. Knepley           /* It looks like Stefano and Lisandro are allowing localized coordinates without defining the periodic boundary, which means that
3832412e9a14SMatthew G. Knepley              DMLocalizeCoordinate_Internal() will not work. Localized coordinates will have to have obtained by the affine map of the larger
3833412e9a14SMatthew G. Knepley              cell to the ones it produces. */
3834412e9a14SMatthew G. Knepley           ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], p, r, &pNew);CHKERRQ(ierr);
3835412e9a14SMatthew G. Knepley           ierr = PetscSectionGetOffset(coordSectionNew, pNew, &offNew);CHKERRQ(ierr);
3836412e9a14SMatthew G. Knepley           ierr = DMPlexCellRefinerMapLocalizedCoordinates(cr, ct, rct[n], r, pcoords, &coordsNew[offNew]);CHKERRQ(ierr);
383790b157c4SStefano Zampini         }
383890b157c4SStefano Zampini       }
383990b157c4SStefano Zampini     }
384090b157c4SStefano Zampini   }
3841412e9a14SMatthew G. Knepley   ierr = VecRestoreArrayRead(coordsLocal, &coords);CHKERRQ(ierr);
3842412e9a14SMatthew G. Knepley   ierr = VecRestoreArray(coordsLocalNew, &coordsNew);CHKERRQ(ierr);
3843412e9a14SMatthew G. Knepley   ierr = DMSetCoordinatesLocal(rdm, coordsLocalNew);CHKERRQ(ierr);
3844412e9a14SMatthew G. Knepley   /* TODO Stefano has a final reduction if some hybrid coordinates cannot be found. (needcoords) Should not be needed. */
3845412e9a14SMatthew G. Knepley   ierr = VecDestroy(&coordsLocalNew);CHKERRQ(ierr);
384675d3a19aSMatthew G. Knepley   ierr = PetscSectionDestroy(&coordSectionNew);CHKERRQ(ierr);
3847412e9a14SMatthew G. Knepley   if (!localizeCells) {ierr = DMLocalizeCoordinates(rdm);CHKERRQ(ierr);}
384875d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
384975d3a19aSMatthew G. Knepley }
385075d3a19aSMatthew G. Knepley 
3851963fc26aSMatthew G. Knepley /*@
3852963fc26aSMatthew G. Knepley   DMPlexCreateProcessSF - Create an SF which just has process connectivity
3853963fc26aSMatthew G. Knepley 
3854d083f849SBarry Smith   Collective on dm
3855963fc26aSMatthew G. Knepley 
3856963fc26aSMatthew G. Knepley   Input Parameters:
3857963fc26aSMatthew G. Knepley + dm      - The DM
3858963fc26aSMatthew G. Knepley - sfPoint - The PetscSF which encodes point connectivity
3859963fc26aSMatthew G. Knepley 
3860963fc26aSMatthew G. Knepley   Output Parameters:
3861963fc26aSMatthew G. Knepley + processRanks - A list of process neighbors, or NULL
3862963fc26aSMatthew G. Knepley - sfProcess    - An SF encoding the process connectivity, or NULL
3863963fc26aSMatthew G. Knepley 
3864963fc26aSMatthew G. Knepley   Level: developer
3865963fc26aSMatthew G. Knepley 
3866963fc26aSMatthew G. Knepley .seealso: PetscSFCreate(), DMPlexCreateTwoSidedProcessSF()
3867963fc26aSMatthew G. Knepley @*/
3868963fc26aSMatthew G. Knepley PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess)
386975d3a19aSMatthew G. Knepley {
387075d3a19aSMatthew G. Knepley   PetscInt           numRoots, numLeaves, l;
387175d3a19aSMatthew G. Knepley   const PetscInt    *localPoints;
387275d3a19aSMatthew G. Knepley   const PetscSFNode *remotePoints;
387375d3a19aSMatthew G. Knepley   PetscInt          *localPointsNew;
387475d3a19aSMatthew G. Knepley   PetscSFNode       *remotePointsNew;
387575d3a19aSMatthew G. Knepley   PetscInt          *ranks, *ranksNew;
38769852e123SBarry Smith   PetscMPIInt        size;
387775d3a19aSMatthew G. Knepley   PetscErrorCode     ierr;
387875d3a19aSMatthew G. Knepley 
387975d3a19aSMatthew G. Knepley   PetscFunctionBegin;
3880963fc26aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3881963fc26aSMatthew G. Knepley   PetscValidHeaderSpecific(sfPoint, PETSCSF_CLASSID, 2);
3882963fc26aSMatthew G. Knepley   if (processRanks) {PetscValidPointer(processRanks, 3);}
3883963fc26aSMatthew G. Knepley   if (sfProcess)    {PetscValidPointer(sfProcess, 4);}
38849852e123SBarry Smith   ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm), &size);CHKERRQ(ierr);
388575d3a19aSMatthew G. Knepley   ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr);
3886785e854fSJed Brown   ierr = PetscMalloc1(numLeaves, &ranks);CHKERRQ(ierr);
388775d3a19aSMatthew G. Knepley   for (l = 0; l < numLeaves; ++l) {
388875d3a19aSMatthew G. Knepley     ranks[l] = remotePoints[l].rank;
388975d3a19aSMatthew G. Knepley   }
389075d3a19aSMatthew G. Knepley   ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr);
3891785e854fSJed Brown   ierr = PetscMalloc1(numLeaves, &ranksNew);CHKERRQ(ierr);
3892785e854fSJed Brown   ierr = PetscMalloc1(numLeaves, &localPointsNew);CHKERRQ(ierr);
3893785e854fSJed Brown   ierr = PetscMalloc1(numLeaves, &remotePointsNew);CHKERRQ(ierr);
389475d3a19aSMatthew G. Knepley   for (l = 0; l < numLeaves; ++l) {
389575d3a19aSMatthew G. Knepley     ranksNew[l]              = ranks[l];
389675d3a19aSMatthew G. Knepley     localPointsNew[l]        = l;
389775d3a19aSMatthew G. Knepley     remotePointsNew[l].index = 0;
389875d3a19aSMatthew G. Knepley     remotePointsNew[l].rank  = ranksNew[l];
389975d3a19aSMatthew G. Knepley   }
390075d3a19aSMatthew G. Knepley   ierr = PetscFree(ranks);CHKERRQ(ierr);
3901963fc26aSMatthew G. Knepley   if (processRanks) {ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr);}
3902963fc26aSMatthew G. Knepley   else              {ierr = PetscFree(ranksNew);CHKERRQ(ierr);}
3903963fc26aSMatthew G. Knepley   if (sfProcess) {
390475d3a19aSMatthew G. Knepley     ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess);CHKERRQ(ierr);
3905963fc26aSMatthew G. Knepley     ierr = PetscObjectSetName((PetscObject) *sfProcess, "Process SF");CHKERRQ(ierr);
390675d3a19aSMatthew G. Knepley     ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr);
39079852e123SBarry Smith     ierr = PetscSFSetGraph(*sfProcess, size, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr);
3908963fc26aSMatthew G. Knepley   }
390975d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
391075d3a19aSMatthew G. Knepley }
391175d3a19aSMatthew G. Knepley 
3912412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerCreateSF(DMPlexCellRefiner cr, DM rdm)
391375d3a19aSMatthew G. Knepley {
3914412e9a14SMatthew G. Knepley   DM                 dm = cr->dm;
3915412e9a14SMatthew G. Knepley   DMPlexCellRefiner *crRem;
391675d3a19aSMatthew G. Knepley   PetscSF            sf, sfNew, sfProcess;
391775d3a19aSMatthew G. Knepley   IS                 processRanks;
3918412e9a14SMatthew G. Knepley   MPI_Datatype       ctType;
391975d3a19aSMatthew G. Knepley   PetscInt           numRoots, numLeaves, numLeavesNew = 0, l, m;
392075d3a19aSMatthew G. Knepley   const PetscInt    *localPoints, *neighbors;
392175d3a19aSMatthew G. Knepley   const PetscSFNode *remotePoints;
392275d3a19aSMatthew G. Knepley   PetscInt          *localPointsNew;
392375d3a19aSMatthew G. Knepley   PetscSFNode       *remotePointsNew;
3924412e9a14SMatthew G. Knepley   PetscInt          *ctStartRem, *ctStartNewRem;
3925412e9a14SMatthew G. Knepley   PetscInt           ctSize = DM_NUM_POLYTOPES+1, numNeighbors, n, pStartNew, pEndNew, pNew, pNewRem;
39263f2a96e3SMatthew G. Knepley   /* Brute force algorithm */
39273f2a96e3SMatthew G. Knepley   PetscSF            rsf;
39283f2a96e3SMatthew G. Knepley   PetscSection       s;
39293f2a96e3SMatthew G. Knepley   const PetscInt    *rootdegree;
39303f2a96e3SMatthew G. Knepley   PetscInt          *rootPointsNew, *remoteOffsets;
39313f2a96e3SMatthew G. Knepley   PetscInt           numPointsNew, pStart, pEnd, p;
393275d3a19aSMatthew G. Knepley   PetscErrorCode     ierr;
393375d3a19aSMatthew G. Knepley 
393475d3a19aSMatthew G. Knepley   PetscFunctionBegin;
393575d3a19aSMatthew G. Knepley   ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr);
393675d3a19aSMatthew G. Knepley   ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr);
393775d3a19aSMatthew G. Knepley   ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr);
3938add09238SMatthew G. Knepley   /* Calculate size of new SF */
393975d3a19aSMatthew G. Knepley   ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr);
394075d3a19aSMatthew G. Knepley   if (numRoots < 0) PetscFunctionReturn(0);
394175d3a19aSMatthew G. Knepley   for (l = 0; l < numLeaves; ++l) {
394275d3a19aSMatthew G. Knepley     const PetscInt  p = localPoints[l];
3943412e9a14SMatthew G. Knepley     DMPolytopeType  ct;
3944412e9a14SMatthew G. Knepley     DMPolytopeType *rct;
3945412e9a14SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt;
3946412e9a14SMatthew G. Knepley     PetscInt        Nct, n;
394775d3a19aSMatthew G. Knepley 
3948412e9a14SMatthew G. Knepley     ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
39493f2a96e3SMatthew G. Knepley     ierr = DMPlexCellRefinerRefine(cr, ct, p, NULL, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
39503f2a96e3SMatthew G. Knepley     for (n = 0; n < Nct; ++n) {
39513f2a96e3SMatthew G. Knepley       numLeavesNew += rsize[n];
39520314a74cSLawrence Mitchell     }
39533f2a96e3SMatthew G. Knepley   }
39543f2a96e3SMatthew G. Knepley   if (cr->refineType) {
39553f2a96e3SMatthew G. Knepley     ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
39563f2a96e3SMatthew G. Knepley     ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &s);CHKERRQ(ierr);
39573f2a96e3SMatthew G. Knepley     ierr = PetscSectionSetChart(s, pStart, pEnd);CHKERRQ(ierr);
39583f2a96e3SMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
39593f2a96e3SMatthew G. Knepley       DMPolytopeType  ct;
39603f2a96e3SMatthew G. Knepley       DMPolytopeType *rct;
39613f2a96e3SMatthew G. Knepley       PetscInt       *rsize, *rcone, *rornt;
39623f2a96e3SMatthew G. Knepley       PetscInt        Nct, n;
39633f2a96e3SMatthew G. Knepley 
39643f2a96e3SMatthew G. Knepley       ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
39653f2a96e3SMatthew G. Knepley       ierr = DMPlexCellRefinerRefine(cr, ct, p, NULL, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
39663f2a96e3SMatthew G. Knepley       for (n = 0; n < Nct; ++n) {
39673f2a96e3SMatthew G. Knepley         ierr = PetscSectionAddDof(s, p, rsize[n]);CHKERRQ(ierr);
39683f2a96e3SMatthew G. Knepley       }
39693f2a96e3SMatthew G. Knepley     }
39703f2a96e3SMatthew G. Knepley     ierr = PetscSectionSetUp(s);CHKERRQ(ierr);
39713f2a96e3SMatthew G. Knepley     ierr = PetscSectionGetStorageSize(s, &numPointsNew);CHKERRQ(ierr);
39723f2a96e3SMatthew G. Knepley     ierr = PetscSFCreateRemoteOffsets(sf, s, s, &remoteOffsets);CHKERRQ(ierr);
39733f2a96e3SMatthew G. Knepley     ierr = PetscSFCreateSectionSF(sf, s, remoteOffsets, s, &rsf);CHKERRQ(ierr);
39743f2a96e3SMatthew G. Knepley     ierr = PetscFree(remoteOffsets);CHKERRQ(ierr);
39753f2a96e3SMatthew G. Knepley     ierr = PetscSFComputeDegreeBegin(sf, &rootdegree);CHKERRQ(ierr);
39763f2a96e3SMatthew G. Knepley     ierr = PetscSFComputeDegreeEnd(sf, &rootdegree);CHKERRQ(ierr);
39773f2a96e3SMatthew G. Knepley     ierr = PetscMalloc1(numPointsNew, &rootPointsNew);CHKERRQ(ierr);
39783f2a96e3SMatthew G. Knepley     for (p = 0; p < numPointsNew; ++p) rootPointsNew[p] = -1;
39793f2a96e3SMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
39803f2a96e3SMatthew G. Knepley       DMPolytopeType  ct;
39813f2a96e3SMatthew G. Knepley       DMPolytopeType *rct;
39823f2a96e3SMatthew G. Knepley       PetscInt       *rsize, *rcone, *rornt;
39833f2a96e3SMatthew G. Knepley       PetscInt        Nct, n, r, off;
39843f2a96e3SMatthew G. Knepley 
39853f2a96e3SMatthew G. Knepley       if (!rootdegree[p-pStart]) continue;
39863f2a96e3SMatthew G. Knepley       ierr = PetscSectionGetOffset(s, p, &off);CHKERRQ(ierr);
39873f2a96e3SMatthew G. Knepley       ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
39883f2a96e3SMatthew G. Knepley       ierr = DMPlexCellRefinerRefine(cr, ct, p, NULL, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
39893f2a96e3SMatthew G. Knepley       for (n = 0, m = 0; n < Nct; ++n) {
39903f2a96e3SMatthew G. Knepley         for (r = 0; r < rsize[n]; ++r, ++m) {
39913f2a96e3SMatthew G. Knepley           ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], p, r, &pNew);CHKERRQ(ierr);
39923f2a96e3SMatthew G. Knepley           rootPointsNew[off+m] = pNew;
39933f2a96e3SMatthew G. Knepley         }
39943f2a96e3SMatthew G. Knepley       }
39953f2a96e3SMatthew G. Knepley     }
39963f2a96e3SMatthew G. Knepley     ierr = PetscSFBcastBegin(rsf, MPIU_INT, rootPointsNew, rootPointsNew);CHKERRQ(ierr);
39973f2a96e3SMatthew G. Knepley     ierr = PetscSFBcastEnd(rsf, MPIU_INT, rootPointsNew, rootPointsNew);CHKERRQ(ierr);
39983f2a96e3SMatthew G. Knepley     ierr = PetscSFDestroy(&rsf);CHKERRQ(ierr);
39993f2a96e3SMatthew G. Knepley     ierr = PetscMalloc1(numLeavesNew, &localPointsNew);CHKERRQ(ierr);
40003f2a96e3SMatthew G. Knepley     ierr = PetscMalloc1(numLeavesNew, &remotePointsNew);CHKERRQ(ierr);
40013f2a96e3SMatthew G. Knepley     for (l = 0, m = 0; l < numLeaves; ++l) {
40023f2a96e3SMatthew G. Knepley       const PetscInt  p = localPoints[l];
40033f2a96e3SMatthew G. Knepley       DMPolytopeType  ct;
40043f2a96e3SMatthew G. Knepley       DMPolytopeType *rct;
40053f2a96e3SMatthew G. Knepley       PetscInt       *rsize, *rcone, *rornt;
40063f2a96e3SMatthew G. Knepley       PetscInt        Nct, n, r, q, off;
40073f2a96e3SMatthew G. Knepley 
40083f2a96e3SMatthew G. Knepley       ierr = PetscSectionGetOffset(s, p, &off);CHKERRQ(ierr);
40093f2a96e3SMatthew G. Knepley       ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
40103f2a96e3SMatthew G. Knepley       ierr = DMPlexCellRefinerRefine(cr, ct, p, NULL, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
40113f2a96e3SMatthew G. Knepley       for (n = 0, q = 0; n < Nct; ++n) {
40123f2a96e3SMatthew G. Knepley         for (r = 0; r < rsize[n]; ++r, ++m, ++q) {
40133f2a96e3SMatthew G. Knepley           ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], p, r, &pNew);CHKERRQ(ierr);
40143f2a96e3SMatthew G. Knepley           localPointsNew[m]        = pNew;
40153f2a96e3SMatthew G. Knepley           remotePointsNew[m].index = rootPointsNew[off+q];
40163f2a96e3SMatthew G. Knepley           remotePointsNew[m].rank  = remotePoints[l].rank;
40173f2a96e3SMatthew G. Knepley         }
40183f2a96e3SMatthew G. Knepley       }
40193f2a96e3SMatthew G. Knepley     }
40203f2a96e3SMatthew G. Knepley     ierr = PetscSectionDestroy(&s);CHKERRQ(ierr);
40213f2a96e3SMatthew G. Knepley     ierr = PetscFree(rootPointsNew);CHKERRQ(ierr);
40223f2a96e3SMatthew G. Knepley   } else {
4023412e9a14SMatthew G. Knepley     /* Communicate ctStart and cStartNew for each remote rank */
402475d3a19aSMatthew G. Knepley     ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr);
402575d3a19aSMatthew G. Knepley     ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr);
4026412e9a14SMatthew G. Knepley     ierr = PetscMalloc2(ctSize*numNeighbors, &ctStartRem, ctSize*numNeighbors, &ctStartNewRem);CHKERRQ(ierr);
4027412e9a14SMatthew G. Knepley     ierr = MPI_Type_contiguous(ctSize, MPIU_INT, &ctType);CHKERRQ(ierr);
4028412e9a14SMatthew G. Knepley     ierr = MPI_Type_commit(&ctType);CHKERRQ(ierr);
4029412e9a14SMatthew G. Knepley     ierr = PetscSFBcastBegin(sfProcess, ctType, cr->ctStart, ctStartRem);CHKERRQ(ierr);
4030412e9a14SMatthew G. Knepley     ierr = PetscSFBcastEnd(sfProcess, ctType, cr->ctStart, ctStartRem);CHKERRQ(ierr);
4031412e9a14SMatthew G. Knepley     ierr = PetscSFBcastBegin(sfProcess, ctType, cr->ctStartNew, ctStartNewRem);CHKERRQ(ierr);
4032412e9a14SMatthew G. Knepley     ierr = PetscSFBcastEnd(sfProcess, ctType, cr->ctStartNew, ctStartNewRem);CHKERRQ(ierr);
4033412e9a14SMatthew G. Knepley     ierr = MPI_Type_free(&ctType);CHKERRQ(ierr);
403475d3a19aSMatthew G. Knepley     ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr);
4035412e9a14SMatthew G. Knepley     ierr = PetscMalloc1(numNeighbors, &crRem);CHKERRQ(ierr);
4036412e9a14SMatthew G. Knepley     for (n = 0; n < numNeighbors; ++n) {
4037412e9a14SMatthew G. Knepley       ierr = DMPlexCellRefinerCreate(dm, &crRem[n]);CHKERRQ(ierr);
4038412e9a14SMatthew G. Knepley       ierr = DMPlexCellRefinerSetStarts(crRem[n], &ctStartRem[n*ctSize], &ctStartNewRem[n*ctSize]);
4039412e9a14SMatthew G. Knepley       ierr = DMPlexCellRefinerSetUp(crRem[n]);CHKERRQ(ierr);
4040412e9a14SMatthew G. Knepley     }
4041412e9a14SMatthew G. Knepley     ierr = PetscFree2(ctStartRem, ctStartNewRem);CHKERRQ(ierr);
404275d3a19aSMatthew G. Knepley     /* Calculate new point SF */
4043785e854fSJed Brown     ierr = PetscMalloc1(numLeavesNew, &localPointsNew);CHKERRQ(ierr);
4044785e854fSJed Brown     ierr = PetscMalloc1(numLeavesNew, &remotePointsNew);CHKERRQ(ierr);
404575d3a19aSMatthew G. Knepley     ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr);
404675d3a19aSMatthew G. Knepley     for (l = 0, m = 0; l < numLeaves; ++l) {
404775d3a19aSMatthew G. Knepley       PetscInt        p       = localPoints[l];
4048412e9a14SMatthew G. Knepley       PetscInt        pRem    = remotePoints[l].index;
4049412e9a14SMatthew G. Knepley       PetscMPIInt     rankRem = remotePoints[l].rank;
4050412e9a14SMatthew G. Knepley       DMPolytopeType  ct;
4051412e9a14SMatthew G. Knepley       DMPolytopeType *rct;
4052412e9a14SMatthew G. Knepley       PetscInt       *rsize, *rcone, *rornt;
4053412e9a14SMatthew G. Knepley       PetscInt        neighbor, Nct, n, r;
405475d3a19aSMatthew G. Knepley 
4055412e9a14SMatthew G. Knepley       ierr = PetscFindInt(rankRem, numNeighbors, neighbors, &neighbor);CHKERRQ(ierr);
4056412e9a14SMatthew G. Knepley       if (neighbor < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %D", rankRem);
4057412e9a14SMatthew G. Knepley       ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
40583f2a96e3SMatthew G. Knepley       ierr = DMPlexCellRefinerRefine(cr, ct, p, NULL, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
4059412e9a14SMatthew G. Knepley       for (n = 0; n < Nct; ++n) {
4060412e9a14SMatthew G. Knepley         for (r = 0; r < rsize[n]; ++r) {
4061412e9a14SMatthew G. Knepley           ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], p, r, &pNew);CHKERRQ(ierr);
4062412e9a14SMatthew G. Knepley           ierr = DMPlexCellRefinerGetNewPoint(crRem[neighbor], ct, rct[n], pRem, r, &pNewRem);CHKERRQ(ierr);
4063412e9a14SMatthew G. Knepley           localPointsNew[m]        = pNew;
4064412e9a14SMatthew G. Knepley           remotePointsNew[m].index = pNewRem;
4065412e9a14SMatthew G. Knepley           remotePointsNew[m].rank  = rankRem;
40660314a74cSLawrence Mitchell           ++m;
40670314a74cSLawrence Mitchell         }
40686ce3c06aSMatthew G. Knepley       }
40696ce3c06aSMatthew G. Knepley     }
4070412e9a14SMatthew G. Knepley     for (n = 0; n < numNeighbors; ++n) {ierr = DMPlexCellRefinerDestroy(&crRem[n]);CHKERRQ(ierr);}
4071412e9a14SMatthew G. Knepley     ierr = PetscFree(crRem);CHKERRQ(ierr);
4072d7eabd03SStefano Zampini     if (m != numLeavesNew) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of leaf point %D should be %D", m, numLeavesNew);
407375d3a19aSMatthew G. Knepley     ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr);
407475d3a19aSMatthew G. Knepley     ierr = ISDestroy(&processRanks);CHKERRQ(ierr);
40753f2a96e3SMatthew G. Knepley   }
4076ba3c3d50SMatthew G. Knepley   {
4077ba3c3d50SMatthew G. Knepley     PetscSFNode *rp, *rtmp;
4078ba3c3d50SMatthew G. Knepley     PetscInt    *lp, *idx, *ltmp, i;
4079ba3c3d50SMatthew G. Knepley 
4080ba3c3d50SMatthew G. Knepley     /* SF needs sorted leaves to correct calculate Gather */
4081ba3c3d50SMatthew G. Knepley     ierr = PetscMalloc1(numLeavesNew, &idx);CHKERRQ(ierr);
4082ba3c3d50SMatthew G. Knepley     ierr = PetscMalloc1(numLeavesNew, &lp);CHKERRQ(ierr);
4083ba3c3d50SMatthew G. Knepley     ierr = PetscMalloc1(numLeavesNew, &rp);CHKERRQ(ierr);
4084c7c54c77SMatthew G. Knepley     for (i = 0; i < numLeavesNew; ++i) {
4085d7eabd03SStefano 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);
4086c7c54c77SMatthew G. Knepley       idx[i] = i;
4087c7c54c77SMatthew G. Knepley     }
4088ba3c3d50SMatthew G. Knepley     ierr = PetscSortIntWithPermutation(numLeavesNew, localPointsNew, idx);CHKERRQ(ierr);
4089ba3c3d50SMatthew G. Knepley     for (i = 0; i < numLeavesNew; ++i) {
4090ba3c3d50SMatthew G. Knepley       lp[i] = localPointsNew[idx[i]];
4091ba3c3d50SMatthew G. Knepley       rp[i] = remotePointsNew[idx[i]];
4092ba3c3d50SMatthew G. Knepley     }
4093ba3c3d50SMatthew G. Knepley     ltmp            = localPointsNew;
4094ba3c3d50SMatthew G. Knepley     localPointsNew  = lp;
4095ba3c3d50SMatthew G. Knepley     rtmp            = remotePointsNew;
4096ba3c3d50SMatthew G. Knepley     remotePointsNew = rp;
4097ba3c3d50SMatthew G. Knepley     ierr = PetscFree(idx);CHKERRQ(ierr);
4098ba3c3d50SMatthew G. Knepley     ierr = PetscFree(ltmp);CHKERRQ(ierr);
4099ba3c3d50SMatthew G. Knepley     ierr = PetscFree(rtmp);CHKERRQ(ierr);
4100ba3c3d50SMatthew G. Knepley   }
410175d3a19aSMatthew G. Knepley   ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr);
410275d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
410375d3a19aSMatthew G. Knepley }
410475d3a19aSMatthew G. Knepley 
4105e7887635SMatthew G. Knepley static PetscErrorCode RefineLabel_Internal(DMPlexCellRefiner cr, DMLabel label, DMLabel labelNew)
410675d3a19aSMatthew G. Knepley {
4107412e9a14SMatthew G. Knepley   DM              dm = cr->dm;
4108e7887635SMatthew G. Knepley   IS              valueIS;
4109e7887635SMatthew G. Knepley   const PetscInt *values;
4110e7887635SMatthew G. Knepley   PetscInt        defVal, Nv, val;
411175d3a19aSMatthew G. Knepley   PetscErrorCode  ierr;
411275d3a19aSMatthew G. Knepley 
411375d3a19aSMatthew G. Knepley   PetscFunctionBegin;
41145aa44df4SToby Isaac   ierr = DMLabelGetDefaultValue(label, &defVal);CHKERRQ(ierr);
41155aa44df4SToby Isaac   ierr = DMLabelSetDefaultValue(labelNew, defVal);CHKERRQ(ierr);
411675d3a19aSMatthew G. Knepley   ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr);
4117e7887635SMatthew G. Knepley   ierr = ISGetLocalSize(valueIS, &Nv);CHKERRQ(ierr);
411875d3a19aSMatthew G. Knepley   ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr);
4119e7887635SMatthew G. Knepley   for (val = 0; val < Nv; ++val) {
412075d3a19aSMatthew G. Knepley     IS              pointIS;
412175d3a19aSMatthew G. Knepley     const PetscInt *points;
4122412e9a14SMatthew G. Knepley     PetscInt        numPoints, p;
412375d3a19aSMatthew G. Knepley 
41242bc5314cSMichael Lange     /* Ensure refined label is created with same number of strata as
41252bc5314cSMichael Lange      * original (even if no entries here). */
4126ad8374ffSToby Isaac     ierr = DMLabelAddStratum(labelNew, values[val]);CHKERRQ(ierr);
4127412e9a14SMatthew G. Knepley     ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr);
4128412e9a14SMatthew G. Knepley     ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr);
4129412e9a14SMatthew G. Knepley     ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr);
4130412e9a14SMatthew G. Knepley     for (p = 0; p < numPoints; ++p) {
4131412e9a14SMatthew G. Knepley       const PetscInt  point = points[p];
4132412e9a14SMatthew G. Knepley       DMPolytopeType  ct;
4133412e9a14SMatthew G. Knepley       DMPolytopeType *rct;
4134412e9a14SMatthew G. Knepley       PetscInt       *rsize, *rcone, *rornt;
4135e7887635SMatthew G. Knepley       PetscInt        Nct, n, r, pNew;
4136412e9a14SMatthew G. Knepley 
4137412e9a14SMatthew G. Knepley       ierr = DMPlexGetCellType(dm, point, &ct);CHKERRQ(ierr);
41383f2a96e3SMatthew G. Knepley       ierr = DMPlexCellRefinerRefine(cr, ct, point, NULL, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
4139412e9a14SMatthew G. Knepley       for (n = 0; n < Nct; ++n) {
4140412e9a14SMatthew G. Knepley         for (r = 0; r < rsize[n]; ++r) {
4141412e9a14SMatthew G. Knepley           ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], point, r, &pNew);CHKERRQ(ierr);
4142412e9a14SMatthew G. Knepley           ierr = DMLabelSetValue(labelNew, pNew, values[val]);CHKERRQ(ierr);
414327fcede3SMatthew G. Knepley         }
414475d3a19aSMatthew G. Knepley       }
414575d3a19aSMatthew G. Knepley     }
414675d3a19aSMatthew G. Knepley     ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr);
414775d3a19aSMatthew G. Knepley     ierr = ISDestroy(&pointIS);CHKERRQ(ierr);
414875d3a19aSMatthew G. Knepley   }
414975d3a19aSMatthew G. Knepley   ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr);
415075d3a19aSMatthew G. Knepley   ierr = ISDestroy(&valueIS);CHKERRQ(ierr);
4151e7887635SMatthew G. Knepley   PetscFunctionReturn(0);
4152e7887635SMatthew G. Knepley }
4153e7887635SMatthew G. Knepley 
4154e7887635SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerCreateLabels(DMPlexCellRefiner cr, DM rdm)
4155e7887635SMatthew G. Knepley {
4156e7887635SMatthew G. Knepley   DM             dm = cr->dm;
4157e7887635SMatthew G. Knepley   PetscInt       numLabels, l;
4158e7887635SMatthew G. Knepley   PetscErrorCode ierr;
4159e7887635SMatthew G. Knepley 
4160e7887635SMatthew G. Knepley   PetscFunctionBegin;
4161e7887635SMatthew G. Knepley   ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr);
4162e7887635SMatthew G. Knepley   for (l = 0; l < numLabels; ++l) {
4163e7887635SMatthew G. Knepley     DMLabel         label, labelNew;
4164e7887635SMatthew G. Knepley     const char     *lname;
4165e7887635SMatthew G. Knepley     PetscBool       isDepth, isCellType;
4166e7887635SMatthew G. Knepley 
4167e7887635SMatthew G. Knepley     ierr = DMGetLabelName(dm, l, &lname);CHKERRQ(ierr);
4168e7887635SMatthew G. Knepley     ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr);
4169e7887635SMatthew G. Knepley     if (isDepth) continue;
4170e7887635SMatthew G. Knepley     ierr = PetscStrcmp(lname, "celltype", &isCellType);CHKERRQ(ierr);
4171e7887635SMatthew G. Knepley     if (isCellType) continue;
4172e7887635SMatthew G. Knepley     ierr = DMCreateLabel(rdm, lname);CHKERRQ(ierr);
4173e7887635SMatthew G. Knepley     ierr = DMGetLabel(dm, lname, &label);CHKERRQ(ierr);
4174e7887635SMatthew G. Knepley     ierr = DMGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr);
4175e7887635SMatthew G. Knepley     ierr = RefineLabel_Internal(cr, label, labelNew);CHKERRQ(ierr);
417675d3a19aSMatthew G. Knepley   }
417775d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
417875d3a19aSMatthew G. Knepley }
417975d3a19aSMatthew G. Knepley 
418075d3a19aSMatthew G. Knepley /* This will only work for interpolated meshes */
4181412e9a14SMatthew G. Knepley PetscErrorCode DMPlexRefineUniform(DM dm, DMPlexCellRefiner cr, DM *dmRefined)
418275d3a19aSMatthew G. Knepley {
418375d3a19aSMatthew G. Knepley   DM              rdm;
4184412e9a14SMatthew G. Knepley   PetscInt        dim, embedDim, depth;
418575d3a19aSMatthew G. Knepley   PetscErrorCode  ierr;
418675d3a19aSMatthew G. Knepley 
418775d3a19aSMatthew G. Knepley   PetscFunctionBegin;
4188412e9a14SMatthew G. Knepley   PetscValidHeader(cr, 1);
418975d3a19aSMatthew G. Knepley   ierr = DMCreate(PetscObjectComm((PetscObject)dm), &rdm);CHKERRQ(ierr);
419075d3a19aSMatthew G. Knepley   ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr);
4191c73cfb54SMatthew G. Knepley   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
4192c73cfb54SMatthew G. Knepley   ierr = DMSetDimension(rdm, dim);CHKERRQ(ierr);
41936dcbd917SStefano Zampini   ierr = DMGetCoordinateDim(dm, &embedDim);CHKERRQ(ierr);
41946dcbd917SStefano Zampini   ierr = DMSetCoordinateDim(rdm, embedDim);CHKERRQ(ierr);
419575d3a19aSMatthew G. Knepley   /* Calculate number of new points of each depth */
419675d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
41971e573d11SMatthew G. Knepley   if (depth >= 0 && dim != depth) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Mesh must be interpolated for regular refinement");
419875d3a19aSMatthew G. Knepley   /* Step 1: Set chart */
4199412e9a14SMatthew G. Knepley   ierr = DMPlexSetChart(rdm, 0, cr->ctStartNew[cr->ctOrder[DM_NUM_POLYTOPES]]);CHKERRQ(ierr);
42006d7373e8SToby Isaac   /* Step 2: Set cone/support sizes (automatically stratifies) */
4201412e9a14SMatthew G. Knepley   ierr = DMPlexCellRefinerSetConeSizes(cr, rdm);CHKERRQ(ierr);
420275d3a19aSMatthew G. Knepley   /* Step 3: Setup refined DM */
420375d3a19aSMatthew G. Knepley   ierr = DMSetUp(rdm);CHKERRQ(ierr);
42046d7373e8SToby Isaac   /* Step 4: Set cones and supports (automatically symmetrizes) */
4205412e9a14SMatthew G. Knepley   ierr = DMPlexCellRefinerSetCones(cr, rdm);CHKERRQ(ierr);
42066d7373e8SToby Isaac   /* Step 5: Create pointSF */
4207412e9a14SMatthew G. Knepley   ierr = DMPlexCellRefinerCreateSF(cr, rdm);CHKERRQ(ierr);
42086d7373e8SToby Isaac   /* Step 6: Create labels */
4209412e9a14SMatthew G. Knepley   ierr = DMPlexCellRefinerCreateLabels(cr, rdm);CHKERRQ(ierr);
42106d7373e8SToby Isaac   /* Step 7: Set coordinates */
4211412e9a14SMatthew G. Knepley   ierr = DMPlexCellRefinerSetCoordinates(cr, rdm);CHKERRQ(ierr);
421275d3a19aSMatthew G. Knepley   *dmRefined = rdm;
421375d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
421475d3a19aSMatthew G. Knepley }
421575d3a19aSMatthew G. Knepley 
42162389894bSMatthew G. Knepley /*@
42172389894bSMatthew G. Knepley   DMPlexCreateCoarsePointIS - Creates an IS covering the coarse DM chart with the fine points as data
42182389894bSMatthew G. Knepley 
42192389894bSMatthew G. Knepley   Input Parameter:
42202389894bSMatthew G. Knepley . dm - The coarse DM
42212389894bSMatthew G. Knepley 
42222389894bSMatthew G. Knepley   Output Parameter:
42232389894bSMatthew G. Knepley . fpointIS - The IS of all the fine points which exist in the original coarse mesh
42242389894bSMatthew G. Knepley 
42252389894bSMatthew G. Knepley   Level: developer
42262389894bSMatthew G. Knepley 
422797d8846cSMatthew Knepley .seealso: DMRefine(), DMPlexSetRefinementUniform(), DMPlexGetSubpointIS()
42282389894bSMatthew G. Knepley @*/
42292389894bSMatthew G. Knepley PetscErrorCode DMPlexCreateCoarsePointIS(DM dm, IS *fpointIS)
42302389894bSMatthew G. Knepley {
4231412e9a14SMatthew G. Knepley   DMPlexCellRefiner cr;
4232412e9a14SMatthew G. Knepley   PetscInt         *fpoints;
4233327c2912SStefano Zampini   PetscInt          pStart, pEnd, p, vStart, vEnd, v;
42342389894bSMatthew G. Knepley   PetscErrorCode    ierr;
42352389894bSMatthew G. Knepley 
42362389894bSMatthew G. Knepley   PetscFunctionBegin;
42372389894bSMatthew G. Knepley   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
42382389894bSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
4239412e9a14SMatthew G. Knepley   ierr = DMPlexCellRefinerCreate(dm, &cr);CHKERRQ(ierr);
4240412e9a14SMatthew G. Knepley   ierr = DMPlexCellRefinerSetUp(cr);CHKERRQ(ierr);
42412389894bSMatthew G. Knepley   ierr = PetscMalloc1(pEnd-pStart, &fpoints);CHKERRQ(ierr);
42422389894bSMatthew G. Knepley   for (p = 0; p < pEnd-pStart; ++p) fpoints[p] = -1;
4243412e9a14SMatthew G. Knepley   for (v = vStart; v < vEnd; ++v) {
4244327c2912SStefano Zampini     PetscInt vNew = -1; /* silent overzelous may be used uninitialized */
4245327c2912SStefano Zampini 
4246412e9a14SMatthew G. Knepley     ierr = DMPlexCellRefinerGetNewPoint(cr, DM_POLYTOPE_POINT, DM_POLYTOPE_POINT, p, 0, &vNew);CHKERRQ(ierr);
4247412e9a14SMatthew G. Knepley     fpoints[v-pStart] = vNew;
42482389894bSMatthew G. Knepley   }
4249412e9a14SMatthew G. Knepley   ierr = DMPlexCellRefinerDestroy(&cr);CHKERRQ(ierr);
42502389894bSMatthew G. Knepley   ierr = ISCreateGeneral(PETSC_COMM_SELF, pEnd-pStart, fpoints, PETSC_OWN_POINTER, fpointIS);CHKERRQ(ierr);
42512389894bSMatthew G. Knepley   PetscFunctionReturn(0);
42522389894bSMatthew G. Knepley }
42532389894bSMatthew G. Knepley 
42540e2b6761SMatthew G. Knepley /*@
42550e2b6761SMatthew G. Knepley   DMPlexSetRefinementUniform - Set the flag for uniform refinement
42560e2b6761SMatthew G. Knepley 
42570e2b6761SMatthew G. Knepley   Input Parameters:
42580e2b6761SMatthew G. Knepley + dm - The DM
42590e2b6761SMatthew G. Knepley - refinementUniform - The flag for uniform refinement
42600e2b6761SMatthew G. Knepley 
42610e2b6761SMatthew G. Knepley   Level: developer
42620e2b6761SMatthew G. Knepley 
42630e2b6761SMatthew G. Knepley .seealso: DMRefine(), DMPlexGetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
42640e2b6761SMatthew G. Knepley @*/
426575d3a19aSMatthew G. Knepley PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform)
426675d3a19aSMatthew G. Knepley {
426775d3a19aSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
426875d3a19aSMatthew G. Knepley 
426975d3a19aSMatthew G. Knepley   PetscFunctionBegin;
427075d3a19aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
427175d3a19aSMatthew G. Knepley   mesh->refinementUniform = refinementUniform;
427275d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
427375d3a19aSMatthew G. Knepley }
427475d3a19aSMatthew G. Knepley 
42750e2b6761SMatthew G. Knepley /*@
42760e2b6761SMatthew G. Knepley   DMPlexGetRefinementUniform - Retrieve the flag for uniform refinement
42770e2b6761SMatthew G. Knepley 
42780e2b6761SMatthew G. Knepley   Input Parameter:
42790e2b6761SMatthew G. Knepley . dm - The DM
42800e2b6761SMatthew G. Knepley 
42810e2b6761SMatthew G. Knepley   Output Parameter:
42820e2b6761SMatthew G. Knepley . refinementUniform - The flag for uniform refinement
42830e2b6761SMatthew G. Knepley 
42840e2b6761SMatthew G. Knepley   Level: developer
42850e2b6761SMatthew G. Knepley 
42860e2b6761SMatthew G. Knepley .seealso: DMRefine(), DMPlexSetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
42870e2b6761SMatthew G. Knepley @*/
428875d3a19aSMatthew G. Knepley PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform)
428975d3a19aSMatthew G. Knepley {
429075d3a19aSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
429175d3a19aSMatthew G. Knepley 
429275d3a19aSMatthew G. Knepley   PetscFunctionBegin;
429375d3a19aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
429475d3a19aSMatthew G. Knepley   PetscValidPointer(refinementUniform,  2);
429575d3a19aSMatthew G. Knepley   *refinementUniform = mesh->refinementUniform;
429675d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
429775d3a19aSMatthew G. Knepley }
429875d3a19aSMatthew G. Knepley 
42990e2b6761SMatthew G. Knepley /*@
43000e2b6761SMatthew G. Knepley   DMPlexSetRefinementLimit - Set the maximum cell volume for refinement
43010e2b6761SMatthew G. Knepley 
43020e2b6761SMatthew G. Knepley   Input Parameters:
43030e2b6761SMatthew G. Knepley + dm - The DM
43040e2b6761SMatthew G. Knepley - refinementLimit - The maximum cell volume in the refined mesh
43050e2b6761SMatthew G. Knepley 
43060e2b6761SMatthew G. Knepley   Level: developer
43070e2b6761SMatthew G. Knepley 
43080e2b6761SMatthew G. Knepley .seealso: DMRefine(), DMPlexGetRefinementLimit(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform()
43090e2b6761SMatthew G. Knepley @*/
431075d3a19aSMatthew G. Knepley PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit)
431175d3a19aSMatthew G. Knepley {
431275d3a19aSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
431375d3a19aSMatthew G. Knepley 
431475d3a19aSMatthew G. Knepley   PetscFunctionBegin;
431575d3a19aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
431675d3a19aSMatthew G. Knepley   mesh->refinementLimit = refinementLimit;
431775d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
431875d3a19aSMatthew G. Knepley }
431975d3a19aSMatthew G. Knepley 
43200e2b6761SMatthew G. Knepley /*@
43210e2b6761SMatthew G. Knepley   DMPlexGetRefinementLimit - Retrieve the maximum cell volume for refinement
43220e2b6761SMatthew G. Knepley 
43230e2b6761SMatthew G. Knepley   Input Parameter:
43240e2b6761SMatthew G. Knepley . dm - The DM
43250e2b6761SMatthew G. Knepley 
43260e2b6761SMatthew G. Knepley   Output Parameter:
43270e2b6761SMatthew G. Knepley . refinementLimit - The maximum cell volume in the refined mesh
43280e2b6761SMatthew G. Knepley 
43290e2b6761SMatthew G. Knepley   Level: developer
43300e2b6761SMatthew G. Knepley 
43310e2b6761SMatthew G. Knepley .seealso: DMRefine(), DMPlexSetRefinementLimit(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform()
43320e2b6761SMatthew G. Knepley @*/
433375d3a19aSMatthew G. Knepley PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit)
433475d3a19aSMatthew G. Knepley {
433575d3a19aSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
433675d3a19aSMatthew G. Knepley 
433775d3a19aSMatthew G. Knepley   PetscFunctionBegin;
433875d3a19aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
433975d3a19aSMatthew G. Knepley   PetscValidPointer(refinementLimit,  2);
434075d3a19aSMatthew G. Knepley   /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */
434175d3a19aSMatthew G. Knepley   *refinementLimit = mesh->refinementLimit;
434275d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
434375d3a19aSMatthew G. Knepley }
434475d3a19aSMatthew G. Knepley 
4345b28003e6SMatthew G. Knepley /*@
4346b28003e6SMatthew G. Knepley   DMPlexSetRefinementFunction - Set the function giving the maximum cell volume for refinement
4347b28003e6SMatthew G. Knepley 
4348b28003e6SMatthew G. Knepley   Input Parameters:
4349b28003e6SMatthew G. Knepley + dm - The DM
4350b28003e6SMatthew G. Knepley - refinementFunc - Function giving the maximum cell volume in the refined mesh
4351b28003e6SMatthew G. Knepley 
4352b28003e6SMatthew G. Knepley   Note: The calling sequence is refinementFunc(coords, limit)
4353b28003e6SMatthew G. Knepley $ coords - Coordinates of the current point, usually a cell centroid
4354b28003e6SMatthew G. Knepley $ limit  - The maximum cell volume for a cell containing this point
4355b28003e6SMatthew G. Knepley 
4356b28003e6SMatthew G. Knepley   Level: developer
4357b28003e6SMatthew G. Knepley 
4358b28003e6SMatthew G. Knepley .seealso: DMRefine(), DMPlexGetRefinementFunction(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
4359b28003e6SMatthew G. Knepley @*/
4360b28003e6SMatthew G. Knepley PetscErrorCode DMPlexSetRefinementFunction(DM dm, PetscErrorCode (*refinementFunc)(const PetscReal [], PetscReal *))
4361b28003e6SMatthew G. Knepley {
4362b28003e6SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
4363b28003e6SMatthew G. Knepley 
4364b28003e6SMatthew G. Knepley   PetscFunctionBegin;
4365b28003e6SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4366b28003e6SMatthew G. Knepley   mesh->refinementFunc = refinementFunc;
4367b28003e6SMatthew G. Knepley   PetscFunctionReturn(0);
4368b28003e6SMatthew G. Knepley }
4369b28003e6SMatthew G. Knepley 
4370b28003e6SMatthew G. Knepley /*@
4371b28003e6SMatthew G. Knepley   DMPlexGetRefinementFunction - Get the function giving the maximum cell volume for refinement
4372b28003e6SMatthew G. Knepley 
4373b28003e6SMatthew G. Knepley   Input Parameter:
4374b28003e6SMatthew G. Knepley . dm - The DM
4375b28003e6SMatthew G. Knepley 
4376b28003e6SMatthew G. Knepley   Output Parameter:
4377b28003e6SMatthew G. Knepley . refinementFunc - Function giving the maximum cell volume in the refined mesh
4378b28003e6SMatthew G. Knepley 
4379b28003e6SMatthew G. Knepley   Note: The calling sequence is refinementFunc(coords, limit)
4380b28003e6SMatthew G. Knepley $ coords - Coordinates of the current point, usually a cell centroid
4381b28003e6SMatthew G. Knepley $ limit  - The maximum cell volume for a cell containing this point
4382b28003e6SMatthew G. Knepley 
4383b28003e6SMatthew G. Knepley   Level: developer
4384b28003e6SMatthew G. Knepley 
4385b28003e6SMatthew G. Knepley .seealso: DMRefine(), DMPlexSetRefinementFunction(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
4386b28003e6SMatthew G. Knepley @*/
4387b28003e6SMatthew G. Knepley PetscErrorCode DMPlexGetRefinementFunction(DM dm, PetscErrorCode (**refinementFunc)(const PetscReal [], PetscReal *))
4388b28003e6SMatthew G. Knepley {
4389b28003e6SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
4390b28003e6SMatthew G. Knepley 
4391b28003e6SMatthew G. Knepley   PetscFunctionBegin;
4392b28003e6SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4393b28003e6SMatthew G. Knepley   PetscValidPointer(refinementFunc,  2);
4394b28003e6SMatthew G. Knepley   *refinementFunc = mesh->refinementFunc;
4395b28003e6SMatthew G. Knepley   PetscFunctionReturn(0);
4396b28003e6SMatthew G. Knepley }
4397b28003e6SMatthew G. Knepley 
4398e7887635SMatthew G. Knepley static PetscErrorCode RefineDiscLabels_Internal(DMPlexCellRefiner cr, DM rdm)
4399e7887635SMatthew G. Knepley {
4400e7887635SMatthew G. Knepley   DM             dm = cr->dm;
4401e7887635SMatthew G. Knepley   PetscInt       Nf, f, Nds, s;
4402e7887635SMatthew G. Knepley   PetscErrorCode ierr;
4403e7887635SMatthew G. Knepley 
4404e7887635SMatthew G. Knepley   PetscFunctionBegin;
4405e7887635SMatthew G. Knepley   ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr);
4406e7887635SMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
4407e7887635SMatthew G. Knepley     DMLabel     label, labelNew;
4408e7887635SMatthew G. Knepley     PetscObject obj;
4409e7887635SMatthew G. Knepley     const char *lname;
4410e7887635SMatthew G. Knepley 
4411e7887635SMatthew G. Knepley     ierr = DMGetField(rdm, f, &label, &obj);CHKERRQ(ierr);
4412e7887635SMatthew G. Knepley     if (!label) continue;
4413e7887635SMatthew G. Knepley     ierr = PetscObjectGetName((PetscObject) label, &lname);CHKERRQ(ierr);
4414e7887635SMatthew G. Knepley     ierr = DMLabelCreate(PETSC_COMM_SELF, lname, &labelNew);CHKERRQ(ierr);
4415e7887635SMatthew G. Knepley     ierr = RefineLabel_Internal(cr, label, labelNew);CHKERRQ(ierr);
4416e7887635SMatthew G. Knepley     ierr = DMSetField_Internal(rdm, f, labelNew, obj);CHKERRQ(ierr);
4417e7887635SMatthew G. Knepley     ierr = DMLabelDestroy(&labelNew);CHKERRQ(ierr);
4418e7887635SMatthew G. Knepley   }
4419e7887635SMatthew G. Knepley   ierr = DMGetNumDS(dm, &Nds);CHKERRQ(ierr);
4420e7887635SMatthew G. Knepley   for (s = 0; s < Nds; ++s) {
4421e7887635SMatthew G. Knepley     DMLabel     label, labelNew;
4422e7887635SMatthew G. Knepley     const char *lname;
4423e7887635SMatthew G. Knepley 
4424e7887635SMatthew G. Knepley     ierr = DMGetRegionNumDS(rdm, s, &label, NULL, NULL);CHKERRQ(ierr);
4425e7887635SMatthew G. Knepley     if (!label) continue;
4426e7887635SMatthew G. Knepley     ierr = PetscObjectGetName((PetscObject) label, &lname);CHKERRQ(ierr);
4427e7887635SMatthew G. Knepley     ierr = DMLabelCreate(PETSC_COMM_SELF, lname, &labelNew);CHKERRQ(ierr);
4428e7887635SMatthew G. Knepley     ierr = RefineLabel_Internal(cr, label, labelNew);CHKERRQ(ierr);
4429e7887635SMatthew G. Knepley     ierr = DMSetRegionNumDS(rdm, s, labelNew, NULL, NULL);CHKERRQ(ierr);
4430e7887635SMatthew G. Knepley     ierr = DMLabelDestroy(&labelNew);CHKERRQ(ierr);
4431e7887635SMatthew G. Knepley   }
4432e7887635SMatthew G. Knepley   PetscFunctionReturn(0);
4433e7887635SMatthew G. Knepley }
4434e7887635SMatthew G. Knepley 
44353f2a96e3SMatthew G. Knepley PetscErrorCode DMPlexCellRefinerAdaptLabel(DM dm, DMLabel adaptLabel, DM *dmRefined)
44363f2a96e3SMatthew G. Knepley {
44373f2a96e3SMatthew G. Knepley   DMPlexCellRefiner cr;
44383f2a96e3SMatthew G. Knepley   DM                cdm, rcdm;
44393f2a96e3SMatthew G. Knepley   PetscErrorCode    ierr;
44403f2a96e3SMatthew G. Knepley 
44413f2a96e3SMatthew G. Knepley   PetscFunctionBegin;
44423f2a96e3SMatthew G. Knepley   ierr = DMPlexCellRefinerCreate(dm, &cr);CHKERRQ(ierr);
44433f2a96e3SMatthew G. Knepley   cr->adaptLabel = adaptLabel;
44443f2a96e3SMatthew G. Knepley   ierr = DMPlexCellRefinerSetUp(cr);CHKERRQ(ierr);
44453f2a96e3SMatthew G. Knepley   ierr = DMPlexRefineUniform(dm, cr, dmRefined);CHKERRQ(ierr);
44463f2a96e3SMatthew G. Knepley   ierr = DMCopyDisc(dm, *dmRefined);CHKERRQ(ierr);
44473f2a96e3SMatthew G. Knepley   ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
44483f2a96e3SMatthew G. Knepley   ierr = DMGetCoordinateDM(*dmRefined, &rcdm);CHKERRQ(ierr);
44493f2a96e3SMatthew G. Knepley   ierr = DMCopyDisc(cdm, rcdm);CHKERRQ(ierr);
44503f2a96e3SMatthew G. Knepley   ierr = RefineDiscLabels_Internal(cr, *dmRefined);CHKERRQ(ierr);
44513f2a96e3SMatthew G. Knepley   ierr = DMCopyBoundary(dm, *dmRefined);CHKERRQ(ierr);
44523f2a96e3SMatthew G. Knepley   ierr = DMPlexCellRefinerDestroy(&cr);CHKERRQ(ierr);
44533f2a96e3SMatthew G. Knepley   PetscFunctionReturn(0);
44543f2a96e3SMatthew G. Knepley }
44553f2a96e3SMatthew G. Knepley 
44560d1cd5e0SMatthew G. Knepley PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined)
44570d1cd5e0SMatthew G. Knepley {
4458492b8470SStefano Zampini   PetscBool         isUniform;
4459412e9a14SMatthew G. Knepley   DMPlexCellRefiner cr;
44600d1cd5e0SMatthew G. Knepley   PetscErrorCode    ierr;
44610d1cd5e0SMatthew G. Knepley 
44620d1cd5e0SMatthew G. Knepley   PetscFunctionBegin;
44630d1cd5e0SMatthew G. Knepley   ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr);
4464412e9a14SMatthew G. Knepley   ierr = DMViewFromOptions(dm, NULL, "-initref_dm_view");CHKERRQ(ierr);
44650d1cd5e0SMatthew G. Knepley   if (isUniform) {
446651a74b61SMatthew G. Knepley     DM        cdm, rcdm;
4467492b8470SStefano Zampini     PetscBool localized;
44680d1cd5e0SMatthew G. Knepley 
4469412e9a14SMatthew G. Knepley     ierr = DMPlexCellRefinerCreate(dm, &cr);CHKERRQ(ierr);
4470412e9a14SMatthew G. Knepley     ierr = DMPlexCellRefinerSetUp(cr);CHKERRQ(ierr);
4471492b8470SStefano Zampini     ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr);
4472412e9a14SMatthew G. Knepley     ierr = DMPlexRefineUniform(dm, cr, dmRefined);CHKERRQ(ierr);
44739a7e3c0aSMatthew G. Knepley     ierr = DMPlexSetRegularRefinement(*dmRefined, PETSC_TRUE);CHKERRQ(ierr);
4474e7887635SMatthew G. Knepley     ierr = DMCopyDisc(dm, *dmRefined);CHKERRQ(ierr);
447551a74b61SMatthew G. Knepley     ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
447651a74b61SMatthew G. Knepley     ierr = DMGetCoordinateDM(*dmRefined, &rcdm);CHKERRQ(ierr);
447751a74b61SMatthew G. Knepley     ierr = DMCopyDisc(cdm, rcdm);CHKERRQ(ierr);
4478e7887635SMatthew G. Knepley     ierr = RefineDiscLabels_Internal(cr, *dmRefined);CHKERRQ(ierr);
44790d1cd5e0SMatthew G. Knepley     ierr = DMCopyBoundary(dm, *dmRefined);CHKERRQ(ierr);
4480412e9a14SMatthew G. Knepley     ierr = DMPlexCellRefinerDestroy(&cr);CHKERRQ(ierr);
44810d1cd5e0SMatthew G. Knepley   } else {
44820d1cd5e0SMatthew G. Knepley     ierr = DMPlexRefine_Internal(dm, NULL, dmRefined);CHKERRQ(ierr);
44830d1cd5e0SMatthew G. Knepley   }
4484*6d7c9049SMatthew G. Knepley   if (*dmRefined) {
4485*6d7c9049SMatthew G. Knepley     ((DM_Plex *) (*dmRefined)->data)->printFEM = ((DM_Plex *) dm->data)->printFEM;
4486*6d7c9049SMatthew G. Knepley     ((DM_Plex *) (*dmRefined)->data)->printL2  = ((DM_Plex *) dm->data)->printL2;
4487*6d7c9049SMatthew G. Knepley   }
44880d1cd5e0SMatthew G. Knepley   PetscFunctionReturn(0);
44890d1cd5e0SMatthew G. Knepley }
44900d1cd5e0SMatthew G. Knepley 
44910d1cd5e0SMatthew G. Knepley PetscErrorCode DMRefineHierarchy_Plex(DM dm, PetscInt nlevels, DM dmRefined[])
44920d1cd5e0SMatthew G. Knepley {
44930d1cd5e0SMatthew G. Knepley   DM             cdm = dm;
44940d1cd5e0SMatthew G. Knepley   PetscInt       r;
44950d1cd5e0SMatthew G. Knepley   PetscBool      isUniform, localized;
44960d1cd5e0SMatthew G. Knepley   PetscErrorCode ierr;
44970d1cd5e0SMatthew G. Knepley 
44980d1cd5e0SMatthew G. Knepley   PetscFunctionBegin;
44990d1cd5e0SMatthew G. Knepley   ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr);
45000d1cd5e0SMatthew G. Knepley   ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr);
45010d1cd5e0SMatthew G. Knepley   if (isUniform) {
45020d1cd5e0SMatthew G. Knepley     for (r = 0; r < nlevels; ++r) {
4503412e9a14SMatthew G. Knepley       DMPlexCellRefiner cr;
450451a74b61SMatthew G. Knepley       DM                codm, rcodm;
45050d1cd5e0SMatthew G. Knepley 
4506412e9a14SMatthew G. Knepley       ierr = DMPlexCellRefinerCreate(cdm, &cr);CHKERRQ(ierr);
4507412e9a14SMatthew G. Knepley       ierr = DMPlexCellRefinerSetUp(cr);CHKERRQ(ierr);
4508412e9a14SMatthew G. Knepley       ierr = DMPlexRefineUniform(cdm, cr, &dmRefined[r]);CHKERRQ(ierr);
45099a7e3c0aSMatthew G. Knepley       ierr = DMSetCoarsenLevel(dmRefined[r], cdm->leveldown);CHKERRQ(ierr);
45109a7e3c0aSMatthew G. Knepley       ierr = DMSetRefineLevel(dmRefined[r], cdm->levelup+1);CHKERRQ(ierr);
4511e7887635SMatthew G. Knepley       ierr = DMCopyDisc(cdm, dmRefined[r]);CHKERRQ(ierr);
451251a74b61SMatthew G. Knepley       ierr = DMGetCoordinateDM(dm, &codm);CHKERRQ(ierr);
451351a74b61SMatthew G. Knepley       ierr = DMGetCoordinateDM(dmRefined[r], &rcodm);CHKERRQ(ierr);
451451a74b61SMatthew G. Knepley       ierr = DMCopyDisc(codm, rcodm);CHKERRQ(ierr);
4515e7887635SMatthew G. Knepley       ierr = RefineDiscLabels_Internal(cr, dmRefined[r]);CHKERRQ(ierr);
45160d1cd5e0SMatthew G. Knepley       ierr = DMCopyBoundary(cdm, dmRefined[r]);CHKERRQ(ierr);
45170d1cd5e0SMatthew G. Knepley       ierr = DMSetCoarseDM(dmRefined[r], cdm);CHKERRQ(ierr);
45180d1cd5e0SMatthew G. Knepley       ierr = DMPlexSetRegularRefinement(dmRefined[r], PETSC_TRUE);CHKERRQ(ierr);
4519*6d7c9049SMatthew G. Knepley       if (dmRefined[r]) {
4520*6d7c9049SMatthew G. Knepley         ((DM_Plex *) (dmRefined[r])->data)->printFEM = ((DM_Plex *) dm->data)->printFEM;
4521*6d7c9049SMatthew G. Knepley         ((DM_Plex *) (dmRefined[r])->data)->printL2  = ((DM_Plex *) dm->data)->printL2;
4522*6d7c9049SMatthew G. Knepley       }
45230d1cd5e0SMatthew G. Knepley       cdm  = dmRefined[r];
4524412e9a14SMatthew G. Knepley       ierr = DMPlexCellRefinerDestroy(&cr);CHKERRQ(ierr);
45250d1cd5e0SMatthew G. Knepley     }
45260d1cd5e0SMatthew G. Knepley   } else {
45270d1cd5e0SMatthew G. Knepley     for (r = 0; r < nlevels; ++r) {
45280d1cd5e0SMatthew G. Knepley       ierr = DMRefine(cdm, PetscObjectComm((PetscObject) dm), &dmRefined[r]);CHKERRQ(ierr);
4529e7887635SMatthew G. Knepley       ierr = DMCopyDisc(cdm, dmRefined[r]);CHKERRQ(ierr);
45300d1cd5e0SMatthew G. Knepley       ierr = DMCopyBoundary(cdm, dmRefined[r]);CHKERRQ(ierr);
45310d1cd5e0SMatthew G. Knepley       if (localized) {ierr = DMLocalizeCoordinates(dmRefined[r]);CHKERRQ(ierr);}
45320d1cd5e0SMatthew G. Knepley       ierr = DMSetCoarseDM(dmRefined[r], cdm);CHKERRQ(ierr);
4533*6d7c9049SMatthew G. Knepley       if (dmRefined[r]) {
4534*6d7c9049SMatthew G. Knepley         ((DM_Plex *) (dmRefined[r])->data)->printFEM = ((DM_Plex *) dm->data)->printFEM;
4535*6d7c9049SMatthew G. Knepley         ((DM_Plex *) (dmRefined[r])->data)->printL2  = ((DM_Plex *) dm->data)->printL2;
4536*6d7c9049SMatthew G. Knepley       }
45370d1cd5e0SMatthew G. Knepley       cdm  = dmRefined[r];
45380d1cd5e0SMatthew G. Knepley     }
45390d1cd5e0SMatthew G. Knepley   }
45400d1cd5e0SMatthew G. Knepley   PetscFunctionReturn(0);
45410d1cd5e0SMatthew G. Knepley }
4542