xref: /petsc/src/dm/impls/plex/plexrefine.c (revision 97d8846ca695d7e93a80b03b34bde28fe6a79ca9)
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 
596ca5757SLisandro Dalcin const char * const DMPlexCellRefinerTypes[] = {"Regular", "ToBox", "ToSimplex", "DMPlexCellRefinerTypes", "DM_REFINER_", 0};
675d3a19aSMatthew G. Knepley 
709789c4cSMatthew G. Knepley /*
809789c4cSMatthew G. Knepley   Note that j and invj are non-square:
909789c4cSMatthew G. Knepley          v0 + j x_face = x_cell
1009789c4cSMatthew G. Knepley     invj (x_cell - v0) = x_face
1109789c4cSMatthew G. Knepley */
12412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerGetAffineFaceTransforms_Regular(DMPlexCellRefiner cr, DMPolytopeType ct, PetscInt *Nf, PetscReal *v0[], PetscReal *J[], PetscReal *invJ[], PetscReal *detJ[])
1309789c4cSMatthew G. Knepley {
1409789c4cSMatthew G. Knepley   /*
1509789c4cSMatthew G. Knepley    2
1609789c4cSMatthew G. Knepley    |\
1709789c4cSMatthew G. Knepley    | \
1809789c4cSMatthew G. Knepley    |  \
1909789c4cSMatthew G. Knepley    |   \
2009789c4cSMatthew G. Knepley    |    \
2109789c4cSMatthew G. Knepley    |     \
2209789c4cSMatthew G. Knepley    |      \
2309789c4cSMatthew G. Knepley    2       1
2409789c4cSMatthew G. Knepley    |        \
2509789c4cSMatthew G. Knepley    |         \
2609789c4cSMatthew G. Knepley    |          \
2709789c4cSMatthew G. Knepley    0---0-------1
28412e9a14SMatthew G. Knepley    v0[Nf][dc]:       3 x 2
29412e9a14SMatthew G. Knepley    J[Nf][df][dc]:    3 x 1 x 2
30412e9a14SMatthew G. Knepley    invJ[Nf][dc][df]: 3 x 2 x 1
31412e9a14SMatthew G. Knepley    detJ[Nf]:         3
3209789c4cSMatthew G. Knepley    */
33412e9a14SMatthew G. Knepley   static PetscReal tri_v0[]   = {0.0, -1.0,  0.0, 0.0,  -1.0,  0.0};
34412e9a14SMatthew G. Knepley   static PetscReal tri_J[]    = {1.0, 0.0,  -1.0, 1.0,   0.0, -1.0};
35412e9a14SMatthew G. Knepley   static PetscReal tri_invJ[] = {1.0, 0.0,  -0.5, 0.5,   0.0, -1.0};
36412e9a14SMatthew G. Knepley   static PetscReal tri_detJ[] = {1.0,  1.414213562373095,  1.0};
3709789c4cSMatthew G. Knepley   /*
3809789c4cSMatthew G. Knepley    3---------2---------2
3909789c4cSMatthew G. Knepley    |                   |
4009789c4cSMatthew G. Knepley    |                   |
4109789c4cSMatthew G. Knepley    |                   |
4209789c4cSMatthew G. Knepley    3                   1
4309789c4cSMatthew G. Knepley    |                   |
4409789c4cSMatthew G. Knepley    |                   |
4509789c4cSMatthew G. Knepley    |                   |
4609789c4cSMatthew G. Knepley    0---------0---------1
47412e9a14SMatthew G. Knepley 
48412e9a14SMatthew G. Knepley    v0[Nf][dc]:       4 x 2
49412e9a14SMatthew G. Knepley    J[Nf][df][dc]:    4 x 1 x 2
50412e9a14SMatthew G. Knepley    invJ[Nf][dc][df]: 4 x 2 x 1
51412e9a14SMatthew G. Knepley    detJ[Nf]:         4
5209789c4cSMatthew G. Knepley    */
53412e9a14SMatthew G. Knepley   static PetscReal quad_v0[]   = {0.0, -1.0,  1.0, 0.0,   0.0, 1.0  -1.0,  0.0};
54412e9a14SMatthew G. Knepley   static PetscReal quad_J[]    = {1.0, 0.0,   0.0, 1.0,  -1.0, 0.0,  0.0, -1.0};
55412e9a14SMatthew G. Knepley   static PetscReal quad_invJ[] = {1.0, 0.0,   0.0, 1.0,  -1.0, 0.0,  0.0, -1.0};
56412e9a14SMatthew G. Knepley   static PetscReal quad_detJ[] = {1.0,  1.0,  1.0,  1.0};
57412e9a14SMatthew G. Knepley 
58412e9a14SMatthew G. Knepley   PetscFunctionBegin;
59412e9a14SMatthew G. Knepley   switch (ct) {
60412e9a14SMatthew 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;
61412e9a14SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL: if (Nf) *Nf = 4; if (v0) *v0 = quad_v0; if (J) *J = quad_J; if (invJ) *invJ = quad_invJ; if (detJ) *detJ = quad_detJ; break;
6209789c4cSMatthew G. Knepley   default:
63412e9a14SMatthew G. Knepley     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unsupported polytope type %s", DMPolytopeTypes[ct]);
6409789c4cSMatthew G. Knepley   }
6509789c4cSMatthew G. Knepley   PetscFunctionReturn(0);
6609789c4cSMatthew G. Knepley }
6709789c4cSMatthew G. Knepley 
68bed052eaSMatthew G. Knepley /* Gets the affine map from the original cell to each subcell */
69412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerGetAffineTransforms_Regular(DMPlexCellRefiner cr, DMPolytopeType ct, PetscInt *Nc, PetscReal *v0[], PetscReal *J[], PetscReal *invJ[])
70bed052eaSMatthew G. Knepley {
71260b6d3fSMatthew G. Knepley   /*
72260b6d3fSMatthew G. Knepley    2
73260b6d3fSMatthew G. Knepley    |\
74260b6d3fSMatthew G. Knepley    | \
75260b6d3fSMatthew G. Knepley    |  \
76260b6d3fSMatthew G. Knepley    |   \
77260b6d3fSMatthew G. Knepley    | C  \
78260b6d3fSMatthew G. Knepley    |     \
79260b6d3fSMatthew G. Knepley    |      \
80260b6d3fSMatthew G. Knepley    2---1---1
81260b6d3fSMatthew G. Knepley    |\  D  / \
82260b6d3fSMatthew G. Knepley    | 2   0   \
83260b6d3fSMatthew G. Knepley    |A \ /  B  \
84260b6d3fSMatthew G. Knepley    0---0-------1
85260b6d3fSMatthew G. Knepley    */
86412e9a14SMatthew G. Knepley   static PetscReal tri_v0[]   = {-1.0, -1.0,  0.0, -1.0,  -1.0, 0.0,  0.0, -1.0};
87412e9a14SMatthew G. Knepley   static PetscReal tri_J[]    = {0.5, 0.0,
88412e9a14SMatthew G. Knepley                                  0.0, 0.5,
89412e9a14SMatthew G. Knepley 
90412e9a14SMatthew G. Knepley                                  0.5, 0.0,
91412e9a14SMatthew G. Knepley                                  0.0, 0.5,
92412e9a14SMatthew G. Knepley 
93412e9a14SMatthew G. Knepley                                  0.5, 0.0,
94412e9a14SMatthew G. Knepley                                  0.0, 0.5,
95412e9a14SMatthew G. Knepley 
96412e9a14SMatthew G. Knepley                                  0.0, -0.5,
97412e9a14SMatthew G. Knepley                                  0.5,  0.5};
98412e9a14SMatthew G. Knepley   static PetscReal tri_invJ[] = {2.0, 0.0,
99412e9a14SMatthew G. Knepley                                  0.0, 2.0,
100412e9a14SMatthew G. Knepley 
101412e9a14SMatthew G. Knepley                                  2.0, 0.0,
102412e9a14SMatthew G. Knepley                                  0.0, 2.0,
103412e9a14SMatthew G. Knepley 
104412e9a14SMatthew G. Knepley                                  2.0, 0.0,
105412e9a14SMatthew G. Knepley                                  0.0, 2.0,
106412e9a14SMatthew G. Knepley 
107412e9a14SMatthew G. Knepley                                  2.0,  2.0,
108412e9a14SMatthew G. Knepley                                 -2.0,  0.0};
109260b6d3fSMatthew G. Knepley     /*
110260b6d3fSMatthew G. Knepley      3---------2---------2
111260b6d3fSMatthew G. Knepley      |         |         |
112260b6d3fSMatthew G. Knepley      |    D    2    C    |
113260b6d3fSMatthew G. Knepley      |         |         |
114260b6d3fSMatthew G. Knepley      3----3----0----1----1
115260b6d3fSMatthew G. Knepley      |         |         |
116260b6d3fSMatthew G. Knepley      |    A    0    B    |
117260b6d3fSMatthew G. Knepley      |         |         |
118260b6d3fSMatthew G. Knepley      0---------0---------1
119260b6d3fSMatthew G. Knepley      */
120412e9a14SMatthew G. Knepley   static PetscReal quad_v0[]   = {-1.0, -1.0,  0.0, -1.0,  0.0, 0.0,  -1.0, 0.0};
121412e9a14SMatthew G. Knepley   static PetscReal quad_J[]    = {0.5, 0.0,
122412e9a14SMatthew G. Knepley                                   0.0, 0.5,
123412e9a14SMatthew G. Knepley 
124412e9a14SMatthew G. Knepley                                   0.5, 0.0,
125412e9a14SMatthew G. Knepley                                   0.0, 0.5,
126412e9a14SMatthew G. Knepley 
127412e9a14SMatthew G. Knepley                                   0.5, 0.0,
128412e9a14SMatthew G. Knepley                                   0.0, 0.5,
129412e9a14SMatthew G. Knepley 
130412e9a14SMatthew G. Knepley                                   0.5, 0.0,
131412e9a14SMatthew G. Knepley                                   0.0, 0.5};
132412e9a14SMatthew G. Knepley   static PetscReal quad_invJ[] = {2.0, 0.0,
133412e9a14SMatthew G. Knepley                                   0.0, 2.0,
134412e9a14SMatthew G. Knepley 
135412e9a14SMatthew G. Knepley                                   2.0, 0.0,
136412e9a14SMatthew G. Knepley                                   0.0, 2.0,
137412e9a14SMatthew G. Knepley 
138412e9a14SMatthew G. Knepley                                   2.0, 0.0,
139412e9a14SMatthew G. Knepley                                   0.0, 2.0,
140412e9a14SMatthew G. Knepley 
141412e9a14SMatthew G. Knepley                                   2.0, 0.0,
142412e9a14SMatthew G. Knepley                                   0.0, 2.0};
143c1879b55SMatthew G. Knepley     /*
144c1879b55SMatthew G. Knepley      Bottom (viewed from top)    Top
145c1879b55SMatthew G. Knepley      1---------2---------2       7---------2---------6
146c1879b55SMatthew G. Knepley      |         |         |       |         |         |
147c1879b55SMatthew G. Knepley      |    B    2    C    |       |    H    2    G    |
148c1879b55SMatthew G. Knepley      |         |         |       |         |         |
149c1879b55SMatthew G. Knepley      3----3----0----1----1       3----3----0----1----1
150c1879b55SMatthew G. Knepley      |         |         |       |         |         |
151c1879b55SMatthew G. Knepley      |    A    0    D    |       |    E    0    F    |
152c1879b55SMatthew G. Knepley      |         |         |       |         |         |
153c1879b55SMatthew G. Knepley      0---------0---------3       4---------0---------5
154c1879b55SMatthew G. Knepley      */
155412e9a14SMatthew 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,
156412e9a14SMatthew 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};
157412e9a14SMatthew G. Knepley   static PetscReal hex_J[]    = {0.5, 0.0, 0.0,
158412e9a14SMatthew G. Knepley                                  0.0, 0.5, 0.0,
159412e9a14SMatthew G. Knepley                                  0.0, 0.0, 0.5,
160bed052eaSMatthew G. Knepley 
161412e9a14SMatthew G. Knepley                                  0.5, 0.0, 0.0,
162412e9a14SMatthew G. Knepley                                  0.0, 0.5, 0.0,
163412e9a14SMatthew G. Knepley                                  0.0, 0.0, 0.5,
164412e9a14SMatthew G. Knepley 
165412e9a14SMatthew G. Knepley                                  0.5, 0.0, 0.0,
166412e9a14SMatthew G. Knepley                                  0.0, 0.5, 0.0,
167412e9a14SMatthew G. Knepley                                  0.0, 0.0, 0.5,
168412e9a14SMatthew G. Knepley 
169412e9a14SMatthew G. Knepley                                  0.5, 0.0, 0.0,
170412e9a14SMatthew G. Knepley                                  0.0, 0.5, 0.0,
171412e9a14SMatthew G. Knepley                                  0.0, 0.0, 0.5,
172412e9a14SMatthew G. Knepley 
173412e9a14SMatthew G. Knepley                                  0.5, 0.0, 0.0,
174412e9a14SMatthew G. Knepley                                  0.0, 0.5, 0.0,
175412e9a14SMatthew G. Knepley                                  0.0, 0.0, 0.5,
176412e9a14SMatthew G. Knepley 
177412e9a14SMatthew G. Knepley                                  0.5, 0.0, 0.0,
178412e9a14SMatthew G. Knepley                                  0.0, 0.5, 0.0,
179412e9a14SMatthew G. Knepley                                  0.0, 0.0, 0.5,
180412e9a14SMatthew G. Knepley 
181412e9a14SMatthew G. Knepley                                  0.5, 0.0, 0.0,
182412e9a14SMatthew G. Knepley                                  0.0, 0.5, 0.0,
183412e9a14SMatthew G. Knepley                                  0.0, 0.0, 0.5,
184412e9a14SMatthew G. Knepley 
185412e9a14SMatthew G. Knepley                                  0.5, 0.0, 0.0,
186412e9a14SMatthew G. Knepley                                  0.0, 0.5, 0.0,
187412e9a14SMatthew G. Knepley                                  0.0, 0.0, 0.5};
188412e9a14SMatthew G. Knepley   static PetscReal hex_invJ[] = {2.0, 0.0, 0.0,
189412e9a14SMatthew G. Knepley                                  0.0, 2.0, 0.0,
190412e9a14SMatthew G. Knepley                                  0.0, 0.0, 2.0,
191412e9a14SMatthew G. Knepley 
192412e9a14SMatthew G. Knepley                                  2.0, 0.0, 0.0,
193412e9a14SMatthew G. Knepley                                  0.0, 2.0, 0.0,
194412e9a14SMatthew G. Knepley                                  0.0, 0.0, 2.0,
195412e9a14SMatthew G. Knepley 
196412e9a14SMatthew G. Knepley                                  2.0, 0.0, 0.0,
197412e9a14SMatthew G. Knepley                                  0.0, 2.0, 0.0,
198412e9a14SMatthew G. Knepley                                  0.0, 0.0, 2.0,
199412e9a14SMatthew G. Knepley 
200412e9a14SMatthew G. Knepley                                  2.0, 0.0, 0.0,
201412e9a14SMatthew G. Knepley                                  0.0, 2.0, 0.0,
202412e9a14SMatthew G. Knepley                                  0.0, 0.0, 2.0,
203412e9a14SMatthew G. Knepley 
204412e9a14SMatthew G. Knepley                                  2.0, 0.0, 0.0,
205412e9a14SMatthew G. Knepley                                  0.0, 2.0, 0.0,
206412e9a14SMatthew G. Knepley                                  0.0, 0.0, 2.0,
207412e9a14SMatthew G. Knepley 
208412e9a14SMatthew G. Knepley                                  2.0, 0.0, 0.0,
209412e9a14SMatthew G. Knepley                                  0.0, 2.0, 0.0,
210412e9a14SMatthew G. Knepley                                  0.0, 0.0, 2.0,
211412e9a14SMatthew G. Knepley 
212412e9a14SMatthew G. Knepley                                  2.0, 0.0, 0.0,
213412e9a14SMatthew G. Knepley                                  0.0, 2.0, 0.0,
214412e9a14SMatthew G. Knepley                                  0.0, 0.0, 2.0,
215412e9a14SMatthew G. Knepley 
216412e9a14SMatthew G. Knepley                                  2.0, 0.0, 0.0,
217412e9a14SMatthew G. Knepley                                  0.0, 2.0, 0.0,
218412e9a14SMatthew G. Knepley                                  0.0, 0.0, 2.0};
219bed052eaSMatthew G. Knepley 
220bed052eaSMatthew G. Knepley   PetscFunctionBegin;
221412e9a14SMatthew G. Knepley   switch (ct) {
222412e9a14SMatthew 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;
223412e9a14SMatthew 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;
224412e9a14SMatthew 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;
225412e9a14SMatthew G. Knepley   default:
226412e9a14SMatthew G. Knepley     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unsupported polytope type %s", DMPolytopeTypes[ct]);
227412e9a14SMatthew G. Knepley   }
228bed052eaSMatthew G. Knepley   PetscFunctionReturn(0);
229bed052eaSMatthew G. Knepley }
230bed052eaSMatthew G. Knepley 
23180389061SMatthew G. Knepley /* Should this be here or in the DualSpace somehow? */
232412e9a14SMatthew G. Knepley PetscErrorCode CellRefinerInCellTest_Internal(DMPolytopeType ct, const PetscReal point[], PetscBool *inside)
23380389061SMatthew G. Knepley {
23480389061SMatthew G. Knepley   PetscReal sum = 0.0;
23580389061SMatthew G. Knepley   PetscInt  d;
23680389061SMatthew G. Knepley 
23780389061SMatthew G. Knepley   PetscFunctionBegin;
23880389061SMatthew G. Knepley   *inside = PETSC_TRUE;
239412e9a14SMatthew G. Knepley   switch (ct) {
240412e9a14SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
241412e9a14SMatthew G. Knepley   case DM_POLYTOPE_TETRAHEDRON:
242412e9a14SMatthew G. Knepley     for (d = 0; d < DMPolytopeTypeGetDim(ct); ++d) {
24380389061SMatthew G. Knepley       if (point[d] < -1.0) {*inside = PETSC_FALSE; break;}
24480389061SMatthew G. Knepley       sum += point[d];
24580389061SMatthew G. Knepley     }
246412e9a14SMatthew G. Knepley     if (sum > PETSC_SMALL) {*inside = PETSC_FALSE; break;}
24780389061SMatthew G. Knepley     break;
248412e9a14SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
249412e9a14SMatthew G. Knepley   case DM_POLYTOPE_HEXAHEDRON:
250412e9a14SMatthew G. Knepley     for (d = 0; d < DMPolytopeTypeGetDim(ct); ++d)
251412e9a14SMatthew G. Knepley       if (PetscAbsReal(point[d]) > 1.+PETSC_SMALL) {*inside = PETSC_FALSE; break;}
25294339e62SJed Brown     break;
25380389061SMatthew G. Knepley   default:
254412e9a14SMatthew G. Knepley     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unsupported polytope type %s", DMPolytopeTypes[ct]);
25580389061SMatthew G. Knepley   }
25680389061SMatthew G. Knepley   PetscFunctionReturn(0);
25780389061SMatthew G. Knepley }
25880389061SMatthew G. Knepley 
259412e9a14SMatthew G. Knepley /* Regular Refinment of Hybrid Meshes
26075d3a19aSMatthew G. Knepley 
261412e9a14SMatthew 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
262412e9a14SMatthew G. Knepley    to automatically generate a refined Plex. In fact, we would like these rules to be general enough to encompass other
263412e9a14SMatthew G. Knepley    transformations, such as changing from one type of cell to another, as simplex to hex.
26475d3a19aSMatthew G. Knepley 
265412e9a14SMatthew G. Knepley    To start, we can create a function that takes an original cell type and returns the number of new cells replacing it
266412e9a14SMatthew G. Knepley    and the types of the new cells.
267518a8359SMatthew G. Knepley 
268412e9a14SMatthew G. Knepley    We need the group multiplication table for group actions from the dihedral group for each cell type.
26942525629SMatthew G. Knepley 
270412e9a14SMatthew 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
271412e9a14SMatthew G. Knepley    we can just write this operator for faces with identity, and then compose the face orientation actions to get the actual
272412e9a14SMatthew G. Knepley    (face, orient) pairs for each subcell.
273412e9a14SMatthew G. Knepley */
2740314a74cSLawrence Mitchell 
27575d3a19aSMatthew G. Knepley /*
276412e9a14SMatthew G. Knepley   Input Parameters:
277412e9a14SMatthew G. Knepley + ct - The type of the input cell
278412e9a14SMatthew G. Knepley . co - The orientation of this cell in it parent
279412e9a14SMatthew G. Knepley - cp - The requested cone point of this cell assuming orientation 0
280412e9a14SMatthew G. Knepley 
281412e9a14SMatthew G. Knepley   Output Parameters:
282412e9a14SMatthew G. Knepley . cpnew - The new cone point, taking inout account the orientation co
283412e9a14SMatthew G. Knepley */
284412e9a14SMatthew G. Knepley PETSC_STATIC_INLINE PetscErrorCode DMPolytopeMapCell(DMPolytopeType ct, PetscInt co, PetscInt cp, PetscInt *cpnew)
285412e9a14SMatthew G. Knepley {
286412e9a14SMatthew G. Knepley   const PetscInt csize = DMPolytopeTypeGetConeSize(ct);
287412e9a14SMatthew G. Knepley 
288412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
289412e9a14SMatthew G. Knepley   if (ct == DM_POLYTOPE_POINT) {*cpnew = cp;}
290412e9a14SMatthew G. Knepley   else                         {*cpnew = (co < 0 ? -(co+1)-cp+csize : co+cp)%csize;}
291412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
292412e9a14SMatthew G. Knepley }
293412e9a14SMatthew G. Knepley 
294412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerGetCellVertices_Regular(DMPlexCellRefiner cr, DMPolytopeType ct, PetscInt *Nv, PetscReal *subcellV[])
295412e9a14SMatthew G. Knepley {
296412e9a14SMatthew G. Knepley   static PetscReal seg_v[]  = {-1.0,  0.0,  1.0};
297412e9a14SMatthew 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};
298412e9a14SMatthew 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};
299412e9a14SMatthew G. Knepley   static PetscReal tet_v[]  = {-1.0, -1.0, -1.0,   0.0, -1.0, -1.0,   1.0, -1.0, -1.0,
300412e9a14SMatthew G. Knepley                                -1.0,  0.0, -1.0,   0.0,  0.0, -1.0,  -1.0,  1.0, -1.0,
301412e9a14SMatthew 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};
302412e9a14SMatthew G. Knepley   static PetscReal hex_v[]  = {-1.0, -1.0, -1.0,   0.0, -1.0, -1.0,   1.0, -1.0, -1.0,
303412e9a14SMatthew G. Knepley                                -1.0,  0.0, -1.0,   0.0,  0.0, -1.0,   1.0,  0.0, -1.0,
304412e9a14SMatthew G. Knepley                                -1.0,  1.0, -1.0,   0.0,  1.0, -1.0,   1.0,  1.0, -1.0,
305412e9a14SMatthew G. Knepley                                -1.0, -1.0,  0.0,   0.0, -1.0,  0.0,   1.0, -1.0,  0.0,
306412e9a14SMatthew G. Knepley                                -1.0,  0.0,  0.0,   0.0,  0.0,  0.0,   1.0,  0.0,  0.0,
307412e9a14SMatthew G. Knepley                                -1.0,  1.0,  0.0,   0.0,  1.0,  0.0,   1.0,  1.0,  0.0,
308412e9a14SMatthew G. Knepley                                -1.0, -1.0,  1.0,   0.0, -1.0,  1.0,   1.0, -1.0,  1.0,
309412e9a14SMatthew G. Knepley                                -1.0,  0.0,  1.0,   0.0,  0.0,  1.0,   1.0,  0.0,  1.0,
310412e9a14SMatthew G. Knepley                                -1.0,  1.0,  1.0,   0.0,  1.0,  1.0,   1.0,  1.0,  1.0};
311412e9a14SMatthew G. Knepley 
312412e9a14SMatthew G. Knepley   PetscFunctionBegin;
313412e9a14SMatthew G. Knepley   switch (ct) {
314412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:       *Nv =  3; *subcellV = seg_v;  break;
315412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:      *Nv =  6; *subcellV = tri_v;  break;
316412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL: *Nv =  9; *subcellV = quad_v; break;
317412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TETRAHEDRON:   *Nv = 10; *subcellV = tet_v;  break;
318412e9a14SMatthew G. Knepley     case DM_POLYTOPE_HEXAHEDRON:    *Nv = 27; *subcellV = hex_v;  break;
319412e9a14SMatthew G. Knepley     default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "No subcell vertices for cell type %s", DMPolytopeTypes[ct]);
320412e9a14SMatthew G. Knepley   }
321412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
322412e9a14SMatthew G. Knepley }
323412e9a14SMatthew G. Knepley 
32496ca5757SLisandro Dalcin static PetscErrorCode DMPlexCellRefinerGetCellVertices_ToBox(DMPlexCellRefiner cr, DMPolytopeType ct, PetscInt *Nv, PetscReal *subcellV[])
325412e9a14SMatthew G. Knepley {
326412e9a14SMatthew 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};
327412e9a14SMatthew G. Knepley   static PetscReal tet_v[] = {-1.0, -1.0, -1.0,   0.0, -1.0, -1.0,   1.0, -1.0, -1.0,
328412e9a14SMatthew 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,
329412e9a14SMatthew G. Knepley                               -1.0, -1.0,  0.0,  -1.0/3.0, -1.0, -1.0/3.0,   0.0, -1.0,  0.0,
330412e9a14SMatthew 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,
331412e9a14SMatthew G. Knepley                               -1.0, -1.0,  1.0,  -0.5, -0.5, -0.5};
332412e9a14SMatthew G. Knepley   PetscErrorCode   ierr;
333412e9a14SMatthew G. Knepley 
334412e9a14SMatthew G. Knepley   PetscFunctionBegin;
335412e9a14SMatthew G. Knepley   switch (ct) {
336412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:
337412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:
338412e9a14SMatthew G. Knepley     case DM_POLYTOPE_HEXAHEDRON:
339412e9a14SMatthew G. Knepley       ierr = DMPlexCellRefinerGetCellVertices_Regular(cr, ct, Nv, subcellV);CHKERRQ(ierr);break;
340412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:    *Nv =  7; *subcellV = tri_v; break;
341412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TETRAHEDRON: *Nv = 15; *subcellV = tet_v;  break;
342412e9a14SMatthew G. Knepley     default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "No subcell vertices for cell type %s", DMPolytopeTypes[ct]);
343412e9a14SMatthew G. Knepley   }
344412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
345412e9a14SMatthew G. Knepley }
346412e9a14SMatthew G. Knepley 
347412e9a14SMatthew G. Knepley /*
348412e9a14SMatthew G. Knepley   DMPlexCellRefinerGetCellVertices - Get the set of refined vertices lying in the closure of a reference cell of given type
349412e9a14SMatthew G. Knepley 
350412e9a14SMatthew G. Knepley   Input Parameters:
351412e9a14SMatthew G. Knepley + cr - The DMPlexCellRefiner object
352412e9a14SMatthew G. Knepley - ct - The cell type
353412e9a14SMatthew G. Knepley 
354412e9a14SMatthew G. Knepley   Output Parameters:
355412e9a14SMatthew G. Knepley + Nv       - The number of refined vertices in the closure of the reference cell of given type
356412e9a14SMatthew G. Knepley - subcellV - The coordinates of these vertices in the reference cell
357412e9a14SMatthew G. Knepley 
358412e9a14SMatthew G. Knepley   Level: developer
359412e9a14SMatthew G. Knepley 
360412e9a14SMatthew G. Knepley .seealso: DMPlexCellRefinerGetSubcellVertices()
361412e9a14SMatthew G. Knepley */
362412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerGetCellVertices(DMPlexCellRefiner cr, DMPolytopeType ct, PetscInt *Nv, PetscReal *subcellV[])
363412e9a14SMatthew G. Knepley {
364412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
365412e9a14SMatthew G. Knepley 
366412e9a14SMatthew G. Knepley   PetscFunctionBegin;
367412e9a14SMatthew G. Knepley   ierr = (*cr->ops->getcellvertices)(cr, ct, Nv, subcellV);CHKERRQ(ierr);
368412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
369412e9a14SMatthew G. Knepley }
370412e9a14SMatthew G. Knepley 
371412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerGetSubcellVertices_Regular(DMPlexCellRefiner cr, DMPolytopeType ct, DMPolytopeType rct, PetscInt r, PetscInt *Nv, PetscInt *subcellV[])
372412e9a14SMatthew G. Knepley {
373412e9a14SMatthew G. Knepley   static PetscInt seg_v[]  = {0, 1, 1, 2};
374412e9a14SMatthew G. Knepley   static PetscInt tri_v[]  = {0, 3, 5,  3, 1, 4,  5, 4, 2,  3, 4, 5};
375412e9a14SMatthew G. Knepley   static PetscInt quad_v[] = {0, 4, 8, 7,  4, 1, 5, 8,  8, 5, 2, 6,  7, 8, 6, 3};
376412e9a14SMatthew G. Knepley   static PetscInt tet_v[]  = {0, 3, 1, 6,  3, 2, 4, 8,  1, 4, 5, 7,  6, 8, 7, 9,
377412e9a14SMatthew G. Knepley                               1, 6, 3, 7,  8, 4, 3, 7,  7, 3, 1, 4,  7, 3, 8, 6};
378412e9a14SMatthew 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,
379412e9a14SMatthew 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};
380412e9a14SMatthew G. Knepley 
381412e9a14SMatthew G. Knepley   PetscFunctionBegin;
382412e9a14SMatthew G. Knepley   if (ct != rct) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Cell type %s does not produce %s", DMPolytopeTypes[ct], DMPolytopeTypes[rct]);
383412e9a14SMatthew G. Knepley   switch (ct) {
384412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:       *Nv = 2; *subcellV = &seg_v[r*(*Nv)];  break;
385412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:      *Nv = 3; *subcellV = &tri_v[r*(*Nv)];  break;
386412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL: *Nv = 4; *subcellV = &quad_v[r*(*Nv)]; break;
387412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TETRAHEDRON:   *Nv = 4; *subcellV = &tet_v[r*(*Nv)];  break;
388412e9a14SMatthew G. Knepley     case DM_POLYTOPE_HEXAHEDRON:    *Nv = 8; *subcellV = &hex_v[r*(*Nv)];  break;
389412e9a14SMatthew G. Knepley     default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "No subcell vertices for cell type %s", DMPolytopeTypes[ct]);
390412e9a14SMatthew G. Knepley   }
391412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
392412e9a14SMatthew G. Knepley }
393412e9a14SMatthew G. Knepley 
39496ca5757SLisandro Dalcin static PetscErrorCode DMPlexCellRefinerGetSubcellVertices_ToBox(DMPlexCellRefiner cr, DMPolytopeType ct, DMPolytopeType rct, PetscInt r, PetscInt *Nv, PetscInt *subcellV[])
395412e9a14SMatthew G. Knepley {
396412e9a14SMatthew G. Knepley   static PetscInt tri_v[]  = {0, 3, 6, 5,  3, 1, 4, 6,  5, 6, 4, 2};
397412e9a14SMatthew 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};
398412e9a14SMatthew G. Knepley   PetscErrorCode  ierr;
399412e9a14SMatthew G. Knepley 
400412e9a14SMatthew G. Knepley   PetscFunctionBegin;
401412e9a14SMatthew G. Knepley   switch (ct) {
402412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:
403412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:
404412e9a14SMatthew G. Knepley     case DM_POLYTOPE_HEXAHEDRON:
405412e9a14SMatthew G. Knepley       ierr = DMPlexCellRefinerGetSubcellVertices_Regular(cr, ct, rct, r, Nv, subcellV);CHKERRQ(ierr);break;
406412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:
407412e9a14SMatthew 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]);
408412e9a14SMatthew G. Knepley       *Nv = 4; *subcellV = &tri_v[r*(*Nv)]; break;
409412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TETRAHEDRON:
410412e9a14SMatthew 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]);
411412e9a14SMatthew G. Knepley       *Nv = 8; *subcellV = &tet_v[r*(*Nv)]; break;
412412e9a14SMatthew G. Knepley     default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "No subcell vertices for cell type %s", DMPolytopeTypes[ct]);
413412e9a14SMatthew G. Knepley   }
414412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
415412e9a14SMatthew G. Knepley }
416412e9a14SMatthew G. Knepley 
417412e9a14SMatthew G. Knepley /*
418412e9a14SMatthew G. Knepley   DMPlexCellRefinerGetSubcellVertices - Get the set of refined vertices defining a subcell in the reference cell of given type
419412e9a14SMatthew G. Knepley 
420412e9a14SMatthew G. Knepley   Input Parameters:
421412e9a14SMatthew G. Knepley + cr  - The DMPlexCellRefiner object
422412e9a14SMatthew G. Knepley . ct  - The cell type
423412e9a14SMatthew G. Knepley . rct - The type of subcell
424412e9a14SMatthew G. Knepley - r   - The subcell index
425412e9a14SMatthew G. Knepley 
426412e9a14SMatthew G. Knepley   Output Parameters:
427412e9a14SMatthew G. Knepley + Nv       - The number of refined vertices in the subcell
428412e9a14SMatthew G. Knepley - subcellV - The indices of these vertices in the set of vertices returned by DMPlexCellRefinerGetCellVertices()
429412e9a14SMatthew G. Knepley 
430412e9a14SMatthew G. Knepley   Level: developer
431412e9a14SMatthew G. Knepley 
432412e9a14SMatthew G. Knepley .seealso: DMPlexCellRefinerGetCellVertices()
433412e9a14SMatthew G. Knepley */
434412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerGetSubcellVertices(DMPlexCellRefiner cr, DMPolytopeType ct, DMPolytopeType rct, PetscInt r, PetscInt *Nv, PetscInt *subcellV[])
435412e9a14SMatthew G. Knepley {
436412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
437412e9a14SMatthew G. Knepley 
438412e9a14SMatthew G. Knepley   PetscFunctionBegin;
439412e9a14SMatthew G. Knepley   ierr = (*cr->ops->getsubcellvertices)(cr, ct, rct, r, Nv, subcellV);CHKERRQ(ierr);
440412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
441412e9a14SMatthew G. Knepley }
442412e9a14SMatthew G. Knepley 
443412e9a14SMatthew G. Knepley /*
444412e9a14SMatthew G. Knepley   Input Parameters:
445412e9a14SMatthew G. Knepley + cr  - The DMPlexCellRefiner
446412e9a14SMatthew G. Knepley . pct - The cell type of the parent, from whom the new cell is being produced
447412e9a14SMatthew G. Knepley . po  - The orientation of the parent cell in its enclosing parent
448412e9a14SMatthew G. Knepley . ct  - The type being produced
449412e9a14SMatthew G. Knepley . r   - The replica number requested for the produced cell type
450412e9a14SMatthew G. Knepley - o   - The relative orientation of the replica
451412e9a14SMatthew G. Knepley 
452412e9a14SMatthew G. Knepley   Output Parameters:
453412e9a14SMatthew G. Knepley + rnew - The replica number, given the orientation of of the parent
454412e9a14SMatthew G. Knepley - onew - The replica orientation, given the orientation of the parent
455412e9a14SMatthew G. Knepley */
456412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerMapSubcells(DMPlexCellRefiner cr, DMPolytopeType pct, PetscInt po, DMPolytopeType ct, PetscInt r, PetscInt o, PetscInt *rnew, PetscInt *onew)
457412e9a14SMatthew G. Knepley {
458412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
459412e9a14SMatthew G. Knepley 
460412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
461412e9a14SMatthew G. Knepley   ierr = (*cr->ops->mapsubcells)(cr, pct, po, ct, r, o, rnew, onew);CHKERRQ(ierr);
462412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
463412e9a14SMatthew G. Knepley }
464412e9a14SMatthew G. Knepley 
465412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerMapSubcells_Regular(DMPlexCellRefiner cr, DMPolytopeType pct, PetscInt po, DMPolytopeType ct, PetscInt r, PetscInt o, PetscInt *rnew, PetscInt *onew)
466412e9a14SMatthew G. Knepley {
467412e9a14SMatthew G. Knepley   /* We shift any input orientation in order to make it non-negative
468412e9a14SMatthew 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)
469412e9a14SMatthew G. Knepley        The replica array r[po][r] gives the new replica number rnew given that the parent point has orientation po
470412e9a14SMatthew G. Knepley        Overall, replica (r, o) in a parent with orientation 0 matches replica (rnew, onew) in a parent with orientation po
471412e9a14SMatthew G. Knepley   */
472412e9a14SMatthew G. Knepley   PetscInt tri_seg_o[] = {-2, 0,
473412e9a14SMatthew G. Knepley                           -2, 0,
474412e9a14SMatthew G. Knepley                           -2, 0,
475412e9a14SMatthew G. Knepley                           0, -2,
476412e9a14SMatthew G. Knepley                           0, -2,
477412e9a14SMatthew G. Knepley                           0, -2};
478412e9a14SMatthew G. Knepley   PetscInt tri_seg_r[] = {1, 0, 2,
479412e9a14SMatthew G. Knepley                           0, 2, 1,
480412e9a14SMatthew G. Knepley                           2, 1, 0,
481412e9a14SMatthew G. Knepley                           0, 1, 2,
482412e9a14SMatthew G. Knepley                           1, 2, 0,
483412e9a14SMatthew G. Knepley                           2, 0, 1};
484412e9a14SMatthew G. Knepley   PetscInt tri_tri_o[] = {0,  1,  2, -3, -2, -1,
485412e9a14SMatthew G. Knepley                           2,  0,  1, -2, -1, -3,
486412e9a14SMatthew G. Knepley                           1,  2,  0, -1, -3, -2,
487412e9a14SMatthew G. Knepley                          -3, -2, -1,  0,  1,  2,
488412e9a14SMatthew G. Knepley                          -1, -3, -2,  1,  2,  0,
489412e9a14SMatthew G. Knepley                          -2, -1, -3,  2,  0,  1};
490412e9a14SMatthew G. Knepley   /* orientation if the replica is the center triangle */
491412e9a14SMatthew G. Knepley   PetscInt tri_tri_o_c[] = {2,  0,  1, -2, -1, -3,
492412e9a14SMatthew G. Knepley                             1,  2,  0, -1, -3, -2,
493412e9a14SMatthew G. Knepley                             0,  1,  2, -3, -2, -1,
494412e9a14SMatthew G. Knepley                            -3, -2, -1,  0,  1,  2,
495412e9a14SMatthew G. Knepley                            -1, -3, -2,  1,  2,  0,
496412e9a14SMatthew G. Knepley                            -2, -1, -3,  2,  0,  1};
497412e9a14SMatthew G. Knepley   PetscInt tri_tri_r[] = {0, 2, 1, 3,
498412e9a14SMatthew G. Knepley                           2, 1, 0, 3,
499412e9a14SMatthew G. Knepley                           1, 0, 2, 3,
500412e9a14SMatthew G. Knepley                           0, 1, 2, 3,
501412e9a14SMatthew G. Knepley                           1, 2, 0, 3,
502412e9a14SMatthew G. Knepley                           2, 0, 1, 3};
503412e9a14SMatthew G. Knepley   PetscInt quad_seg_r[] = {3, 2, 1, 0,
504412e9a14SMatthew G. Knepley                            2, 1, 0, 3,
505412e9a14SMatthew G. Knepley                            1, 0, 3, 2,
506412e9a14SMatthew G. Knepley                            0, 3, 2, 1,
507412e9a14SMatthew G. Knepley                            0, 1, 2, 3,
508412e9a14SMatthew G. Knepley                            1, 2, 3, 0,
509412e9a14SMatthew G. Knepley                            2, 3, 0, 1,
510412e9a14SMatthew G. Knepley                            3, 0, 1, 2};
511412e9a14SMatthew G. Knepley   PetscInt quad_quad_o[] = { 0,  1,  2,  3, -4, -3, -2, -1,
512412e9a14SMatthew G. Knepley                              4,  0,  1,  2, -3, -2, -1, -4,
513412e9a14SMatthew G. Knepley                              3,  4,  0,  1, -2, -1, -4, -3,
514412e9a14SMatthew G. Knepley                              2,  3,  4,  0, -1, -4, -3, -2,
515412e9a14SMatthew G. Knepley                             -4, -3, -2, -1,  0,  1,  2,  3,
516412e9a14SMatthew G. Knepley                             -1, -4, -3, -2,  1,  2,  3,  0,
517412e9a14SMatthew G. Knepley                             -2, -1, -4, -3,  2,  3,  0,  1,
518412e9a14SMatthew G. Knepley                             -3, -2, -1, -4,  3,  0,  1,  2};
519412e9a14SMatthew G. Knepley   PetscInt quad_quad_r[] = {0, 3, 2, 1,
520412e9a14SMatthew G. Knepley                             3, 2, 1, 0,
521412e9a14SMatthew G. Knepley                             2, 1, 0, 3,
522412e9a14SMatthew G. Knepley                             1, 0, 3, 2,
523412e9a14SMatthew G. Knepley                             0, 1, 2, 3,
524412e9a14SMatthew G. Knepley                             1, 2, 3, 0,
525412e9a14SMatthew G. Knepley                             2, 3, 0, 1,
526412e9a14SMatthew G. Knepley                             3, 0, 1, 2};
527412e9a14SMatthew G. Knepley   PetscInt tquad_tquad_o[] = { 0,  1, -2, -1,
528412e9a14SMatthew G. Knepley                                1,  0, -1, -2,
529412e9a14SMatthew G. Knepley                               -2, -1,  0,  1,
530412e9a14SMatthew G. Knepley                               -1, -2,  1,  0};
531412e9a14SMatthew G. Knepley   PetscInt tquad_tquad_r[] = {1, 0,
532412e9a14SMatthew G. Knepley                               1, 0,
533412e9a14SMatthew G. Knepley                               0, 1,
534412e9a14SMatthew G. Knepley                               0, 1};
535412e9a14SMatthew G. Knepley 
536412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
537412e9a14SMatthew G. Knepley   /* The default is no transformation */
538412e9a14SMatthew G. Knepley   *rnew = r;
539412e9a14SMatthew G. Knepley   *onew = o;
540412e9a14SMatthew G. Knepley   switch (pct) {
541412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:
542412e9a14SMatthew G. Knepley       if (ct == DM_POLYTOPE_SEGMENT) {
543412e9a14SMatthew G. Knepley         if      (po == 0 || po == -1) {*rnew = r;       *onew = o;}
544412e9a14SMatthew G. Knepley         else if (po == 1 || po == -2) {*rnew = (r+1)%2; *onew = (o == 0 || o == -1) ? -2 : 0;}
545412e9a14SMatthew G. Knepley         else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid orientation %D for segment", po);
546412e9a14SMatthew G. Knepley       }
547412e9a14SMatthew G. Knepley       break;
548412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:
549412e9a14SMatthew G. Knepley       switch (ct) {
550412e9a14SMatthew G. Knepley         case DM_POLYTOPE_SEGMENT:
551412e9a14SMatthew G. Knepley           if (o == -1) o = 0;
552412e9a14SMatthew G. Knepley           if (o == -2) o = 1;
553412e9a14SMatthew G. Knepley           *onew = tri_seg_o[(po+3)*2+o];
554412e9a14SMatthew G. Knepley           *rnew = tri_seg_r[(po+3)*3+r];
555412e9a14SMatthew G. Knepley           break;
556412e9a14SMatthew G. Knepley         case DM_POLYTOPE_TRIANGLE:
557412e9a14SMatthew 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];
558412e9a14SMatthew G. Knepley           *rnew = tri_tri_r[(po+3)*4+r];
559412e9a14SMatthew G. Knepley           break;
560412e9a14SMatthew G. Knepley         default: break;
561412e9a14SMatthew G. Knepley       }
562412e9a14SMatthew G. Knepley       break;
563412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:
564412e9a14SMatthew G. Knepley       switch (ct) {
565412e9a14SMatthew G. Knepley         case DM_POLYTOPE_SEGMENT:
566412e9a14SMatthew G. Knepley           *onew = o;
567412e9a14SMatthew G. Knepley           *rnew = quad_seg_r[(po+4)*4+r];
568412e9a14SMatthew G. Knepley           break;
569412e9a14SMatthew G. Knepley         case DM_POLYTOPE_QUADRILATERAL:
570412e9a14SMatthew G. Knepley           *onew = quad_quad_o[(po+4)*8+o+4];
571412e9a14SMatthew G. Knepley           *rnew = quad_quad_r[(po+4)*4+r];
572412e9a14SMatthew G. Knepley           break;
573412e9a14SMatthew G. Knepley         default: break;
574412e9a14SMatthew G. Knepley       }
575412e9a14SMatthew G. Knepley       break;
576412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEG_PRISM_TENSOR:
577412e9a14SMatthew G. Knepley       switch (ct) {
578412e9a14SMatthew G. Knepley         /* DM_POLYTOPE_POINT_PRISM_TENSOR does not change */
579412e9a14SMatthew G. Knepley         case DM_POLYTOPE_SEG_PRISM_TENSOR:
580412e9a14SMatthew G. Knepley           *onew = tquad_tquad_o[(po+2)*4+o+2];
581412e9a14SMatthew G. Knepley           *rnew = tquad_tquad_r[(po+2)*2+r];
582412e9a14SMatthew G. Knepley           break;
583412e9a14SMatthew G. Knepley         default: break;
584412e9a14SMatthew G. Knepley       }
585412e9a14SMatthew G. Knepley       break;
586412e9a14SMatthew G. Knepley     default: break;
587412e9a14SMatthew G. Knepley   }
588412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
589412e9a14SMatthew G. Knepley }
590412e9a14SMatthew G. Knepley 
59196ca5757SLisandro Dalcin static PetscErrorCode DMPlexCellRefinerMapSubcells_ToBox(DMPlexCellRefiner cr, DMPolytopeType pct, PetscInt po, DMPolytopeType ct, PetscInt r, PetscInt o, PetscInt *rnew, PetscInt *onew)
592412e9a14SMatthew G. Knepley {
593412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
594412e9a14SMatthew G. Knepley   /* We shift any input orientation in order to make it non-negative
595412e9a14SMatthew 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)
596412e9a14SMatthew G. Knepley        The replica array r[po][r] gives the new replica number rnew given that the parent point has orientation po
597412e9a14SMatthew G. Knepley        Overall, replica (r, o) in a parent with orientation 0 matches replica (rnew, onew) in a parent with orientation po
598412e9a14SMatthew G. Knepley   */
599412e9a14SMatthew G. Knepley   PetscInt tri_seg_o[] = {0, -2,
600412e9a14SMatthew G. Knepley                           0, -2,
601412e9a14SMatthew G. Knepley                           0, -2,
602412e9a14SMatthew G. Knepley                           0, -2,
603412e9a14SMatthew G. Knepley                           0, -2,
604412e9a14SMatthew G. Knepley                           0, -2};
605412e9a14SMatthew G. Knepley   PetscInt tri_seg_r[] = {2, 1, 0,
606412e9a14SMatthew G. Knepley                           1, 0, 2,
607412e9a14SMatthew G. Knepley                           0, 2, 1,
608412e9a14SMatthew G. Knepley                           0, 1, 2,
609412e9a14SMatthew G. Knepley                           1, 2, 0,
610412e9a14SMatthew G. Knepley                           2, 0, 1};
611412e9a14SMatthew G. Knepley   PetscInt tri_tri_o[] = {0,  1,  2,  3, -4, -3, -2, -1,
612412e9a14SMatthew G. Knepley                           3,  0,  1,  2, -3, -2, -1, -4,
613412e9a14SMatthew G. Knepley                           1,  2,  3,  0, -1, -4, -3, -2,
614412e9a14SMatthew G. Knepley                          -4, -3, -2, -1,  0,  1,  2,  3,
615412e9a14SMatthew G. Knepley                          -1, -4, -3, -2,  1,  2,  3,  0,
616412e9a14SMatthew G. Knepley                          -3, -2, -1, -4,  3,  0,  1,  2};
617412e9a14SMatthew G. Knepley   PetscInt tri_tri_r[] = {0, 2, 1,
618412e9a14SMatthew G. Knepley                           2, 1, 0,
619412e9a14SMatthew G. Knepley                           1, 0, 2,
620412e9a14SMatthew G. Knepley                           0, 1, 2,
621412e9a14SMatthew G. Knepley                           1, 2, 0,
622412e9a14SMatthew G. Knepley                           2, 0, 1};
623412e9a14SMatthew G. Knepley   PetscInt tquad_tquad_o[] = { 0,  1, -2, -1,
624412e9a14SMatthew G. Knepley                                1,  0, -1, -2,
625412e9a14SMatthew G. Knepley                               -2, -1,  0,  1,
626412e9a14SMatthew G. Knepley                               -1, -2,  1,  0};
627412e9a14SMatthew G. Knepley   PetscInt tquad_tquad_r[] = {1, 0,
628412e9a14SMatthew G. Knepley                               1, 0,
629412e9a14SMatthew G. Knepley                               0, 1,
630412e9a14SMatthew G. Knepley                               0, 1};
631412e9a14SMatthew G. Knepley   PetscInt tquad_quad_o[] = {-2, -1, -4, -3,  2,  3,  0,  1,
632412e9a14SMatthew G. Knepley                               1,  2,  3,  0, -1, -4, -3, -2,
633412e9a14SMatthew G. Knepley                              -4, -3, -2, -1,  0,  1,  2,  3,
634412e9a14SMatthew G. Knepley                               1,  0,  3,  2, -3, -4, -1, -2};
635412e9a14SMatthew G. Knepley 
636412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
637412e9a14SMatthew G. Knepley   *rnew = r;
638412e9a14SMatthew G. Knepley   *onew = o;
639412e9a14SMatthew G. Knepley   switch (pct) {
640412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:
641412e9a14SMatthew G. Knepley       switch (ct) {
642412e9a14SMatthew G. Knepley         case DM_POLYTOPE_SEGMENT:
643412e9a14SMatthew G. Knepley           if (o == -1) o = 0;
644412e9a14SMatthew G. Knepley           if (o == -2) o = 1;
645412e9a14SMatthew G. Knepley           *onew = tri_seg_o[(po+3)*2+o];
646412e9a14SMatthew G. Knepley           *rnew = tri_seg_r[(po+3)*3+r];
647412e9a14SMatthew G. Knepley           break;
648412e9a14SMatthew G. Knepley         case DM_POLYTOPE_QUADRILATERAL:
649412e9a14SMatthew G. Knepley           *onew = tri_tri_o[(po+3)*8+o+4];
650412e9a14SMatthew G. Knepley           /* TODO See sheet, for fixing po == 1 and 2 */
651412e9a14SMatthew G. Knepley           if (po ==  2 && r == 2 && o >= 0) *onew = tri_tri_o[(po+3)*8+((o+3)%4)+4];
652412e9a14SMatthew G. Knepley           if (po ==  2 && r == 2 && o <  0) *onew = tri_tri_o[(po+3)*8+((o+5)%4)];
653412e9a14SMatthew G. Knepley           if (po ==  1 && r == 1 && o >= 0) *onew = tri_tri_o[(po+3)*8+((o+1)%4)+4];
654412e9a14SMatthew G. Knepley           if (po ==  1 && r == 1 && o <  0) *onew = tri_tri_o[(po+3)*8+((o+7)%4)];
655412e9a14SMatthew G. Knepley           if (po == -1 && r == 2 && o >= 0) *onew = tri_tri_o[(po+3)*8+((o+3)%4)+4];
656412e9a14SMatthew G. Knepley           if (po == -1 && r == 2 && o <  0) *onew = tri_tri_o[(po+3)*8+((o+5)%4)];
657412e9a14SMatthew G. Knepley           if (po == -2 && r == 1 && o >= 0) *onew = tri_tri_o[(po+3)*8+((o+1)%4)+4];
658412e9a14SMatthew G. Knepley           if (po == -2 && r == 1 && o <  0) *onew = tri_tri_o[(po+3)*8+((o+7)%4)];
659412e9a14SMatthew G. Knepley           *rnew = tri_tri_r[(po+3)*3+r];
660412e9a14SMatthew G. Knepley           break;
661412e9a14SMatthew G. Knepley         default: break;
662412e9a14SMatthew G. Knepley       }
663412e9a14SMatthew G. Knepley       break;
664412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEG_PRISM_TENSOR:
665412e9a14SMatthew G. Knepley       switch (ct) {
666412e9a14SMatthew G. Knepley         /* DM_POLYTOPE_POINT_PRISM_TENSOR does not change */
667412e9a14SMatthew G. Knepley         case DM_POLYTOPE_SEG_PRISM_TENSOR:
668412e9a14SMatthew G. Knepley           *onew = tquad_tquad_o[(po+2)*4+o+2];
669412e9a14SMatthew G. Knepley           *rnew = tquad_tquad_r[(po+2)*2+r];
670412e9a14SMatthew G. Knepley           break;
671412e9a14SMatthew G. Knepley         case DM_POLYTOPE_QUADRILATERAL:
672412e9a14SMatthew G. Knepley           *onew = tquad_quad_o[(po+2)*8+o+4];
673412e9a14SMatthew G. Knepley           *rnew = tquad_tquad_r[(po+2)*2+r];
674412e9a14SMatthew G. Knepley           break;
675412e9a14SMatthew G. Knepley         default: break;
676412e9a14SMatthew G. Knepley       }
677412e9a14SMatthew G. Knepley       break;
678412e9a14SMatthew G. Knepley     default:
679412e9a14SMatthew G. Knepley       ierr = DMPlexCellRefinerMapSubcells_Regular(cr, pct, po, ct, r, o, rnew, onew);CHKERRQ(ierr);
680412e9a14SMatthew G. Knepley   }
681412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
682412e9a14SMatthew G. Knepley }
683412e9a14SMatthew G. Knepley 
684412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerMapSubcells_ToSimplex(DMPlexCellRefiner cr, DMPolytopeType pct, PetscInt po, DMPolytopeType ct, PetscInt r, PetscInt o, PetscInt *rnew, PetscInt *onew)
685412e9a14SMatthew G. Knepley {
686412e9a14SMatthew G. Knepley   return DMPlexCellRefinerMapSubcells_Regular(cr, pct, po, ct, r, o, rnew, onew);
687412e9a14SMatthew G. Knepley }
688412e9a14SMatthew G. Knepley 
689412e9a14SMatthew G. Knepley /*@
690412e9a14SMatthew G. Knepley   DMPlexCellRefinerRefine - Return a description of the refinement for a given cell type
691412e9a14SMatthew G. Knepley 
692412e9a14SMatthew G. Knepley   Input Parameter:
693412e9a14SMatthew G. Knepley . source - The cell type for a source point
694412e9a14SMatthew G. Knepley 
695412e9a14SMatthew G. Knepley   Output Parameter:
696412e9a14SMatthew G. Knepley + Nt     - The number of cell types generated by refinement
697412e9a14SMatthew G. Knepley . target - The cell types generated
698412e9a14SMatthew G. Knepley . size   - The number of subcells of each type, ordered by dimension
699412e9a14SMatthew G. Knepley . cone   - A list of the faces for each subcell of the same type as source
700412e9a14SMatthew G. Knepley - ornt   - A list of the face orientations for each subcell of the same type as source
701412e9a14SMatthew G. Knepley 
702412e9a14SMatthew G. Knepley   Note: The cone array gives the cone of each subcell listed by the first three outputs. For the each cone point, we
703412e9a14SMatthew G. Knepley   need the cell type, point identifier, and orientation within the subcell. The orientation is with respect to the canonical
704412e9a14SMatthew G. Knepley   division (described in these outputs) of the cell in the original mesh. The point identifier is given by
705412e9a14SMatthew G. Knepley $   the number of cones to be taken, or 0 for the current cell
706412e9a14SMatthew G. Knepley $   the cell cone point number at each level from which it is subdivided
707412e9a14SMatthew G. Knepley $   the replica number r of the subdivision.
708412e9a14SMatthew G. Knepley   The orientation is with respect to the canonical cone orientation. For example, the prescription for edge division is
709412e9a14SMatthew G. Knepley $   Nt     = 2
710412e9a14SMatthew G. Knepley $   target = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT}
711412e9a14SMatthew G. Knepley $   size   = {1, 2}
712412e9a14SMatthew 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}
713412e9a14SMatthew G. Knepley $   ornt   = {                         0,                       0,                        0,                          0}
714412e9a14SMatthew G. Knepley 
715412e9a14SMatthew G. Knepley   Level: developer
716412e9a14SMatthew G. Knepley 
71796ca5757SLisandro Dalcin .seealso: DMPlexCellRefinerCreate(), DMPlexRefineUniform()
718412e9a14SMatthew G. Knepley @*/
719412e9a14SMatthew G. Knepley PetscErrorCode DMPlexCellRefinerRefine(DMPlexCellRefiner cr, DMPolytopeType source, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[])
720412e9a14SMatthew G. Knepley {
721412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
722412e9a14SMatthew G. Knepley 
723412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
724412e9a14SMatthew G. Knepley   ierr = (*cr->ops->refine)(cr, source, Nt, target, size, cone, ornt);CHKERRQ(ierr);
725412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
726412e9a14SMatthew G. Knepley }
727412e9a14SMatthew G. Knepley 
728412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerRefine_Regular(DMPlexCellRefiner cr, DMPolytopeType source, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[])
729412e9a14SMatthew G. Knepley {
730412e9a14SMatthew G. Knepley   /* All vertices remain in the refined mesh */
731412e9a14SMatthew G. Knepley   static DMPolytopeType vertexT[] = {DM_POLYTOPE_POINT};
732412e9a14SMatthew G. Knepley   static PetscInt       vertexS[] = {1};
733412e9a14SMatthew G. Knepley   static PetscInt       vertexC[] = {0};
734412e9a14SMatthew G. Knepley   static PetscInt       vertexO[] = {0};
735412e9a14SMatthew G. Knepley   /* Split all edges with a new vertex, making two new 2 edges
736412e9a14SMatthew G. Knepley      0--0--0--1--1
737412e9a14SMatthew G. Knepley   */
738412e9a14SMatthew G. Knepley   static DMPolytopeType edgeT[]   = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT};
739412e9a14SMatthew G. Knepley   static PetscInt       edgeS[]   = {1, 2};
740412e9a14SMatthew 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};
741412e9a14SMatthew G. Knepley   static PetscInt       edgeO[]   = {                         0,                       0,                        0,                          0};
742412e9a14SMatthew G. Knepley   /* Do not split tensor edges */
743412e9a14SMatthew G. Knepley   static DMPolytopeType tedgeT[]  = {DM_POLYTOPE_POINT_PRISM_TENSOR};
744412e9a14SMatthew G. Knepley   static PetscInt       tedgeS[]  = {1};
745412e9a14SMatthew G. Knepley   static PetscInt       tedgeC[]  = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0};
746412e9a14SMatthew G. Knepley   static PetscInt       tedgeO[]  = {                         0,                          0};
747412e9a14SMatthew G. Knepley   /* Add 3 edges inside every triangle, making 4 new triangles.
74875d3a19aSMatthew G. Knepley    2
74975d3a19aSMatthew G. Knepley    |\
75075d3a19aSMatthew G. Knepley    | \
75175d3a19aSMatthew G. Knepley    |  \
752412e9a14SMatthew G. Knepley    0   1
75375d3a19aSMatthew G. Knepley    | C  \
75475d3a19aSMatthew G. Knepley    |     \
75575d3a19aSMatthew G. Knepley    |      \
75675d3a19aSMatthew G. Knepley    2---1---1
75775d3a19aSMatthew G. Knepley    |\  D  / \
758412e9a14SMatthew G. Knepley    1 2   0   0
75975d3a19aSMatthew G. Knepley    |A \ /  B  \
760412e9a14SMatthew G. Knepley    0-0-0---1---1
76175d3a19aSMatthew G. Knepley   */
762412e9a14SMatthew G. Knepley   static DMPolytopeType triT[]    = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_TRIANGLE};
763412e9a14SMatthew G. Knepley   static PetscInt       triS[]    = {3, 4};
764412e9a14SMatthew G. Knepley   static PetscInt       triC[]    = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
765412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 1, 2, 0,
766412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 1, 0, 0,
767412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 1, 2, 1,
768412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0,    0,
769412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 2, 0,
770412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,    2};
771412e9a14SMatthew G. Knepley   static PetscInt       triO[]    = {0, 0,
772412e9a14SMatthew G. Knepley                                      0, 0,
773412e9a14SMatthew G. Knepley                                      0, 0,
774412e9a14SMatthew G. Knepley                                      0, -2,  0,
775412e9a14SMatthew G. Knepley                                      0,  0, -2,
776412e9a14SMatthew G. Knepley                                     -2,  0,  0,
777412e9a14SMatthew G. Knepley                                      0,  0,  0};
778412e9a14SMatthew G. Knepley   /* Add a vertex in the center of each quadrilateral, and 4 edges inside, making 4 new quads.
779412e9a14SMatthew G. Knepley      3----1----2----0----2
780412e9a14SMatthew G. Knepley      |         |         |
781412e9a14SMatthew G. Knepley      0    D    2    C    1
782412e9a14SMatthew G. Knepley      |         |         |
783412e9a14SMatthew G. Knepley      3----3----0----1----1
784412e9a14SMatthew G. Knepley      |         |         |
785412e9a14SMatthew G. Knepley      1    A    0    B    0
786412e9a14SMatthew G. Knepley      |         |         |
787412e9a14SMatthew G. Knepley      0----0----0----1----1
788412e9a14SMatthew G. Knepley   */
789412e9a14SMatthew G. Knepley   static DMPolytopeType quadT[]   = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL};
790412e9a14SMatthew G. Knepley   static PetscInt       quadS[]   = {1, 4, 4};
791412e9a14SMatthew G. Knepley   static PetscInt       quadC[]   = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 0, 0,
792412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 0, 0,
793412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 0, 0,
794412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 3, 0, DM_POLYTOPE_POINT, 0, 0,
795412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 1, 3, 1,
796412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,    0,
797412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0,    2,
798412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 3, 0};
799412e9a14SMatthew G. Knepley   static PetscInt       quadO[]   = {0, 0,
800412e9a14SMatthew G. Knepley                                      0, 0,
801412e9a14SMatthew G. Knepley                                      0, 0,
802412e9a14SMatthew G. Knepley                                      0, 0,
803412e9a14SMatthew G. Knepley                                      0,  0, -2,  0,
804412e9a14SMatthew G. Knepley                                      0,  0,  0, -2,
805412e9a14SMatthew G. Knepley                                     -2,  0,  0,  0,
806412e9a14SMatthew G. Knepley                                      0, -2,  0,  0};
807412e9a14SMatthew G. Knepley   /* Add 1 edge inside every tensor quad, making 2 new tensor quads
808412e9a14SMatthew G. Knepley      2----2----1----3----3
809412e9a14SMatthew G. Knepley      |         |         |
810412e9a14SMatthew G. Knepley      |         |         |
811412e9a14SMatthew G. Knepley      |         |         |
812412e9a14SMatthew G. Knepley      4    A    6    B    5
813412e9a14SMatthew G. Knepley      |         |         |
814412e9a14SMatthew G. Knepley      |         |         |
815412e9a14SMatthew G. Knepley      |         |         |
816412e9a14SMatthew G. Knepley      0----0----0----1----1
817412e9a14SMatthew G. Knepley   */
818412e9a14SMatthew G. Knepley   static DMPolytopeType tquadT[]  = {DM_POLYTOPE_POINT_PRISM_TENSOR, DM_POLYTOPE_SEG_PRISM_TENSOR};
819412e9a14SMatthew G. Knepley   static PetscInt       tquadS[]  = {1, 2};
820412e9a14SMatthew G. Knepley   static PetscInt       tquadC[]  = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
821412e9a14SMatthew 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,
822412e9a14SMatthew 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};
823412e9a14SMatthew G. Knepley   static PetscInt       tquadO[]  = {0, 0,
824412e9a14SMatthew G. Knepley                                      0, 0, 0, 0,
825412e9a14SMatthew G. Knepley                                      0, 0, 0, 0};
826412e9a14SMatthew G. Knepley   /* Add 1 edge and 8 triangles inside every cell, making 8 new tets
827412e9a14SMatthew 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
828412e9a14SMatthew 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]
829412e9a14SMatthew G. Knepley      called e3, e4, and e5. The faces of a tet, given in DMPlexGetRawFaces_Internal() are
830412e9a14SMatthew G. Knepley        [v0, v1, v2], [v0, v3, v1], [v0, v2, v3], [v2, v1, v3]
831412e9a14SMatthew G. Knepley      The first four tets just cut off the corners, using the replica notation for new vertices,
832412e9a14SMatthew G. Knepley        [v0,      (e0, 0), (e2, 0), (e3, 0)]
833412e9a14SMatthew G. Knepley        [(e0, 0), v1,      (e1, 0), (e4, 0)]
834412e9a14SMatthew G. Knepley        [(e2, 0), (e1, 0), v2,      (e5, 0)]
835412e9a14SMatthew G. Knepley        [(e3, 0), (e4, 0), (e5, 0), v3     ]
836412e9a14SMatthew G. Knepley      The next four tets match a vertex to the newly created faces from cutting off those first tets.
837412e9a14SMatthew G. Knepley        [(e2, 0), (e3, 0), (e0, 0), (e5, 0)]
838412e9a14SMatthew G. Knepley        [(e4, 0), (e1, 0), (e0, 0), (e5, 0)]
839412e9a14SMatthew G. Knepley        [(e5, 0), (e0, 0), (e2, 0), (e1, 0)]
840412e9a14SMatthew G. Knepley        [(e5, 0), (e0, 0), (e4, 0), (e3, 0)]
841412e9a14SMatthew 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
842412e9a14SMatthew G. Knepley        [(e2, 0), (e0, 0), (e3, 0)]
843412e9a14SMatthew G. Knepley        [(e0, 0), (e1, 0), (e4, 0)]
844412e9a14SMatthew G. Knepley        [(e2, 0), (e5, 0), (e1, 0)]
845412e9a14SMatthew G. Knepley        [(e3, 0), (e4, 0), (e5, 0)]
846412e9a14SMatthew G. Knepley      The next four, from the second group of tets, are
847412e9a14SMatthew G. Knepley        [(e2, 0), (e0, 0), (e5, 0)]
848412e9a14SMatthew G. Knepley        [(e4, 0), (e0, 0), (e5, 0)]
849412e9a14SMatthew G. Knepley        [(e0, 0), (e1, 0), (e5, 0)]
850412e9a14SMatthew G. Knepley        [(e5, 0), (e3, 0), (e0, 0)]
851412e9a14SMatthew G. Knepley      I could write a program to generate these orientations by comparing the faces from GetRawFaces() with my existing table.
852412e9a14SMatthew G. Knepley    */
853412e9a14SMatthew G. Knepley   static DMPolytopeType tetT[]    = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_TRIANGLE, DM_POLYTOPE_TETRAHEDRON};
854412e9a14SMatthew G. Knepley   static PetscInt       tetS[]    = {1, 8, 8};
855412e9a14SMatthew G. Knepley   static PetscInt       tetC[]    = {DM_POLYTOPE_POINT, 2, 0, 0, 0, DM_POLYTOPE_POINT, 2, 2, 1, 0,
856412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 1, 2, 2,
857412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 3, 0, DM_POLYTOPE_SEGMENT, 1, 1, 1,
858412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 1, 3, 2, DM_POLYTOPE_SEGMENT, 1, 0, 1,
859412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 3, 1, DM_POLYTOPE_SEGMENT, 1, 2, 1,
860412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 1, 2, 0,
861412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 1, 3, 1,
862412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 3, 2, DM_POLYTOPE_SEGMENT, 0,    0,
863412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 0,    0,
864412e9a14SMatthew 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,
865412e9a14SMatthew 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,
866412e9a14SMatthew 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,
867412e9a14SMatthew 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,
868412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_TRIANGLE, 0,    0, DM_POLYTOPE_TRIANGLE, 1, 2, 3, DM_POLYTOPE_TRIANGLE, 0,    4, DM_POLYTOPE_TRIANGLE, 0,    7,
869412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_TRIANGLE, 0,    1, DM_POLYTOPE_TRIANGLE, 1, 3, 3, DM_POLYTOPE_TRIANGLE, 0,    5, DM_POLYTOPE_TRIANGLE, 0,    6,
870412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_TRIANGLE, 0,    4, DM_POLYTOPE_TRIANGLE, 0,    6, DM_POLYTOPE_TRIANGLE, 0,    2, DM_POLYTOPE_TRIANGLE, 1, 0, 3,
871412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_TRIANGLE, 0,    5, DM_POLYTOPE_TRIANGLE, 0,    7, DM_POLYTOPE_TRIANGLE, 0,    3, DM_POLYTOPE_TRIANGLE, 1, 1, 3};
872412e9a14SMatthew G. Knepley   static PetscInt       tetO[]    = {0, 0,
873412e9a14SMatthew G. Knepley                                      0,  0,  0,
874412e9a14SMatthew G. Knepley                                      0,  0,  0,
875412e9a14SMatthew G. Knepley                                      0,  0,  0,
876412e9a14SMatthew G. Knepley                                      0,  0,  0,
877412e9a14SMatthew G. Knepley                                      0,  0, -2,
878412e9a14SMatthew G. Knepley                                      0,  0, -2,
879412e9a14SMatthew G. Knepley                                      0, -2, -2,
880412e9a14SMatthew G. Knepley                                      0, -2,  0,
881412e9a14SMatthew G. Knepley                                      0,  0,  0,  0,
882412e9a14SMatthew G. Knepley                                      0,  0,  0,  0,
883412e9a14SMatthew G. Knepley                                      0,  0,  0,  0,
884412e9a14SMatthew G. Knepley                                      0,  0,  0,  0,
885412e9a14SMatthew G. Knepley                                     -3,  0,  0, -2,
886412e9a14SMatthew G. Knepley                                     -2,  1,  0,  0,
887412e9a14SMatthew G. Knepley                                     -2, -2, -1,  2,
888412e9a14SMatthew G. Knepley                                     -2,  0, -2,  1};
889412e9a14SMatthew G. Knepley   /* Add a vertex in the center of each cell, add 6 edges and 12 quads inside every cell, making 8 new hexes
890412e9a14SMatthew 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
891412e9a14SMatthew G. Knepley        [v0, v1, v2, v3] f0 bottom
892412e9a14SMatthew G. Knepley        [v4, v5, v6, v7] f1 top
893412e9a14SMatthew G. Knepley        [v0, v3, v5, v4] f2 front
894412e9a14SMatthew G. Knepley        [v2, v1, v7, v6] f3 back
895412e9a14SMatthew G. Knepley        [v3, v2, v6, v5] f4 right
896412e9a14SMatthew G. Knepley        [v0, v4, v7, v1] f5 left
897412e9a14SMatthew G. Knepley      The eight hexes are divided into four on the bottom, and four on the top,
898412e9a14SMatthew G. Knepley        [v0,      (e0, 0),  (f0, 0),  (e3, 0),  (e9, 0), (f2, 0),  (c0, 0),  (f5, 0)]
899412e9a14SMatthew G. Knepley        [(e0, 0), v1,       (e1, 0),  (f0, 0),  (f5, 0), (c0, 0),  (f3, 0),  (e10, 0)]
900412e9a14SMatthew G. Knepley        [(f0, 0), (e1, 0),  v2,       (e2, 0),  (c0, 0), (f4, 0),  (e11, 0), (f3, 0)]
901412e9a14SMatthew G. Knepley        [(e3, 0), (f0, 0),  (e2, 0),  v3,       (f2, 0), (e8, 0),  (f4, 0),  (c0, 0)]
902412e9a14SMatthew G. Knepley        [(e9, 0), (f5, 0),  (c0, 0),  (f2, 0),  v4,      (e4, 0),  (f1, 0),  (e7, 0)]
903412e9a14SMatthew G. Knepley        [(f2, 0), (c0, 0),  (f4, 0),  (e8, 0),  (e4, 0), v5,       (e5, 0),  (f1, 0)]
904412e9a14SMatthew G. Knepley        [(c0, 0), (f3, 0),  (e11, 0), (f4, 0),  (f1, 0), (e5, 0),  v6,       (e6, 0)]
905412e9a14SMatthew G. Knepley        [(f5, 0), (e10, 0), (f3, 0),  (c0, 0),  (e7, 0), (f1, 0),  (e6, 0),  v7]
906412e9a14SMatthew 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,
907412e9a14SMatthew G. Knepley        [(e9, 0), (f2, 0),  (c0, 0),  (f5, 0)]
908412e9a14SMatthew G. Knepley        [(f5, 0), (c0, 0),  (f3, 0),  (e10, 0)]
909412e9a14SMatthew G. Knepley        [(c0, 0), (f4, 0),  (e11, 0), (f3, 0)]
910412e9a14SMatthew G. Knepley        [(f2, 0), (e8, 0),  (f4, 0),  (c0, 0)]
911412e9a14SMatthew G. Knepley      and on the x-z plane,
912412e9a14SMatthew G. Knepley        [(f0, 0), (e0, 0), (f5, 0), (c0, 0)]
913412e9a14SMatthew G. Knepley        [(c0, 0), (f5, 0), (e7, 0), (f1, 0)]
914412e9a14SMatthew G. Knepley        [(f4, 0), (c0, 0), (f1, 0), (e5, 0)]
915412e9a14SMatthew G. Knepley        [(e2, 0), (f0, 0), (c0, 0), (f4, 0)]
916412e9a14SMatthew G. Knepley      and on the y-z plane,
917412e9a14SMatthew G. Knepley        [(e3, 0), (f2, 0), (c0, 0), (f0, 0)]
918412e9a14SMatthew G. Knepley        [(f2, 0), (e4, 0), (f1, 0), (c0, 0)]
919412e9a14SMatthew G. Knepley        [(c0, 0), (f1, 0), (e6, 0), (f3, 0)]
920412e9a14SMatthew G. Knepley        [(f0, 0), (c0, 0), (f3, 0), (e1, 0)]
921412e9a14SMatthew G. Knepley   */
922412e9a14SMatthew G. Knepley   static DMPolytopeType hexT[]    = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL, DM_POLYTOPE_HEXAHEDRON};
923412e9a14SMatthew G. Knepley   static PetscInt       hexS[]    = {1, 6, 12, 8};
924412e9a14SMatthew G. Knepley   static PetscInt       hexC[]    = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 0, 0,
925412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 0, 0,
926412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 0, 0,
927412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 3, 0, DM_POLYTOPE_POINT, 0, 0,
928412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 4, 0, DM_POLYTOPE_POINT, 0, 0,
929412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 5, 0, DM_POLYTOPE_POINT, 0, 0,
930412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 3, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 0,    5, DM_POLYTOPE_SEGMENT, 1, 5, 0,
931412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    5, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 1, 3, 1, DM_POLYTOPE_SEGMENT, 1, 5, 2,
932412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    4, DM_POLYTOPE_SEGMENT, 1, 4, 1, DM_POLYTOPE_SEGMENT, 1, 3, 3, DM_POLYTOPE_SEGMENT, 0,    3,
933412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 4, 3, DM_POLYTOPE_SEGMENT, 0,    4, DM_POLYTOPE_SEGMENT, 0,    2,
934412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 5, 3, DM_POLYTOPE_SEGMENT, 0,    5, DM_POLYTOPE_SEGMENT, 0,    0,
935412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    5, DM_POLYTOPE_SEGMENT, 1, 5, 1, DM_POLYTOPE_SEGMENT, 1, 1, 3, DM_POLYTOPE_SEGMENT, 0,    1,
936412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    4, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 4, 2,
937412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    4, DM_POLYTOPE_SEGMENT, 1, 4, 0,
938412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 1, 0, 3,
939412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 2, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,    2,
940412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 1, 3, 2, DM_POLYTOPE_SEGMENT, 0,    3,
941412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 1, 3, 0, DM_POLYTOPE_SEGMENT, 1, 0, 1,
942412e9a14SMatthew 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,
943412e9a14SMatthew 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,
944412e9a14SMatthew 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,
945412e9a14SMatthew 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,
946412e9a14SMatthew 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,
947412e9a14SMatthew 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,
948412e9a14SMatthew 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,
949412e9a14SMatthew 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};
950412e9a14SMatthew G. Knepley   static PetscInt       hexO[]    = {0, 0,
951412e9a14SMatthew G. Knepley                                      0, 0,
952412e9a14SMatthew G. Knepley                                      0, 0,
953412e9a14SMatthew G. Knepley                                      0, 0,
954412e9a14SMatthew G. Knepley                                      0, 0,
955412e9a14SMatthew G. Knepley                                      0, 0,
956412e9a14SMatthew G. Knepley                                      0,  0, -2, -2,
957412e9a14SMatthew G. Knepley                                      0, -2, -2,  0,
958412e9a14SMatthew G. Knepley                                     -2, -2,  0,  0,
959412e9a14SMatthew G. Knepley                                     -2,  0,  0, -2,
960412e9a14SMatthew G. Knepley                                     -2,  0,  0, -2,
961412e9a14SMatthew G. Knepley                                     -2, -2,  0,  0,
962412e9a14SMatthew G. Knepley                                      0, -2, -2,  0,
963412e9a14SMatthew G. Knepley                                      0,  0, -2, -2,
964412e9a14SMatthew G. Knepley                                      0,  0, -2, -2,
965412e9a14SMatthew G. Knepley                                     -2,  0,  0, -2,
966412e9a14SMatthew G. Knepley                                     -2, -2,  0,  0,
967412e9a14SMatthew G. Knepley                                      0, -2, -2,  0,
968412e9a14SMatthew G. Knepley                                      0, 0,  0, 0, -4, 0,
969412e9a14SMatthew G. Knepley                                      0, 0, -1, 0, -4, 0,
970412e9a14SMatthew G. Knepley                                      0, 0, -1, 0,  0, 0,
971412e9a14SMatthew G. Knepley                                      0, 0,  0, 0,  0, 0,
972412e9a14SMatthew G. Knepley                                     -4, 0,  0, 0, -4, 0,
973412e9a14SMatthew G. Knepley                                     -4, 0,  0, 0,  0, 0,
974412e9a14SMatthew G. Knepley                                     -4, 0, -1, 0,  0, 0,
975412e9a14SMatthew G. Knepley                                     -4, 0, -1, 0, -4, 0};
976412e9a14SMatthew G. Knepley   /* Add 3 quads inside every triangular prism, making 4 new prisms. */
977412e9a14SMatthew G. Knepley   static DMPolytopeType tripT[]   = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_TRIANGLE, DM_POLYTOPE_QUADRILATERAL, DM_POLYTOPE_TRI_PRISM};
978412e9a14SMatthew G. Knepley   static PetscInt       tripS[]   = {3, 4, 6, 8};
979412e9a14SMatthew G. Knepley   static PetscInt       tripC[]   = {DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 1, 3, 0,
980412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 3, 0, DM_POLYTOPE_POINT, 1, 4, 0,
981412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 4, 0, DM_POLYTOPE_POINT, 1, 2, 0,
982412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 3, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 1, 4, 1,
983412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 3, 3, DM_POLYTOPE_SEGMENT, 0,    0,
984412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 3, 1, DM_POLYTOPE_SEGMENT, 1, 4, 3,
985412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,    2,
986412e9a14SMatthew 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,
987412e9a14SMatthew 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,
988412e9a14SMatthew 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,
989412e9a14SMatthew 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,
990412e9a14SMatthew 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,
991412e9a14SMatthew 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,
992412e9a14SMatthew 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,
993412e9a14SMatthew 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,
994412e9a14SMatthew 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,
995412e9a14SMatthew 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,
996412e9a14SMatthew 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,
997412e9a14SMatthew 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,
998412e9a14SMatthew 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,
999412e9a14SMatthew 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};
1000412e9a14SMatthew G. Knepley   static PetscInt       tripO[]   = {0, 0,
1001412e9a14SMatthew G. Knepley                                      0, 0,
1002412e9a14SMatthew G. Knepley                                      0, 0,
1003412e9a14SMatthew G. Knepley                                      0, -2, -2,
1004412e9a14SMatthew G. Knepley                                     -2,  0, -2,
1005412e9a14SMatthew G. Knepley                                     -2, -2,  0,
1006412e9a14SMatthew G. Knepley                                      0,  0,  0,
1007412e9a14SMatthew G. Knepley                                     -2,  0, -2, -2,
1008412e9a14SMatthew G. Knepley                                     -2,  0, -2, -2,
1009412e9a14SMatthew G. Knepley                                     -2,  0, -2, -2,
1010412e9a14SMatthew G. Knepley                                      0, -2, -2,  0,
1011412e9a14SMatthew G. Knepley                                      0, -2, -2,  0,
1012412e9a14SMatthew G. Knepley                                      0, -2, -2,  0,
1013412e9a14SMatthew G. Knepley                                      0,  0,  0, -1,  0,
1014412e9a14SMatthew G. Knepley                                      0,  0,  0,  0, -1,
1015412e9a14SMatthew G. Knepley                                      0,  0, -1,  0,  0,
1016412e9a14SMatthew G. Knepley                                      2,  0,  0,  0,  0,
1017412e9a14SMatthew G. Knepley                                     -3,  0,  0, -1,  0,
1018412e9a14SMatthew G. Knepley                                     -3,  0,  0,  0, -1,
1019412e9a14SMatthew G. Knepley                                     -3,  0, -1,  0,  0,
1020412e9a14SMatthew G. Knepley                                     -3,  0,  0,  0,  0};
1021412e9a14SMatthew G. Knepley   /* Add 3 tensor quads inside every tensor triangular prism, making 4 new prisms.
1022412e9a14SMatthew G. Knepley       2
1023412e9a14SMatthew G. Knepley       |\
1024412e9a14SMatthew G. Knepley       | \
1025412e9a14SMatthew G. Knepley       |  \
1026412e9a14SMatthew G. Knepley       0---1
102775d3a19aSMatthew G. Knepley 
1028412e9a14SMatthew G. Knepley       2
102975d3a19aSMatthew G. Knepley 
1030412e9a14SMatthew G. Knepley       0   1
103175d3a19aSMatthew G. Knepley 
1032412e9a14SMatthew G. Knepley       2
1033412e9a14SMatthew G. Knepley       |\
1034412e9a14SMatthew G. Knepley       | \
1035412e9a14SMatthew G. Knepley       |  \
1036412e9a14SMatthew G. Knepley       0---1
1037412e9a14SMatthew G. Knepley   */
1038412e9a14SMatthew G. Knepley   static DMPolytopeType ttripT[]  = {DM_POLYTOPE_SEG_PRISM_TENSOR, DM_POLYTOPE_TRI_PRISM_TENSOR};
1039412e9a14SMatthew G. Knepley   static PetscInt       ttripS[]  = {3, 4};
1040412e9a14SMatthew 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,
1041412e9a14SMatthew 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,
1042412e9a14SMatthew 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,
1043412e9a14SMatthew 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,
1044412e9a14SMatthew 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,
1045412e9a14SMatthew 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,
1046412e9a14SMatthew 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};
1047412e9a14SMatthew G. Knepley   static PetscInt       ttripO[]  = {0, 0, 0, 0,
1048412e9a14SMatthew G. Knepley                                      0, 0, 0, 0,
1049412e9a14SMatthew G. Knepley                                      0, 0, 0, 0,
1050412e9a14SMatthew G. Knepley                                      0, 0,  0, -1,  0,
1051412e9a14SMatthew G. Knepley                                      0, 0,  0,  0, -1,
1052412e9a14SMatthew G. Knepley                                      0, 0, -1,  0,  0,
1053412e9a14SMatthew G. Knepley                                      0, 0,  0,  0,  0};
1054412e9a14SMatthew G. Knepley   /* Add 1 edge and 4 tensor quads inside every tensor quad prism, making 4 new prisms. */
1055412e9a14SMatthew G. Knepley   static DMPolytopeType tquadpT[]  = {DM_POLYTOPE_POINT_PRISM_TENSOR, DM_POLYTOPE_SEG_PRISM_TENSOR, DM_POLYTOPE_QUAD_PRISM_TENSOR};
1056412e9a14SMatthew G. Knepley   static PetscInt       tquadpS[]  = {1, 4, 4};
1057412e9a14SMatthew G. Knepley   static PetscInt       tquadpC[]  = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
1058412e9a14SMatthew 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,
1059412e9a14SMatthew 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,
1060412e9a14SMatthew 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,
1061412e9a14SMatthew 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,
1062412e9a14SMatthew 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,
1063412e9a14SMatthew 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,
1064412e9a14SMatthew 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,
1065412e9a14SMatthew 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};
1066412e9a14SMatthew G. Knepley   static PetscInt       tquadpO[]  = {0, 0,
1067412e9a14SMatthew G. Knepley                                       0, 0, 0, 0,
1068412e9a14SMatthew G. Knepley                                       0, 0, 0, 0,
1069412e9a14SMatthew G. Knepley                                       0, 0, 0, 0,
1070412e9a14SMatthew G. Knepley                                       0, 0, 0, 0,
1071412e9a14SMatthew G. Knepley                                       0, 0,  0,  0, -1,  0,
1072412e9a14SMatthew G. Knepley                                       0, 0,  0,  0,  0, -1,
1073412e9a14SMatthew G. Knepley                                       0, 0, -1,  0,  0,  0,
1074412e9a14SMatthew G. Knepley                                       0, 0,  0, -1,  0,  0};
107575d3a19aSMatthew G. Knepley 
1076412e9a14SMatthew G. Knepley   PetscFunctionBegin;
1077412e9a14SMatthew G. Knepley   switch (source) {
1078412e9a14SMatthew G. Knepley     case DM_POLYTOPE_POINT:              *Nt = 1; *target = vertexT; *size = vertexS; *cone = vertexC; *ornt = vertexO; break;
1079412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:            *Nt = 2; *target = edgeT;   *size = edgeS;   *cone = edgeC;   *ornt = edgeO;   break;
1080412e9a14SMatthew G. Knepley     case DM_POLYTOPE_POINT_PRISM_TENSOR: *Nt = 1; *target = tedgeT;  *size = tedgeS;  *cone = tedgeC;  *ornt = tedgeO;  break;
1081412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:           *Nt = 2; *target = triT;    *size = triS;    *cone = triC;    *ornt = triO;    break;
1082412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:      *Nt = 3; *target = quadT;   *size = quadS;   *cone = quadC;   *ornt = quadO;   break;
1083412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEG_PRISM_TENSOR:   *Nt = 2; *target = tquadT;  *size = tquadS;  *cone = tquadC;  *ornt = tquadO;  break;
1084412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TETRAHEDRON:        *Nt = 3; *target = tetT;    *size = tetS;    *cone = tetC;    *ornt = tetO;    break;
1085412e9a14SMatthew G. Knepley     case DM_POLYTOPE_HEXAHEDRON:         *Nt = 4; *target = hexT;    *size = hexS;    *cone = hexC;    *ornt = hexO;    break;
1086412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM:          *Nt = 4; *target = tripT;   *size = tripS;   *cone = tripC;   *ornt = tripO;   break;
1087412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:   *Nt = 2; *target = ttripT;  *size = ttripS;  *cone = ttripC;  *ornt = ttripO;  break;
1088412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUAD_PRISM_TENSOR:  *Nt = 3; *target = tquadpT; *size = tquadpS; *cone = tquadpC; *ornt = tquadpO; break;
1089412e9a14SMatthew G. Knepley     default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No refinement strategy for %s", DMPolytopeTypes[source]);
1090412e9a14SMatthew G. Knepley   }
1091412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1092412e9a14SMatthew G. Knepley }
109375d3a19aSMatthew G. Knepley 
109496ca5757SLisandro Dalcin static PetscErrorCode DMPlexCellRefinerRefine_ToBox(DMPlexCellRefiner cr, DMPolytopeType source, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[])
1095412e9a14SMatthew G. Knepley {
1096412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
1097412e9a14SMatthew G. Knepley   /* Change tensor edges to segments */
1098412e9a14SMatthew G. Knepley   static DMPolytopeType tedgeT[]  = {DM_POLYTOPE_SEGMENT};
1099412e9a14SMatthew G. Knepley   static PetscInt       tedgeS[]  = {1};
1100412e9a14SMatthew G. Knepley   static PetscInt       tedgeC[]  = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0};
1101412e9a14SMatthew G. Knepley   static PetscInt       tedgeO[]  = {                         0,                          0};
1102412e9a14SMatthew G. Knepley   /* Add 1 vertex, 3 edges inside every triangle, making 3 new quadrilaterals.
1103e5337592SStefano Zampini    2
1104e5337592SStefano Zampini    |\
1105e5337592SStefano Zampini    | \
1106e5337592SStefano Zampini    |  \
1107e5337592SStefano Zampini    |   \
1108412e9a14SMatthew G. Knepley    0    1
1109412e9a14SMatthew G. Knepley    |     \
1110e5337592SStefano Zampini    |      \
1111e5337592SStefano Zampini    2       1
1112e5337592SStefano Zampini    |\     / \
1113e5337592SStefano Zampini    | 2   1   \
1114e5337592SStefano Zampini    |  \ /     \
1115412e9a14SMatthew G. Knepley    1   |       0
1116e5337592SStefano Zampini    |   0        \
1117e5337592SStefano Zampini    |   |         \
1118412e9a14SMatthew G. Knepley    |   |          \
1119412e9a14SMatthew G. Knepley    0-0-0-----1-----1
1120e5337592SStefano Zampini   */
1121412e9a14SMatthew G. Knepley   static DMPolytopeType triT[]    = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL};
1122412e9a14SMatthew G. Knepley   static PetscInt       triS[]    = {1, 3, 3};
1123412e9a14SMatthew G. Knepley   static PetscInt       triC[]    = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 0,    0,
1124412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 0,    0,
1125412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 0,    0,
1126412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 1, 2, 1,
1127412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,    0,
1128412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 2, 0};
1129412e9a14SMatthew G. Knepley   static PetscInt       triO[]    = {0, 0,
1130412e9a14SMatthew G. Knepley                                      0, 0,
1131412e9a14SMatthew G. Knepley                                      0, 0,
1132412e9a14SMatthew G. Knepley                                      0,  0, -2,  0,
1133412e9a14SMatthew G. Knepley                                      0,  0,  0, -2,
1134412e9a14SMatthew G. Knepley                                      0, -2,  0,  0};
1135412e9a14SMatthew G. Knepley   /* Add 1 edge inside every tensor quad, making 2 new quadrilaterals
1136412e9a14SMatthew G. Knepley      2----2----1----3----3
11374330a3fcSStefano Zampini      |         |         |
11384330a3fcSStefano Zampini      |         |         |
11394330a3fcSStefano Zampini      |         |         |
1140412e9a14SMatthew G. Knepley      4    A    6    B    5
11414330a3fcSStefano Zampini      |         |         |
1142412e9a14SMatthew G. Knepley      |         |         |
1143412e9a14SMatthew G. Knepley      |         |         |
1144412e9a14SMatthew G. Knepley      0----0----0----1----1
11454330a3fcSStefano Zampini   */
1146412e9a14SMatthew G. Knepley   static DMPolytopeType tquadT[]  = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL};
1147412e9a14SMatthew G. Knepley   static PetscInt       tquadS[]  = {1, 2};
1148412e9a14SMatthew G. Knepley   static PetscInt       tquadC[]  = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
1149412e9a14SMatthew G. Knepley                                      /* TODO  Fix these */
1150412e9a14SMatthew 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,
1151412e9a14SMatthew 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};
1152412e9a14SMatthew G. Knepley   static PetscInt       tquadO[]  = {0, 0,
1153412e9a14SMatthew G. Knepley                                      0, 0, -2, -2,
1154412e9a14SMatthew G. Knepley                                      0, 0, -2, -2};
1155412e9a14SMatthew G. Knepley   /* Add 6 triangles inside every cell, making 4 new hexs
1156412e9a14SMatthew G. Knepley      TODO: Need different SubcellMap(). Need to make a struct with the function pointers in it
1157412e9a14SMatthew 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
1158412e9a14SMatthew 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]
1159412e9a14SMatthew G. Knepley      called e3, e4, and e5. The faces of a tet, given in DMPlexGetRawFaces_Internal() are
1160412e9a14SMatthew G. Knepley        [v0, v1, v2], [v0, v3, v1], [v0, v2, v3], [v2, v1, v3]
1161412e9a14SMatthew G. Knepley      We make a new hex in each corner
1162412e9a14SMatthew G. Knepley        [v0, (e0, 0), (f0, 0), (e2, 0), (e3, 0), (f2, 0), (c0, 0), (f1, 0)]
1163412e9a14SMatthew G. Knepley        [v1, (e4, 0), (f3, 0), (e1, 0), (e0, 0), (f0, 0), (c0, 0), (f1, 0)]
1164412e9a14SMatthew G. Knepley        [v2, (e1, 0), (f3, 0), (e5, 0), (e2, 0), (f2, 0), (c0, 0), (f0, 0)]
1165412e9a14SMatthew G. Knepley        [v3, (e4, 0), (f1, 0), (e3, 0), (e5, 0), (f2, 0), (c0, 0), (f3, 0)]
1166412e9a14SMatthew G. Knepley      We create a new face for each edge
1167412e9a14SMatthew G. Knepley        [(e3, 0), (f2, 0), (c0, 0), (f1, 0)]
1168412e9a14SMatthew G. Knepley        [(f0, 0), (e0, 0), (f1, 0), (c0, 0)]
1169412e9a14SMatthew G. Knepley        [(e2, 0), (f0, 0), (c0, 0), (f2, 0)]
1170412e9a14SMatthew G. Knepley        [(f3, 0), (e4, 0), (f1, 0), (c0, 0)]
1171412e9a14SMatthew G. Knepley        [(e1, 0), (f3, 0), (c0, 0), (f0, 0)]
1172412e9a14SMatthew G. Knepley        [(e5, 0), (f3, 0), (c0, 0), (f2, 0)]
1173412e9a14SMatthew G. Knepley      I could write a program to generate these from the first hex by acting with the symmetry group to take one subcell into another.
117475d3a19aSMatthew G. Knepley    */
1175412e9a14SMatthew G. Knepley   static DMPolytopeType tetT[]    = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL, DM_POLYTOPE_HEXAHEDRON};
1176412e9a14SMatthew G. Knepley   static PetscInt       tetS[]    = {1, 4, 6, 4};
1177412e9a14SMatthew G. Knepley   static PetscInt       tetC[]    = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 0, 0,
1178412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 0, 0,
1179412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 0, 0,
1180412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 3, 0, DM_POLYTOPE_POINT, 0, 0,
1181412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 2, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 0,
1182412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,    0,
1183412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 1, 2, 0,
1184412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 3, 1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 0,    3,
1185412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 3, 0, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 1, 0, 1,
1186412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 3, 2, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 1, 2, 1,
1187412e9a14SMatthew 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,
1188412e9a14SMatthew 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,
1189412e9a14SMatthew 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,
1190412e9a14SMatthew 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};
1191412e9a14SMatthew G. Knepley   static PetscInt       tetO[]    = {0, 0,
1192412e9a14SMatthew G. Knepley                                      0, 0,
1193412e9a14SMatthew G. Knepley                                      0, 0,
1194412e9a14SMatthew G. Knepley                                      0, 0,
1195412e9a14SMatthew G. Knepley                                      0,  0, -2, -2,
1196412e9a14SMatthew G. Knepley                                     -2,  0,  0, -2,
1197412e9a14SMatthew G. Knepley                                      0,  0, -2, -2,
1198412e9a14SMatthew G. Knepley                                     -2,  0,  0, -2,
1199412e9a14SMatthew G. Knepley                                      0,  0, -2, -2,
1200412e9a14SMatthew G. Knepley                                      0,  0, -2, -2,
1201412e9a14SMatthew G. Knepley                                      0,  0,  0,  0,  0,  0,
1202412e9a14SMatthew G. Knepley                                      1, -1,  1,  0,  0,  3,
1203412e9a14SMatthew G. Knepley                                      0, -4,  1, -1,  0,  3,
1204412e9a14SMatthew G. Knepley                                      1, -4,  3, -2, -4,  3};
1205412e9a14SMatthew G. Knepley   /* Add 3 quads inside every triangular prism, making 4 new prisms. */
1206412e9a14SMatthew G. Knepley   static DMPolytopeType tripT[]   = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL, DM_POLYTOPE_HEXAHEDRON};
1207412e9a14SMatthew G. Knepley   static PetscInt       tripS[]   = {1, 5, 9, 6};
1208412e9a14SMatthew G. Knepley   static PetscInt       tripC[]   = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 0, 0,
1209412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 1, 0, DM_POLYTOPE_POINT, 0, 0,
1210412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 2, 0, DM_POLYTOPE_POINT, 0, 0,
1211412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 3, 0, DM_POLYTOPE_POINT, 0, 0,
1212412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_POINT, 1, 4, 0, DM_POLYTOPE_POINT, 0, 0,
1213412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 3, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 0,    4, DM_POLYTOPE_SEGMENT, 1, 4, 1,
1214412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 2, 1, DM_POLYTOPE_SEGMENT, 1, 3, 3, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 0,    2,
1215412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    4, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 1, 3, 1, DM_POLYTOPE_SEGMENT, 1, 4, 3,
1216412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 2, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 1, 2, 0,
1217412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 1, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 1, 3, 0,
1218412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 0,    0, DM_POLYTOPE_SEGMENT, 0,    4, DM_POLYTOPE_SEGMENT, 1, 4, 0,
1219412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    2, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 2, 2,
1220412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    3, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 1, DM_POLYTOPE_SEGMENT, 1, 3, 2,
1221412e9a14SMatthew G. Knepley                                      DM_POLYTOPE_SEGMENT, 0,    4, DM_POLYTOPE_SEGMENT, 0,    1, DM_POLYTOPE_SEGMENT, 1, 1, 2, DM_POLYTOPE_SEGMENT, 1, 4, 2,
1222412e9a14SMatthew 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,
1223412e9a14SMatthew 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,
1224412e9a14SMatthew 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,
1225412e9a14SMatthew 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,
1226412e9a14SMatthew 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,
1227412e9a14SMatthew 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};
1228412e9a14SMatthew G. Knepley   static PetscInt       tripO[]   = {0, 0,
1229412e9a14SMatthew G. Knepley                                      0, 0,
1230412e9a14SMatthew G. Knepley                                      0, 0,
1231412e9a14SMatthew G. Knepley                                      0, 0,
1232412e9a14SMatthew G. Knepley                                      0, 0,
1233412e9a14SMatthew G. Knepley                                      0,  0, -2, -2,
1234412e9a14SMatthew G. Knepley                                     -2,  0,  0, -2,
1235412e9a14SMatthew G. Knepley                                      0, -2, -2,  0,
1236412e9a14SMatthew G. Knepley                                      0,  0, -2, -2,
1237412e9a14SMatthew G. Knepley                                      0,  0, -2, -2,
1238412e9a14SMatthew G. Knepley                                      0,  0, -2, -2,
1239412e9a14SMatthew G. Knepley                                      0, -2, -2,  0,
1240412e9a14SMatthew G. Knepley                                      0, -2, -2,  0,
1241412e9a14SMatthew G. Knepley                                      0, -2, -2,  0,
1242412e9a14SMatthew G. Knepley                                      0,  0,  0, -1,  0,  1,
1243412e9a14SMatthew G. Knepley                                      0,  0,  0,  0,  0, -4,
1244412e9a14SMatthew G. Knepley                                      0,  0,  0,  0, -1,  1,
1245412e9a14SMatthew G. Knepley                                     -4,  0,  0, -1,  0,  1,
1246412e9a14SMatthew G. Knepley                                     -4,  0,  0,  0,  0, -4,
1247412e9a14SMatthew G. Knepley                                     -4,  0,  0,  0, -1,  1};
1248412e9a14SMatthew G. Knepley   /* Add 3 tensor quads inside every tensor triangular prism, making 4 new tensor triangular prisms.
1249412e9a14SMatthew G. Knepley       2
1250412e9a14SMatthew G. Knepley       |\
1251412e9a14SMatthew G. Knepley       | \
1252412e9a14SMatthew G. Knepley       |  \
1253412e9a14SMatthew G. Knepley       0---1
125475d3a19aSMatthew G. Knepley 
1255412e9a14SMatthew G. Knepley       2
125675d3a19aSMatthew G. Knepley 
1257412e9a14SMatthew G. Knepley       0   1
125875d3a19aSMatthew G. Knepley 
1259412e9a14SMatthew G. Knepley       2
1260412e9a14SMatthew G. Knepley       |\
1261412e9a14SMatthew G. Knepley       | \
1262412e9a14SMatthew G. Knepley       |  \
1263412e9a14SMatthew G. Knepley       0---1
126475d3a19aSMatthew G. Knepley   */
1265412e9a14SMatthew G. Knepley   static DMPolytopeType ttripT[]  = {DM_POLYTOPE_POINT_PRISM_TENSOR, DM_POLYTOPE_SEG_PRISM_TENSOR, DM_POLYTOPE_QUAD_PRISM_TENSOR};
1266412e9a14SMatthew G. Knepley   static PetscInt       ttripS[]  = {1, 3, 3};
1267412e9a14SMatthew G. Knepley   static PetscInt       ttripC[]  = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
1268412e9a14SMatthew 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,
1269412e9a14SMatthew 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,
1270412e9a14SMatthew 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,
1271412e9a14SMatthew 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,
1272412e9a14SMatthew 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,
1273412e9a14SMatthew 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};
1274412e9a14SMatthew G. Knepley   static PetscInt       ttripO[]  = {0, 0,
1275412e9a14SMatthew G. Knepley                                      0, 0, 0, 0,
1276412e9a14SMatthew G. Knepley                                      0, 0, 0, 0,
1277412e9a14SMatthew G. Knepley                                      0, 0, 0, 0,
1278412e9a14SMatthew G. Knepley                                      0, 0, 0,  0, -1, 0,
1279412e9a14SMatthew G. Knepley                                      0, 0, 0,  0,  0, -1,
1280412e9a14SMatthew G. Knepley                                      0, 0, 0, -1,  0, 0};
1281412e9a14SMatthew G. Knepley   /* TODO Add 3 quads inside every tensor triangular prism, making 4 new triangular prisms.
1282412e9a14SMatthew G. Knepley       2
1283412e9a14SMatthew G. Knepley       |\
1284412e9a14SMatthew G. Knepley       | \
1285412e9a14SMatthew G. Knepley       |  \
1286412e9a14SMatthew G. Knepley       0---1
128775d3a19aSMatthew G. Knepley 
1288412e9a14SMatthew G. Knepley       2
128975d3a19aSMatthew G. Knepley 
1290412e9a14SMatthew G. Knepley       0   1
129175d3a19aSMatthew G. Knepley 
1292412e9a14SMatthew G. Knepley       2
1293412e9a14SMatthew G. Knepley       |\
1294412e9a14SMatthew G. Knepley       | \
1295412e9a14SMatthew G. Knepley       |  \
1296412e9a14SMatthew G. Knepley       0---1
1297a97b51b8SMatthew G. Knepley   */
1298412e9a14SMatthew G. Knepley   static DMPolytopeType ctripT[]  = {DM_POLYTOPE_SEGMENT, DM_POLYTOPE_QUADRILATERAL, DM_POLYTOPE_HEXAHEDRON};
1299412e9a14SMatthew G. Knepley   static PetscInt       ctripS[]  = {1, 3, 3};
1300412e9a14SMatthew G. Knepley   static PetscInt       ctripC[]  = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
1301412e9a14SMatthew 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,
1302412e9a14SMatthew 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,
1303412e9a14SMatthew 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,
1304412e9a14SMatthew 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,
1305412e9a14SMatthew 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,
1306412e9a14SMatthew 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};
1307412e9a14SMatthew G. Knepley   static PetscInt       ctripO[]  = {0, 0,
1308412e9a14SMatthew G. Knepley                                      0, 0, -2, -2,
1309412e9a14SMatthew G. Knepley                                      0, 0, -2, -2,
1310412e9a14SMatthew G. Knepley                                      0, 0, -2, -2,
1311412e9a14SMatthew G. Knepley                                     -4, 0, 0, -1,  0,  1,
1312412e9a14SMatthew G. Knepley                                     -4, 0, 0,  0,  0, -4,
1313412e9a14SMatthew G. Knepley                                     -4, 0, 0,  0, -1,  1};
1314412e9a14SMatthew G. Knepley   /* Add 1 edge and 4 quads inside every tensor quad prism, making 4 new hexahedra. */
1315412e9a14SMatthew G. Knepley   static DMPolytopeType tquadpT[]  = {DM_POLYTOPE_POINT_PRISM_TENSOR, DM_POLYTOPE_SEG_PRISM_TENSOR, DM_POLYTOPE_QUAD_PRISM_TENSOR};
1316412e9a14SMatthew G. Knepley   static PetscInt       tquadpS[]  = {1, 4, 4};
1317412e9a14SMatthew G. Knepley   static PetscInt       tquadpC[]  = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0,
1318412e9a14SMatthew 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,
1319412e9a14SMatthew 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,
1320412e9a14SMatthew 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,
1321412e9a14SMatthew 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,
1322412e9a14SMatthew 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,
1323412e9a14SMatthew 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,
1324412e9a14SMatthew 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,
1325412e9a14SMatthew 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};
1326412e9a14SMatthew G. Knepley   static PetscInt       tquadpO[]  = {0, 0,
1327412e9a14SMatthew G. Knepley                                       0, 0, 0, 0,
1328412e9a14SMatthew G. Knepley                                       0, 0, 0, 0,
1329412e9a14SMatthew G. Knepley                                       0, 0, 0, 0,
1330412e9a14SMatthew G. Knepley                                       0, 0, 0, 0,
1331412e9a14SMatthew G. Knepley                                       0, 0,  0,  0, -1,  0,
1332412e9a14SMatthew G. Knepley                                       0, 0,  0,  0,  0, -1,
1333412e9a14SMatthew G. Knepley                                       0, 0, -1,  0,  0,  0,
1334412e9a14SMatthew G. Knepley                                       0, 0,  0, -1,  0,  0};
1335412e9a14SMatthew G. Knepley   PetscBool convertTensor = PETSC_TRUE;
1336a97b51b8SMatthew G. Knepley 
1337412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
1338412e9a14SMatthew G. Knepley   if (convertTensor) {
1339412e9a14SMatthew G. Knepley     switch (source) {
1340412e9a14SMatthew G. Knepley       case DM_POLYTOPE_POINT:
1341412e9a14SMatthew G. Knepley       case DM_POLYTOPE_SEGMENT:
1342412e9a14SMatthew G. Knepley       case DM_POLYTOPE_QUADRILATERAL:
1343412e9a14SMatthew G. Knepley       case DM_POLYTOPE_HEXAHEDRON:
1344412e9a14SMatthew G. Knepley         ierr = DMPlexCellRefinerRefine_Regular(cr, source, Nt, target, size, cone, ornt);CHKERRQ(ierr);
1345a97b51b8SMatthew G. Knepley         break;
1346412e9a14SMatthew G. Knepley       case DM_POLYTOPE_POINT_PRISM_TENSOR: *Nt = 1; *target = tedgeT;  *size = tedgeS;  *cone = tedgeC;  *ornt = tedgeO;  break;
1347412e9a14SMatthew G. Knepley       case DM_POLYTOPE_SEG_PRISM_TENSOR:   *Nt = 2; *target = tquadT;  *size = tquadS;  *cone = tquadC;  *ornt = tquadO;  break;
1348412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM_TENSOR:   *Nt = 3; *target = ctripT;  *size = ctripS;  *cone = ctripC;  *ornt = ctripO;  break;
1349412e9a14SMatthew G. Knepley       case DM_POLYTOPE_QUAD_PRISM_TENSOR:  *Nt = 3; *target = tquadpT; *size = tquadpS; *cone = tquadpC; *ornt = tquadpO; break;
1350412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRIANGLE:           *Nt = 3; *target = triT;    *size = triS;    *cone = triC;    *ornt = triO;    break;
1351412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TETRAHEDRON:        *Nt = 4; *target = tetT;    *size = tetS;    *cone = tetC;    *ornt = tetO;    break;
1352412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM:          *Nt = 4; *target = tripT;   *size = tripS;   *cone = tripC;   *ornt = tripO;   break;
1353412e9a14SMatthew G. Knepley       default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No refinement strategy for %s", DMPolytopeTypes[source]);
1354b5da9499SMatthew G. Knepley     }
1355b5da9499SMatthew G. Knepley   } else {
1356412e9a14SMatthew G. Knepley     switch (source) {
1357412e9a14SMatthew G. Knepley       case DM_POLYTOPE_POINT:
1358412e9a14SMatthew G. Knepley       case DM_POLYTOPE_POINT_PRISM_TENSOR:
1359412e9a14SMatthew G. Knepley       case DM_POLYTOPE_SEGMENT:
1360412e9a14SMatthew G. Knepley       case DM_POLYTOPE_QUADRILATERAL:
1361412e9a14SMatthew G. Knepley       case DM_POLYTOPE_SEG_PRISM_TENSOR:
1362412e9a14SMatthew G. Knepley       case DM_POLYTOPE_HEXAHEDRON:
1363412e9a14SMatthew G. Knepley       case DM_POLYTOPE_QUAD_PRISM_TENSOR:
1364412e9a14SMatthew G. Knepley         ierr = DMPlexCellRefinerRefine_Regular(cr, source, Nt, target, size, cone, ornt);CHKERRQ(ierr);
1365b5da9499SMatthew G. Knepley         break;
1366412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRIANGLE:           *Nt = 3; *target = triT;    *size = triS;    *cone = triC;    *ornt = triO;    break;
1367412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TETRAHEDRON:        *Nt = 4; *target = tetT;    *size = tetS;    *cone = tetC;    *ornt = tetO;    break;
1368412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM:          *Nt = 4; *target = tripT;   *size = tripS;   *cone = tripC;   *ornt = tripO;   break;
1369412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM_TENSOR:   *Nt = 3; *target = ttripT;  *size = ttripS;  *cone = ttripC;  *ornt = ttripO;  break;
1370412e9a14SMatthew G. Knepley       default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No refinement strategy for %s", DMPolytopeTypes[source]);
137127fcede3SMatthew G. Knepley     }
137275d3a19aSMatthew G. Knepley   }
137375d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
137475d3a19aSMatthew G. Knepley }
137575d3a19aSMatthew G. Knepley 
1376412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerRefine_ToSimplex(DMPlexCellRefiner cr, DMPolytopeType source, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[])
137775d3a19aSMatthew G. Knepley {
1378412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
1379412e9a14SMatthew G. Knepley 
1380412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
1381412e9a14SMatthew G. Knepley   switch (source) {
1382412e9a14SMatthew G. Knepley     case DM_POLYTOPE_POINT:
1383412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:
1384412e9a14SMatthew G. Knepley     case DM_POLYTOPE_POINT_PRISM_TENSOR:
1385412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:
1386412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TETRAHEDRON:
1387412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM:
1388412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:
1389412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:
1390412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEG_PRISM_TENSOR:
1391412e9a14SMatthew G. Knepley     case DM_POLYTOPE_HEXAHEDRON:
1392412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
1393412e9a14SMatthew G. Knepley       ierr = DMPlexCellRefinerRefine_Regular(cr, source, Nt, target, size, cone, ornt);CHKERRQ(ierr);
1394412e9a14SMatthew G. Knepley       break;
1395412e9a14SMatthew G. Knepley     default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No refinement strategy for %s", DMPolytopeTypes[source]);
1396412e9a14SMatthew G. Knepley   }
1397412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1398412e9a14SMatthew G. Knepley }
1399412e9a14SMatthew G. Knepley 
1400412e9a14SMatthew G. Knepley static PetscErrorCode CellRefinerCreateOffset_Internal(DMPlexCellRefiner cr, PetscInt ctOrder[], PetscInt ctStart[], PetscInt **offset)
1401412e9a14SMatthew G. Knepley {
1402412e9a14SMatthew G. Knepley   PetscInt       c, cN, *off;
140375d3a19aSMatthew G. Knepley   PetscErrorCode ierr;
140475d3a19aSMatthew G. Knepley 
140575d3a19aSMatthew G. Knepley   PetscFunctionBegin;
1406412e9a14SMatthew G. Knepley   ierr = PetscCalloc1(DM_NUM_POLYTOPES*DM_NUM_POLYTOPES, &off);CHKERRQ(ierr);
1407412e9a14SMatthew G. Knepley   for (c = DM_POLYTOPE_POINT; c < DM_NUM_POLYTOPES; ++c) {
1408412e9a14SMatthew G. Knepley     const DMPolytopeType ct = (DMPolytopeType) c;
1409412e9a14SMatthew G. Knepley     for (cN = DM_POLYTOPE_POINT; cN < DM_NUM_POLYTOPES; ++cN) {
1410412e9a14SMatthew G. Knepley       const DMPolytopeType ctNew = (DMPolytopeType) cN;
1411412e9a14SMatthew G. Knepley       DMPolytopeType      *rct;
1412412e9a14SMatthew G. Knepley       PetscInt            *rsize, *cone, *ornt;
1413412e9a14SMatthew G. Knepley       PetscInt             Nct, n, i;
1414412e9a14SMatthew G. Knepley 
1415412e9a14SMatthew G. Knepley       if (DMPolytopeTypeGetDim(ct) < 0 || DMPolytopeTypeGetDim(ctNew) < 0) {off[ct*DM_NUM_POLYTOPES+ctNew] = -1; break;}
1416412e9a14SMatthew G. Knepley       off[ct*DM_NUM_POLYTOPES+ctNew] = 0;
1417412e9a14SMatthew G. Knepley       for (i = DM_POLYTOPE_POINT; i < DM_NUM_POLYTOPES; ++i) {
1418412e9a14SMatthew G. Knepley         const DMPolytopeType ict  = (DMPolytopeType) ctOrder[i];
1419412e9a14SMatthew G. Knepley         const DMPolytopeType ictn = (DMPolytopeType) ctOrder[i+1];
1420412e9a14SMatthew G. Knepley 
1421412e9a14SMatthew G. Knepley         ierr = DMPlexCellRefinerRefine(cr, ict, &Nct, &rct, &rsize, &cone, &ornt);CHKERRQ(ierr);
1422412e9a14SMatthew G. Knepley         if (ict == ct) {
1423412e9a14SMatthew G. Knepley           for (n = 0; n < Nct; ++n) if (rct[n] == ctNew) break;
1424412e9a14SMatthew G. Knepley           if (n == Nct) off[ct*DM_NUM_POLYTOPES+ctNew] = -1;
1425412e9a14SMatthew G. Knepley           break;
1426412e9a14SMatthew G. Knepley         }
1427412e9a14SMatthew G. Knepley         for (n = 0; n < Nct; ++n) if (rct[n] == ctNew) off[ct*DM_NUM_POLYTOPES+ctNew] += (ctStart[ictn]-ctStart[ict]) * rsize[n];
1428412e9a14SMatthew G. Knepley       }
1429412e9a14SMatthew G. Knepley     }
1430412e9a14SMatthew G. Knepley   }
1431412e9a14SMatthew G. Knepley   *offset = off;
1432412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1433412e9a14SMatthew G. Knepley }
1434412e9a14SMatthew G. Knepley 
1435412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerSetStarts(DMPlexCellRefiner cr, const PetscInt ctStart[], const PetscInt ctStartNew[])
1436412e9a14SMatthew G. Knepley {
1437412e9a14SMatthew G. Knepley   const PetscInt ctSize = DM_NUM_POLYTOPES+1;
1438412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
1439412e9a14SMatthew G. Knepley 
1440412e9a14SMatthew G. Knepley   PetscFunctionBegin;
1441412e9a14SMatthew G. Knepley   if (cr->setupcalled) SETERRQ(PetscObjectComm((PetscObject) cr), PETSC_ERR_ARG_WRONGSTATE, "Must call this function before DMPlexCellRefinerSetUp()");
1442412e9a14SMatthew G. Knepley   ierr = PetscCalloc2(ctSize, &cr->ctStart, ctSize, &cr->ctStartNew);CHKERRQ(ierr);
1443412e9a14SMatthew G. Knepley   ierr = PetscArraycpy(cr->ctStart,    ctStart,    ctSize);CHKERRQ(ierr);
1444412e9a14SMatthew G. Knepley   ierr = PetscArraycpy(cr->ctStartNew, ctStartNew, ctSize);CHKERRQ(ierr);
1445412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1446412e9a14SMatthew G. Knepley }
1447412e9a14SMatthew G. Knepley 
1448412e9a14SMatthew G. Knepley /* Construct cell type order since we must loop over cell types in depth order */
1449412e9a14SMatthew G. Knepley PetscErrorCode DMPlexCreateCellTypeOrder_Internal(DMPolytopeType ctCell, PetscInt *ctOrder[], PetscInt *ctOrderInv[])
1450412e9a14SMatthew G. Knepley {
1451412e9a14SMatthew G. Knepley   PetscInt      *ctO, *ctOInv;
1452412e9a14SMatthew G. Knepley   PetscInt       c, d, off = 0;
1453412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
1454412e9a14SMatthew G. Knepley 
1455412e9a14SMatthew G. Knepley   PetscFunctionBegin;
1456412e9a14SMatthew G. Knepley   ierr = PetscCalloc2(DM_NUM_POLYTOPES+1, &ctO, DM_NUM_POLYTOPES+1, &ctOInv);CHKERRQ(ierr);
1457412e9a14SMatthew G. Knepley   for (d = 3; d >= DMPolytopeTypeGetDim(ctCell); --d) {
1458412e9a14SMatthew G. Knepley     for (c = 0; c <= DM_NUM_POLYTOPES; ++c) {
1459412e9a14SMatthew G. Knepley       if (DMPolytopeTypeGetDim((DMPolytopeType) c) != d) continue;
1460412e9a14SMatthew G. Knepley       ctO[off++] = c;
1461412e9a14SMatthew G. Knepley     }
1462412e9a14SMatthew G. Knepley   }
1463412e9a14SMatthew G. Knepley   if (DMPolytopeTypeGetDim(ctCell) != 0) {
1464412e9a14SMatthew G. Knepley     for (c = 0; c <= DM_NUM_POLYTOPES; ++c) {
1465412e9a14SMatthew G. Knepley       if (DMPolytopeTypeGetDim((DMPolytopeType) c) != 0) continue;
1466412e9a14SMatthew G. Knepley       ctO[off++] = c;
1467412e9a14SMatthew G. Knepley     }
1468412e9a14SMatthew G. Knepley   }
1469412e9a14SMatthew G. Knepley   for (d = DMPolytopeTypeGetDim(ctCell)-1; d > 0; --d) {
1470412e9a14SMatthew G. Knepley     for (c = 0; c <= DM_NUM_POLYTOPES; ++c) {
1471412e9a14SMatthew G. Knepley       if (DMPolytopeTypeGetDim((DMPolytopeType) c) != d) continue;
1472412e9a14SMatthew G. Knepley       ctO[off++] = c;
1473412e9a14SMatthew G. Knepley     }
1474412e9a14SMatthew G. Knepley   }
1475412e9a14SMatthew G. Knepley   for (c = 0; c <= DM_NUM_POLYTOPES; ++c) {
1476412e9a14SMatthew G. Knepley     if (DMPolytopeTypeGetDim((DMPolytopeType) c) >= 0) continue;
1477412e9a14SMatthew G. Knepley     ctO[off++] = c;
1478412e9a14SMatthew G. Knepley   }
1479412e9a14SMatthew G. Knepley   if (off != DM_NUM_POLYTOPES+1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid offset %D for cell type order", off);
1480412e9a14SMatthew G. Knepley   for (c = 0; c <= DM_NUM_POLYTOPES; ++c) {
1481412e9a14SMatthew G. Knepley     ctOInv[ctO[c]] = c;
1482412e9a14SMatthew G. Knepley   }
1483412e9a14SMatthew G. Knepley   *ctOrder    = ctO;
1484412e9a14SMatthew G. Knepley   *ctOrderInv = ctOInv;
1485412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1486412e9a14SMatthew G. Knepley }
1487412e9a14SMatthew G. Knepley 
1488412e9a14SMatthew G. Knepley PetscErrorCode DMPlexCellRefinerSetUp(DMPlexCellRefiner cr)
1489412e9a14SMatthew G. Knepley {
1490412e9a14SMatthew G. Knepley   DM             dm = cr->dm;
1491412e9a14SMatthew G. Knepley   DMPolytopeType ctCell;
1492412e9a14SMatthew G. Knepley   PetscInt       pStart, pEnd, p, c;
1493412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
1494412e9a14SMatthew G. Knepley 
1495412e9a14SMatthew G. Knepley   PetscFunctionBegin;
1496412e9a14SMatthew G. Knepley   PetscValidHeader(cr, 1);
1497412e9a14SMatthew G. Knepley   if (cr->setupcalled) PetscFunctionReturn(0);
1498412e9a14SMatthew G. Knepley   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
1499412e9a14SMatthew G. Knepley   if (pEnd > pStart) {ierr = DMPlexGetCellType(dm, 0, &ctCell);CHKERRQ(ierr);}
1500412e9a14SMatthew G. Knepley   else               {
1501412e9a14SMatthew G. Knepley     PetscInt dim;
1502a57030b0SMatthew G. Knepley     ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
1503412e9a14SMatthew G. Knepley     switch (dim) {
1504412e9a14SMatthew G. Knepley       case 0: ctCell = DM_POLYTOPE_POINT;break;
1505412e9a14SMatthew G. Knepley       case 1: ctCell = DM_POLYTOPE_SEGMENT;break;
1506412e9a14SMatthew G. Knepley       case 2: ctCell = DM_POLYTOPE_TRIANGLE;break;
1507412e9a14SMatthew G. Knepley       case 3: ctCell = DM_POLYTOPE_TETRAHEDRON;break;
1508412e9a14SMatthew G. Knepley       default: ctCell = DM_POLYTOPE_TETRAHEDRON;
1509412e9a14SMatthew G. Knepley     }
1510412e9a14SMatthew G. Knepley   }
1511412e9a14SMatthew G. Knepley   ierr = DMPlexCreateCellTypeOrder_Internal(ctCell, &cr->ctOrder, &cr->ctOrderInv);CHKERRQ(ierr);
1512412e9a14SMatthew G. Knepley   /* Construct sizes and offsets for each cell type */
1513412e9a14SMatthew G. Knepley   if (!cr->ctStart) {
1514412e9a14SMatthew G. Knepley     PetscInt *ctS, *ctSN, *ctC, *ctCN;
1515412e9a14SMatthew G. Knepley 
1516412e9a14SMatthew G. Knepley     ierr = PetscCalloc2(DM_NUM_POLYTOPES+1, &ctS, DM_NUM_POLYTOPES+1, &ctSN);CHKERRQ(ierr);
1517412e9a14SMatthew G. Knepley     ierr = PetscCalloc2(DM_NUM_POLYTOPES+1, &ctC, DM_NUM_POLYTOPES+1, &ctCN);CHKERRQ(ierr);
1518412e9a14SMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
1519412e9a14SMatthew G. Knepley       DMPolytopeType  ct;
1520412e9a14SMatthew G. Knepley       DMPolytopeType *rct;
1521412e9a14SMatthew G. Knepley       PetscInt       *rsize, *cone, *ornt;
1522412e9a14SMatthew G. Knepley       PetscInt        Nct, n;
1523412e9a14SMatthew G. Knepley 
1524412e9a14SMatthew G. Knepley       ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
1525412e9a14SMatthew G. Knepley       if ((PetscInt) ct < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No cell type for point %D", p);
1526412e9a14SMatthew G. Knepley       ++ctC[ct];
1527412e9a14SMatthew G. Knepley       ierr = DMPlexCellRefinerRefine(cr, ct, &Nct, &rct, &rsize, &cone, &ornt);CHKERRQ(ierr);
1528412e9a14SMatthew G. Knepley       for (n = 0; n < Nct; ++n) ctCN[rct[n]] += rsize[n];
1529412e9a14SMatthew G. Knepley     }
1530412e9a14SMatthew G. Knepley     for (c = 0; c < DM_NUM_POLYTOPES; ++c) {
1531412e9a14SMatthew G. Knepley       const PetscInt ct  = cr->ctOrder[c];
1532412e9a14SMatthew G. Knepley       const PetscInt ctn = cr->ctOrder[c+1];
1533412e9a14SMatthew G. Knepley 
1534412e9a14SMatthew G. Knepley       ctS[ctn]  = ctS[ct]  + ctC[ct];
1535412e9a14SMatthew G. Knepley       ctSN[ctn] = ctSN[ct] + ctCN[ct];
1536412e9a14SMatthew G. Knepley     }
1537412e9a14SMatthew G. Knepley     ierr = PetscFree2(ctC, ctCN);CHKERRQ(ierr);
1538412e9a14SMatthew G. Knepley     cr->ctStart    = ctS;
1539412e9a14SMatthew G. Knepley     cr->ctStartNew = ctSN;
1540412e9a14SMatthew G. Knepley   }
1541412e9a14SMatthew G. Knepley   ierr = CellRefinerCreateOffset_Internal(cr, cr->ctOrder, cr->ctStart, &cr->offset);CHKERRQ(ierr);
1542412e9a14SMatthew G. Knepley   cr->setupcalled = PETSC_TRUE;
1543412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1544412e9a14SMatthew G. Knepley }
1545412e9a14SMatthew G. Knepley 
1546412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerView_Ascii(DMPlexCellRefiner cr, PetscViewer v)
1547412e9a14SMatthew G. Knepley {
1548412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
1549412e9a14SMatthew G. Knepley 
1550412e9a14SMatthew G. Knepley   PetscFunctionBegin;
1551412e9a14SMatthew G. Knepley   ierr = PetscViewerASCIIPrintf(v, "Cell Refiner: %s\n", DMPlexCellRefinerTypes[cr->type]);CHKERRQ(ierr);
1552412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1553412e9a14SMatthew G. Knepley }
1554412e9a14SMatthew G. Knepley 
1555412e9a14SMatthew G. Knepley /*
1556412e9a14SMatthew G. Knepley   DMPlexCellRefinerView - Views a DMPlexCellRefiner object
1557412e9a14SMatthew G. Knepley 
1558412e9a14SMatthew G. Knepley   Collective on cr
1559412e9a14SMatthew G. Knepley 
1560412e9a14SMatthew G. Knepley   Input Parameters:
1561412e9a14SMatthew G. Knepley + cr     - The DMPlexCellRefiner object
1562412e9a14SMatthew G. Knepley - viewer - The PetscViewer object
1563412e9a14SMatthew G. Knepley 
1564412e9a14SMatthew G. Knepley   Level: beginner
1565412e9a14SMatthew G. Knepley 
1566412e9a14SMatthew G. Knepley .seealso: DMPlexCellRefinerCreate()
1567412e9a14SMatthew G. Knepley */
1568412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerView(DMPlexCellRefiner cr, PetscViewer viewer)
1569412e9a14SMatthew G. Knepley {
1570412e9a14SMatthew G. Knepley   PetscBool      iascii;
1571412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
1572412e9a14SMatthew G. Knepley 
1573412e9a14SMatthew G. Knepley   PetscFunctionBegin;
1574412e9a14SMatthew G. Knepley   PetscValidHeader(cr, 1);
1575412e9a14SMatthew G. Knepley   if (viewer) PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1576412e9a14SMatthew G. Knepley   if (!viewer) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject) cr), &viewer);CHKERRQ(ierr);}
1577412e9a14SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
1578412e9a14SMatthew G. Knepley   ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
1579412e9a14SMatthew G. Knepley   if (iascii) {ierr = DMPlexCellRefinerView_Ascii(cr, viewer);CHKERRQ(ierr);}
1580412e9a14SMatthew G. Knepley   ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1581412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1582412e9a14SMatthew G. Knepley }
1583412e9a14SMatthew G. Knepley 
1584412e9a14SMatthew G. Knepley PetscErrorCode DMPlexCellRefinerDestroy(DMPlexCellRefiner *cr)
1585412e9a14SMatthew G. Knepley {
1586412e9a14SMatthew G. Knepley   PetscInt       c;
1587412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
1588412e9a14SMatthew G. Knepley 
1589412e9a14SMatthew G. Knepley   PetscFunctionBegin;
1590412e9a14SMatthew G. Knepley   if (!*cr) PetscFunctionReturn(0);
1591412e9a14SMatthew G. Knepley   PetscValidHeaderSpecific(*cr, DM_CLASSID, 1);
1592412e9a14SMatthew G. Knepley   ierr = PetscObjectDereference((PetscObject) (*cr)->dm);CHKERRQ(ierr);
1593412e9a14SMatthew G. Knepley   ierr = PetscFree2((*cr)->ctOrder, (*cr)->ctOrderInv);CHKERRQ(ierr);
1594412e9a14SMatthew G. Knepley   ierr = PetscFree2((*cr)->ctStart, (*cr)->ctStartNew);CHKERRQ(ierr);
1595412e9a14SMatthew G. Knepley   ierr = PetscFree((*cr)->offset);CHKERRQ(ierr);
1596412e9a14SMatthew G. Knepley   for (c = 0; c < DM_NUM_POLYTOPES; ++c) {
1597412e9a14SMatthew G. Knepley     ierr = PetscFEDestroy(&(*cr)->coordFE[c]);CHKERRQ(ierr);
1598412e9a14SMatthew G. Knepley     ierr = PetscFEGeomDestroy(&(*cr)->refGeom[c]);CHKERRQ(ierr);
1599412e9a14SMatthew G. Knepley   }
1600412e9a14SMatthew G. Knepley   ierr = PetscFree2((*cr)->coordFE, (*cr)->refGeom);CHKERRQ(ierr);
1601412e9a14SMatthew G. Knepley   ierr = PetscHeaderDestroy(cr);CHKERRQ(ierr);
1602412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1603412e9a14SMatthew G. Knepley }
1604412e9a14SMatthew G. Knepley 
1605412e9a14SMatthew G. Knepley PetscErrorCode DMPlexCellRefinerCreate(DM dm, DMPlexCellRefiner *cr)
1606412e9a14SMatthew G. Knepley {
1607412e9a14SMatthew G. Knepley   DMPlexCellRefiner tmp;
1608412e9a14SMatthew G. Knepley   PetscErrorCode    ierr;
1609412e9a14SMatthew G. Knepley 
1610412e9a14SMatthew G. Knepley   PetscFunctionBegin;
1611412e9a14SMatthew G. Knepley   PetscValidPointer(cr, 2);
1612412e9a14SMatthew G. Knepley   *cr  = NULL;
1613412e9a14SMatthew G. Knepley   ierr = PetscHeaderCreate(tmp, DM_CLASSID, "DMPlexCellRefiner", "Cell Refiner", "DMPlexCellRefiner", PETSC_COMM_SELF, DMPlexCellRefinerDestroy, DMPlexCellRefinerView);CHKERRQ(ierr);
1614412e9a14SMatthew G. Knepley   tmp->setupcalled = PETSC_FALSE;
1615412e9a14SMatthew G. Knepley 
1616412e9a14SMatthew G. Knepley   tmp->dm = dm;
1617412e9a14SMatthew G. Knepley   ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr);
1618412e9a14SMatthew G. Knepley   ierr = DMPlexGetCellRefinerType(dm, &tmp->type);CHKERRQ(ierr);
1619412e9a14SMatthew G. Knepley   switch (tmp->type) {
162096ca5757SLisandro Dalcin     case DM_REFINER_REGULAR:
1621412e9a14SMatthew G. Knepley       tmp->ops->refine                  = DMPlexCellRefinerRefine_Regular;
1622412e9a14SMatthew G. Knepley       tmp->ops->mapsubcells             = DMPlexCellRefinerMapSubcells_Regular;
1623412e9a14SMatthew G. Knepley       tmp->ops->getcellvertices         = DMPlexCellRefinerGetCellVertices_Regular;
1624412e9a14SMatthew G. Knepley       tmp->ops->getsubcellvertices      = DMPlexCellRefinerGetSubcellVertices_Regular;
1625412e9a14SMatthew G. Knepley       tmp->ops->getaffinetransforms     = DMPlexCellRefinerGetAffineTransforms_Regular;
1626412e9a14SMatthew G. Knepley       tmp->ops->getaffinefacetransforms = DMPlexCellRefinerGetAffineFaceTransforms_Regular;
1627412e9a14SMatthew G. Knepley       break;
162896ca5757SLisandro Dalcin     case DM_REFINER_TO_BOX:
162996ca5757SLisandro Dalcin       tmp->ops->refine             = DMPlexCellRefinerRefine_ToBox;
163096ca5757SLisandro Dalcin       tmp->ops->mapsubcells        = DMPlexCellRefinerMapSubcells_ToBox;
163196ca5757SLisandro Dalcin       tmp->ops->getcellvertices    = DMPlexCellRefinerGetCellVertices_ToBox;
163296ca5757SLisandro Dalcin       tmp->ops->getsubcellvertices = DMPlexCellRefinerGetSubcellVertices_ToBox;
1633412e9a14SMatthew G. Knepley       break;
163496ca5757SLisandro Dalcin     case DM_REFINER_TO_SIMPLEX:
1635412e9a14SMatthew G. Knepley       tmp->ops->refine      = DMPlexCellRefinerRefine_ToSimplex;
1636412e9a14SMatthew G. Knepley       tmp->ops->mapsubcells = DMPlexCellRefinerMapSubcells_ToSimplex;
1637412e9a14SMatthew G. Knepley       break;
1638412e9a14SMatthew G. Knepley     default: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Invalid cell refiner type %s", DMPlexCellRefinerTypes[tmp->type]);
1639412e9a14SMatthew G. Knepley   }
1640412e9a14SMatthew G. Knepley   ierr = PetscCalloc2(DM_NUM_POLYTOPES, &tmp->coordFE, DM_NUM_POLYTOPES, &tmp->refGeom);CHKERRQ(ierr);
1641412e9a14SMatthew G. Knepley   *cr = tmp;
1642412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1643412e9a14SMatthew G. Knepley }
1644412e9a14SMatthew G. Knepley 
1645412e9a14SMatthew G. Knepley /*@
1646412e9a14SMatthew G. Knepley   DMPlexCellRefinerGetAffineTransforms - Gets the affine map from the reference cell to each subcell
1647412e9a14SMatthew G. Knepley 
1648412e9a14SMatthew G. Knepley   Input Parameters:
1649412e9a14SMatthew G. Knepley + cr - The DMPlexCellRefiner object
1650412e9a14SMatthew G. Knepley - ct - The cell type
1651412e9a14SMatthew G. Knepley 
1652412e9a14SMatthew G. Knepley   Output Parameters:
1653412e9a14SMatthew G. Knepley + Nc   - The number of subcells produced from this cell type
1654412e9a14SMatthew G. Knepley . v0   - The translation of the first vertex for each subcell
1655412e9a14SMatthew G. Knepley . J    - The Jacobian for each subcell (map from reference cell to subcell)
1656412e9a14SMatthew G. Knepley - invJ - The inverse Jacobian for each subcell
1657412e9a14SMatthew G. Knepley 
1658412e9a14SMatthew G. Knepley   Level: developer
1659412e9a14SMatthew G. Knepley 
1660412e9a14SMatthew G. Knepley .seealso: DMPlexCellRefinerGetAffineFaceTransforms(), Create()
1661412e9a14SMatthew G. Knepley @*/
1662412e9a14SMatthew G. Knepley PetscErrorCode DMPlexCellRefinerGetAffineTransforms(DMPlexCellRefiner cr, DMPolytopeType ct, PetscInt *Nc, PetscReal *v0[], PetscReal *J[], PetscReal *invJ[])
1663412e9a14SMatthew G. Knepley {
1664412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
1665412e9a14SMatthew G. Knepley 
1666412e9a14SMatthew G. Knepley   PetscFunctionBegin;
1667412e9a14SMatthew G. Knepley   if (!cr->ops->getaffinetransforms) SETERRQ(PetscObjectComm((PetscObject) cr), PETSC_ERR_SUP, "No support for affine transforms from this refiner");
1668412e9a14SMatthew G. Knepley   ierr = (*cr->ops->getaffinetransforms)(cr, ct, Nc, v0, J, invJ);CHKERRQ(ierr);
1669412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1670412e9a14SMatthew G. Knepley }
1671412e9a14SMatthew G. Knepley 
1672412e9a14SMatthew G. Knepley /*@
1673412e9a14SMatthew G. Knepley   DMPlexCellRefinerGetAffineFaceTransforms - Gets the affine map from the reference face cell to each face in the given cell
1674412e9a14SMatthew G. Knepley 
1675412e9a14SMatthew G. Knepley   Input Parameters:
1676412e9a14SMatthew G. Knepley + cr - The DMPlexCellRefiner object
1677412e9a14SMatthew G. Knepley - ct - The cell type
1678412e9a14SMatthew G. Knepley 
1679412e9a14SMatthew G. Knepley   Output Parameters:
1680412e9a14SMatthew G. Knepley + Nf   - The number of faces for this cell type
1681412e9a14SMatthew G. Knepley . v0   - The translation of the first vertex for each face
1682412e9a14SMatthew G. Knepley . J    - The Jacobian for each face (map from original cell to subcell)
1683412e9a14SMatthew G. Knepley . invJ - The inverse Jacobian for each face
1684412e9a14SMatthew G. Knepley - detJ - The determinant of the Jacobian for each face
1685412e9a14SMatthew G. Knepley 
1686412e9a14SMatthew G. Knepley   Note: The Jacobian and inverse Jacboian will be rectangular, and the inverse is really a generalized inverse.
1687412e9a14SMatthew G. Knepley 
1688412e9a14SMatthew G. Knepley   Level: developer
1689412e9a14SMatthew G. Knepley 
1690412e9a14SMatthew G. Knepley .seealso: DMPlexCellRefinerGetAffineTransforms(), Create()
1691412e9a14SMatthew G. Knepley @*/
1692412e9a14SMatthew G. Knepley PetscErrorCode DMPlexCellRefinerGetAffineFaceTransforms(DMPlexCellRefiner cr, DMPolytopeType ct, PetscInt *Nf, PetscReal *v0[], PetscReal *J[], PetscReal *invJ[], PetscReal *detJ[])
1693412e9a14SMatthew G. Knepley {
1694412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
1695412e9a14SMatthew G. Knepley 
1696412e9a14SMatthew G. Knepley   PetscFunctionBegin;
1697412e9a14SMatthew G. Knepley   if (!cr->ops->getaffinefacetransforms) SETERRQ(PetscObjectComm((PetscObject) cr), PETSC_ERR_SUP, "No support for affine face transforms from this refiner");
1698412e9a14SMatthew G. Knepley   ierr = (*cr->ops->getaffinefacetransforms)(cr, ct, Nf, v0, J, invJ, detJ);CHKERRQ(ierr);
1699412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1700412e9a14SMatthew G. Knepley }
1701412e9a14SMatthew G. Knepley 
1702412e9a14SMatthew G. Knepley /* Numbering regularly refined meshes
1703412e9a14SMatthew G. Knepley 
1704412e9a14SMatthew G. Knepley    We want the numbering of the new mesh to respect the same depth stratification as the old mesh. We first compute
1705412e9a14SMatthew G. Knepley    the number of new points at each depth. This means that offsets for each depth can be computed, making no assumptions
1706412e9a14SMatthew G. Knepley    about the order of different cell types.
1707412e9a14SMatthew G. Knepley 
1708412e9a14SMatthew G. Knepley    However, when we want to order different depth strata, it will be very useful to make assumptions about contiguous
1709412e9a14SMatthew G. Knepley    numbering of different cell types, especially if we want to compute new numberings without communication. Therefore, we
1710412e9a14SMatthew G. Knepley    will require that cells are numbering contiguously for each cell type, and that those blocks come in the same order as
1711412e9a14SMatthew G. Knepley    the cell type enumeration within a given depth stratum.
1712412e9a14SMatthew G. Knepley 
1713412e9a14SMatthew 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
1714412e9a14SMatthew G. Knepley    start at the new depth offset, run through all prior cell types incrementing by the total addition from that type, then
1715412e9a14SMatthew G. Knepley    offset by the old cell type number and replica number for the insertion.
1716412e9a14SMatthew G. Knepley */
1717412e9a14SMatthew G. Knepley PetscErrorCode DMPlexCellRefinerGetNewPoint(DMPlexCellRefiner cr, DMPolytopeType ct, DMPolytopeType ctNew, PetscInt p, PetscInt r, PetscInt *pNew)
1718412e9a14SMatthew G. Knepley {
1719412e9a14SMatthew G. Knepley   DMPolytopeType  *rct;
1720412e9a14SMatthew G. Knepley   PetscInt        *rsize, *cone, *ornt;
1721412e9a14SMatthew G. Knepley   PetscInt         Nct, n;
1722412e9a14SMatthew G. Knepley   PetscInt         off  = cr->offset[ct*DM_NUM_POLYTOPES+ctNew];
1723412e9a14SMatthew G. Knepley   PetscInt         ctS  = cr->ctStart[ct],       ctE  = cr->ctStart[cr->ctOrder[cr->ctOrderInv[ct]+1]];
1724412e9a14SMatthew G. Knepley   PetscInt         ctSN = cr->ctStartNew[ctNew], ctEN = cr->ctStartNew[cr->ctOrder[cr->ctOrderInv[ctNew]+1]];
1725412e9a14SMatthew G. Knepley   PetscInt         newp = ctSN;
1726412e9a14SMatthew G. Knepley   PetscErrorCode   ierr;
1727412e9a14SMatthew G. Knepley 
1728412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
1729412e9a14SMatthew 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);
1730412e9a14SMatthew G. Knepley   if (off < 0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell type %s does not produce type %s", DMPolytopeTypes[ct], DMPolytopeTypes[ctNew]);
1731412e9a14SMatthew G. Knepley 
1732412e9a14SMatthew G. Knepley   newp += off;
1733412e9a14SMatthew G. Knepley   ierr = DMPlexCellRefinerRefine(cr, ct, &Nct, &rct, &rsize, &cone, &ornt);CHKERRQ(ierr);
1734412e9a14SMatthew G. Knepley   for (n = 0; n < Nct; ++n) {
1735412e9a14SMatthew G. Knepley     if (rct[n] == ctNew) {
1736412e9a14SMatthew G. Knepley       if (rsize[n] && r >= rsize[n])
1737412e9a14SMatthew 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]);
1738412e9a14SMatthew G. Knepley       newp += (p - ctS) * rsize[n] + r;
1739412e9a14SMatthew G. Knepley       break;
1740412e9a14SMatthew G. Knepley     }
1741412e9a14SMatthew G. Knepley   }
1742412e9a14SMatthew G. Knepley 
1743412e9a14SMatthew 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);
1744412e9a14SMatthew G. Knepley   *pNew = newp;
1745412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1746412e9a14SMatthew G. Knepley }
1747412e9a14SMatthew G. Knepley 
1748412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerSetConeSizes(DMPlexCellRefiner cr, DM rdm)
1749412e9a14SMatthew G. Knepley {
1750412e9a14SMatthew G. Knepley   DM              dm = cr->dm;
1751412e9a14SMatthew G. Knepley   PetscInt        pStart, pEnd, p, pNew;
1752412e9a14SMatthew G. Knepley   PetscErrorCode  ierr;
1753412e9a14SMatthew G. Knepley 
1754412e9a14SMatthew G. Knepley   PetscFunctionBegin;
1755412e9a14SMatthew G. Knepley   /* Must create the celltype label here so that we do not automatically try to compute the types */
1756412e9a14SMatthew G. Knepley   ierr = DMCreateLabel(rdm, "celltype");CHKERRQ(ierr);
1757412e9a14SMatthew G. Knepley   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
1758412e9a14SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
1759412e9a14SMatthew G. Knepley     DMPolytopeType  ct;
1760412e9a14SMatthew G. Knepley     DMPolytopeType *rct;
1761412e9a14SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt;
1762412e9a14SMatthew G. Knepley     PetscInt        Nct, n, r;
1763412e9a14SMatthew G. Knepley 
1764412e9a14SMatthew G. Knepley     ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
1765412e9a14SMatthew G. Knepley     ierr = DMPlexCellRefinerRefine(cr, ct, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
1766412e9a14SMatthew G. Knepley     for (n = 0; n < Nct; ++n) {
1767412e9a14SMatthew G. Knepley       for (r = 0; r < rsize[n]; ++r) {
1768412e9a14SMatthew G. Knepley         ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], p, r, &pNew);CHKERRQ(ierr);
1769412e9a14SMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, pNew, DMPolytopeTypeGetConeSize(rct[n]));CHKERRQ(ierr);
1770412e9a14SMatthew G. Knepley         ierr = DMPlexSetCellType(rdm, pNew, rct[n]);CHKERRQ(ierr);
1771412e9a14SMatthew G. Knepley       }
1772412e9a14SMatthew G. Knepley     }
1773412e9a14SMatthew G. Knepley   }
1774412e9a14SMatthew G. Knepley   {
1775412e9a14SMatthew G. Knepley     DMLabel  ctLabel;
1776412e9a14SMatthew G. Knepley     DM_Plex *plex = (DM_Plex *) rdm->data;
1777412e9a14SMatthew G. Knepley 
1778412e9a14SMatthew G. Knepley     ierr = DMPlexGetCellTypeLabel(rdm, &ctLabel);CHKERRQ(ierr);
1779412e9a14SMatthew G. Knepley     ierr = PetscObjectStateGet((PetscObject) ctLabel, &plex->celltypeState);CHKERRQ(ierr);
1780412e9a14SMatthew G. Knepley   }
1781412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1782412e9a14SMatthew G. Knepley }
1783412e9a14SMatthew G. Knepley 
1784412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerSetCones(DMPlexCellRefiner cr, DM rdm)
1785412e9a14SMatthew G. Knepley {
1786412e9a14SMatthew G. Knepley   DM             dm = cr->dm;
1787412e9a14SMatthew G. Knepley   DMPolytopeType ct;
1788412e9a14SMatthew G. Knepley   PetscInt      *coneNew, *orntNew;
1789412e9a14SMatthew G. Knepley   PetscInt       maxConeSize = 0, pStart, pEnd, p, pNew;
1790412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
1791412e9a14SMatthew G. Knepley 
1792412e9a14SMatthew G. Knepley   PetscFunctionBegin;
1793412e9a14SMatthew G. Knepley   for (p = 0; p < DM_NUM_POLYTOPES; ++p) maxConeSize = PetscMax(maxConeSize, DMPolytopeTypeGetConeSize((DMPolytopeType) p));
1794412e9a14SMatthew G. Knepley   ierr = PetscMalloc2(maxConeSize, &coneNew, maxConeSize, &orntNew);CHKERRQ(ierr);
1795412e9a14SMatthew G. Knepley   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
1796412e9a14SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
1797412e9a14SMatthew G. Knepley     const PetscInt *cone, *ornt;
1798412e9a14SMatthew G. Knepley     PetscInt        coff, ooff, c;
1799412e9a14SMatthew G. Knepley     DMPolytopeType *rct;
1800412e9a14SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt;
1801412e9a14SMatthew G. Knepley     PetscInt        Nct, n, r;
1802412e9a14SMatthew G. Knepley 
1803412e9a14SMatthew G. Knepley     ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
1804412e9a14SMatthew G. Knepley     ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr);
1805412e9a14SMatthew G. Knepley     ierr = DMPlexGetConeOrientation(dm, p, &ornt);CHKERRQ(ierr);
1806412e9a14SMatthew G. Knepley     ierr = DMPlexCellRefinerRefine(cr, ct, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
1807412e9a14SMatthew G. Knepley     for (n = 0, coff = 0, ooff = 0; n < Nct; ++n) {
1808412e9a14SMatthew G. Knepley       const DMPolytopeType ctNew    = rct[n];
1809412e9a14SMatthew G. Knepley       const PetscInt       csizeNew = DMPolytopeTypeGetConeSize(ctNew);
1810412e9a14SMatthew G. Knepley 
1811412e9a14SMatthew G. Knepley       for (r = 0; r < rsize[n]; ++r) {
1812412e9a14SMatthew G. Knepley         /* pNew is a subcell produced by subdividing p */
1813412e9a14SMatthew G. Knepley         ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], p, r, &pNew);CHKERRQ(ierr);
1814412e9a14SMatthew G. Knepley         for (c = 0; c < csizeNew; ++c) {
1815412e9a14SMatthew G. Knepley           PetscInt             ppp   = -1;                             /* Parent Parent point: Parent of point pp */
1816412e9a14SMatthew G. Knepley           PetscInt             pp    = p;                              /* Parent point: Point in the original mesh producing new cone point */
1817412e9a14SMatthew G. Knepley           PetscInt             po    = 0;                              /* Orientation of parent point pp in parent parent point ppp */
1818412e9a14SMatthew G. Knepley           DMPolytopeType       pct   = ct;                             /* Parent type:  Cell type for parent of new cone point */
1819412e9a14SMatthew G. Knepley           const PetscInt      *pcone = cone;                           /* Parent cone: Cone of parent point pp */
1820412e9a14SMatthew G. Knepley           PetscInt             pr    = -1;                             /* Replica number of pp that produces new cone point  */
1821412e9a14SMatthew G. Knepley           const DMPolytopeType ft    = (DMPolytopeType) rcone[coff++]; /* Cell type for new cone point of pNew */
1822412e9a14SMatthew G. Knepley           const PetscInt       fn    = rcone[coff++];                  /* Number of cones of p that need to be taken when producing new cone point */
1823412e9a14SMatthew G. Knepley           PetscInt             fo    = rornt[ooff++];                  /* Orientation of new cone point in pNew */
1824412e9a14SMatthew G. Knepley           PetscInt             lc;
1825412e9a14SMatthew G. Knepley 
1826412e9a14SMatthew G. Knepley           /* Get the type (pct) and point number (pp) of the parent point in the original mesh which produces this cone point */
1827412e9a14SMatthew G. Knepley           for (lc = 0; lc < fn; ++lc) {
1828412e9a14SMatthew G. Knepley             const PetscInt *ppornt;
1829412e9a14SMatthew G. Knepley             PetscInt        pcp;
1830412e9a14SMatthew G. Knepley 
1831412e9a14SMatthew G. Knepley             ierr = DMPolytopeMapCell(pct, po, rcone[coff++], &pcp);CHKERRQ(ierr);
1832412e9a14SMatthew G. Knepley             ppp  = pp;
1833412e9a14SMatthew G. Knepley             pp   = pcone[pcp];
1834412e9a14SMatthew G. Knepley             ierr = DMPlexGetCellType(dm, pp, &pct);CHKERRQ(ierr);
1835412e9a14SMatthew G. Knepley             ierr = DMPlexGetCone(dm, pp, &pcone);CHKERRQ(ierr);
1836412e9a14SMatthew G. Knepley             ierr = DMPlexGetConeOrientation(dm, ppp, &ppornt);CHKERRQ(ierr);
1837412e9a14SMatthew G. Knepley             po   = ppornt[pcp];
1838412e9a14SMatthew G. Knepley           }
1839412e9a14SMatthew G. Knepley           pr = rcone[coff++];
1840412e9a14SMatthew G. Knepley           /* Orientation po of pp maps (pr, fo) -> (pr', fo') */
1841412e9a14SMatthew G. Knepley           ierr = DMPlexCellRefinerMapSubcells(cr, pct, po, ft, pr, fo, &pr, &fo);CHKERRQ(ierr);
1842412e9a14SMatthew G. Knepley           ierr = DMPlexCellRefinerGetNewPoint(cr, pct, ft, pp, pr, &coneNew[c]);CHKERRQ(ierr);
1843412e9a14SMatthew G. Knepley           orntNew[c] = fo;
1844412e9a14SMatthew G. Knepley         }
1845412e9a14SMatthew G. Knepley         ierr = DMPlexSetCone(rdm, pNew, coneNew);CHKERRQ(ierr);
1846412e9a14SMatthew G. Knepley         ierr = DMPlexSetConeOrientation(rdm, pNew, orntNew);CHKERRQ(ierr);
1847412e9a14SMatthew G. Knepley       }
1848412e9a14SMatthew G. Knepley     }
1849412e9a14SMatthew G. Knepley   }
1850412e9a14SMatthew G. Knepley   ierr = PetscFree2(coneNew, orntNew);CHKERRQ(ierr);
1851412e9a14SMatthew G. Knepley   ierr = DMPlexSymmetrize(rdm);CHKERRQ(ierr);
1852412e9a14SMatthew G. Knepley   ierr = DMPlexStratify(rdm);CHKERRQ(ierr);
1853412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1854412e9a14SMatthew G. Knepley }
1855412e9a14SMatthew G. Knepley 
1856412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerGetCoordinateFE(DMPlexCellRefiner cr, DMPolytopeType ct, PetscFE *fe)
1857412e9a14SMatthew G. Knepley {
1858412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
1859412e9a14SMatthew G. Knepley 
1860412e9a14SMatthew G. Knepley   PetscFunctionBegin;
1861412e9a14SMatthew G. Knepley   if (!cr->coordFE[ct]) {
1862412e9a14SMatthew G. Knepley     PetscInt  dim, cdim;
1863412e9a14SMatthew G. Knepley     PetscBool isSimplex;
1864412e9a14SMatthew G. Knepley 
1865412e9a14SMatthew G. Knepley     switch (ct) {
1866412e9a14SMatthew G. Knepley       case DM_POLYTOPE_SEGMENT:       dim = 1; isSimplex = PETSC_TRUE;  break;
1867412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRIANGLE:      dim = 2; isSimplex = PETSC_TRUE;  break;
1868412e9a14SMatthew G. Knepley       case DM_POLYTOPE_QUADRILATERAL: dim = 2; isSimplex = PETSC_FALSE; break;
1869412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TETRAHEDRON:   dim = 3; isSimplex = PETSC_TRUE;  break;
1870412e9a14SMatthew G. Knepley       case DM_POLYTOPE_HEXAHEDRON:    dim = 3; isSimplex = PETSC_FALSE; break;
1871412e9a14SMatthew G. Knepley       default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "No coordinate FE for cell type %s", DMPolytopeTypes[ct]);
1872412e9a14SMatthew G. Knepley     }
1873412e9a14SMatthew G. Knepley     ierr = DMGetCoordinateDim(cr->dm, &cdim);CHKERRQ(ierr);
1874412e9a14SMatthew G. Knepley     ierr = PetscFECreateLagrange(PETSC_COMM_SELF, dim, cdim, isSimplex, 1, PETSC_DETERMINE, &cr->coordFE[ct]);CHKERRQ(ierr);
1875412e9a14SMatthew G. Knepley     {
1876412e9a14SMatthew G. Knepley       PetscDualSpace  dsp;
1877412e9a14SMatthew G. Knepley       PetscQuadrature quad;
1878412e9a14SMatthew G. Knepley       DM              K;
1879412e9a14SMatthew G. Knepley       PetscFEGeom    *cg;
1880412e9a14SMatthew G. Knepley       PetscReal      *Xq, *xq, *wq;
1881412e9a14SMatthew G. Knepley       PetscInt        Nq, q;
1882412e9a14SMatthew G. Knepley 
1883412e9a14SMatthew G. Knepley       ierr = DMPlexCellRefinerGetCellVertices(cr, ct, &Nq, &Xq);CHKERRQ(ierr);
1884412e9a14SMatthew G. Knepley       ierr = PetscMalloc1(Nq*cdim, &xq);CHKERRQ(ierr);
1885412e9a14SMatthew G. Knepley       for (q = 0; q < Nq*cdim; ++q) xq[q] = Xq[q];
1886412e9a14SMatthew G. Knepley       ierr = PetscMalloc1(Nq, &wq);CHKERRQ(ierr);
1887412e9a14SMatthew G. Knepley       for (q = 0; q < Nq; ++q) wq[q] = 1.0;
1888412e9a14SMatthew G. Knepley       ierr = PetscQuadratureCreate(PETSC_COMM_SELF, &quad);CHKERRQ(ierr);
1889412e9a14SMatthew G. Knepley       ierr = PetscQuadratureSetData(quad, dim, 1, Nq, xq, wq);CHKERRQ(ierr);
1890412e9a14SMatthew G. Knepley       ierr = PetscFESetQuadrature(cr->coordFE[ct], quad);CHKERRQ(ierr);
1891412e9a14SMatthew G. Knepley 
1892412e9a14SMatthew G. Knepley       ierr = PetscFEGetDualSpace(cr->coordFE[ct], &dsp);CHKERRQ(ierr);
1893412e9a14SMatthew G. Knepley       ierr = PetscDualSpaceGetDM(dsp, &K);CHKERRQ(ierr);
1894412e9a14SMatthew G. Knepley       ierr = PetscFEGeomCreate(quad, 1, cdim, PETSC_FALSE, &cr->refGeom[ct]);CHKERRQ(ierr);
1895412e9a14SMatthew G. Knepley       cg   = cr->refGeom[ct];
1896412e9a14SMatthew G. Knepley       ierr = DMPlexComputeCellGeometryFEM(K, 0, NULL, cg->v, cg->J, cg->invJ, cg->detJ);CHKERRQ(ierr);
1897412e9a14SMatthew G. Knepley       ierr = PetscQuadratureDestroy(&quad);CHKERRQ(ierr);
1898412e9a14SMatthew G. Knepley     }
1899412e9a14SMatthew G. Knepley   }
1900412e9a14SMatthew G. Knepley   *fe = cr->coordFE[ct];
1901412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1902412e9a14SMatthew G. Knepley }
1903412e9a14SMatthew G. Knepley 
1904412e9a14SMatthew G. Knepley /*
1905412e9a14SMatthew G. Knepley   DMPlexCellRefinerMapLocalizedCoordinates - Given a cell of type ct with localized coordinates x, we generate localized coordinates xr for subcell r of type rct.
1906412e9a14SMatthew G. Knepley 
1907412e9a14SMatthew G. Knepley   Not collective
1908412e9a14SMatthew G. Knepley 
1909412e9a14SMatthew G. Knepley   Input Parameters:
1910412e9a14SMatthew G. Knepley + cr  - The DMPlexCellRefiner
1911412e9a14SMatthew G. Knepley . ct  - The type of the parent cell
1912412e9a14SMatthew G. Knepley . rct - The type of the produced cell
1913412e9a14SMatthew G. Knepley . r   - The index of the produced cell
1914412e9a14SMatthew G. Knepley - x   - The localized coordinates for the parent cell
1915412e9a14SMatthew G. Knepley 
1916412e9a14SMatthew G. Knepley   Output Parameter:
1917412e9a14SMatthew G. Knepley . xr  - The localized coordinates for the produced cell
1918412e9a14SMatthew G. Knepley 
1919412e9a14SMatthew G. Knepley   Level: developer
1920412e9a14SMatthew G. Knepley 
1921412e9a14SMatthew G. Knepley .seealso: DMPlexCellRefinerSetCoordinates()
1922412e9a14SMatthew G. Knepley */
1923412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerMapLocalizedCoordinates(DMPlexCellRefiner cr, DMPolytopeType ct, DMPolytopeType rct, PetscInt r, const PetscScalar x[], PetscScalar xr[])
1924412e9a14SMatthew G. Knepley {
1925412e9a14SMatthew G. Knepley   PetscFE        fe = NULL;
1926412e9a14SMatthew G. Knepley   PetscInt       cdim, Nv, v, *subcellV;
1927412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
1928412e9a14SMatthew G. Knepley 
1929412e9a14SMatthew G. Knepley   PetscFunctionBegin;
1930412e9a14SMatthew G. Knepley   ierr = DMPlexCellRefinerGetCoordinateFE(cr, ct, &fe);CHKERRQ(ierr);
1931412e9a14SMatthew G. Knepley   ierr = DMPlexCellRefinerGetSubcellVertices(cr, ct, rct, r, &Nv, &subcellV);CHKERRQ(ierr);
1932412e9a14SMatthew G. Knepley   ierr = PetscFEGetNumComponents(fe, &cdim);CHKERRQ(ierr);
1933412e9a14SMatthew G. Knepley   for (v = 0; v < Nv; ++v) {
1934412e9a14SMatthew G. Knepley     ierr = PetscFEInterpolate_Static(fe, x, cr->refGeom[ct], subcellV[v], &xr[v*cdim]);CHKERRQ(ierr);
1935412e9a14SMatthew G. Knepley   }
1936412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
1937412e9a14SMatthew G. Knepley }
1938412e9a14SMatthew G. Knepley 
1939412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerSetCoordinates(DMPlexCellRefiner cr, DM rdm)
1940412e9a14SMatthew G. Knepley {
1941412e9a14SMatthew G. Knepley   DM                    dm = cr->dm, cdm;
1942412e9a14SMatthew G. Knepley   PetscSection          coordSection, coordSectionNew;
1943412e9a14SMatthew G. Knepley   Vec                   coordsLocal, coordsLocalNew;
1944412e9a14SMatthew G. Knepley   const PetscScalar    *coords;
1945412e9a14SMatthew G. Knepley   PetscScalar          *coordsNew;
1946412e9a14SMatthew G. Knepley   const DMBoundaryType *bd;
1947412e9a14SMatthew G. Knepley   const PetscReal      *maxCell, *L;
1948412e9a14SMatthew G. Knepley   PetscBool             isperiodic, localizeVertices = PETSC_FALSE, localizeCells = PETSC_FALSE;
1949412e9a14SMatthew G. Knepley   PetscInt              dE, d, cStart, cEnd, c, vStartNew, vEndNew, v, pStart, pEnd, p, ocStart, ocEnd;
1950412e9a14SMatthew G. Knepley   PetscErrorCode        ierr;
1951412e9a14SMatthew G. Knepley 
1952412e9a14SMatthew G. Knepley   PetscFunctionBegin;
1953412e9a14SMatthew G. Knepley   ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
195490b157c4SStefano Zampini   ierr = DMGetPeriodicity(dm, &isperiodic, &maxCell, &L, &bd);CHKERRQ(ierr);
195590b157c4SStefano Zampini   /* Determine if we need to localize coordinates when generating them */
1956b9ccc978SStefano Zampini   if (isperiodic) {
1957412e9a14SMatthew G. Knepley     localizeVertices = PETSC_TRUE;
1958412e9a14SMatthew G. Knepley     if (!maxCell) {
1959412e9a14SMatthew G. Knepley       PetscBool localized;
1960412e9a14SMatthew G. Knepley       ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr);
1961412e9a14SMatthew G. Knepley       if (!localized) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_USER, "Cannot refine a periodic mesh if coordinates have not been localized");
1962412e9a14SMatthew G. Knepley       localizeCells = PETSC_TRUE;
1963b9ccc978SStefano Zampini     }
1964b9ccc978SStefano Zampini   }
1965b9ccc978SStefano Zampini 
1966b9ccc978SStefano Zampini   ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr);
1967412e9a14SMatthew G. Knepley   ierr = PetscSectionGetFieldComponents(coordSection, 0, &dE);CHKERRQ(ierr);
1968412e9a14SMatthew G. Knepley   if (maxCell) {
1969412e9a14SMatthew G. Knepley     PetscReal maxCellNew[3];
1970412e9a14SMatthew G. Knepley 
1971412e9a14SMatthew G. Knepley     for (d = 0; d < dE; ++d) maxCellNew[d] = maxCell[d]/2.0;
1972412e9a14SMatthew G. Knepley     ierr = DMSetPeriodicity(rdm, isperiodic, maxCellNew, L, bd);CHKERRQ(ierr);
1973412e9a14SMatthew G. Knepley   } else {
1974412e9a14SMatthew G. Knepley     ierr = DMSetPeriodicity(rdm, isperiodic, maxCell, L, bd);CHKERRQ(ierr);
1975412e9a14SMatthew G. Knepley   }
1976b9ccc978SStefano Zampini   ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &coordSectionNew);CHKERRQ(ierr);
1977b9ccc978SStefano Zampini   ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr);
1978412e9a14SMatthew G. Knepley   ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dE);CHKERRQ(ierr);
1979412e9a14SMatthew G. Knepley   ierr = DMPlexGetDepthStratum(rdm, 0, &vStartNew, &vEndNew);CHKERRQ(ierr);
1980412e9a14SMatthew G. Knepley   if (localizeCells) {ierr = PetscSectionSetChart(coordSectionNew, 0,         vEndNew);CHKERRQ(ierr);}
1981412e9a14SMatthew G. Knepley   else               {ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vEndNew);CHKERRQ(ierr);}
1982b9ccc978SStefano Zampini 
1983412e9a14SMatthew G. Knepley   /* Localization should be inherited */
1984412e9a14SMatthew G. Knepley   /*   Stefano calculates parent cells for each new cell for localization */
1985412e9a14SMatthew G. Knepley   /*   Localized cells need coordinates of closure */
1986412e9a14SMatthew G. Knepley   for (v = vStartNew; v < vEndNew; ++v) {
1987412e9a14SMatthew G. Knepley     ierr = PetscSectionSetDof(coordSectionNew, v, dE);CHKERRQ(ierr);
1988412e9a14SMatthew G. Knepley     ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dE);CHKERRQ(ierr);
1989412e9a14SMatthew G. Knepley   }
1990412e9a14SMatthew G. Knepley   if (localizeCells) {
1991412e9a14SMatthew G. Knepley     ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
1992412e9a14SMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
1993412e9a14SMatthew G. Knepley       PetscInt dof;
199490b157c4SStefano Zampini 
1995412e9a14SMatthew G. Knepley       ierr = PetscSectionGetDof(coordSection, c, &dof); CHKERRQ(ierr);
1996412e9a14SMatthew G. Knepley       if (dof) {
1997412e9a14SMatthew G. Knepley         DMPolytopeType  ct;
1998412e9a14SMatthew G. Knepley         DMPolytopeType *rct;
1999412e9a14SMatthew G. Knepley         PetscInt       *rsize, *rcone, *rornt;
2000412e9a14SMatthew G. Knepley         PetscInt        dim, cNew, Nct, n, r;
200190b157c4SStefano Zampini 
2002412e9a14SMatthew G. Knepley         ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr);
2003412e9a14SMatthew G. Knepley         dim  = DMPolytopeTypeGetDim(ct);
2004412e9a14SMatthew G. Knepley         ierr = DMPlexCellRefinerRefine(cr, ct, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
2005412e9a14SMatthew G. Knepley         /* This allows for different cell types */
2006412e9a14SMatthew G. Knepley         for (n = 0; n < Nct; ++n) {
2007412e9a14SMatthew G. Knepley           if (dim != DMPolytopeTypeGetDim(rct[n])) continue;
2008412e9a14SMatthew G. Knepley           for (r = 0; r < rsize[n]; ++r) {
2009412e9a14SMatthew G. Knepley             PetscInt *closure = NULL;
2010412e9a14SMatthew G. Knepley             PetscInt  clSize, cl, Nv = 0;
201190b157c4SStefano Zampini 
2012412e9a14SMatthew G. Knepley             ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], c, r, &cNew);CHKERRQ(ierr);
2013412e9a14SMatthew G. Knepley             ierr = DMPlexGetTransitiveClosure(rdm, cNew, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr);
2014412e9a14SMatthew G. Knepley             for (cl = 0; cl < clSize*2; cl += 2) {if ((closure[cl] >= vStartNew) && (closure[cl] < vEndNew)) ++Nv;}
2015412e9a14SMatthew G. Knepley             ierr = DMPlexRestoreTransitiveClosure(rdm, cNew, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr);
2016412e9a14SMatthew G. Knepley             ierr = PetscSectionSetDof(coordSectionNew, cNew, Nv * dE);CHKERRQ(ierr);
2017412e9a14SMatthew G. Knepley             ierr = PetscSectionSetFieldDof(coordSectionNew, cNew, 0, Nv * dE);CHKERRQ(ierr);
20189fc2a3f3SStefano Zampini           }
201990b157c4SStefano Zampini         }
202090b157c4SStefano Zampini       }
2021412e9a14SMatthew G. Knepley     }
202275d3a19aSMatthew G. Knepley   }
202375d3a19aSMatthew G. Knepley   ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr);
2024412e9a14SMatthew G. Knepley   ierr = DMViewFromOptions(dm, NULL, "-coarse_dm_view");CHKERRQ(ierr);
202546e270d4SMatthew G. Knepley   ierr = DMSetCoordinateSection(rdm, PETSC_DETERMINE, coordSectionNew);CHKERRQ(ierr);
2026412e9a14SMatthew G. Knepley   {
2027412e9a14SMatthew G. Knepley     VecType     vtype;
2028412e9a14SMatthew G. Knepley     PetscInt    coordSizeNew, bs;
2029412e9a14SMatthew G. Knepley     const char *name;
2030412e9a14SMatthew G. Knepley 
2031412e9a14SMatthew G. Knepley     ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr);
2032412e9a14SMatthew G. Knepley     ierr = VecCreate(PETSC_COMM_SELF, &coordsLocalNew);CHKERRQ(ierr);
203375d3a19aSMatthew G. Knepley     ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr);
2034412e9a14SMatthew G. Knepley     ierr = VecSetSizes(coordsLocalNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr);
2035412e9a14SMatthew G. Knepley     ierr = PetscObjectGetName((PetscObject) coordsLocal, &name);CHKERRQ(ierr);
2036412e9a14SMatthew G. Knepley     ierr = PetscObjectSetName((PetscObject) coordsLocalNew, name);CHKERRQ(ierr);
2037412e9a14SMatthew G. Knepley     ierr = VecGetBlockSize(coordsLocal, &bs);CHKERRQ(ierr);
2038412e9a14SMatthew G. Knepley     ierr = VecSetBlockSize(coordsLocalNew, bs);CHKERRQ(ierr);
2039412e9a14SMatthew G. Knepley     ierr = VecGetType(coordsLocal, &vtype);CHKERRQ(ierr);
2040412e9a14SMatthew G. Knepley     ierr = VecSetType(coordsLocalNew, vtype);CHKERRQ(ierr);
2041b5da9499SMatthew G. Knepley   }
2042412e9a14SMatthew G. Knepley   ierr = VecGetArrayRead(coordsLocal, &coords);CHKERRQ(ierr);
2043412e9a14SMatthew G. Knepley   ierr = VecGetArray(coordsLocalNew, &coordsNew);CHKERRQ(ierr);
2044412e9a14SMatthew G. Knepley   ierr = PetscSectionGetChart(coordSection, &ocStart, &ocEnd);CHKERRQ(ierr);
2045412e9a14SMatthew G. Knepley   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
2046412e9a14SMatthew G. Knepley   /* First set coordinates for vertices*/
2047412e9a14SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
2048412e9a14SMatthew G. Knepley     DMPolytopeType  ct;
2049412e9a14SMatthew G. Knepley     DMPolytopeType *rct;
2050412e9a14SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt;
2051412e9a14SMatthew G. Knepley     PetscInt        Nct, n, r;
2052412e9a14SMatthew G. Knepley     PetscBool       hasVertex = PETSC_FALSE, isLocalized = PETSC_FALSE;
205390b157c4SStefano Zampini 
2054412e9a14SMatthew G. Knepley     ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
2055412e9a14SMatthew G. Knepley     ierr = DMPlexCellRefinerRefine(cr, ct, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
2056412e9a14SMatthew G. Knepley     for (n = 0; n < Nct; ++n) {
2057412e9a14SMatthew G. Knepley       if (rct[n] == DM_POLYTOPE_POINT) {hasVertex = PETSC_TRUE; break;}
2058412e9a14SMatthew G. Knepley     }
2059412e9a14SMatthew G. Knepley     if (localizeVertices && ct != DM_POLYTOPE_POINT && (p >= ocStart) && (p < ocEnd)) {
2060412e9a14SMatthew G. Knepley       PetscInt dof;
2061412e9a14SMatthew G. Knepley       ierr = PetscSectionGetDof(coordSection, p, &dof); CHKERRQ(ierr);
2062412e9a14SMatthew G. Knepley       if (dof) isLocalized = PETSC_TRUE;
2063412e9a14SMatthew G. Knepley     }
2064412e9a14SMatthew G. Knepley     if (hasVertex) {
2065412e9a14SMatthew G. Knepley       PetscScalar *pcoords = NULL;
2066412e9a14SMatthew G. Knepley       PetscScalar  vcoords[3] = {0., 0., 0.};
2067412e9a14SMatthew G. Knepley       PetscInt     Nc, Nv, v, d;
206890b157c4SStefano Zampini 
2069412e9a14SMatthew G. Knepley       ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, p, &Nc, &pcoords);CHKERRQ(ierr);
2070412e9a14SMatthew G. Knepley       if (ct == DM_POLYTOPE_POINT) {
2071412e9a14SMatthew G. Knepley         for (d = 0; d < dE; ++d) vcoords[d] = pcoords[d];
20729fc2a3f3SStefano Zampini       } else {
2073412e9a14SMatthew G. Knepley         if (localizeVertices) {
2074412e9a14SMatthew G. Knepley           PetscScalar anchor[3];
207590b157c4SStefano Zampini 
2076412e9a14SMatthew G. Knepley           for (d = 0; d < dE; ++d) anchor[d] = pcoords[d];
2077412e9a14SMatthew G. Knepley           if (!isLocalized) {
2078412e9a14SMatthew G. Knepley             Nv = Nc/dE;
2079412e9a14SMatthew G. Knepley             for (v = 0; v < Nv; ++v) {ierr = DMLocalizeAddCoordinate_Internal(dm, dE, anchor, &pcoords[v*dE], vcoords);CHKERRQ(ierr);}
2080412e9a14SMatthew G. Knepley           } else {
2081412e9a14SMatthew G. Knepley             Nv = Nc/(2*dE);
2082412e9a14SMatthew G. Knepley             for (v = Nv; v < Nv*2; ++v) {ierr = DMLocalizeAddCoordinate_Internal(dm, dE, anchor, &pcoords[v*dE], vcoords);CHKERRQ(ierr);}
208390b157c4SStefano Zampini           }
208490b157c4SStefano Zampini         } else {
2085412e9a14SMatthew G. Knepley           Nv = Nc/dE;
2086412e9a14SMatthew G. Knepley           for (v = 0; v < Nv; ++v) for (d = 0; d < dE; ++d) vcoords[d] += pcoords[v*dE+d];
2087b5da9499SMatthew G. Knepley         }
2088412e9a14SMatthew G. Knepley         for (d = 0; d < dE; ++d) vcoords[d] /= Nv;
208990b157c4SStefano Zampini       }
2090412e9a14SMatthew G. Knepley       ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, p, &Nc, &pcoords);CHKERRQ(ierr);
2091412e9a14SMatthew G. Knepley       for (n = 0; n < Nct; ++n) {
2092412e9a14SMatthew G. Knepley         if (rct[n] != DM_POLYTOPE_POINT) continue;
2093412e9a14SMatthew G. Knepley         for (r = 0; r < rsize[n]; ++r) {
2094412e9a14SMatthew G. Knepley           PetscInt vNew, off;
2095b5da9499SMatthew G. Knepley 
2096412e9a14SMatthew G. Knepley           ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], p, r, &vNew);CHKERRQ(ierr);
2097412e9a14SMatthew G. Knepley           ierr = PetscSectionGetOffset(coordSectionNew, vNew, &off);CHKERRQ(ierr);
2098412e9a14SMatthew G. Knepley           for (d = 0; d < dE; ++d) coordsNew[off+d] = vcoords[d];
2099b5da9499SMatthew G. Knepley         }
21009fc2a3f3SStefano Zampini       }
2101412e9a14SMatthew G. Knepley     }
2102412e9a14SMatthew G. Knepley   }
2103412e9a14SMatthew G. Knepley   /* Then set coordinates for cells by localizing */
2104412e9a14SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
2105412e9a14SMatthew G. Knepley     DMPolytopeType  ct;
2106412e9a14SMatthew G. Knepley     DMPolytopeType *rct;
2107412e9a14SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt;
2108412e9a14SMatthew G. Knepley     PetscInt        Nct, n, r;
2109412e9a14SMatthew G. Knepley     PetscBool       isLocalized = PETSC_FALSE;
211090b157c4SStefano Zampini 
2111412e9a14SMatthew G. Knepley     ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
2112412e9a14SMatthew G. Knepley     ierr = DMPlexCellRefinerRefine(cr, ct, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
2113412e9a14SMatthew G. Knepley     if (localizeCells && ct != DM_POLYTOPE_POINT && (p >= ocStart) && (p < ocEnd)) {
2114412e9a14SMatthew G. Knepley       PetscInt dof;
2115412e9a14SMatthew G. Knepley       ierr = PetscSectionGetDof(coordSection, p, &dof); CHKERRQ(ierr);
2116412e9a14SMatthew G. Knepley       if (dof) isLocalized = PETSC_TRUE;
2117b5da9499SMatthew G. Knepley     }
2118412e9a14SMatthew G. Knepley     if (isLocalized) {
2119412e9a14SMatthew G. Knepley       const PetscScalar *pcoords;
21209fc2a3f3SStefano Zampini 
2121412e9a14SMatthew G. Knepley       ierr = DMPlexPointLocalRead(cdm, p, coords, &pcoords);CHKERRQ(ierr);
2122412e9a14SMatthew G. Knepley       for (n = 0; n < Nct; ++n) {
2123412e9a14SMatthew G. Knepley         const PetscInt Nr = rsize[n];
212490b157c4SStefano Zampini 
2125412e9a14SMatthew G. Knepley         if (DMPolytopeTypeGetDim(ct) != DMPolytopeTypeGetDim(rct[n])) continue;
2126412e9a14SMatthew G. Knepley         for (r = 0; r < Nr; ++r) {
2127412e9a14SMatthew G. Knepley           PetscInt pNew, offNew;
212890b157c4SStefano Zampini 
2129412e9a14SMatthew G. Knepley           /* It looks like Stefano and Lisandro are allowing localized coordinates without defining the periodic boundary, which means that
2130412e9a14SMatthew G. Knepley              DMLocalizeCoordinate_Internal() will not work. Localized coordinates will have to have obtained by the affine map of the larger
2131412e9a14SMatthew G. Knepley              cell to the ones it produces. */
2132412e9a14SMatthew G. Knepley           ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], p, r, &pNew);CHKERRQ(ierr);
2133412e9a14SMatthew G. Knepley           ierr = PetscSectionGetOffset(coordSectionNew, pNew, &offNew);CHKERRQ(ierr);
2134412e9a14SMatthew G. Knepley           ierr = DMPlexCellRefinerMapLocalizedCoordinates(cr, ct, rct[n], r, pcoords, &coordsNew[offNew]);CHKERRQ(ierr);
213590b157c4SStefano Zampini         }
213690b157c4SStefano Zampini       }
213790b157c4SStefano Zampini     }
213890b157c4SStefano Zampini   }
2139412e9a14SMatthew G. Knepley   ierr = VecRestoreArrayRead(coordsLocal, &coords);CHKERRQ(ierr);
2140412e9a14SMatthew G. Knepley   ierr = VecRestoreArray(coordsLocalNew, &coordsNew);CHKERRQ(ierr);
2141412e9a14SMatthew G. Knepley   ierr = DMSetCoordinatesLocal(rdm, coordsLocalNew);CHKERRQ(ierr);
2142412e9a14SMatthew G. Knepley   /* TODO Stefano has a final reduction if some hybrid coordinates cannot be found. (needcoords) Should not be needed. */
2143412e9a14SMatthew G. Knepley   ierr = VecDestroy(&coordsLocalNew);CHKERRQ(ierr);
214475d3a19aSMatthew G. Knepley   ierr = PetscSectionDestroy(&coordSectionNew);CHKERRQ(ierr);
2145412e9a14SMatthew G. Knepley   if (!localizeCells) {ierr = DMLocalizeCoordinates(rdm);CHKERRQ(ierr);}
214675d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
214775d3a19aSMatthew G. Knepley }
214875d3a19aSMatthew G. Knepley 
2149963fc26aSMatthew G. Knepley /*@
2150963fc26aSMatthew G. Knepley   DMPlexCreateProcessSF - Create an SF which just has process connectivity
2151963fc26aSMatthew G. Knepley 
2152d083f849SBarry Smith   Collective on dm
2153963fc26aSMatthew G. Knepley 
2154963fc26aSMatthew G. Knepley   Input Parameters:
2155963fc26aSMatthew G. Knepley + dm      - The DM
2156963fc26aSMatthew G. Knepley - sfPoint - The PetscSF which encodes point connectivity
2157963fc26aSMatthew G. Knepley 
2158963fc26aSMatthew G. Knepley   Output Parameters:
2159963fc26aSMatthew G. Knepley + processRanks - A list of process neighbors, or NULL
2160963fc26aSMatthew G. Knepley - sfProcess    - An SF encoding the process connectivity, or NULL
2161963fc26aSMatthew G. Knepley 
2162963fc26aSMatthew G. Knepley   Level: developer
2163963fc26aSMatthew G. Knepley 
2164963fc26aSMatthew G. Knepley .seealso: PetscSFCreate(), DMPlexCreateTwoSidedProcessSF()
2165963fc26aSMatthew G. Knepley @*/
2166963fc26aSMatthew G. Knepley PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess)
216775d3a19aSMatthew G. Knepley {
216875d3a19aSMatthew G. Knepley   PetscInt           numRoots, numLeaves, l;
216975d3a19aSMatthew G. Knepley   const PetscInt    *localPoints;
217075d3a19aSMatthew G. Knepley   const PetscSFNode *remotePoints;
217175d3a19aSMatthew G. Knepley   PetscInt          *localPointsNew;
217275d3a19aSMatthew G. Knepley   PetscSFNode       *remotePointsNew;
217375d3a19aSMatthew G. Knepley   PetscInt          *ranks, *ranksNew;
21749852e123SBarry Smith   PetscMPIInt        size;
217575d3a19aSMatthew G. Knepley   PetscErrorCode     ierr;
217675d3a19aSMatthew G. Knepley 
217775d3a19aSMatthew G. Knepley   PetscFunctionBegin;
2178963fc26aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2179963fc26aSMatthew G. Knepley   PetscValidHeaderSpecific(sfPoint, PETSCSF_CLASSID, 2);
2180963fc26aSMatthew G. Knepley   if (processRanks) {PetscValidPointer(processRanks, 3);}
2181963fc26aSMatthew G. Knepley   if (sfProcess)    {PetscValidPointer(sfProcess, 4);}
21829852e123SBarry Smith   ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dm), &size);CHKERRQ(ierr);
218375d3a19aSMatthew G. Knepley   ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr);
2184785e854fSJed Brown   ierr = PetscMalloc1(numLeaves, &ranks);CHKERRQ(ierr);
218575d3a19aSMatthew G. Knepley   for (l = 0; l < numLeaves; ++l) {
218675d3a19aSMatthew G. Knepley     ranks[l] = remotePoints[l].rank;
218775d3a19aSMatthew G. Knepley   }
218875d3a19aSMatthew G. Knepley   ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr);
2189785e854fSJed Brown   ierr = PetscMalloc1(numLeaves, &ranksNew);CHKERRQ(ierr);
2190785e854fSJed Brown   ierr = PetscMalloc1(numLeaves, &localPointsNew);CHKERRQ(ierr);
2191785e854fSJed Brown   ierr = PetscMalloc1(numLeaves, &remotePointsNew);CHKERRQ(ierr);
219275d3a19aSMatthew G. Knepley   for (l = 0; l < numLeaves; ++l) {
219375d3a19aSMatthew G. Knepley     ranksNew[l]              = ranks[l];
219475d3a19aSMatthew G. Knepley     localPointsNew[l]        = l;
219575d3a19aSMatthew G. Knepley     remotePointsNew[l].index = 0;
219675d3a19aSMatthew G. Knepley     remotePointsNew[l].rank  = ranksNew[l];
219775d3a19aSMatthew G. Knepley   }
219875d3a19aSMatthew G. Knepley   ierr = PetscFree(ranks);CHKERRQ(ierr);
2199963fc26aSMatthew G. Knepley   if (processRanks) {ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr);}
2200963fc26aSMatthew G. Knepley   else              {ierr = PetscFree(ranksNew);CHKERRQ(ierr);}
2201963fc26aSMatthew G. Knepley   if (sfProcess) {
220275d3a19aSMatthew G. Knepley     ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess);CHKERRQ(ierr);
2203963fc26aSMatthew G. Knepley     ierr = PetscObjectSetName((PetscObject) *sfProcess, "Process SF");CHKERRQ(ierr);
220475d3a19aSMatthew G. Knepley     ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr);
22059852e123SBarry Smith     ierr = PetscSFSetGraph(*sfProcess, size, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr);
2206963fc26aSMatthew G. Knepley   }
220775d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
220875d3a19aSMatthew G. Knepley }
220975d3a19aSMatthew G. Knepley 
2210412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerCreateSF(DMPlexCellRefiner cr, DM rdm)
221175d3a19aSMatthew G. Knepley {
2212412e9a14SMatthew G. Knepley   DM                 dm = cr->dm;
2213412e9a14SMatthew G. Knepley   DMPlexCellRefiner *crRem;
221475d3a19aSMatthew G. Knepley   PetscSF            sf, sfNew, sfProcess;
221575d3a19aSMatthew G. Knepley   IS                 processRanks;
2216412e9a14SMatthew G. Knepley   MPI_Datatype       ctType;
221775d3a19aSMatthew G. Knepley   PetscInt           numRoots, numLeaves, numLeavesNew = 0, l, m;
221875d3a19aSMatthew G. Knepley   const PetscInt    *localPoints, *neighbors;
221975d3a19aSMatthew G. Knepley   const PetscSFNode *remotePoints;
222075d3a19aSMatthew G. Knepley   PetscInt          *localPointsNew;
222175d3a19aSMatthew G. Knepley   PetscSFNode       *remotePointsNew;
2222412e9a14SMatthew G. Knepley   PetscInt          *ctStartRem, *ctStartNewRem;
2223412e9a14SMatthew G. Knepley   PetscInt           ctSize = DM_NUM_POLYTOPES+1, numNeighbors, n, pStartNew, pEndNew, pNew, pNewRem;
222475d3a19aSMatthew G. Knepley   PetscErrorCode     ierr;
222575d3a19aSMatthew G. Knepley 
222675d3a19aSMatthew G. Knepley   PetscFunctionBegin;
222775d3a19aSMatthew G. Knepley   ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr);
222875d3a19aSMatthew G. Knepley   ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr);
222975d3a19aSMatthew G. Knepley   ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr);
2230add09238SMatthew G. Knepley   /* Calculate size of new SF */
223175d3a19aSMatthew G. Knepley   ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr);
223275d3a19aSMatthew G. Knepley   if (numRoots < 0) PetscFunctionReturn(0);
223375d3a19aSMatthew G. Knepley   for (l = 0; l < numLeaves; ++l) {
223475d3a19aSMatthew G. Knepley     const PetscInt  p = localPoints[l];
2235412e9a14SMatthew G. Knepley     DMPolytopeType  ct;
2236412e9a14SMatthew G. Knepley     DMPolytopeType *rct;
2237412e9a14SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt;
2238412e9a14SMatthew G. Knepley     PetscInt        Nct, n;
223975d3a19aSMatthew G. Knepley 
2240412e9a14SMatthew G. Knepley     ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
2241412e9a14SMatthew G. Knepley     ierr = DMPlexCellRefinerRefine(cr, ct, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
2242412e9a14SMatthew G. Knepley     for (n = 0; n < Nct; ++n) numLeavesNew += rsize[n];
22430314a74cSLawrence Mitchell   }
2244412e9a14SMatthew G. Knepley   /* Communicate ctStart and cStartNew for each remote rank */
224575d3a19aSMatthew G. Knepley   ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr);
224675d3a19aSMatthew G. Knepley   ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr);
2247412e9a14SMatthew G. Knepley   ierr = PetscMalloc2(ctSize*numNeighbors, &ctStartRem, ctSize*numNeighbors, &ctStartNewRem);CHKERRQ(ierr);
2248412e9a14SMatthew G. Knepley   ierr = MPI_Type_contiguous(ctSize, MPIU_INT, &ctType);CHKERRQ(ierr);
2249412e9a14SMatthew G. Knepley   ierr = MPI_Type_commit(&ctType);CHKERRQ(ierr);
2250412e9a14SMatthew G. Knepley   ierr = PetscSFBcastBegin(sfProcess, ctType, cr->ctStart, ctStartRem);CHKERRQ(ierr);
2251412e9a14SMatthew G. Knepley   ierr = PetscSFBcastEnd(sfProcess, ctType, cr->ctStart, ctStartRem);CHKERRQ(ierr);
2252412e9a14SMatthew G. Knepley   ierr = PetscSFBcastBegin(sfProcess, ctType, cr->ctStartNew, ctStartNewRem);CHKERRQ(ierr);
2253412e9a14SMatthew G. Knepley   ierr = PetscSFBcastEnd(sfProcess, ctType, cr->ctStartNew, ctStartNewRem);CHKERRQ(ierr);
2254412e9a14SMatthew G. Knepley   ierr = MPI_Type_free(&ctType);CHKERRQ(ierr);
225575d3a19aSMatthew G. Knepley   ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr);
2256412e9a14SMatthew G. Knepley   ierr = PetscMalloc1(numNeighbors, &crRem);CHKERRQ(ierr);
2257412e9a14SMatthew G. Knepley   for (n = 0; n < numNeighbors; ++n) {
2258412e9a14SMatthew G. Knepley     ierr = DMPlexCellRefinerCreate(dm, &crRem[n]);CHKERRQ(ierr);
2259412e9a14SMatthew G. Knepley     ierr = DMPlexCellRefinerSetStarts(crRem[n], &ctStartRem[n*ctSize], &ctStartNewRem[n*ctSize]);
2260412e9a14SMatthew G. Knepley     ierr = DMPlexCellRefinerSetUp(crRem[n]);CHKERRQ(ierr);
2261412e9a14SMatthew G. Knepley   }
2262412e9a14SMatthew G. Knepley   ierr = PetscFree2(ctStartRem, ctStartNewRem);CHKERRQ(ierr);
226375d3a19aSMatthew G. Knepley   /* Calculate new point SF */
2264785e854fSJed Brown   ierr = PetscMalloc1(numLeavesNew, &localPointsNew);CHKERRQ(ierr);
2265785e854fSJed Brown   ierr = PetscMalloc1(numLeavesNew, &remotePointsNew);CHKERRQ(ierr);
226675d3a19aSMatthew G. Knepley   ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr);
226775d3a19aSMatthew G. Knepley   for (l = 0, m = 0; l < numLeaves; ++l) {
226875d3a19aSMatthew G. Knepley     PetscInt        p       = localPoints[l];
2269412e9a14SMatthew G. Knepley     PetscInt        pRem    = remotePoints[l].index;
2270412e9a14SMatthew G. Knepley     PetscMPIInt     rankRem = remotePoints[l].rank;
2271412e9a14SMatthew G. Knepley     DMPolytopeType  ct;
2272412e9a14SMatthew G. Knepley     DMPolytopeType *rct;
2273412e9a14SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt;
2274412e9a14SMatthew G. Knepley     PetscInt        neighbor, Nct, n, r;
227575d3a19aSMatthew G. Knepley 
2276412e9a14SMatthew G. Knepley     ierr = PetscFindInt(rankRem, numNeighbors, neighbors, &neighbor);CHKERRQ(ierr);
2277412e9a14SMatthew G. Knepley     if (neighbor < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %D", rankRem);
2278412e9a14SMatthew G. Knepley     ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
2279412e9a14SMatthew G. Knepley     ierr = DMPlexCellRefinerRefine(cr, ct, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
2280412e9a14SMatthew G. Knepley     for (n = 0; n < Nct; ++n) {
2281412e9a14SMatthew G. Knepley       for (r = 0; r < rsize[n]; ++r) {
2282412e9a14SMatthew G. Knepley         ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], p, r, &pNew);CHKERRQ(ierr);
2283412e9a14SMatthew G. Knepley         ierr = DMPlexCellRefinerGetNewPoint(crRem[neighbor], ct, rct[n], pRem, r, &pNewRem);CHKERRQ(ierr);
2284412e9a14SMatthew G. Knepley         localPointsNew[m]        = pNew;
2285412e9a14SMatthew G. Knepley         remotePointsNew[m].index = pNewRem;
2286412e9a14SMatthew G. Knepley         remotePointsNew[m].rank  = rankRem;
22870314a74cSLawrence Mitchell         ++m;
22880314a74cSLawrence Mitchell       }
22896ce3c06aSMatthew G. Knepley     }
22906ce3c06aSMatthew G. Knepley   }
2291412e9a14SMatthew G. Knepley   for (n = 0; n < numNeighbors; ++n) {ierr = DMPlexCellRefinerDestroy(&crRem[n]);CHKERRQ(ierr);}
2292412e9a14SMatthew G. Knepley   ierr = PetscFree(crRem);CHKERRQ(ierr);
2293d7eabd03SStefano Zampini   if (m != numLeavesNew) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of leaf point %D should be %D", m, numLeavesNew);
229475d3a19aSMatthew G. Knepley   ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr);
229575d3a19aSMatthew G. Knepley   ierr = ISDestroy(&processRanks);CHKERRQ(ierr);
2296ba3c3d50SMatthew G. Knepley   {
2297ba3c3d50SMatthew G. Knepley     PetscSFNode *rp, *rtmp;
2298ba3c3d50SMatthew G. Knepley     PetscInt    *lp, *idx, *ltmp, i;
2299ba3c3d50SMatthew G. Knepley 
2300ba3c3d50SMatthew G. Knepley     /* SF needs sorted leaves to correct calculate Gather */
2301ba3c3d50SMatthew G. Knepley     ierr = PetscMalloc1(numLeavesNew, &idx);CHKERRQ(ierr);
2302ba3c3d50SMatthew G. Knepley     ierr = PetscMalloc1(numLeavesNew, &lp);CHKERRQ(ierr);
2303ba3c3d50SMatthew G. Knepley     ierr = PetscMalloc1(numLeavesNew, &rp);CHKERRQ(ierr);
2304c7c54c77SMatthew G. Knepley     for (i = 0; i < numLeavesNew; ++i) {
2305d7eabd03SStefano Zampini       if ((localPointsNew[i] < pStartNew) || (localPointsNew[i] >= pEndNew)) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Local SF point %D (%D) not in [%D, %D)", localPointsNew[i], i, pStartNew, pEndNew);
2306c7c54c77SMatthew G. Knepley       idx[i] = i;
2307c7c54c77SMatthew G. Knepley     }
2308ba3c3d50SMatthew G. Knepley     ierr = PetscSortIntWithPermutation(numLeavesNew, localPointsNew, idx);CHKERRQ(ierr);
2309ba3c3d50SMatthew G. Knepley     for (i = 0; i < numLeavesNew; ++i) {
2310ba3c3d50SMatthew G. Knepley       lp[i] = localPointsNew[idx[i]];
2311ba3c3d50SMatthew G. Knepley       rp[i] = remotePointsNew[idx[i]];
2312ba3c3d50SMatthew G. Knepley     }
2313ba3c3d50SMatthew G. Knepley     ltmp            = localPointsNew;
2314ba3c3d50SMatthew G. Knepley     localPointsNew  = lp;
2315ba3c3d50SMatthew G. Knepley     rtmp            = remotePointsNew;
2316ba3c3d50SMatthew G. Knepley     remotePointsNew = rp;
2317ba3c3d50SMatthew G. Knepley     ierr = PetscFree(idx);CHKERRQ(ierr);
2318ba3c3d50SMatthew G. Knepley     ierr = PetscFree(ltmp);CHKERRQ(ierr);
2319ba3c3d50SMatthew G. Knepley     ierr = PetscFree(rtmp);CHKERRQ(ierr);
2320ba3c3d50SMatthew G. Knepley   }
232175d3a19aSMatthew G. Knepley   ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr);
232275d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
232375d3a19aSMatthew G. Knepley }
232475d3a19aSMatthew G. Knepley 
2325412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellRefinerCreateLabels(DMPlexCellRefiner cr, DM rdm)
232675d3a19aSMatthew G. Knepley {
2327412e9a14SMatthew G. Knepley   DM             dm = cr->dm;
232875d3a19aSMatthew G. Knepley   PetscInt       numLabels, l;
2329412e9a14SMatthew G. Knepley   PetscInt       pNew;
233075d3a19aSMatthew G. Knepley   PetscErrorCode ierr;
233175d3a19aSMatthew G. Knepley 
233275d3a19aSMatthew G. Knepley   PetscFunctionBegin;
2333c58f1c22SToby Isaac   ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr);
233475d3a19aSMatthew G. Knepley   for (l = 0; l < numLabels; ++l) {
233575d3a19aSMatthew G. Knepley     DMLabel         label, labelNew;
233675d3a19aSMatthew G. Knepley     const char     *lname;
2337ba2698f1SMatthew G. Knepley     PetscBool       isDepth, isCellType;
233875d3a19aSMatthew G. Knepley     IS              valueIS;
233975d3a19aSMatthew G. Knepley     const PetscInt *values;
23405aa44df4SToby Isaac     PetscInt        defVal;
234175d3a19aSMatthew G. Knepley     PetscInt        numValues, val;
234275d3a19aSMatthew G. Knepley 
2343c58f1c22SToby Isaac     ierr = DMGetLabelName(dm, l, &lname);CHKERRQ(ierr);
234475d3a19aSMatthew G. Knepley     ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr);
234575d3a19aSMatthew G. Knepley     if (isDepth) continue;
2346ba2698f1SMatthew G. Knepley     ierr = PetscStrcmp(lname, "celltype", &isCellType);CHKERRQ(ierr);
2347ba2698f1SMatthew G. Knepley     if (isCellType) continue;
2348c58f1c22SToby Isaac     ierr = DMCreateLabel(rdm, lname);CHKERRQ(ierr);
2349c58f1c22SToby Isaac     ierr = DMGetLabel(dm, lname, &label);CHKERRQ(ierr);
2350c58f1c22SToby Isaac     ierr = DMGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr);
23515aa44df4SToby Isaac     ierr = DMLabelGetDefaultValue(label, &defVal);CHKERRQ(ierr);
23525aa44df4SToby Isaac     ierr = DMLabelSetDefaultValue(labelNew, defVal);CHKERRQ(ierr);
235375d3a19aSMatthew G. Knepley     ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr);
235475d3a19aSMatthew G. Knepley     ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr);
235575d3a19aSMatthew G. Knepley     ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr);
235675d3a19aSMatthew G. Knepley     for (val = 0; val < numValues; ++val) {
235775d3a19aSMatthew G. Knepley       IS              pointIS;
235875d3a19aSMatthew G. Knepley       const PetscInt *points;
2359412e9a14SMatthew G. Knepley       PetscInt        numPoints, p;
236075d3a19aSMatthew G. Knepley 
23612bc5314cSMichael Lange       /* Ensure refined label is created with same number of strata as
23622bc5314cSMichael Lange        * original (even if no entries here). */
2363ad8374ffSToby Isaac       ierr = DMLabelAddStratum(labelNew, values[val]);CHKERRQ(ierr);
2364412e9a14SMatthew G. Knepley       ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr);
2365412e9a14SMatthew G. Knepley       ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr);
2366412e9a14SMatthew G. Knepley       ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr);
2367412e9a14SMatthew G. Knepley       for (p = 0; p < numPoints; ++p) {
2368412e9a14SMatthew G. Knepley         const PetscInt  point = points[p];
2369412e9a14SMatthew G. Knepley         DMPolytopeType  ct;
2370412e9a14SMatthew G. Knepley         DMPolytopeType *rct;
2371412e9a14SMatthew G. Knepley         PetscInt       *rsize, *rcone, *rornt;
2372412e9a14SMatthew G. Knepley         PetscInt        Nct, n, r;
2373412e9a14SMatthew G. Knepley 
2374412e9a14SMatthew G. Knepley         ierr = DMPlexGetCellType(dm, point, &ct);CHKERRQ(ierr);
2375412e9a14SMatthew G. Knepley         ierr = DMPlexCellRefinerRefine(cr, ct, &Nct, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
2376412e9a14SMatthew G. Knepley         for (n = 0; n < Nct; ++n) {
2377412e9a14SMatthew G. Knepley           for (r = 0; r < rsize[n]; ++r) {
2378412e9a14SMatthew G. Knepley             ierr = DMPlexCellRefinerGetNewPoint(cr, ct, rct[n], point, r, &pNew);CHKERRQ(ierr);
2379412e9a14SMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, pNew, values[val]);CHKERRQ(ierr);
238027fcede3SMatthew G. Knepley           }
238175d3a19aSMatthew G. Knepley         }
238275d3a19aSMatthew G. Knepley       }
238375d3a19aSMatthew G. Knepley       ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr);
238475d3a19aSMatthew G. Knepley       ierr = ISDestroy(&pointIS);CHKERRQ(ierr);
238575d3a19aSMatthew G. Knepley     }
238675d3a19aSMatthew G. Knepley     ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr);
238775d3a19aSMatthew G. Knepley     ierr = ISDestroy(&valueIS);CHKERRQ(ierr);
238875d3a19aSMatthew G. Knepley   }
238975d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
239075d3a19aSMatthew G. Knepley }
239175d3a19aSMatthew G. Knepley 
239275d3a19aSMatthew G. Knepley /* This will only work for interpolated meshes */
2393412e9a14SMatthew G. Knepley PetscErrorCode DMPlexRefineUniform(DM dm, DMPlexCellRefiner cr, DM *dmRefined)
239475d3a19aSMatthew G. Knepley {
239575d3a19aSMatthew G. Knepley   DM              rdm;
2396412e9a14SMatthew G. Knepley   PetscInt        dim, embedDim, depth;
239775d3a19aSMatthew G. Knepley   PetscErrorCode  ierr;
239875d3a19aSMatthew G. Knepley 
239975d3a19aSMatthew G. Knepley   PetscFunctionBegin;
2400412e9a14SMatthew G. Knepley   PetscValidHeader(cr, 1);
240175d3a19aSMatthew G. Knepley   ierr = DMCreate(PetscObjectComm((PetscObject)dm), &rdm);CHKERRQ(ierr);
240275d3a19aSMatthew G. Knepley   ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr);
2403c73cfb54SMatthew G. Knepley   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
2404c73cfb54SMatthew G. Knepley   ierr = DMSetDimension(rdm, dim);CHKERRQ(ierr);
24056dcbd917SStefano Zampini   ierr = DMGetCoordinateDim(dm, &embedDim);CHKERRQ(ierr);
24066dcbd917SStefano Zampini   ierr = DMSetCoordinateDim(rdm, embedDim);CHKERRQ(ierr);
240775d3a19aSMatthew G. Knepley   /* Calculate number of new points of each depth */
240875d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
24091e573d11SMatthew G. Knepley   if (depth >= 0 && dim != depth) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Mesh must be interpolated for regular refinement");
241075d3a19aSMatthew G. Knepley   /* Step 1: Set chart */
2411412e9a14SMatthew G. Knepley   ierr = DMPlexSetChart(rdm, 0, cr->ctStartNew[cr->ctOrder[DM_NUM_POLYTOPES]]);CHKERRQ(ierr);
24126d7373e8SToby Isaac   /* Step 2: Set cone/support sizes (automatically stratifies) */
2413412e9a14SMatthew G. Knepley   ierr = DMPlexCellRefinerSetConeSizes(cr, rdm);CHKERRQ(ierr);
241475d3a19aSMatthew G. Knepley   /* Step 3: Setup refined DM */
241575d3a19aSMatthew G. Knepley   ierr = DMSetUp(rdm);CHKERRQ(ierr);
24166d7373e8SToby Isaac   /* Step 4: Set cones and supports (automatically symmetrizes) */
2417412e9a14SMatthew G. Knepley   ierr = DMPlexCellRefinerSetCones(cr, rdm);CHKERRQ(ierr);
24186d7373e8SToby Isaac   /* Step 5: Create pointSF */
2419412e9a14SMatthew G. Knepley   ierr = DMPlexCellRefinerCreateSF(cr, rdm);CHKERRQ(ierr);
24206d7373e8SToby Isaac   /* Step 6: Create labels */
2421412e9a14SMatthew G. Knepley   ierr = DMPlexCellRefinerCreateLabels(cr, rdm);CHKERRQ(ierr);
24226d7373e8SToby Isaac   /* Step 7: Set coordinates */
2423412e9a14SMatthew G. Knepley   ierr = DMPlexCellRefinerSetCoordinates(cr, rdm);CHKERRQ(ierr);
242475d3a19aSMatthew G. Knepley   *dmRefined = rdm;
242575d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
242675d3a19aSMatthew G. Knepley }
242775d3a19aSMatthew G. Knepley 
24282389894bSMatthew G. Knepley /*@
24292389894bSMatthew G. Knepley   DMPlexCreateCoarsePointIS - Creates an IS covering the coarse DM chart with the fine points as data
24302389894bSMatthew G. Knepley 
24312389894bSMatthew G. Knepley   Input Parameter:
24322389894bSMatthew G. Knepley . dm - The coarse DM
24332389894bSMatthew G. Knepley 
24342389894bSMatthew G. Knepley   Output Parameter:
24352389894bSMatthew G. Knepley . fpointIS - The IS of all the fine points which exist in the original coarse mesh
24362389894bSMatthew G. Knepley 
24372389894bSMatthew G. Knepley   Level: developer
24382389894bSMatthew G. Knepley 
2439*97d8846cSMatthew Knepley .seealso: DMRefine(), DMPlexSetRefinementUniform(), DMPlexGetSubpointIS()
24402389894bSMatthew G. Knepley @*/
24412389894bSMatthew G. Knepley PetscErrorCode DMPlexCreateCoarsePointIS(DM dm, IS *fpointIS)
24422389894bSMatthew G. Knepley {
2443412e9a14SMatthew G. Knepley   DMPlexCellRefiner cr;
2444412e9a14SMatthew G. Knepley   PetscInt         *fpoints;
2445412e9a14SMatthew G. Knepley   PetscInt          pStart, pEnd, p, vStart, vEnd, v, vNew;
24462389894bSMatthew G. Knepley   PetscErrorCode    ierr;
24472389894bSMatthew G. Knepley 
24482389894bSMatthew G. Knepley   PetscFunctionBegin;
24492389894bSMatthew G. Knepley   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
24502389894bSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
2451412e9a14SMatthew G. Knepley   ierr = DMPlexCellRefinerCreate(dm, &cr);CHKERRQ(ierr);
2452412e9a14SMatthew G. Knepley   ierr = DMPlexCellRefinerSetUp(cr);CHKERRQ(ierr);
24532389894bSMatthew G. Knepley   ierr = PetscMalloc1(pEnd-pStart, &fpoints);CHKERRQ(ierr);
24542389894bSMatthew G. Knepley   for (p = 0; p < pEnd-pStart; ++p) fpoints[p] = -1;
2455412e9a14SMatthew G. Knepley   for (v = vStart; v < vEnd; ++v) {
2456412e9a14SMatthew G. Knepley     ierr = DMPlexCellRefinerGetNewPoint(cr, DM_POLYTOPE_POINT, DM_POLYTOPE_POINT, p, 0, &vNew);CHKERRQ(ierr);
2457412e9a14SMatthew G. Knepley     fpoints[v-pStart] = vNew;
24582389894bSMatthew G. Knepley   }
2459412e9a14SMatthew G. Knepley   ierr = DMPlexCellRefinerDestroy(&cr);CHKERRQ(ierr);
24602389894bSMatthew G. Knepley   ierr = ISCreateGeneral(PETSC_COMM_SELF, pEnd-pStart, fpoints, PETSC_OWN_POINTER, fpointIS);CHKERRQ(ierr);
24612389894bSMatthew G. Knepley   PetscFunctionReturn(0);
24622389894bSMatthew G. Knepley }
24632389894bSMatthew G. Knepley 
24640e2b6761SMatthew G. Knepley /*@
24650e2b6761SMatthew G. Knepley   DMPlexSetRefinementUniform - Set the flag for uniform refinement
24660e2b6761SMatthew G. Knepley 
24670e2b6761SMatthew G. Knepley   Input Parameters:
24680e2b6761SMatthew G. Knepley + dm - The DM
24690e2b6761SMatthew G. Knepley - refinementUniform - The flag for uniform refinement
24700e2b6761SMatthew G. Knepley 
24710e2b6761SMatthew G. Knepley   Level: developer
24720e2b6761SMatthew G. Knepley 
24730e2b6761SMatthew G. Knepley .seealso: DMRefine(), DMPlexGetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
24740e2b6761SMatthew G. Knepley @*/
247575d3a19aSMatthew G. Knepley PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform)
247675d3a19aSMatthew G. Knepley {
247775d3a19aSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
247875d3a19aSMatthew G. Knepley 
247975d3a19aSMatthew G. Knepley   PetscFunctionBegin;
248075d3a19aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
248175d3a19aSMatthew G. Knepley   mesh->refinementUniform = refinementUniform;
248275d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
248375d3a19aSMatthew G. Knepley }
248475d3a19aSMatthew G. Knepley 
24850e2b6761SMatthew G. Knepley /*@
24860e2b6761SMatthew G. Knepley   DMPlexGetRefinementUniform - Retrieve the flag for uniform refinement
24870e2b6761SMatthew G. Knepley 
24880e2b6761SMatthew G. Knepley   Input Parameter:
24890e2b6761SMatthew G. Knepley . dm - The DM
24900e2b6761SMatthew G. Knepley 
24910e2b6761SMatthew G. Knepley   Output Parameter:
24920e2b6761SMatthew G. Knepley . refinementUniform - The flag for uniform refinement
24930e2b6761SMatthew G. Knepley 
24940e2b6761SMatthew G. Knepley   Level: developer
24950e2b6761SMatthew G. Knepley 
24960e2b6761SMatthew G. Knepley .seealso: DMRefine(), DMPlexSetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
24970e2b6761SMatthew G. Knepley @*/
249875d3a19aSMatthew G. Knepley PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform)
249975d3a19aSMatthew G. Knepley {
250075d3a19aSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
250175d3a19aSMatthew G. Knepley 
250275d3a19aSMatthew G. Knepley   PetscFunctionBegin;
250375d3a19aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
250475d3a19aSMatthew G. Knepley   PetscValidPointer(refinementUniform,  2);
250575d3a19aSMatthew G. Knepley   *refinementUniform = mesh->refinementUniform;
250675d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
250775d3a19aSMatthew G. Knepley }
250875d3a19aSMatthew G. Knepley 
25090e2b6761SMatthew G. Knepley /*@
25100e2b6761SMatthew G. Knepley   DMPlexSetRefinementLimit - Set the maximum cell volume for refinement
25110e2b6761SMatthew G. Knepley 
25120e2b6761SMatthew G. Knepley   Input Parameters:
25130e2b6761SMatthew G. Knepley + dm - The DM
25140e2b6761SMatthew G. Knepley - refinementLimit - The maximum cell volume in the refined mesh
25150e2b6761SMatthew G. Knepley 
25160e2b6761SMatthew G. Knepley   Level: developer
25170e2b6761SMatthew G. Knepley 
25180e2b6761SMatthew G. Knepley .seealso: DMRefine(), DMPlexGetRefinementLimit(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform()
25190e2b6761SMatthew G. Knepley @*/
252075d3a19aSMatthew G. Knepley PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit)
252175d3a19aSMatthew G. Knepley {
252275d3a19aSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
252375d3a19aSMatthew G. Knepley 
252475d3a19aSMatthew G. Knepley   PetscFunctionBegin;
252575d3a19aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
252675d3a19aSMatthew G. Knepley   mesh->refinementLimit = refinementLimit;
252775d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
252875d3a19aSMatthew G. Knepley }
252975d3a19aSMatthew G. Knepley 
25300e2b6761SMatthew G. Knepley /*@
25310e2b6761SMatthew G. Knepley   DMPlexGetRefinementLimit - Retrieve the maximum cell volume for refinement
25320e2b6761SMatthew G. Knepley 
25330e2b6761SMatthew G. Knepley   Input Parameter:
25340e2b6761SMatthew G. Knepley . dm - The DM
25350e2b6761SMatthew G. Knepley 
25360e2b6761SMatthew G. Knepley   Output Parameter:
25370e2b6761SMatthew G. Knepley . refinementLimit - The maximum cell volume in the refined mesh
25380e2b6761SMatthew G. Knepley 
25390e2b6761SMatthew G. Knepley   Level: developer
25400e2b6761SMatthew G. Knepley 
25410e2b6761SMatthew G. Knepley .seealso: DMRefine(), DMPlexSetRefinementLimit(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform()
25420e2b6761SMatthew G. Knepley @*/
254375d3a19aSMatthew G. Knepley PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit)
254475d3a19aSMatthew G. Knepley {
254575d3a19aSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
254675d3a19aSMatthew G. Knepley 
254775d3a19aSMatthew G. Knepley   PetscFunctionBegin;
254875d3a19aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
254975d3a19aSMatthew G. Knepley   PetscValidPointer(refinementLimit,  2);
255075d3a19aSMatthew G. Knepley   /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */
255175d3a19aSMatthew G. Knepley   *refinementLimit = mesh->refinementLimit;
255275d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
255375d3a19aSMatthew G. Knepley }
255475d3a19aSMatthew G. Knepley 
2555b28003e6SMatthew G. Knepley /*@
2556b28003e6SMatthew G. Knepley   DMPlexSetRefinementFunction - Set the function giving the maximum cell volume for refinement
2557b28003e6SMatthew G. Knepley 
2558b28003e6SMatthew G. Knepley   Input Parameters:
2559b28003e6SMatthew G. Knepley + dm - The DM
2560b28003e6SMatthew G. Knepley - refinementFunc - Function giving the maximum cell volume in the refined mesh
2561b28003e6SMatthew G. Knepley 
2562b28003e6SMatthew G. Knepley   Note: The calling sequence is refinementFunc(coords, limit)
2563b28003e6SMatthew G. Knepley $ coords - Coordinates of the current point, usually a cell centroid
2564b28003e6SMatthew G. Knepley $ limit  - The maximum cell volume for a cell containing this point
2565b28003e6SMatthew G. Knepley 
2566b28003e6SMatthew G. Knepley   Level: developer
2567b28003e6SMatthew G. Knepley 
2568b28003e6SMatthew G. Knepley .seealso: DMRefine(), DMPlexGetRefinementFunction(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
2569b28003e6SMatthew G. Knepley @*/
2570b28003e6SMatthew G. Knepley PetscErrorCode DMPlexSetRefinementFunction(DM dm, PetscErrorCode (*refinementFunc)(const PetscReal [], PetscReal *))
2571b28003e6SMatthew G. Knepley {
2572b28003e6SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
2573b28003e6SMatthew G. Knepley 
2574b28003e6SMatthew G. Knepley   PetscFunctionBegin;
2575b28003e6SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2576b28003e6SMatthew G. Knepley   mesh->refinementFunc = refinementFunc;
2577b28003e6SMatthew G. Knepley   PetscFunctionReturn(0);
2578b28003e6SMatthew G. Knepley }
2579b28003e6SMatthew G. Knepley 
2580b28003e6SMatthew G. Knepley /*@
2581b28003e6SMatthew G. Knepley   DMPlexGetRefinementFunction - Get the function giving the maximum cell volume for refinement
2582b28003e6SMatthew G. Knepley 
2583b28003e6SMatthew G. Knepley   Input Parameter:
2584b28003e6SMatthew G. Knepley . dm - The DM
2585b28003e6SMatthew G. Knepley 
2586b28003e6SMatthew G. Knepley   Output Parameter:
2587b28003e6SMatthew G. Knepley . refinementFunc - Function giving the maximum cell volume in the refined mesh
2588b28003e6SMatthew G. Knepley 
2589b28003e6SMatthew G. Knepley   Note: The calling sequence is refinementFunc(coords, limit)
2590b28003e6SMatthew G. Knepley $ coords - Coordinates of the current point, usually a cell centroid
2591b28003e6SMatthew G. Knepley $ limit  - The maximum cell volume for a cell containing this point
2592b28003e6SMatthew G. Knepley 
2593b28003e6SMatthew G. Knepley   Level: developer
2594b28003e6SMatthew G. Knepley 
2595b28003e6SMatthew G. Knepley .seealso: DMRefine(), DMPlexSetRefinementFunction(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
2596b28003e6SMatthew G. Knepley @*/
2597b28003e6SMatthew G. Knepley PetscErrorCode DMPlexGetRefinementFunction(DM dm, PetscErrorCode (**refinementFunc)(const PetscReal [], PetscReal *))
2598b28003e6SMatthew G. Knepley {
2599b28003e6SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
2600b28003e6SMatthew G. Knepley 
2601b28003e6SMatthew G. Knepley   PetscFunctionBegin;
2602b28003e6SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2603b28003e6SMatthew G. Knepley   PetscValidPointer(refinementFunc,  2);
2604b28003e6SMatthew G. Knepley   *refinementFunc = mesh->refinementFunc;
2605b28003e6SMatthew G. Knepley   PetscFunctionReturn(0);
2606b28003e6SMatthew G. Knepley }
2607b28003e6SMatthew G. Knepley 
26080d1cd5e0SMatthew G. Knepley PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined)
26090d1cd5e0SMatthew G. Knepley {
2610492b8470SStefano Zampini   PetscBool         isUniform;
2611412e9a14SMatthew G. Knepley   DMPlexCellRefiner cr;
26120d1cd5e0SMatthew G. Knepley   PetscErrorCode    ierr;
26130d1cd5e0SMatthew G. Knepley 
26140d1cd5e0SMatthew G. Knepley   PetscFunctionBegin;
26150d1cd5e0SMatthew G. Knepley   ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr);
2616412e9a14SMatthew G. Knepley   ierr = DMViewFromOptions(dm, NULL, "-initref_dm_view");CHKERRQ(ierr);
26170d1cd5e0SMatthew G. Knepley   if (isUniform) {
2618492b8470SStefano Zampini     PetscBool localized;
26190d1cd5e0SMatthew G. Knepley 
2620412e9a14SMatthew G. Knepley     ierr = DMPlexCellRefinerCreate(dm, &cr);CHKERRQ(ierr);
2621412e9a14SMatthew G. Knepley     ierr = DMPlexCellRefinerSetUp(cr);CHKERRQ(ierr);
2622492b8470SStefano Zampini     ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr);
2623412e9a14SMatthew G. Knepley     ierr = DMPlexRefineUniform(dm, cr, dmRefined);CHKERRQ(ierr);
26249a7e3c0aSMatthew G. Knepley     ierr = DMPlexSetRegularRefinement(*dmRefined, PETSC_TRUE);CHKERRQ(ierr);
26250d1cd5e0SMatthew G. Knepley     ierr = DMCopyBoundary(dm, *dmRefined);CHKERRQ(ierr);
26260d1cd5e0SMatthew G. Knepley     if (localized) {ierr = DMLocalizeCoordinates(*dmRefined);CHKERRQ(ierr);}
2627412e9a14SMatthew G. Knepley     ierr = DMPlexCellRefinerDestroy(&cr);CHKERRQ(ierr);
26280d1cd5e0SMatthew G. Knepley   } else {
26290d1cd5e0SMatthew G. Knepley     ierr = DMPlexRefine_Internal(dm, NULL, dmRefined);CHKERRQ(ierr);
26300d1cd5e0SMatthew G. Knepley   }
26310d1cd5e0SMatthew G. Knepley   PetscFunctionReturn(0);
26320d1cd5e0SMatthew G. Knepley }
26330d1cd5e0SMatthew G. Knepley 
26340d1cd5e0SMatthew G. Knepley PetscErrorCode DMRefineHierarchy_Plex(DM dm, PetscInt nlevels, DM dmRefined[])
26350d1cd5e0SMatthew G. Knepley {
26360d1cd5e0SMatthew G. Knepley   DM             cdm = dm;
26370d1cd5e0SMatthew G. Knepley   PetscInt       r;
26380d1cd5e0SMatthew G. Knepley   PetscBool      isUniform, localized;
26390d1cd5e0SMatthew G. Knepley   PetscErrorCode ierr;
26400d1cd5e0SMatthew G. Knepley 
26410d1cd5e0SMatthew G. Knepley   PetscFunctionBegin;
26420d1cd5e0SMatthew G. Knepley   ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr);
26430d1cd5e0SMatthew G. Knepley   ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr);
26440d1cd5e0SMatthew G. Knepley   if (isUniform) {
26450d1cd5e0SMatthew G. Knepley     for (r = 0; r < nlevels; ++r) {
2646412e9a14SMatthew G. Knepley       DMPlexCellRefiner cr;
26470d1cd5e0SMatthew G. Knepley 
2648412e9a14SMatthew G. Knepley       ierr = DMPlexCellRefinerCreate(cdm, &cr);CHKERRQ(ierr);
2649412e9a14SMatthew G. Knepley       ierr = DMPlexCellRefinerSetUp(cr);CHKERRQ(ierr);
2650412e9a14SMatthew G. Knepley       ierr = DMPlexRefineUniform(cdm, cr, &dmRefined[r]);CHKERRQ(ierr);
26519a7e3c0aSMatthew G. Knepley       ierr = DMSetCoarsenLevel(dmRefined[r], cdm->leveldown);CHKERRQ(ierr);
26529a7e3c0aSMatthew G. Knepley       ierr = DMSetRefineLevel(dmRefined[r], cdm->levelup+1);CHKERRQ(ierr);
26530d1cd5e0SMatthew G. Knepley       ierr = DMCopyBoundary(cdm, dmRefined[r]);CHKERRQ(ierr);
26540d1cd5e0SMatthew G. Knepley       if (localized) {ierr = DMLocalizeCoordinates(dmRefined[r]);CHKERRQ(ierr);}
26550d1cd5e0SMatthew G. Knepley       ierr = DMSetCoarseDM(dmRefined[r], cdm);CHKERRQ(ierr);
26560d1cd5e0SMatthew G. Knepley       ierr = DMPlexSetRegularRefinement(dmRefined[r], PETSC_TRUE);CHKERRQ(ierr);
26570d1cd5e0SMatthew G. Knepley       cdm  = dmRefined[r];
2658412e9a14SMatthew G. Knepley       ierr = DMPlexCellRefinerDestroy(&cr);CHKERRQ(ierr);
26590d1cd5e0SMatthew G. Knepley     }
26600d1cd5e0SMatthew G. Knepley   } else {
26610d1cd5e0SMatthew G. Knepley     for (r = 0; r < nlevels; ++r) {
26620d1cd5e0SMatthew G. Knepley       ierr = DMRefine(cdm, PetscObjectComm((PetscObject) dm), &dmRefined[r]);CHKERRQ(ierr);
26630d1cd5e0SMatthew G. Knepley       ierr = DMCopyBoundary(cdm, dmRefined[r]);CHKERRQ(ierr);
26640d1cd5e0SMatthew G. Knepley       if (localized) {ierr = DMLocalizeCoordinates(dmRefined[r]);CHKERRQ(ierr);}
26650d1cd5e0SMatthew G. Knepley       ierr = DMSetCoarseDM(dmRefined[r], cdm);CHKERRQ(ierr);
26660d1cd5e0SMatthew G. Knepley       cdm  = dmRefined[r];
26670d1cd5e0SMatthew G. Knepley     }
26680d1cd5e0SMatthew G. Knepley   }
26690d1cd5e0SMatthew G. Knepley   PetscFunctionReturn(0);
26700d1cd5e0SMatthew G. Knepley }
2671