Actual source code: plexrefine.c
petsc-3.9.4 2018-09-11
1: #include <petsc/private/dmpleximpl.h>
2: #include <petscsf.h>
4: PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart)
5: {
7: if (cStart) *cStart = 0;
8: if (vStart) *vStart = depth < 0 ? 0 : depthSize[depth];
9: if (fStart) *fStart = depth < 0 ? 0 : depthSize[depth] + depthSize[0];
10: if (eStart) *eStart = depth < 0 ? 0 : depthSize[depth] + depthSize[0] + depthSize[depth-1];
11: return(0);
12: }
14: PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd)
15: {
17: if (cEnd) *cEnd = depth < 0 ? 0 : depthSize[depth];
18: if (vEnd) *vEnd = depth < 0 ? 0 : depthSize[depth] + depthSize[0];
19: if (fEnd) *fEnd = depth < 0 ? 0 : depthSize[depth] + depthSize[0] + depthSize[depth-1];
20: if (eEnd) *eEnd = depth < 0 ? 0 : depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1];
21: return(0);
22: }
24: /* Gets the affine map from the original cell to each subcell */
25: PetscErrorCode CellRefinerGetAffineTransforms_Internal(CellRefiner refiner, PetscInt *numSubcells, PetscReal *v0[], PetscReal *jac[], PetscReal *invjac[])
26: {
27: PetscReal *v = NULL, *j = NULL, *invj = NULL, detJ;
28: PetscInt dim, s;
32: switch (refiner) {
33: case REFINER_NOOP: break;
34: case REFINER_SIMPLEX_2D:
35: /*
36: 2
37: |\
38: | \
39: | \
40: | \
41: | C \
42: | \
43: | \
44: 2---1---1
45: |\ D / \
46: | 2 0 \
47: |A \ / B \
48: 0---0-------1
49: */
50: dim = 2;
51: if (numSubcells) *numSubcells = 4;
52: if (v0) {
53: PetscMalloc3(4*dim,&v,4*dim*dim,&j,4*dim*dim,&invj);
54: /* A */
55: v[0+0] = -1.0; v[0+1] = -1.0;
56: j[0+0] = 0.5; j[0+1] = 0.0;
57: j[0+2] = 0.0; j[0+3] = 0.5;
58: /* B */
59: v[2+0] = 0.0; v[2+1] = -1.0;
60: j[4+0] = 0.5; j[4+1] = 0.0;
61: j[4+2] = 0.0; j[4+3] = 0.5;
62: /* C */
63: v[4+0] = -1.0; v[4+1] = 0.0;
64: j[8+0] = 0.5; j[8+1] = 0.0;
65: j[8+2] = 0.0; j[8+3] = 0.5;
66: /* D */
67: v[6+0] = 0.0; v[6+1] = -1.0;
68: j[12+0] = 0.0; j[12+1] = -0.5;
69: j[12+2] = 0.5; j[12+3] = 0.5;
70: for (s = 0; s < 4; ++s) {
71: DMPlex_Det2D_Internal(&detJ, &j[s*dim*dim]);
72: DMPlex_Invert2D_Internal(&invj[s*dim*dim], &j[s*dim*dim], detJ);
73: }
74: }
75: break;
76: case REFINER_HEX_2D:
77: /*
78: 3---------2---------2
79: | | |
80: | D 2 C |
81: | | |
82: 3----3----0----1----1
83: | | |
84: | A 0 B |
85: | | |
86: 0---------0---------1
87: */
88: dim = 2;
89: if (numSubcells) *numSubcells = 4;
90: if (v0) {
91: PetscMalloc3(4*dim,&v,4*dim*dim,&j,4*dim*dim,&invj);
92: /* A */
93: v[0+0] = -1.0; v[0+1] = -1.0;
94: j[0+0] = 0.5; j[0+1] = 0.0;
95: j[0+2] = 0.0; j[0+3] = 0.5;
96: /* B */
97: v[2+0] = 0.0; v[2+1] = -1.0;
98: j[4+0] = 0.5; j[4+1] = 0.0;
99: j[4+2] = 0.0; j[4+3] = 0.5;
100: /* C */
101: v[4+0] = 0.0; v[4+1] = 0.0;
102: j[8+0] = 0.5; j[8+1] = 0.0;
103: j[8+2] = 0.0; j[8+3] = 0.5;
104: /* D */
105: v[6+0] = -1.0; v[6+1] = 0.0;
106: j[12+0] = 0.5; j[12+1] = 0.0;
107: j[12+2] = 0.0; j[12+3] = 0.5;
108: for (s = 0; s < 4; ++s) {
109: DMPlex_Det2D_Internal(&detJ, &j[s*dim*dim]);
110: DMPlex_Invert2D_Internal(&invj[s*dim*dim], &j[s*dim*dim], detJ);
111: }
112: }
113: break;
114: case REFINER_HEX_3D:
115: /*
116: Bottom (viewed from top) Top
117: 1---------2---------2 7---------2---------6
118: | | | | | |
119: | B 2 C | | H 2 G |
120: | | | | | |
121: 3----3----0----1----1 3----3----0----1----1
122: | | | | | |
123: | A 0 D | | E 0 F |
124: | | | | | |
125: 0---------0---------3 4---------0---------5
126: */
127: break;
128: dim = 3;
129: if (numSubcells) *numSubcells = 8;
130: if (v0) {
131: PetscMalloc3(4*dim,&v,4*dim*dim,&j,4*dim*dim,&invj);
132: /* A */
133: v[0+0] = -1.0; v[0+1] = -1.0; v[0+2] = -1.0;
134: j[0+0] = 0.5; j[0+1] = 0.0; j[0+2] = 0.0;
135: j[0+3] = 0.0; j[0+4] = 0.5; j[0+5] = 0.0;
136: j[0+6] = 0.0; j[0+7] = 0.0; j[0+8] = 0.5;
137: /* B */
138: v[3+0] = -1.0; v[3+1] = 0.0; v[3+2] = -1.0;
139: j[9+0] = 0.5; j[9+1] = 0.0; j[9+2] = 0.0;
140: j[9+3] = 0.0; j[9+4] = 0.5; j[9+5] = 0.0;
141: j[9+6] = 0.0; j[9+7] = 0.0; j[9+8] = 0.5;
142: /* C */
143: v[6+0] = 0.0; v[6+1] = 0.0; v[6+2] = -1.0;
144: j[18+0] = 0.5; j[18+1] = 0.0; j[18+2] = 0.0;
145: j[18+3] = 0.0; j[18+4] = 0.5; j[18+5] = 0.0;
146: j[18+6] = 0.0; j[18+7] = 0.0; j[18+8] = 0.5;
147: /* D */
148: v[9+0] = 0.0; v[9+1] = -1.0; v[9+2] = -1.0;
149: j[27+0] = 0.5; j[27+1] = 0.0; j[27+2] = 0.0;
150: j[27+3] = 0.0; j[27+4] = 0.5; j[27+5] = 0.0;
151: j[27+6] = 0.0; j[27+7] = 0.0; j[27+8] = 0.5;
152: /* E */
153: v[12+0] = -1.0; v[12+1] = -1.0; v[12+2] = 0.0;
154: j[36+0] = 0.5; j[36+1] = 0.0; j[36+2] = 0.0;
155: j[36+3] = 0.0; j[36+4] = 0.5; j[36+5] = 0.0;
156: j[36+6] = 0.0; j[36+7] = 0.0; j[36+8] = 0.5;
157: /* F */
158: v[15+0] = 0.0; v[15+1] = -1.0; v[15+2] = 0.0;
159: j[45+0] = 0.5; j[45+1] = 0.0; j[45+2] = 0.0;
160: j[45+3] = 0.0; j[45+4] = 0.5; j[45+5] = 0.0;
161: j[45+6] = 0.0; j[45+7] = 0.0; j[45+8] = 0.5;
162: /* G */
163: v[18+0] = 0.0; v[18+1] = 0.0; v[18+2] = 0.0;
164: j[54+0] = 0.5; j[54+1] = 0.0; j[54+2] = 0.0;
165: j[54+3] = 0.0; j[54+4] = 0.5; j[54+5] = 0.0;
166: j[54+6] = 0.0; j[54+7] = 0.0; j[54+8] = 0.5;
167: /* H */
168: v[21+0] = -1.0; v[21+1] = 0.0; v[21+2] = 0.0;
169: j[63+0] = 0.5; j[63+1] = 0.0; j[63+2] = 0.0;
170: j[63+3] = 0.0; j[63+4] = 0.5; j[63+5] = 0.0;
171: j[63+6] = 0.0; j[63+7] = 0.0; j[63+8] = 0.5;
172: for (s = 0; s < 8; ++s) {
173: DMPlex_Det3D_Internal(&detJ, &j[s*dim*dim]);
174: DMPlex_Invert3D_Internal(&invj[s*dim*dim], &j[s*dim*dim], detJ);
175: }
176: }
177: default:
178: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
179: }
180: if (v0) {*v0 = v; *jac = j; *invjac = invj;}
181: return(0);
182: }
184: PetscErrorCode CellRefinerRestoreAffineTransforms_Internal(CellRefiner refiner, PetscInt *numSubcells, PetscReal *v0[], PetscReal *jac[], PetscReal *invjac[])
185: {
189: PetscFree3(*v0,*jac,*invjac);
190: return(0);
191: }
193: /* Should this be here or in the DualSpace somehow? */
194: PetscErrorCode CellRefinerInCellTest_Internal(CellRefiner refiner, const PetscReal point[], PetscBool *inside)
195: {
196: PetscReal sum = 0.0;
197: PetscInt d;
200: *inside = PETSC_TRUE;
201: switch (refiner) {
202: case REFINER_NOOP: break;
203: case REFINER_SIMPLEX_2D:
204: for (d = 0; d < 2; ++d) {
205: if (point[d] < -1.0) {*inside = PETSC_FALSE; break;}
206: sum += point[d];
207: }
208: if (sum > 1.0e-10) {*inside = PETSC_FALSE; break;}
209: break;
210: case REFINER_HEX_2D:
211: for (d = 0; d < 2; ++d) if ((point[d] < -1.00000000001) || (point[d] > 1.000000000001)) {*inside = PETSC_FALSE; break;}
212: break;
213: default:
214: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
215: }
216: return(0);
217: }
219: static PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[])
220: {
221: PetscInt cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax;
225: DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
226: DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);
227: DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
228: DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);
229: DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);
230: switch (refiner) {
231: case REFINER_NOOP:
232: break;
233: case REFINER_SIMPLEX_1D:
234: depthSize[0] = vEnd - vStart + cEnd - cStart; /* Add a vertex on every cell. */
235: depthSize[1] = 2*(cEnd - cStart); /* Split every cell in 2. */
236: break;
237: case REFINER_SIMPLEX_2D:
238: depthSize[0] = vEnd - vStart + fEnd - fStart; /* Add a vertex on every face */
239: depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */
240: depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */
241: break;
242: case REFINER_HYBRID_SIMPLEX_2D:
243: if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
244: if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
245: depthSize[0] = vEnd - vStart + fMax - fStart; /* Add a vertex on every face, but not hybrid faces */
246: depthSize[1] = 2*(fMax - fStart) + 3*(cMax - cStart) + (fEnd - fMax) + (cEnd - cMax); /* Every interior face is split into 2 faces, 3 faces are added for each interior cell, and one in each hybrid cell */
247: depthSize[2] = 4*(cMax - cStart) + 2*(cEnd - cMax); /* Interior cells split into 4 cells, Hybrid cells split into 2 cells */
248: break;
249: case REFINER_SIMPLEX_TO_HEX_2D:
250: depthSize[0] = vEnd - vStart + fEnd - fStart + cEnd - cStart; /* Add a vertex on every face and cell */
251: depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */
252: depthSize[2] = 3*(cEnd - cStart); /* Every cell split into 3 cells */
253: break;
254: case REFINER_HEX_2D:
255: depthSize[0] = vEnd - vStart + fEnd - fStart + cEnd - cStart; /* Add a vertex on every face and cell */
256: depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart); /* Every face is split into 2 faces and 4 faces are added for each cell */
257: depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */
258: break;
259: case REFINER_HYBRID_HEX_2D:
260: if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
261: if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
262: /* Quadrilateral */
263: depthSize[0] = vEnd - vStart + fMax - fStart + cMax - cStart; /* Add a vertex on every face and cell */
264: depthSize[1] = 2*(fMax - fStart) + 4*(cMax - cStart); /* Every face is split into 2 faces, and 4 faces are added for each cell */
265: depthSize[2] = 4*(cMax - cStart); /* Every cell split into 4 cells */
266: /* Segment Prisms */
267: depthSize[0] += 0; /* No hybrid vertices */
268: depthSize[1] += (fEnd - fMax) + (cEnd - cMax); /* Every hybrid face remains and 1 faces is added for each hybrid cell */
269: depthSize[2] += 2*(cEnd - cMax); /* Every hybrid cell split into 2 cells */
270: break;
271: case REFINER_SIMPLEX_3D:
272: depthSize[0] = vEnd - vStart + eEnd - eStart; /* Add a vertex on every edge */
273: depthSize[1] = 2*(eEnd - eStart) + 3*(fEnd - fStart) + (cEnd - cStart); /* Every edge is split into 2 edges, 3 edges are added for each face, and 1 edge for each cell */
274: depthSize[2] = 4*(fEnd - fStart) + 8*(cEnd - cStart); /* Every face split into 4 faces and 8 faces are added for each cell */
275: depthSize[3] = 8*(cEnd - cStart); /* Every cell split into 8 cells */
276: break;
277: case REFINER_HYBRID_SIMPLEX_3D:
278: if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
279: if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
280: if (eMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No edge maximum specified in hybrid mesh");
281: /* Tetrahedra */
282: depthSize[0] = vEnd - vStart + eMax - eStart; /* Add a vertex on every interior edge */
283: depthSize[1] = 2*(eMax - eStart) + 3*(fMax - fStart) + (cMax - cStart); /* Every interior edge split into 2 edges, 3 edges added for each interior face, 1 edge for each interior cell */
284: depthSize[2] = 4*(fMax - fStart) + 8*(cMax - cStart); /* Every interior face split into 4 faces, 8 faces added for each interior cell */
285: depthSize[3] = 8*(cMax - cStart); /* Every interior cell split into 8 cells */
286: /* Triangular Prisms */
287: depthSize[0] += 0; /* No hybrid vertices */
288: depthSize[1] += (eEnd - eMax) + (fEnd - fMax); /* Every hybrid edge remains, 1 edge for every hybrid face */
289: depthSize[2] += 2*(fEnd - fMax) + 3*(cEnd - cMax); /* Every hybrid face split into 2 faces and 3 faces are added for each hybrid cell */
290: depthSize[3] += 4*(cEnd - cMax); /* Every hybrid cell split into 4 cells */
291: break;
292: case REFINER_SIMPLEX_TO_HEX_3D:
293: depthSize[0] = vEnd - vStart + fEnd - fStart + eEnd - eStart + cEnd - cStart; /* Add a vertex on every face, edge and cell */
294: depthSize[1] = 2*(eEnd - eStart) + 3*(fEnd - fStart) + 4*(cEnd - cStart); /* Every edge is split into 2 edges, 3 edges are added for each face, and 4 for each cell */
295: depthSize[2] = 3*(fEnd - fStart) + 6*(cEnd - cStart); /* Every face is split into 3 faces and 6 faces are added for each cell */
296: depthSize[3] = 4*(cEnd - cStart); /* Every cell split into 4 cells */
297: break;
298: case REFINER_HEX_3D:
299: depthSize[0] = vEnd - vStart + eEnd - eStart + fEnd - fStart + cEnd - cStart; /* Add a vertex on every edge, face and cell */
300: depthSize[1] = 2*(eEnd - eStart) + 4*(fEnd - fStart) + 6*(cEnd - cStart); /* Every edge is split into 2 edge, 4 edges are added for each face, and 6 edges for each cell */
301: depthSize[2] = 4*(fEnd - fStart) + 12*(cEnd - cStart); /* Every face is split into 4 faces, and 12 faces are added for each cell */
302: depthSize[3] = 8*(cEnd - cStart); /* Every cell split into 8 cells */
303: break;
304: case REFINER_HYBRID_HEX_3D:
305: if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
306: if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
307: if (eMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No edge maximum specified in hybrid mesh");
308: /* Hexahedra */
309: depthSize[0] = vEnd - vStart + eMax - eStart + fMax - fStart + cMax - cStart; /* Add a vertex on every edge, face and cell */
310: depthSize[1] = 2*(eMax - eStart) + 4*(fMax - fStart) + 6*(cMax - cStart); /* Every edge is split into 2 edge, 4 edges are added for each face, and 6 edges for each cell */
311: depthSize[2] = 4*(fMax - fStart) + 12*(cMax - cStart); /* Every face is split into 4 faces, and 12 faces are added for each cell */
312: depthSize[3] = 8*(cMax - cStart); /* Every cell split into 8 cells */
313: /* Quadrilateral Prisms */
314: depthSize[0] += 0; /* No hybrid vertices */
315: depthSize[1] += (eEnd - eMax) + (fEnd - fMax) + (cEnd - cMax); /* Every hybrid edge remains, 1 edge for every hybrid face and hybrid cell */
316: depthSize[2] += 2*(fEnd - fMax) + 4*(cEnd - cMax); /* Every hybrid face split into 2 faces and 4 faces are added for each hybrid cell */
317: depthSize[3] += 4*(cEnd - cMax); /* Every hybrid cell split into 4 cells */
318: break;
319: default:
320: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
321: }
322: return(0);
323: }
325: /* Return triangle edge for orientation o, if it is r for o == 0 */
326: PETSC_STATIC_INLINE PetscInt GetTriEdge_Static(PetscInt o, PetscInt r) {
327: return (o < 0 ? 2-(o+r) : o+r)%3;
328: }
329: PETSC_STATIC_INLINE PetscInt GetTriEdgeInverse_Static(PetscInt o, PetscInt s) {
330: return (o < 0 ? 2-(o+s) : 3+s-o)%3;
331: }
333: /* Return triangle subface for orientation o, if it is r for o == 0 */
334: PETSC_STATIC_INLINE PetscInt GetTriSubface_Static(PetscInt o, PetscInt r) {
335: return (o < 0 ? 3-(o+r) : o+r)%3;
336: }
337: PETSC_STATIC_INLINE PetscInt GetTriSubfaceInverse_Static(PetscInt o, PetscInt s) {
338: return (o < 0 ? 3-(o+s) : 3+s-o)%3;
339: }
341: /* Return the interior edge number connecting the midpoints of the triangle edges r
342: and r+1 in the transitive closure for triangle orientation o */
343: PETSC_STATIC_INLINE PetscInt GetTriMidEdge_Static(PetscInt o, PetscInt r) {
344: return (o < 0 ? 1-(o+r) : o+r)%3;
345: }
346: PETSC_STATIC_INLINE PetscInt GetTriMidEdgeInverse_Static(PetscInt o, PetscInt s) {
347: return (o < 0 ? 1-(o+s) : 3+s-o)%3;
348: }
350: /* Return the interior edge number connecting the midpoint of the triangle edge r
351: (in the transitive closure) and the vertex in the interior of the face for triangle orientation o */
352: PETSC_STATIC_INLINE PetscInt GetTriInteriorEdge_Static(PetscInt o, PetscInt r) {
353: return (o < 0 ? 2-(o+r) : o+r)%3;
354: }
355: PETSC_STATIC_INLINE PetscInt GetTriInteriorEdgeInverse_Static(PetscInt o, PetscInt s) {
356: return (o < 0 ? 2-(o+s) : 3+s-o)%3;
357: }
359: /* Return quad edge for orientation o, if it is r for o == 0 */
360: PETSC_STATIC_INLINE PetscInt GetQuadEdge_Static(PetscInt o, PetscInt r) {
361: return (o < 0 ? 3-(o+r) : o+r)%4;
362: }
363: PETSC_STATIC_INLINE PetscInt GetQuadEdgeInverse_Static(PetscInt o, PetscInt s) {
364: return (o < 0 ? 3-(o+s) : 4+s-o)%4;
365: }
367: /* Return quad subface for orientation o, if it is r for o == 0 */
368: PETSC_STATIC_INLINE PetscInt GetQuadSubface_Static(PetscInt o, PetscInt r) {
369: return (o < 0 ? 4-(o+r) : o+r)%4;
370: }
371: PETSC_STATIC_INLINE PetscInt GetQuadSubfaceInverse_Static(PetscInt o, PetscInt s) {
372: return (o < 0 ? 4-(o+s) : 4+s-o)%4;
373: }
375: static PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
376: {
377: PetscInt depth, cStart, cStartNew, cEnd, cMax, c, vStart, vStartNew, vEnd, vMax, v, fStart, fStartNew, fEnd, fMax, f, eStart, eStartNew, eEnd, eMax, e, r;
381: if (!refiner) return(0);
382: DMPlexGetDepth(dm, &depth);
383: DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
384: DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);
385: DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
386: DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);
387: DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);
388: GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);
389: switch (refiner) {
390: case REFINER_SIMPLEX_1D:
391: /* All cells have 2 vertices */
392: for (c = cStart; c < cEnd; ++c) {
393: for (r = 0; r < 2; ++r) {
394: const PetscInt newp = cStartNew + (c - cStart)*2 + r;
396: DMPlexSetConeSize(rdm, newp, 2);
397: }
398: }
399: /* Old vertices have identical supports */
400: for (v = vStart; v < vEnd; ++v) {
401: const PetscInt newp = vStartNew + (v - vStart);
402: PetscInt size;
404: DMPlexGetSupportSize(dm, v, &size);
405: DMPlexSetSupportSize(rdm, newp, size);
406: }
407: /* Cell vertices have support 2 */
408: for (c = cStart; c < cEnd; ++c) {
409: const PetscInt newp = vStartNew + (vEnd - vStart) + (c - cStart);
411: DMPlexSetSupportSize(rdm, newp, 2);
412: }
413: break;
414: case REFINER_SIMPLEX_2D:
415: /* All cells have 3 faces */
416: for (c = cStart; c < cEnd; ++c) {
417: for (r = 0; r < 4; ++r) {
418: const PetscInt newp = (c - cStart)*4 + r;
420: DMPlexSetConeSize(rdm, newp, 3);
421: }
422: }
423: /* Split faces have 2 vertices and the same cells as the parent */
424: for (f = fStart; f < fEnd; ++f) {
425: for (r = 0; r < 2; ++r) {
426: const PetscInt newp = fStartNew + (f - fStart)*2 + r;
427: PetscInt size;
429: DMPlexSetConeSize(rdm, newp, 2);
430: DMPlexGetSupportSize(dm, f, &size);
431: DMPlexSetSupportSize(rdm, newp, size);
432: }
433: }
434: /* Interior faces have 2 vertices and 2 cells */
435: for (c = cStart; c < cEnd; ++c) {
436: for (r = 0; r < 3; ++r) {
437: const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r;
439: DMPlexSetConeSize(rdm, newp, 2);
440: DMPlexSetSupportSize(rdm, newp, 2);
441: }
442: }
443: /* Old vertices have identical supports */
444: for (v = vStart; v < vEnd; ++v) {
445: const PetscInt newp = vStartNew + (v - vStart);
446: PetscInt size;
448: DMPlexGetSupportSize(dm, v, &size);
449: DMPlexSetSupportSize(rdm, newp, size);
450: }
451: /* Face vertices have 2 + cells*2 supports */
452: for (f = fStart; f < fEnd; ++f) {
453: const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
454: PetscInt size;
456: DMPlexGetSupportSize(dm, f, &size);
457: DMPlexSetSupportSize(rdm, newp, 2 + size*2);
458: }
459: break;
460: case REFINER_SIMPLEX_TO_HEX_2D:
461: /* All cells have 4 faces */
462: for (c = cStart; c < cEnd; ++c) {
463: for (r = 0; r < 3; ++r) {
464: const PetscInt newp = (c - cStart)*3 + r;
466: DMPlexSetConeSize(rdm, newp, 4);
467: }
468: }
469: /* Split faces have 2 vertices and the same cells as the parent */
470: for (f = fStart; f < fEnd; ++f) {
471: for (r = 0; r < 2; ++r) {
472: const PetscInt newp = fStartNew + (f - fStart)*2 + r;
473: PetscInt size;
475: DMPlexSetConeSize(rdm, newp, 2);
476: DMPlexGetSupportSize(dm, f, &size);
477: DMPlexSetSupportSize(rdm, newp, size);
478: }
479: }
480: /* Interior faces have 2 vertices and 2 cells */
481: for (c = cStart; c < cEnd; ++c) {
482: for (r = 0; r < 3; ++r) {
483: const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r;
485: DMPlexSetConeSize(rdm, newp, 2);
486: DMPlexSetSupportSize(rdm, newp, 2);
487: }
488: }
489: /* Old vertices have identical supports */
490: for (v = vStart; v < vEnd; ++v) {
491: const PetscInt newp = vStartNew + (v - vStart);
492: PetscInt size;
494: DMPlexGetSupportSize(dm, v, &size);
495: DMPlexSetSupportSize(rdm, newp, size);
496: }
497: /* Split-face vertices have cells + 2 supports */
498: for (f = fStart; f < fEnd; ++f) {
499: const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
500: PetscInt size;
502: DMPlexGetSupportSize(dm, f, &size);
503: DMPlexSetSupportSize(rdm, newp, size + 2);
504: }
505: /* Interior vertices have 3 supports */
506: for (c = cStart; c < cEnd; ++c) {
507: const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + c - cStart;
509: DMPlexSetSupportSize(rdm, newp, 3);
510: }
511: break;
512: case REFINER_HEX_2D:
513: /* All cells have 4 faces */
514: for (c = cStart; c < cEnd; ++c) {
515: for (r = 0; r < 4; ++r) {
516: const PetscInt newp = cStartNew + (c - cStart)*4 + r;
518: DMPlexSetConeSize(rdm, newp, 4);
519: }
520: }
521: /* Split faces have 2 vertices and the same cells as the parent */
522: for (f = fStart; f < fEnd; ++f) {
523: for (r = 0; r < 2; ++r) {
524: const PetscInt newp = fStartNew + (f - fStart)*2 + r;
525: PetscInt size;
527: DMPlexSetConeSize(rdm, newp, 2);
528: DMPlexGetSupportSize(dm, f, &size);
529: DMPlexSetSupportSize(rdm, newp, size);
530: }
531: }
532: /* Interior faces have 2 vertices and 2 cells */
533: for (c = cStart; c < cEnd; ++c) {
534: for (r = 0; r < 4; ++r) {
535: const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r;
537: DMPlexSetConeSize(rdm, newp, 2);
538: DMPlexSetSupportSize(rdm, newp, 2);
539: }
540: }
541: /* Old vertices have identical supports */
542: for (v = vStart; v < vEnd; ++v) {
543: const PetscInt newp = vStartNew + (v - vStart);
544: PetscInt size;
546: DMPlexGetSupportSize(dm, v, &size);
547: DMPlexSetSupportSize(rdm, newp, size);
548: }
549: /* Face vertices have 2 + cells supports */
550: for (f = fStart; f < fEnd; ++f) {
551: const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
552: PetscInt size;
554: DMPlexGetSupportSize(dm, f, &size);
555: DMPlexSetSupportSize(rdm, newp, 2 + size);
556: }
557: /* Cell vertices have 4 supports */
558: for (c = cStart; c < cEnd; ++c) {
559: const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart);
561: DMPlexSetSupportSize(rdm, newp, 4);
562: }
563: break;
564: case REFINER_HYBRID_SIMPLEX_2D:
565: if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
566: cMax = PetscMin(cEnd, cMax);
567: if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
568: fMax = PetscMin(fEnd, fMax);
569: DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);
570: /* Interior cells have 3 faces */
571: for (c = cStart; c < cMax; ++c) {
572: for (r = 0; r < 4; ++r) {
573: const PetscInt newp = cStartNew + (c - cStart)*4 + r;
575: DMPlexSetConeSize(rdm, newp, 3);
576: }
577: }
578: /* Hybrid cells have 4 faces */
579: for (c = cMax; c < cEnd; ++c) {
580: for (r = 0; r < 2; ++r) {
581: const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r;
583: DMPlexSetConeSize(rdm, newp, 4);
584: }
585: }
586: /* Interior split faces have 2 vertices and the same cells as the parent */
587: for (f = fStart; f < fMax; ++f) {
588: for (r = 0; r < 2; ++r) {
589: const PetscInt newp = fStartNew + (f - fStart)*2 + r;
590: PetscInt size;
592: DMPlexSetConeSize(rdm, newp, 2);
593: DMPlexGetSupportSize(dm, f, &size);
594: DMPlexSetSupportSize(rdm, newp, size);
595: }
596: }
597: /* Interior cell faces have 2 vertices and 2 cells */
598: for (c = cStart; c < cMax; ++c) {
599: for (r = 0; r < 3; ++r) {
600: const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r;
602: DMPlexSetConeSize(rdm, newp, 2);
603: DMPlexSetSupportSize(rdm, newp, 2);
604: }
605: }
606: /* Hybrid faces have 2 vertices and the same cells */
607: for (f = fMax; f < fEnd; ++f) {
608: const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax);
609: PetscInt size;
611: DMPlexSetConeSize(rdm, newp, 2);
612: DMPlexGetSupportSize(dm, f, &size);
613: DMPlexSetSupportSize(rdm, newp, size);
614: }
615: /* Hybrid cell faces have 2 vertices and 2 cells */
616: for (c = cMax; c < cEnd; ++c) {
617: const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax);
619: DMPlexSetConeSize(rdm, newp, 2);
620: DMPlexSetSupportSize(rdm, newp, 2);
621: }
622: /* Old vertices have identical supports */
623: for (v = vStart; v < vEnd; ++v) {
624: const PetscInt newp = vStartNew + (v - vStart);
625: PetscInt size;
627: DMPlexGetSupportSize(dm, v, &size);
628: DMPlexSetSupportSize(rdm, newp, size);
629: }
630: /* Face vertices have 2 + (2 interior, 1 hybrid) supports */
631: for (f = fStart; f < fMax; ++f) {
632: const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
633: const PetscInt *support;
634: PetscInt size, newSize = 2, s;
636: DMPlexGetSupportSize(dm, f, &size);
637: DMPlexGetSupport(dm, f, &support);
638: for (s = 0; s < size; ++s) {
639: if (support[s] >= cMax) newSize += 1;
640: else newSize += 2;
641: }
642: DMPlexSetSupportSize(rdm, newp, newSize);
643: }
644: break;
645: case REFINER_HYBRID_HEX_2D:
646: if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
647: cMax = PetscMin(cEnd, cMax);
648: if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
649: fMax = PetscMin(fEnd, fMax);
650: DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4, PETSC_DETERMINE, PETSC_DETERMINE);
651: /* Interior cells have 4 faces */
652: for (c = cStart; c < cMax; ++c) {
653: for (r = 0; r < 4; ++r) {
654: const PetscInt newp = cStartNew + (c - cStart)*4 + r;
656: DMPlexSetConeSize(rdm, newp, 4);
657: }
658: }
659: /* Hybrid cells have 4 faces */
660: for (c = cMax; c < cEnd; ++c) {
661: for (r = 0; r < 2; ++r) {
662: const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r;
664: DMPlexSetConeSize(rdm, newp, 4);
665: }
666: }
667: /* Interior split faces have 2 vertices and the same cells as the parent */
668: for (f = fStart; f < fMax; ++f) {
669: for (r = 0; r < 2; ++r) {
670: const PetscInt newp = fStartNew + (f - fStart)*2 + r;
671: PetscInt size;
673: DMPlexSetConeSize(rdm, newp, 2);
674: DMPlexGetSupportSize(dm, f, &size);
675: DMPlexSetSupportSize(rdm, newp, size);
676: }
677: }
678: /* Interior cell faces have 2 vertices and 2 cells */
679: for (c = cStart; c < cMax; ++c) {
680: for (r = 0; r < 4; ++r) {
681: const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + r;
683: DMPlexSetConeSize(rdm, newp, 2);
684: DMPlexSetSupportSize(rdm, newp, 2);
685: }
686: }
687: /* Hybrid faces have 2 vertices and the same cells */
688: for (f = fMax; f < fEnd; ++f) {
689: const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (f - fMax);
690: PetscInt size;
692: DMPlexSetConeSize(rdm, newp, 2);
693: DMPlexGetSupportSize(dm, f, &size);
694: DMPlexSetSupportSize(rdm, newp, size);
695: }
696: /* Hybrid cell faces have 2 vertices and 2 cells */
697: for (c = cMax; c < cEnd; ++c) {
698: const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (fEnd - fMax) + (c - cMax);
700: DMPlexSetConeSize(rdm, newp, 2);
701: DMPlexSetSupportSize(rdm, newp, 2);
702: }
703: /* Old vertices have identical supports */
704: for (v = vStart; v < vEnd; ++v) {
705: const PetscInt newp = vStartNew + (v - vStart);
706: PetscInt size;
708: DMPlexGetSupportSize(dm, v, &size);
709: DMPlexSetSupportSize(rdm, newp, size);
710: }
711: /* Face vertices have 2 + cells supports */
712: for (f = fStart; f < fMax; ++f) {
713: const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
714: PetscInt size;
716: DMPlexGetSupportSize(dm, f, &size);
717: DMPlexSetSupportSize(rdm, newp, 2 + size);
718: }
719: /* Cell vertices have 4 supports */
720: for (c = cStart; c < cMax; ++c) {
721: const PetscInt newp = vStartNew + (vEnd - vStart) + (fMax - fStart) + (c - cStart);
723: DMPlexSetSupportSize(rdm, newp, 4);
724: }
725: break;
726: case REFINER_SIMPLEX_3D:
727: /* All cells have 4 faces */
728: for (c = cStart; c < cEnd; ++c) {
729: for (r = 0; r < 8; ++r) {
730: const PetscInt newp = cStartNew + (c - cStart)*8 + r;
732: DMPlexSetConeSize(rdm, newp, 4);
733: }
734: }
735: /* Split faces have 3 edges and the same cells as the parent */
736: for (f = fStart; f < fEnd; ++f) {
737: for (r = 0; r < 4; ++r) {
738: const PetscInt newp = fStartNew + (f - fStart)*4 + r;
739: PetscInt size;
741: DMPlexSetConeSize(rdm, newp, 3);
742: DMPlexGetSupportSize(dm, f, &size);
743: DMPlexSetSupportSize(rdm, newp, size);
744: }
745: }
746: /* Interior cell faces have 3 edges and 2 cells */
747: for (c = cStart; c < cEnd; ++c) {
748: for (r = 0; r < 8; ++r) {
749: const PetscInt newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + r;
751: DMPlexSetConeSize(rdm, newp, 3);
752: DMPlexSetSupportSize(rdm, newp, 2);
753: }
754: }
755: /* Split edges have 2 vertices and the same faces */
756: for (e = eStart; e < eEnd; ++e) {
757: for (r = 0; r < 2; ++r) {
758: const PetscInt newp = eStartNew + (e - eStart)*2 + r;
759: PetscInt size;
761: DMPlexSetConeSize(rdm, newp, 2);
762: DMPlexGetSupportSize(dm, e, &size);
763: DMPlexSetSupportSize(rdm, newp, size);
764: }
765: }
766: /* Face edges have 2 vertices and 2+cells*(1/2) faces */
767: for (f = fStart; f < fEnd; ++f) {
768: for (r = 0; r < 3; ++r) {
769: const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + r;
770: const PetscInt *cone, *ornt, *support, eint[4] = {1, 0, 2, 0};
771: PetscInt coneSize, c, supportSize, s, er, intFaces = 0;
773: DMPlexSetConeSize(rdm, newp, 2);
774: DMPlexGetSupportSize(dm, f, &supportSize);
775: DMPlexGetSupport(dm, f, &support);
776: for (s = 0; s < supportSize; ++s) {
777: DMPlexGetConeSize(dm, support[s], &coneSize);
778: DMPlexGetCone(dm, support[s], &cone);
779: DMPlexGetConeOrientation(dm, support[s], &ornt);
780: for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
781: /* Here we want to determine whether edge newp contains a vertex which is part of the cross-tet edge */
782: er = GetTriMidEdgeInverse_Static(ornt[c], r);
783: if (er == eint[c]) {
784: intFaces += 1;
785: } else {
786: intFaces += 2;
787: }
788: }
789: DMPlexSetSupportSize(rdm, newp, 2+intFaces);
790: }
791: }
792: /* Interior cell edges have 2 vertices and 4 faces */
793: for (c = cStart; c < cEnd; ++c) {
794: const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
796: DMPlexSetConeSize(rdm, newp, 2);
797: DMPlexSetSupportSize(rdm, newp, 4);
798: }
799: /* Old vertices have identical supports */
800: for (v = vStart; v < vEnd; ++v) {
801: const PetscInt newp = vStartNew + (v - vStart);
802: PetscInt size;
804: DMPlexGetSupportSize(dm, v, &size);
805: DMPlexSetSupportSize(rdm, newp, size);
806: }
807: /* Edge vertices have 2 + faces*2 + cells*0/1 supports */
808: for (e = eStart; e < eEnd; ++e) {
809: const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
810: PetscInt size, *star = NULL, starSize, s, cellSize = 0;
812: DMPlexGetSupportSize(dm, e, &size);
813: DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
814: for (s = 0; s < starSize*2; s += 2) {
815: const PetscInt *cone, *ornt;
816: PetscInt e01, e23;
818: if ((star[s] >= cStart) && (star[s] < cEnd)) {
819: /* Check edge 0-1 */
820: DMPlexGetCone(dm, star[s], &cone);
821: DMPlexGetConeOrientation(dm, star[s], &ornt);
822: DMPlexGetCone(dm, cone[0], &cone);
823: e01 = cone[GetTriEdge_Static(ornt[0], 0)];
824: /* Check edge 2-3 */
825: DMPlexGetCone(dm, star[s], &cone);
826: DMPlexGetConeOrientation(dm, star[s], &ornt);
827: DMPlexGetCone(dm, cone[2], &cone);
828: e23 = cone[GetTriEdge_Static(ornt[2], 1)];
829: if ((e01 == e) || (e23 == e)) ++cellSize;
830: }
831: }
832: DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
833: DMPlexSetSupportSize(rdm, newp, 2 + size*2 + cellSize);
834: }
835: break;
836: case REFINER_HYBRID_SIMPLEX_3D:
837: DMPlexSetHybridBounds(rdm, cStartNew + 8*(cMax-cStart), fStartNew + 4*(fMax - fStart) + 8*(cMax - cStart),
838: eStartNew + 2*(eMax - eStart) + 3*(fMax - fStart) + (cMax - cStart), PETSC_DETERMINE);
839: /* Interior cells have 4 faces */
840: for (c = cStart; c < cMax; ++c) {
841: for (r = 0; r < 8; ++r) {
842: const PetscInt newp = cStartNew + (c - cStart)*8 + r;
844: DMPlexSetConeSize(rdm, newp, 4);
845: }
846: }
847: /* Hybrid cells have 5 faces */
848: for (c = cMax; c < cEnd; ++c) {
849: for (r = 0; r < 4; ++r) {
850: const PetscInt newp = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + r;
852: DMPlexSetConeSize(rdm, newp, 5);
853: }
854: }
855: /* Interior split faces have 3 edges and the same cells as the parent */
856: for (f = fStart; f < fMax; ++f) {
857: for (r = 0; r < 4; ++r) {
858: const PetscInt newp = fStartNew + (f - fStart)*4 + r;
859: PetscInt size;
861: DMPlexSetConeSize(rdm, newp, 3);
862: DMPlexGetSupportSize(dm, f, &size);
863: DMPlexSetSupportSize(rdm, newp, size);
864: }
865: }
866: /* Interior cell faces have 3 edges and 2 cells */
867: for (c = cStart; c < cMax; ++c) {
868: for (r = 0; r < 8; ++r) {
869: const PetscInt newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + r;
871: DMPlexSetConeSize(rdm, newp, 3);
872: DMPlexSetSupportSize(rdm, newp, 2);
873: }
874: }
875: /* Hybrid split faces have 4 edges and the same cells as the parent */
876: for (f = fMax; f < fEnd; ++f) {
877: for (r = 0; r < 2; ++r) {
878: const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (f - fMax)*2 + r;
879: PetscInt size;
881: DMPlexSetConeSize(rdm, newp, 4);
882: DMPlexGetSupportSize(dm, f, &size);
883: DMPlexSetSupportSize(rdm, newp, size);
884: }
885: }
886: /* Hybrid cells faces have 4 edges and 2 cells */
887: for (c = cMax; c < cEnd; ++c) {
888: for (r = 0; r < 3; ++r) {
889: const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + r;
891: DMPlexSetConeSize(rdm, newp, 4);
892: DMPlexSetSupportSize(rdm, newp, 2);
893: }
894: }
895: /* Interior split edges have 2 vertices and the same faces */
896: for (e = eStart; e < eMax; ++e) {
897: for (r = 0; r < 2; ++r) {
898: const PetscInt newp = eStartNew + (e - eStart)*2 + r;
899: PetscInt size;
901: DMPlexSetConeSize(rdm, newp, 2);
902: DMPlexGetSupportSize(dm, e, &size);
903: DMPlexSetSupportSize(rdm, newp, size);
904: }
905: }
906: /* Interior face edges have 2 vertices and 2+cells*(1/2) faces */
907: for (f = fStart; f < fMax; ++f) {
908: for (r = 0; r < 3; ++r) {
909: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + r;
910: const PetscInt *cone, *ornt, *support, eint[4] = {1, 0, 2, 0};
911: PetscInt coneSize, c, supportSize, s, er, intFaces = 0;
913: DMPlexSetConeSize(rdm, newp, 2);
914: DMPlexGetSupportSize(dm, f, &supportSize);
915: DMPlexGetSupport(dm, f, &support);
916: for (s = 0; s < supportSize; ++s) {
917: DMPlexGetConeSize(dm, support[s], &coneSize);
918: DMPlexGetCone(dm, support[s], &cone);
919: DMPlexGetConeOrientation(dm, support[s], &ornt);
920: for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
921: if (support[s] < cMax) {
922: /* Here we want to determine whether edge newp contains a vertex which is part of the cross-tet edge */
923: er = GetTriMidEdgeInverse_Static(ornt[c], r);
924: if (er == eint[c]) {
925: intFaces += 1;
926: } else {
927: intFaces += 2;
928: }
929: } else {
930: intFaces += 1;
931: }
932: }
933: DMPlexSetSupportSize(rdm, newp, 2+intFaces);
934: }
935: }
936: /* Interior cell edges have 2 vertices and 4 faces */
937: for (c = cStart; c < cMax; ++c) {
938: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
940: DMPlexSetConeSize(rdm, newp, 2);
941: DMPlexSetSupportSize(rdm, newp, 4);
942: }
943: /* Hybrid edges have 2 vertices and the same faces */
944: for (e = eMax; e < eEnd; ++e) {
945: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (e - eMax);
946: PetscInt size;
948: DMPlexSetConeSize(rdm, newp, 2);
949: DMPlexGetSupportSize(dm, e, &size);
950: DMPlexSetSupportSize(rdm, newp, size);
951: }
952: /* Hybrid face edges have 2 vertices and 2+2*cells faces */
953: for (f = fMax; f < fEnd; ++f) {
954: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (f - fMax);
955: PetscInt size;
957: DMPlexSetConeSize(rdm, newp, 2);
958: DMPlexGetSupportSize(dm, f, &size);
959: DMPlexSetSupportSize(rdm, newp, 2+2*size);
960: }
961: /* Interior vertices have identical supports */
962: for (v = vStart; v < vEnd; ++v) {
963: const PetscInt newp = vStartNew + (v - vStart);
964: PetscInt size;
966: DMPlexGetSupportSize(dm, v, &size);
967: DMPlexSetSupportSize(rdm, newp, size);
968: }
969: /* Interior edge vertices have 2 + interior face*2 + hybrid face + cells*0/1 supports */
970: for (e = eStart; e < eMax; ++e) {
971: const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
972: const PetscInt *support;
973: PetscInt size, *star = NULL, starSize, s, faceSize = 0, cellSize = 0;
975: DMPlexGetSupportSize(dm, e, &size);
976: DMPlexGetSupport(dm, e, &support);
977: for (s = 0; s < size; ++s) {
978: if (support[s] < fMax) faceSize += 2;
979: else faceSize += 1;
980: }
981: DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
982: for (s = 0; s < starSize*2; s += 2) {
983: const PetscInt *cone, *ornt;
984: PetscInt e01, e23;
986: if ((star[s] >= cStart) && (star[s] < cMax)) {
987: /* Check edge 0-1 */
988: DMPlexGetCone(dm, star[s], &cone);
989: DMPlexGetConeOrientation(dm, star[s], &ornt);
990: DMPlexGetCone(dm, cone[0], &cone);
991: e01 = cone[GetTriEdge_Static(ornt[0], 0)];
992: /* Check edge 2-3 */
993: DMPlexGetCone(dm, star[s], &cone);
994: DMPlexGetConeOrientation(dm, star[s], &ornt);
995: DMPlexGetCone(dm, cone[2], &cone);
996: e23 = cone[GetTriEdge_Static(ornt[2], 1)];
997: if ((e01 == e) || (e23 == e)) ++cellSize;
998: }
999: }
1000: DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
1001: DMPlexSetSupportSize(rdm, newp, 2 + faceSize + cellSize);
1002: }
1003: break;
1004: case REFINER_SIMPLEX_TO_HEX_3D:
1005: /* All cells have 6 faces */
1006: for (c = cStart; c < cEnd; ++c) {
1007: for (r = 0; r < 4; ++r) {
1008: const PetscInt newp = cStartNew + (c - cStart)*4 + r;
1010: DMPlexSetConeSize(rdm, newp, 6);
1011: }
1012: }
1013: /* Split faces have 4 edges and the same cells as the parent */
1014: for (f = fStart; f < fEnd; ++f) {
1015: for (r = 0; r < 3; ++r) {
1016: const PetscInt newp = fStartNew + (f - fStart)*3 + r;
1017: PetscInt size;
1019: DMPlexSetConeSize(rdm, newp, 4);
1020: DMPlexGetSupportSize(dm, f, &size);
1021: DMPlexSetSupportSize(rdm, newp, size);
1022: }
1023: }
1024: /* Interior cell faces have 4 edges and 2 cells */
1025: for (c = cStart; c < cEnd; ++c) {
1026: for (r = 0; r < 6; ++r) {
1027: const PetscInt newp = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + r;
1029: DMPlexSetConeSize(rdm, newp, 4);
1030: DMPlexSetSupportSize(rdm, newp, 2);
1031: }
1032: }
1033: /* Split edges have 2 vertices and the same faces */
1034: for (e = eStart; e < eEnd; ++e) {
1035: for (r = 0; r < 2; ++r) {
1036: const PetscInt newp = eStartNew + (e - eStart)*2 + r;
1037: PetscInt size;
1039: DMPlexSetConeSize(rdm, newp, 2);
1040: DMPlexGetSupportSize(dm, e, &size);
1041: DMPlexSetSupportSize(rdm, newp, size);
1042: }
1043: }
1044: /* Face edges have 2 vertices and 2 + cell faces supports */
1045: for (f = fStart; f < fEnd; ++f) {
1046: for (r = 0; r < 3; ++r) {
1047: const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + r;
1048: PetscInt size;
1050: DMPlexSetConeSize(rdm, newp, 2);
1051: DMPlexGetSupportSize(dm, f, &size);
1052: DMPlexSetSupportSize(rdm, newp, 2+size);
1053: }
1054: }
1055: /* Interior cell edges have 2 vertices and 3 faces */
1056: for (c = cStart; c < cEnd; ++c) {
1057: for (r = 0; r < 4; ++r) {
1058: const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + r;
1060: DMPlexSetConeSize(rdm, newp, 2);
1061: DMPlexSetSupportSize(rdm, newp, 3);
1062: }
1063: }
1064: /* Old vertices have identical supports */
1065: for (v = vStart; v < vEnd; ++v) {
1066: const PetscInt newp = vStartNew + (v - vStart);
1067: PetscInt size;
1069: DMPlexGetSupportSize(dm, v, &size);
1070: DMPlexSetSupportSize(rdm, newp, size);
1071: }
1072: /* Edge vertices have 2 + faces supports */
1073: for (e = eStart; e < eEnd; ++e) {
1074: const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
1075: PetscInt size;
1077: DMPlexGetSupportSize(dm, e, &size);
1078: DMPlexSetSupportSize(rdm, newp, 2 + size);
1079: }
1080: /* Face vertices have 3 + cells supports */
1081: for (f = fStart; f < fEnd; ++f) {
1082: const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + f - fStart;
1083: PetscInt size;
1085: DMPlexGetSupportSize(dm, f, &size);
1086: DMPlexSetSupportSize(rdm, newp, 3 + size);
1087: }
1088: /* Interior cell vertices have 4 supports */
1089: for (c = cStart; c < cEnd; ++c) {
1090: const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + fEnd - fStart + c - cStart;
1092: DMPlexSetSupportSize(rdm, newp, 4);
1093: }
1094: break;
1095: case REFINER_HEX_3D:
1096: /* All cells have 6 faces */
1097: for (c = cStart; c < cEnd; ++c) {
1098: for (r = 0; r < 8; ++r) {
1099: const PetscInt newp = (c - cStart)*8 + r;
1101: DMPlexSetConeSize(rdm, newp, 6);
1102: }
1103: }
1104: /* Split faces have 4 edges and the same cells as the parent */
1105: for (f = fStart; f < fEnd; ++f) {
1106: for (r = 0; r < 4; ++r) {
1107: const PetscInt newp = fStartNew + (f - fStart)*4 + r;
1108: PetscInt size;
1110: DMPlexSetConeSize(rdm, newp, 4);
1111: DMPlexGetSupportSize(dm, f, &size);
1112: DMPlexSetSupportSize(rdm, newp, size);
1113: }
1114: }
1115: /* Interior faces have 4 edges and 2 cells */
1116: for (c = cStart; c < cEnd; ++c) {
1117: for (r = 0; r < 12; ++r) {
1118: const PetscInt newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + r;
1120: DMPlexSetConeSize(rdm, newp, 4);
1121: DMPlexSetSupportSize(rdm, newp, 2);
1122: }
1123: }
1124: /* Split edges have 2 vertices and the same faces as the parent */
1125: for (e = eStart; e < eEnd; ++e) {
1126: for (r = 0; r < 2; ++r) {
1127: const PetscInt newp = eStartNew + (e - eStart)*2 + r;
1128: PetscInt size;
1130: DMPlexSetConeSize(rdm, newp, 2);
1131: DMPlexGetSupportSize(dm, e, &size);
1132: DMPlexSetSupportSize(rdm, newp, size);
1133: }
1134: }
1135: /* Face edges have 2 vertices and 2+cells faces */
1136: for (f = fStart; f < fEnd; ++f) {
1137: for (r = 0; r < 4; ++r) {
1138: const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + r;
1139: PetscInt size;
1141: DMPlexSetConeSize(rdm, newp, 2);
1142: DMPlexGetSupportSize(dm, f, &size);
1143: DMPlexSetSupportSize(rdm, newp, 2+size);
1144: }
1145: }
1146: /* Cell edges have 2 vertices and 4 faces */
1147: for (c = cStart; c < cEnd; ++c) {
1148: for (r = 0; r < 6; ++r) {
1149: const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + r;
1151: DMPlexSetConeSize(rdm, newp, 2);
1152: DMPlexSetSupportSize(rdm, newp, 4);
1153: }
1154: }
1155: /* Old vertices have identical supports */
1156: for (v = vStart; v < vEnd; ++v) {
1157: const PetscInt newp = vStartNew + (v - vStart);
1158: PetscInt size;
1160: DMPlexGetSupportSize(dm, v, &size);
1161: DMPlexSetSupportSize(rdm, newp, size);
1162: }
1163: /* Edge vertices have 2 + faces supports */
1164: for (e = eStart; e < eEnd; ++e) {
1165: const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
1166: PetscInt size;
1168: DMPlexGetSupportSize(dm, e, &size);
1169: DMPlexSetSupportSize(rdm, newp, 2 + size);
1170: }
1171: /* Face vertices have 4 + cells supports */
1172: for (f = fStart; f < fEnd; ++f) {
1173: const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (f - fStart);
1174: PetscInt size;
1176: DMPlexGetSupportSize(dm, f, &size);
1177: DMPlexSetSupportSize(rdm, newp, 4 + size);
1178: }
1179: /* Cell vertices have 6 supports */
1180: for (c = cStart; c < cEnd; ++c) {
1181: const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (c - cStart);
1183: DMPlexSetSupportSize(rdm, newp, 6);
1184: }
1185: break;
1186: case REFINER_HYBRID_HEX_3D:
1187: DMPlexSetHybridBounds(rdm, cStartNew + 8*(cMax-cStart), fStartNew + 4*(fMax - fStart) + 12*(cMax - cStart),
1188: eStartNew + 2*(eMax - eStart) + 4*(fMax - fStart) + 6*(cMax - cStart), PETSC_DETERMINE);
1189: /* Interior cells have 6 faces */
1190: for (c = cStart; c < cMax; ++c) {
1191: for (r = 0; r < 8; ++r) {
1192: const PetscInt newp = cStartNew + (c - cStart)*8 + r;
1194: DMPlexSetConeSize(rdm, newp, 6);
1195: }
1196: }
1197: /* Hybrid cells have 6 faces */
1198: for (c = cMax; c < cEnd; ++c) {
1199: for (r = 0; r < 4; ++r) {
1200: const PetscInt newp = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + r;
1202: DMPlexSetConeSize(rdm, newp, 6);
1203: }
1204: }
1205: /* Interior split faces have 4 edges and the same cells as the parent */
1206: for (f = fStart; f < fMax; ++f) {
1207: for (r = 0; r < 4; ++r) {
1208: const PetscInt newp = fStartNew + (f - fStart)*4 + r;
1209: PetscInt size;
1211: DMPlexSetConeSize(rdm, newp, 4);
1212: DMPlexGetSupportSize(dm, f, &size);
1213: DMPlexSetSupportSize(rdm, newp, size);
1214: }
1215: }
1216: /* Interior cell faces have 4 edges and 2 cells */
1217: for (c = cStart; c < cMax; ++c) {
1218: for (r = 0; r < 12; ++r) {
1219: const PetscInt newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + r;
1221: DMPlexSetConeSize(rdm, newp, 4);
1222: DMPlexSetSupportSize(rdm, newp, 2);
1223: }
1224: }
1225: /* Hybrid split faces have 4 edges and the same cells as the parent */
1226: for (f = fMax; f < fEnd; ++f) {
1227: for (r = 0; r < 2; ++r) {
1228: const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (f - fMax)*2 + r;
1229: PetscInt size;
1231: DMPlexSetConeSize(rdm, newp, 4);
1232: DMPlexGetSupportSize(dm, f, &size);
1233: DMPlexSetSupportSize(rdm, newp, size);
1234: }
1235: }
1236: /* Hybrid cells faces have 4 edges and 2 cells */
1237: for (c = cMax; c < cEnd; ++c) {
1238: for (r = 0; r < 4; ++r) {
1239: const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + r;
1241: DMPlexSetConeSize(rdm, newp, 4);
1242: DMPlexSetSupportSize(rdm, newp, 2);
1243: }
1244: }
1245: /* Interior split edges have 2 vertices and the same faces as the parent */
1246: for (e = eStart; e < eMax; ++e) {
1247: for (r = 0; r < 2; ++r) {
1248: const PetscInt newp = eStartNew + (e - eStart)*2 + r;
1249: PetscInt size;
1251: DMPlexSetConeSize(rdm, newp, 2);
1252: DMPlexGetSupportSize(dm, e, &size);
1253: DMPlexSetSupportSize(rdm, newp, size);
1254: }
1255: }
1256: /* Interior face edges have 2 vertices and 2+cells faces */
1257: for (f = fStart; f < fMax; ++f) {
1258: for (r = 0; r < 4; ++r) {
1259: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (f - fStart)*4 + r;
1260: PetscInt size;
1262: DMPlexSetConeSize(rdm, newp, 2);
1263: DMPlexGetSupportSize(dm, f, &size);
1264: DMPlexSetSupportSize(rdm, newp, 2+size);
1265: }
1266: }
1267: /* Interior cell edges have 2 vertices and 4 faces */
1268: for (c = cStart; c < cMax; ++c) {
1269: for (r = 0; r < 6; ++r) {
1270: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + r;
1272: DMPlexSetConeSize(rdm, newp, 2);
1273: DMPlexSetSupportSize(rdm, newp, 4);
1274: }
1275: }
1276: /* Hybrid edges have 2 vertices and the same faces */
1277: for (e = eMax; e < eEnd; ++e) {
1278: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (e - eMax);
1279: PetscInt size;
1281: DMPlexSetConeSize(rdm, newp, 2);
1282: DMPlexGetSupportSize(dm, e, &size);
1283: DMPlexSetSupportSize(rdm, newp, size);
1284: }
1285: /* Hybrid face edges have 2 vertices and 2+cells faces */
1286: for (f = fMax; f < fEnd; ++f) {
1287: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (f - fMax);
1288: PetscInt size;
1290: DMPlexSetConeSize(rdm, newp, 2);
1291: DMPlexGetSupportSize(dm, f, &size);
1292: DMPlexSetSupportSize(rdm, newp, 2+size);
1293: }
1294: /* Hybrid cell edges have 2 vertices and 4 faces */
1295: for (c = cMax; c < cEnd; ++c) {
1296: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (fEnd - fMax) + (c - cMax);
1298: DMPlexSetConeSize(rdm, newp, 2);
1299: DMPlexSetSupportSize(rdm, newp, 4);
1300: }
1301: /* Interior vertices have identical supports */
1302: for (v = vStart; v < vEnd; ++v) {
1303: const PetscInt newp = vStartNew + (v - vStart);
1304: PetscInt size;
1306: DMPlexGetSupportSize(dm, v, &size);
1307: DMPlexSetSupportSize(rdm, newp, size);
1308: }
1309: /* Interior edge vertices have 2 + faces supports */
1310: for (e = eStart; e < eMax; ++e) {
1311: const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
1312: PetscInt size;
1314: DMPlexGetSupportSize(dm, e, &size);
1315: DMPlexSetSupportSize(rdm, newp, 2 + size);
1316: }
1317: /* Interior face vertices have 4 + cells supports */
1318: for (f = fStart; f < fMax; ++f) {
1319: const PetscInt newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (f - fStart);
1320: PetscInt size;
1322: DMPlexGetSupportSize(dm, f, &size);
1323: DMPlexSetSupportSize(rdm, newp, 4 + size);
1324: }
1325: /* Interior cell vertices have 6 supports */
1326: for (c = cStart; c < cMax; ++c) {
1327: const PetscInt newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (fMax - fStart) + (c - cStart);
1329: DMPlexSetSupportSize(rdm, newp, 6);
1330: }
1331: break;
1332: default:
1333: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
1334: }
1335: return(0);
1336: }
1338: static PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
1339: {
1340: const PetscInt *faces, cellInd[4] = {0, 1, 2, 3};
1341: PetscInt cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax;
1342: PetscInt cStartNew, cEndNew, cMaxNew, vStartNew, vEndNew, fStartNew, fEndNew, fMaxNew, eStartNew, eEndNew, eMaxNew;
1343: PetscInt depth, maxSupportSize, *supportRef, c, f, e, v, r, p;
1344: PetscErrorCode ierr;
1347: if (!refiner) return(0);
1348: DMPlexGetDepth(dm, &depth);
1349: DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
1350: DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);
1351: DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
1352: DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);
1353: DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);
1354: GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);
1355: GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);
1356: switch (refiner) {
1357: case REFINER_SIMPLEX_1D:
1358: /* Max support size of refined mesh is 2 */
1359: PetscMalloc1(2, &supportRef);
1360: /* All cells have 2 vertices */
1361: for (c = cStart; c < cEnd; ++c) {
1362: const PetscInt newv = vStartNew + (vEnd - vStart) + (c - cStart);
1364: for (r = 0; r < 2; ++r) {
1365: const PetscInt newp = cStartNew + (c - cStart)*2 + r;
1366: const PetscInt *cone;
1367: PetscInt coneNew[2];
1369: DMPlexGetCone(dm, c, &cone);
1370: coneNew[0] = vStartNew + (cone[0] - vStart);
1371: coneNew[1] = vStartNew + (cone[1] - vStart);
1372: coneNew[(r+1)%2] = newv;
1373: DMPlexSetCone(rdm, newp, coneNew);
1374: #if 1
1375: if ((newp < cStartNew) || (newp >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp, cStartNew, cEndNew);
1376: for (p = 0; p < 2; ++p) {
1377: if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
1378: }
1379: #endif
1380: }
1381: }
1382: /* Old vertices have identical supports */
1383: for (v = vStart; v < vEnd; ++v) {
1384: const PetscInt newp = vStartNew + (v - vStart);
1385: const PetscInt *support, *cone;
1386: PetscInt size, s;
1388: DMPlexGetSupportSize(dm, v, &size);
1389: DMPlexGetSupport(dm, v, &support);
1390: for (s = 0; s < size; ++s) {
1391: PetscInt r = 0;
1393: DMPlexGetCone(dm, support[s], &cone);
1394: if (cone[1] == v) r = 1;
1395: supportRef[s] = cStartNew + (support[s] - cStart)*2 + r;
1396: }
1397: DMPlexSetSupport(rdm, newp, supportRef);
1398: #if 1
1399: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
1400: for (p = 0; p < size; ++p) {
1401: if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew);
1402: }
1403: #endif
1404: }
1405: /* Cell vertices have support of 2 cells */
1406: for (c = cStart; c < cEnd; ++c) {
1407: const PetscInt newp = vStartNew + (vEnd - vStart) + (c - cStart);
1409: supportRef[0] = cStartNew + (c - cStart)*2 + 0;
1410: supportRef[1] = cStartNew + (c - cStart)*2 + 1;
1411: DMPlexSetSupport(rdm, newp, supportRef);
1412: #if 1
1413: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
1414: for (p = 0; p < 2; ++p) {
1415: if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew);
1416: }
1417: #endif
1418: }
1419: PetscFree(supportRef);
1420: break;
1421: case REFINER_SIMPLEX_2D:
1422: /*
1423: 2
1424: |\
1425: | \
1426: | \
1427: | \
1428: | C \
1429: | \
1430: | \
1431: 2---1---1
1432: |\ D / \
1433: | 2 0 \
1434: |A \ / B \
1435: 0---0-------1
1436: */
1437: /* All cells have 3 faces */
1438: for (c = cStart; c < cEnd; ++c) {
1439: const PetscInt newp = cStartNew + (c - cStart)*4;
1440: const PetscInt *cone, *ornt;
1441: PetscInt coneNew[3], orntNew[3];
1443: DMPlexGetCone(dm, c, &cone);
1444: DMPlexGetConeOrientation(dm, c, &ornt);
1445: /* A triangle */
1446: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
1447: orntNew[0] = ornt[0];
1448: coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2;
1449: orntNew[1] = -2;
1450: coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
1451: orntNew[2] = ornt[2];
1452: DMPlexSetCone(rdm, newp+0, coneNew);
1453: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
1454: #if 1
1455: if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew);
1456: for (p = 0; p < 3; ++p) {
1457: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
1458: }
1459: #endif
1460: /* B triangle */
1461: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
1462: orntNew[0] = ornt[0];
1463: coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
1464: orntNew[1] = ornt[1];
1465: coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0;
1466: orntNew[2] = -2;
1467: DMPlexSetCone(rdm, newp+1, coneNew);
1468: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
1469: #if 1
1470: if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew);
1471: for (p = 0; p < 3; ++p) {
1472: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
1473: }
1474: #endif
1475: /* C triangle */
1476: coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1;
1477: orntNew[0] = -2;
1478: coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
1479: orntNew[1] = ornt[1];
1480: coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
1481: orntNew[2] = ornt[2];
1482: DMPlexSetCone(rdm, newp+2, coneNew);
1483: DMPlexSetConeOrientation(rdm, newp+2, orntNew);
1484: #if 1
1485: if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew);
1486: for (p = 0; p < 3; ++p) {
1487: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
1488: }
1489: #endif
1490: /* D triangle */
1491: coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0;
1492: orntNew[0] = 0;
1493: coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1;
1494: orntNew[1] = 0;
1495: coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2;
1496: orntNew[2] = 0;
1497: DMPlexSetCone(rdm, newp+3, coneNew);
1498: DMPlexSetConeOrientation(rdm, newp+3, orntNew);
1499: #if 1
1500: if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew);
1501: for (p = 0; p < 3; ++p) {
1502: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
1503: }
1504: #endif
1505: }
1506: /* Split faces have 2 vertices and the same cells as the parent */
1507: DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
1508: PetscMalloc1(2 + maxSupportSize*2, &supportRef);
1509: for (f = fStart; f < fEnd; ++f) {
1510: const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
1512: for (r = 0; r < 2; ++r) {
1513: const PetscInt newp = fStartNew + (f - fStart)*2 + r;
1514: const PetscInt *cone, *ornt, *support;
1515: PetscInt coneNew[2], coneSize, c, supportSize, s;
1517: DMPlexGetCone(dm, f, &cone);
1518: coneNew[0] = vStartNew + (cone[0] - vStart);
1519: coneNew[1] = vStartNew + (cone[1] - vStart);
1520: coneNew[(r+1)%2] = newv;
1521: DMPlexSetCone(rdm, newp, coneNew);
1522: #if 1
1523: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1524: for (p = 0; p < 2; ++p) {
1525: if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
1526: }
1527: #endif
1528: DMPlexGetSupportSize(dm, f, &supportSize);
1529: DMPlexGetSupport(dm, f, &support);
1530: for (s = 0; s < supportSize; ++s) {
1531: DMPlexGetConeSize(dm, support[s], &coneSize);
1532: DMPlexGetCone(dm, support[s], &cone);
1533: DMPlexGetConeOrientation(dm, support[s], &ornt);
1534: for (c = 0; c < coneSize; ++c) {
1535: if (cone[c] == f) break;
1536: }
1537: supportRef[s] = cStartNew + (support[s] - cStart)*4 + (ornt[c] < 0 ? (c+1-r)%3 : (c+r)%3);
1538: }
1539: DMPlexSetSupport(rdm, newp, supportRef);
1540: #if 1
1541: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1542: for (p = 0; p < supportSize; ++p) {
1543: if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew);
1544: }
1545: #endif
1546: }
1547: }
1548: /* Interior faces have 2 vertices and 2 cells */
1549: for (c = cStart; c < cEnd; ++c) {
1550: const PetscInt *cone;
1552: DMPlexGetCone(dm, c, &cone);
1553: for (r = 0; r < 3; ++r) {
1554: const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r;
1555: PetscInt coneNew[2];
1556: PetscInt supportNew[2];
1558: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart);
1559: coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart);
1560: DMPlexSetCone(rdm, newp, coneNew);
1561: #if 1
1562: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1563: for (p = 0; p < 2; ++p) {
1564: if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
1565: }
1566: #endif
1567: supportNew[0] = (c - cStart)*4 + (r+1)%3;
1568: supportNew[1] = (c - cStart)*4 + 3;
1569: DMPlexSetSupport(rdm, newp, supportNew);
1570: #if 1
1571: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1572: for (p = 0; p < 2; ++p) {
1573: if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
1574: }
1575: #endif
1576: }
1577: }
1578: /* Old vertices have identical supports */
1579: for (v = vStart; v < vEnd; ++v) {
1580: const PetscInt newp = vStartNew + (v - vStart);
1581: const PetscInt *support, *cone;
1582: PetscInt size, s;
1584: DMPlexGetSupportSize(dm, v, &size);
1585: DMPlexGetSupport(dm, v, &support);
1586: for (s = 0; s < size; ++s) {
1587: PetscInt r = 0;
1589: DMPlexGetCone(dm, support[s], &cone);
1590: if (cone[1] == v) r = 1;
1591: supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
1592: }
1593: DMPlexSetSupport(rdm, newp, supportRef);
1594: #if 1
1595: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
1596: for (p = 0; p < size; ++p) {
1597: if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
1598: }
1599: #endif
1600: }
1601: /* Face vertices have 2 + cells*2 supports */
1602: for (f = fStart; f < fEnd; ++f) {
1603: const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
1604: const PetscInt *cone, *support;
1605: PetscInt size, s;
1607: DMPlexGetSupportSize(dm, f, &size);
1608: DMPlexGetSupport(dm, f, &support);
1609: supportRef[0] = fStartNew + (f - fStart)*2 + 0;
1610: supportRef[1] = fStartNew + (f - fStart)*2 + 1;
1611: for (s = 0; s < size; ++s) {
1612: PetscInt r = 0;
1614: DMPlexGetCone(dm, support[s], &cone);
1615: if (cone[1] == f) r = 1;
1616: else if (cone[2] == f) r = 2;
1617: supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3;
1618: supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r;
1619: }
1620: DMPlexSetSupport(rdm, newp, supportRef);
1621: #if 1
1622: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
1623: for (p = 0; p < 2+size*2; ++p) {
1624: if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
1625: }
1626: #endif
1627: }
1628: PetscFree(supportRef);
1629: break;
1630: case REFINER_SIMPLEX_TO_HEX_2D:
1631: /*
1632: 2
1633: |\
1634: | \
1635: | \
1636: | \
1637: | C \
1638: | \
1639: 2 1
1640: |\ / \
1641: | 2 1 \
1642: | \/ \
1643: | | \
1644: |A | B \
1645: | 0 \
1646: | | \
1647: 0---0----------1
1648: */
1649: /* All cells have 4 faces */
1650: for (c = cStart; c < cEnd; ++c) {
1651: const PetscInt newp = cStartNew + (c - cStart)*3;
1652: const PetscInt *cone, *ornt;
1653: PetscInt coneNew[4], orntNew[4];
1655: DMPlexGetCone(dm, c, &cone);
1656: DMPlexGetConeOrientation(dm, c, &ornt);
1657: /* A quad */
1658: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
1659: orntNew[0] = ornt[0];
1660: coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0;
1661: orntNew[1] = 0;
1662: coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2;
1663: orntNew[2] = -2;
1664: coneNew[3] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
1665: orntNew[3] = ornt[2];
1666: DMPlexSetCone(rdm, newp+0, coneNew);
1667: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
1668: #if 1
1669: if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew);
1670: for (p = 0; p < 4; ++p) {
1671: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
1672: }
1673: #endif
1674: /* B quad */
1675: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
1676: orntNew[0] = ornt[0];
1677: coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
1678: orntNew[1] = ornt[1];
1679: coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1;
1680: orntNew[2] = 0;
1681: coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0;
1682: orntNew[3] = -2;
1683: DMPlexSetCone(rdm, newp+1, coneNew);
1684: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
1685: #if 1
1686: if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew);
1687: for (p = 0; p < 4; ++p) {
1688: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
1689: }
1690: #endif
1691: /* C quad */
1692: coneNew[0] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
1693: orntNew[0] = ornt[1];
1694: coneNew[1] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
1695: orntNew[1] = ornt[2];
1696: coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2;
1697: orntNew[2] = 0;
1698: coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1;
1699: orntNew[3] = -2;
1700: DMPlexSetCone(rdm, newp+2, coneNew);
1701: DMPlexSetConeOrientation(rdm, newp+2, orntNew);
1702: #if 1
1703: if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew);
1704: for (p = 0; p < 4; ++p) {
1705: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
1706: }
1707: #endif
1708: }
1709: /* Split faces have 2 vertices and the same cells as the parent */
1710: DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
1711: PetscMalloc1(2 + maxSupportSize*2, &supportRef);
1712: for (f = fStart; f < fEnd; ++f) {
1713: const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
1715: for (r = 0; r < 2; ++r) {
1716: const PetscInt newp = fStartNew + (f - fStart)*2 + r;
1717: const PetscInt *cone, *ornt, *support;
1718: PetscInt coneNew[2], coneSize, c, supportSize, s;
1720: DMPlexGetCone(dm, f, &cone);
1721: coneNew[0] = vStartNew + (cone[0] - vStart);
1722: coneNew[1] = vStartNew + (cone[1] - vStart);
1723: coneNew[(r+1)%2] = newv;
1724: DMPlexSetCone(rdm, newp, coneNew);
1725: #if 1
1726: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1727: for (p = 0; p < 2; ++p) {
1728: if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
1729: }
1730: #endif
1731: DMPlexGetSupportSize(dm, f, &supportSize);
1732: DMPlexGetSupport(dm, f, &support);
1733: for (s = 0; s < supportSize; ++s) {
1734: DMPlexGetConeSize(dm, support[s], &coneSize);
1735: DMPlexGetCone(dm, support[s], &cone);
1736: DMPlexGetConeOrientation(dm, support[s], &ornt);
1737: for (c = 0; c < coneSize; ++c) {
1738: if (cone[c] == f) break;
1739: }
1740: supportRef[s] = cStartNew + (support[s] - cStart)*3 + (ornt[c] < 0 ? (c+1-r)%3 : (c+r)%3);
1741: }
1742: DMPlexSetSupport(rdm, newp, supportRef);
1743: #if 1
1744: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1745: for (p = 0; p < supportSize; ++p) {
1746: if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew);
1747: }
1748: #endif
1749: }
1750: }
1751: /* Interior faces have 2 vertices and 2 cells */
1752: for (c = cStart; c < cEnd; ++c) {
1753: const PetscInt *cone;
1755: DMPlexGetCone(dm, c, &cone);
1756: for (r = 0; r < 3; ++r) {
1757: const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r;
1758: PetscInt coneNew[2];
1759: PetscInt supportNew[2];
1761: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart);
1762: coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart);
1763: DMPlexSetCone(rdm, newp, coneNew);
1764: #if 1
1765: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1766: for (p = 0; p < 2; ++p) {
1767: if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
1768: }
1769: #endif
1770: supportNew[0] = (c - cStart)*3 + r%3;
1771: supportNew[1] = (c - cStart)*3 + (r+1)%3;
1772: DMPlexSetSupport(rdm, newp, supportNew);
1773: #if 1
1774: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1775: for (p = 0; p < 2; ++p) {
1776: if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
1777: }
1778: #endif
1779: }
1780: }
1781: /* Old vertices have identical supports */
1782: for (v = vStart; v < vEnd; ++v) {
1783: const PetscInt newp = vStartNew + (v - vStart);
1784: const PetscInt *support, *cone;
1785: PetscInt size, s;
1787: DMPlexGetSupportSize(dm, v, &size);
1788: DMPlexGetSupport(dm, v, &support);
1789: for (s = 0; s < size; ++s) {
1790: PetscInt r = 0;
1792: DMPlexGetCone(dm, support[s], &cone);
1793: if (cone[1] == v) r = 1;
1794: supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
1795: }
1796: DMPlexSetSupport(rdm, newp, supportRef);
1797: #if 1
1798: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
1799: for (p = 0; p < size; ++p) {
1800: if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
1801: }
1802: #endif
1803: }
1804: /* Split-face vertices have cells + 2 supports */
1805: for (f = fStart; f < fEnd; ++f) {
1806: const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
1807: const PetscInt *cone, *support;
1808: PetscInt size, s;
1810: DMPlexGetSupportSize(dm, f, &size);
1811: DMPlexGetSupport(dm, f, &support);
1812: supportRef[0] = fStartNew + (f - fStart)*2 + 0;
1813: supportRef[1] = fStartNew + (f - fStart)*2 + 1;
1814: for (s = 0; s < size; ++s) {
1815: PetscInt r = 0;
1817: DMPlexGetCone(dm, support[s], &cone);
1818: if (cone[1] == f) r = 1;
1819: else if (cone[2] == f) r = 2;
1820: supportRef[2+s+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r;
1821: }
1822: DMPlexSetSupport(rdm, newp, supportRef);
1823: #if 1
1824: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
1825: for (p = 0; p < 2+size; ++p) {
1826: if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
1827: }
1828: #endif
1829: }
1830: /* Interior vertices vertices have 3 supports */
1831: for (c = cStart; c < cEnd; ++c) {
1832: const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + c - cStart;
1834: supportRef[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0;
1835: supportRef[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1;
1836: supportRef[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2;
1837: DMPlexSetSupport(rdm, newp, supportRef);
1838: }
1839: PetscFree(supportRef);
1840: break;
1841: case REFINER_HEX_2D:
1842: /*
1843: 3---------2---------2
1844: | | |
1845: | D 2 C |
1846: | | |
1847: 3----3----0----1----1
1848: | | |
1849: | A 0 B |
1850: | | |
1851: 0---------0---------1
1852: */
1853: /* All cells have 4 faces */
1854: for (c = cStart; c < cEnd; ++c) {
1855: const PetscInt newp = (c - cStart)*4;
1856: const PetscInt *cone, *ornt;
1857: PetscInt coneNew[4], orntNew[4];
1859: DMPlexGetCone(dm, c, &cone);
1860: DMPlexGetConeOrientation(dm, c, &ornt);
1861: /* A quad */
1862: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
1863: orntNew[0] = ornt[0];
1864: coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0;
1865: orntNew[1] = 0;
1866: coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3;
1867: orntNew[2] = -2;
1868: coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1);
1869: orntNew[3] = ornt[3];
1870: DMPlexSetCone(rdm, newp+0, coneNew);
1871: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
1872: #if 1
1873: if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew);
1874: for (p = 0; p < 4; ++p) {
1875: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
1876: }
1877: #endif
1878: /* B quad */
1879: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
1880: orntNew[0] = ornt[0];
1881: coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
1882: orntNew[1] = ornt[1];
1883: coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1;
1884: orntNew[2] = -2;
1885: coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0;
1886: orntNew[3] = -2;
1887: DMPlexSetCone(rdm, newp+1, coneNew);
1888: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
1889: #if 1
1890: if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew);
1891: for (p = 0; p < 4; ++p) {
1892: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
1893: }
1894: #endif
1895: /* C quad */
1896: coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1;
1897: orntNew[0] = 0;
1898: coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
1899: orntNew[1] = ornt[1];
1900: coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
1901: orntNew[2] = ornt[2];
1902: coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2;
1903: orntNew[3] = -2;
1904: DMPlexSetCone(rdm, newp+2, coneNew);
1905: DMPlexSetConeOrientation(rdm, newp+2, orntNew);
1906: #if 1
1907: if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew);
1908: for (p = 0; p < 4; ++p) {
1909: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
1910: }
1911: #endif
1912: /* D quad */
1913: coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3;
1914: orntNew[0] = 0;
1915: coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2;
1916: orntNew[1] = 0;
1917: coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
1918: orntNew[2] = ornt[2];
1919: coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0);
1920: orntNew[3] = ornt[3];
1921: DMPlexSetCone(rdm, newp+3, coneNew);
1922: DMPlexSetConeOrientation(rdm, newp+3, orntNew);
1923: #if 1
1924: if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew);
1925: for (p = 0; p < 4; ++p) {
1926: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
1927: }
1928: #endif
1929: }
1930: /* Split faces have 2 vertices and the same cells as the parent */
1931: DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
1932: PetscMalloc1(2 + maxSupportSize*2, &supportRef);
1933: for (f = fStart; f < fEnd; ++f) {
1934: const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
1936: for (r = 0; r < 2; ++r) {
1937: const PetscInt newp = fStartNew + (f - fStart)*2 + r;
1938: const PetscInt *cone, *ornt, *support;
1939: PetscInt coneNew[2], coneSize, c, supportSize, s;
1941: DMPlexGetCone(dm, f, &cone);
1942: coneNew[0] = vStartNew + (cone[0] - vStart);
1943: coneNew[1] = vStartNew + (cone[1] - vStart);
1944: coneNew[(r+1)%2] = newv;
1945: DMPlexSetCone(rdm, newp, coneNew);
1946: #if 1
1947: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1948: for (p = 0; p < 2; ++p) {
1949: if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
1950: }
1951: #endif
1952: DMPlexGetSupportSize(dm, f, &supportSize);
1953: DMPlexGetSupport(dm, f, &support);
1954: for (s = 0; s < supportSize; ++s) {
1955: DMPlexGetConeSize(dm, support[s], &coneSize);
1956: DMPlexGetCone(dm, support[s], &cone);
1957: DMPlexGetConeOrientation(dm, support[s], &ornt);
1958: for (c = 0; c < coneSize; ++c) {
1959: if (cone[c] == f) break;
1960: }
1961: supportRef[s] = cStartNew + (support[s] - cStart)*4 + (ornt[c] < 0 ? (c+1-r)%4 : (c+r)%4);
1962: }
1963: DMPlexSetSupport(rdm, newp, supportRef);
1964: #if 1
1965: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1966: for (p = 0; p < supportSize; ++p) {
1967: if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew);
1968: }
1969: #endif
1970: }
1971: }
1972: /* Interior faces have 2 vertices and 2 cells */
1973: for (c = cStart; c < cEnd; ++c) {
1974: const PetscInt *cone;
1975: PetscInt coneNew[2], supportNew[2];
1977: DMPlexGetCone(dm, c, &cone);
1978: for (r = 0; r < 4; ++r) {
1979: const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r;
1981: if (r==1 || r==2) {
1982: coneNew[0] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart);
1983: coneNew[1] = vStartNew + (vEnd - vStart) + (cone[r] - fStart);
1984: } else {
1985: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart);
1986: coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart);
1987: }
1988: DMPlexSetCone(rdm, newp, coneNew);
1989: #if 1
1990: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1991: for (p = 0; p < 2; ++p) {
1992: if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
1993: }
1994: #endif
1995: supportNew[0] = (c - cStart)*4 + r;
1996: supportNew[1] = (c - cStart)*4 + (r+1)%4;
1997: DMPlexSetSupport(rdm, newp, supportNew);
1998: #if 1
1999: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2000: for (p = 0; p < 2; ++p) {
2001: if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
2002: }
2003: #endif
2004: }
2005: }
2006: /* Old vertices have identical supports */
2007: for (v = vStart; v < vEnd; ++v) {
2008: const PetscInt newp = vStartNew + (v - vStart);
2009: const PetscInt *support, *cone;
2010: PetscInt size, s;
2012: DMPlexGetSupportSize(dm, v, &size);
2013: DMPlexGetSupport(dm, v, &support);
2014: for (s = 0; s < size; ++s) {
2015: PetscInt r = 0;
2017: DMPlexGetCone(dm, support[s], &cone);
2018: if (cone[1] == v) r = 1;
2019: supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
2020: }
2021: DMPlexSetSupport(rdm, newp, supportRef);
2022: #if 1
2023: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
2024: for (p = 0; p < size; ++p) {
2025: if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
2026: }
2027: #endif
2028: }
2029: /* Face vertices have 2 + cells supports */
2030: for (f = fStart; f < fEnd; ++f) {
2031: const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
2032: const PetscInt *cone, *support;
2033: PetscInt size, s;
2035: DMPlexGetSupportSize(dm, f, &size);
2036: DMPlexGetSupport(dm, f, &support);
2037: supportRef[0] = fStartNew + (f - fStart)*2 + 0;
2038: supportRef[1] = fStartNew + (f - fStart)*2 + 1;
2039: for (s = 0; s < size; ++s) {
2040: PetscInt r = 0;
2042: DMPlexGetCone(dm, support[s], &cone);
2043: if (cone[1] == f) r = 1;
2044: else if (cone[2] == f) r = 2;
2045: else if (cone[3] == f) r = 3;
2046: supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r;
2047: }
2048: DMPlexSetSupport(rdm, newp, supportRef);
2049: #if 1
2050: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
2051: for (p = 0; p < 2+size; ++p) {
2052: if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
2053: }
2054: #endif
2055: }
2056: /* Cell vertices have 4 supports */
2057: for (c = cStart; c < cEnd; ++c) {
2058: const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart);
2059: PetscInt supportNew[4];
2061: for (r = 0; r < 4; ++r) {
2062: supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r;
2063: }
2064: DMPlexSetSupport(rdm, newp, supportNew);
2065: }
2066: PetscFree(supportRef);
2067: break;
2068: case REFINER_HYBRID_SIMPLEX_2D:
2069: if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
2070: cMax = PetscMin(cEnd, cMax);
2071: if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
2072: fMax = PetscMin(fEnd, fMax);
2073: DMPlexGetHybridBounds(rdm, &cMaxNew, &fMaxNew, NULL, NULL);
2074: /* Interior cells have 3 faces */
2075: for (c = cStart; c < cMax; ++c) {
2076: const PetscInt newp = cStartNew + (c - cStart)*4;
2077: const PetscInt *cone, *ornt;
2078: PetscInt coneNew[3], orntNew[3];
2080: DMPlexGetCone(dm, c, &cone);
2081: DMPlexGetConeOrientation(dm, c, &ornt);
2082: /* A triangle */
2083: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
2084: orntNew[0] = ornt[0];
2085: coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2;
2086: orntNew[1] = -2;
2087: coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
2088: orntNew[2] = ornt[2];
2089: DMPlexSetCone(rdm, newp+0, coneNew);
2090: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
2091: #if 1
2092: if ((newp+0 < cStartNew) || (newp+0 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an interior cell [%d, %d)", newp+0, cStartNew, cMaxNew);
2093: for (p = 0; p < 3; ++p) {
2094: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an interior face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
2095: }
2096: #endif
2097: /* B triangle */
2098: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
2099: orntNew[0] = ornt[0];
2100: coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
2101: orntNew[1] = ornt[1];
2102: coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0;
2103: orntNew[2] = -2;
2104: DMPlexSetCone(rdm, newp+1, coneNew);
2105: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
2106: #if 1
2107: if ((newp+1 < cStartNew) || (newp+1 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an interior cell [%d, %d)", newp+1, cStartNew, cMaxNew);
2108: for (p = 0; p < 3; ++p) {
2109: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an interior face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
2110: }
2111: #endif
2112: /* C triangle */
2113: coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1;
2114: orntNew[0] = -2;
2115: coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
2116: orntNew[1] = ornt[1];
2117: coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
2118: orntNew[2] = ornt[2];
2119: DMPlexSetCone(rdm, newp+2, coneNew);
2120: DMPlexSetConeOrientation(rdm, newp+2, orntNew);
2121: #if 1
2122: if ((newp+2 < cStartNew) || (newp+2 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an interior cell [%d, %d)", newp+2, cStartNew, cMaxNew);
2123: for (p = 0; p < 3; ++p) {
2124: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an interior face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
2125: }
2126: #endif
2127: /* D triangle */
2128: coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0;
2129: orntNew[0] = 0;
2130: coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1;
2131: orntNew[1] = 0;
2132: coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2;
2133: orntNew[2] = 0;
2134: DMPlexSetCone(rdm, newp+3, coneNew);
2135: DMPlexSetConeOrientation(rdm, newp+3, orntNew);
2136: #if 1
2137: if ((newp+3 < cStartNew) || (newp+3 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an interior cell [%d, %d)", newp+3, cStartNew, cMaxNew);
2138: for (p = 0; p < 3; ++p) {
2139: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an interior face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
2140: }
2141: #endif
2142: }
2143: /*
2144: 2----3----3
2145: | |
2146: | B |
2147: | |
2148: 0----4--- 1
2149: | |
2150: | A |
2151: | |
2152: 0----2----1
2153: */
2154: /* Hybrid cells have 4 faces */
2155: for (c = cMax; c < cEnd; ++c) {
2156: const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2;
2157: const PetscInt *cone, *ornt;
2158: PetscInt coneNew[4], orntNew[4], r;
2160: DMPlexGetCone(dm, c, &cone);
2161: DMPlexGetConeOrientation(dm, c, &ornt);
2162: r = (ornt[0] < 0 ? 1 : 0);
2163: /* A quad */
2164: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + r;
2165: orntNew[0] = ornt[0];
2166: coneNew[1] = fStartNew + (cone[1] - fStart)*2 + r;
2167: orntNew[1] = ornt[1];
2168: coneNew[2+r] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[2+r] - fMax);
2169: orntNew[2+r] = 0;
2170: coneNew[3-r] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax);
2171: orntNew[3-r] = 0;
2172: DMPlexSetCone(rdm, newp+0, coneNew);
2173: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
2174: #if 1
2175: if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew);
2176: for (p = 0; p < 4; ++p) {
2177: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
2178: }
2179: #endif
2180: /* B quad */
2181: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + 1-r;
2182: orntNew[0] = ornt[0];
2183: coneNew[1] = fStartNew + (cone[1] - fStart)*2 + 1-r;
2184: orntNew[1] = ornt[1];
2185: coneNew[2+r] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax);
2186: orntNew[2+r] = 0;
2187: coneNew[3-r] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[3-r] - fMax);
2188: orntNew[3-r] = 0;
2189: DMPlexSetCone(rdm, newp+1, coneNew);
2190: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
2191: #if 1
2192: if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew);
2193: for (p = 0; p < 4; ++p) {
2194: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
2195: }
2196: #endif
2197: }
2198: /* Interior split faces have 2 vertices and the same cells as the parent */
2199: DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
2200: PetscMalloc1(2 + maxSupportSize*2, &supportRef);
2201: for (f = fStart; f < fMax; ++f) {
2202: const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
2204: for (r = 0; r < 2; ++r) {
2205: const PetscInt newp = fStartNew + (f - fStart)*2 + r;
2206: const PetscInt *cone, *ornt, *support;
2207: PetscInt coneNew[2], coneSize, c, supportSize, s;
2209: DMPlexGetCone(dm, f, &cone);
2210: coneNew[0] = vStartNew + (cone[0] - vStart);
2211: coneNew[1] = vStartNew + (cone[1] - vStart);
2212: coneNew[(r+1)%2] = newv;
2213: DMPlexSetCone(rdm, newp, coneNew);
2214: #if 1
2215: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2216: for (p = 0; p < 2; ++p) {
2217: if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
2218: }
2219: #endif
2220: DMPlexGetSupportSize(dm, f, &supportSize);
2221: DMPlexGetSupport(dm, f, &support);
2222: for (s = 0; s < supportSize; ++s) {
2223: DMPlexGetConeSize(dm, support[s], &coneSize);
2224: DMPlexGetCone(dm, support[s], &cone);
2225: DMPlexGetConeOrientation(dm, support[s], &ornt);
2226: for (c = 0; c < coneSize; ++c) if (cone[c] == f) break;
2227: if (support[s] >= cMax) {
2228: supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + (ornt[c] < 0 ? 1-r : r);
2229: } else {
2230: supportRef[s] = cStartNew + (support[s] - cStart)*4 + (ornt[c] < 0 ? (c+1-r)%3 : (c+r)%3);
2231: }
2232: }
2233: DMPlexSetSupport(rdm, newp, supportRef);
2234: #if 1
2235: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2236: for (p = 0; p < supportSize; ++p) {
2237: if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew);
2238: }
2239: #endif
2240: }
2241: }
2242: /* Interior cell faces have 2 vertices and 2 cells */
2243: for (c = cStart; c < cMax; ++c) {
2244: const PetscInt *cone;
2246: DMPlexGetCone(dm, c, &cone);
2247: for (r = 0; r < 3; ++r) {
2248: const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r;
2249: PetscInt coneNew[2];
2250: PetscInt supportNew[2];
2252: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart);
2253: coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart);
2254: DMPlexSetCone(rdm, newp, coneNew);
2255: #if 1
2256: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2257: for (p = 0; p < 2; ++p) {
2258: if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
2259: }
2260: #endif
2261: supportNew[0] = (c - cStart)*4 + (r+1)%3;
2262: supportNew[1] = (c - cStart)*4 + 3;
2263: DMPlexSetSupport(rdm, newp, supportNew);
2264: #if 1
2265: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2266: for (p = 0; p < 2; ++p) {
2267: if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
2268: }
2269: #endif
2270: }
2271: }
2272: /* Interior hybrid faces have 2 vertices and the same cells */
2273: for (f = fMax; f < fEnd; ++f) {
2274: const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax);
2275: const PetscInt *cone, *ornt;
2276: const PetscInt *support;
2277: PetscInt coneNew[2];
2278: PetscInt supportNew[2];
2279: PetscInt size, s, r;
2281: DMPlexGetCone(dm, f, &cone);
2282: coneNew[0] = vStartNew + (cone[0] - vStart);
2283: coneNew[1] = vStartNew + (cone[1] - vStart);
2284: DMPlexSetCone(rdm, newp, coneNew);
2285: #if 1
2286: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2287: for (p = 0; p < 2; ++p) {
2288: if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
2289: }
2290: #endif
2291: DMPlexGetSupportSize(dm, f, &size);
2292: DMPlexGetSupport(dm, f, &support);
2293: for (s = 0; s < size; ++s) {
2294: DMPlexGetCone(dm, support[s], &cone);
2295: DMPlexGetConeOrientation(dm, support[s], &ornt);
2296: for (r = 0; r < 2; ++r) {
2297: if (cone[r+2] == f) break;
2298: }
2299: supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + (ornt[0] < 0 ? 1-r : r);
2300: }
2301: DMPlexSetSupport(rdm, newp, supportNew);
2302: #if 1
2303: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2304: for (p = 0; p < size; ++p) {
2305: if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
2306: }
2307: #endif
2308: }
2309: /* Cell hybrid faces have 2 vertices and 2 cells */
2310: for (c = cMax; c < cEnd; ++c) {
2311: const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax);
2312: const PetscInt *cone;
2313: PetscInt coneNew[2];
2314: PetscInt supportNew[2];
2316: DMPlexGetCone(dm, c, &cone);
2317: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart);
2318: coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart);
2319: DMPlexSetCone(rdm, newp, coneNew);
2320: #if 1
2321: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2322: for (p = 0; p < 2; ++p) {
2323: if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
2324: }
2325: #endif
2326: supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0;
2327: supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1;
2328: DMPlexSetSupport(rdm, newp, supportNew);
2329: #if 1
2330: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2331: for (p = 0; p < 2; ++p) {
2332: if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
2333: }
2334: #endif
2335: }
2336: /* Old vertices have identical supports */
2337: for (v = vStart; v < vEnd; ++v) {
2338: const PetscInt newp = vStartNew + (v - vStart);
2339: const PetscInt *support, *cone;
2340: PetscInt size, s;
2342: DMPlexGetSupportSize(dm, v, &size);
2343: DMPlexGetSupport(dm, v, &support);
2344: for (s = 0; s < size; ++s) {
2345: if (support[s] >= fMax) {
2346: supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax);
2347: } else {
2348: PetscInt r = 0;
2350: DMPlexGetCone(dm, support[s], &cone);
2351: if (cone[1] == v) r = 1;
2352: supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
2353: }
2354: }
2355: DMPlexSetSupport(rdm, newp, supportRef);
2356: #if 1
2357: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
2358: for (p = 0; p < size; ++p) {
2359: if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
2360: }
2361: #endif
2362: }
2363: /* Face vertices have 2 + (2 interior, 1 hybrid) supports */
2364: for (f = fStart; f < fMax; ++f) {
2365: const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
2366: const PetscInt *cone, *support;
2367: PetscInt size, newSize = 2, s;
2369: DMPlexGetSupportSize(dm, f, &size);
2370: DMPlexGetSupport(dm, f, &support);
2371: supportRef[0] = fStartNew + (f - fStart)*2 + 0;
2372: supportRef[1] = fStartNew + (f - fStart)*2 + 1;
2373: for (s = 0; s < size; ++s) {
2374: PetscInt r = 0;
2376: DMPlexGetCone(dm, support[s], &cone);
2377: if (support[s] >= cMax) {
2378: supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (support[s] - cMax);
2380: newSize += 1;
2381: } else {
2382: if (cone[1] == f) r = 1;
2383: else if (cone[2] == f) r = 2;
2384: supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3;
2385: supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r;
2387: newSize += 2;
2388: }
2389: }
2390: DMPlexSetSupport(rdm, newp, supportRef);
2391: #if 1
2392: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
2393: for (p = 0; p < newSize; ++p) {
2394: if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
2395: }
2396: #endif
2397: }
2398: PetscFree(supportRef);
2399: break;
2400: case REFINER_HYBRID_HEX_2D:
2401: /* Hybrid Hex 2D */
2402: if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
2403: cMax = PetscMin(cEnd, cMax);
2404: if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
2405: fMax = PetscMin(fEnd, fMax);
2406: DMPlexGetHybridBounds(rdm, &cMaxNew, &fMaxNew, NULL, NULL);
2407: /* Interior cells have 4 faces */
2408: for (c = cStart; c < cMax; ++c) {
2409: const PetscInt newp = cStartNew + (c - cStart)*4;
2410: const PetscInt *cone, *ornt;
2411: PetscInt coneNew[4], orntNew[4];
2413: DMPlexGetCone(dm, c, &cone);
2414: DMPlexGetConeOrientation(dm, c, &ornt);
2415: /* A quad */
2416: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
2417: orntNew[0] = ornt[0];
2418: coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + 0;
2419: orntNew[1] = 0;
2420: coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + 3;
2421: orntNew[2] = -2;
2422: coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1);
2423: orntNew[3] = ornt[3];
2424: DMPlexSetCone(rdm, newp+0, coneNew);
2425: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
2426: #if 1
2427: if ((newp+0 < cStartNew) || (newp+0 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an interior cell [%d, %d)", newp+0, cStartNew, cMaxNew);
2428: for (p = 0; p < 4; ++p) {
2429: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an interior face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
2430: }
2431: #endif
2432: /* B quad */
2433: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
2434: orntNew[0] = ornt[0];
2435: coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
2436: orntNew[1] = ornt[1];
2437: coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + 1;
2438: orntNew[2] = 0;
2439: coneNew[3] = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + 0;
2440: orntNew[3] = -2;
2441: DMPlexSetCone(rdm, newp+1, coneNew);
2442: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
2443: #if 1
2444: if ((newp+1 < cStartNew) || (newp+1 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an interior cell [%d, %d)", newp+1, cStartNew, cMaxNew);
2445: for (p = 0; p < 4; ++p) {
2446: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an interior face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
2447: }
2448: #endif
2449: /* C quad */
2450: coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + 1;
2451: orntNew[0] = -2;
2452: coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
2453: orntNew[1] = ornt[1];
2454: coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
2455: orntNew[2] = ornt[2];
2456: coneNew[3] = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + 2;
2457: orntNew[3] = 0;
2458: DMPlexSetCone(rdm, newp+2, coneNew);
2459: DMPlexSetConeOrientation(rdm, newp+2, orntNew);
2460: #if 1
2461: if ((newp+2 < cStartNew) || (newp+2 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an interior cell [%d, %d)", newp+2, cStartNew, cMaxNew);
2462: for (p = 0; p < 4; ++p) {
2463: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an interior face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
2464: }
2465: #endif
2466: /* D quad */
2467: coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + 3;
2468: orntNew[0] = 0;
2469: coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + 2;
2470: orntNew[1] = -2;
2471: coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
2472: orntNew[2] = ornt[2];
2473: coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0);
2474: orntNew[3] = ornt[3];
2475: DMPlexSetCone(rdm, newp+3, coneNew);
2476: DMPlexSetConeOrientation(rdm, newp+3, orntNew);
2477: #if 1
2478: if ((newp+3 < cStartNew) || (newp+3 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an interior cell [%d, %d)", newp+3, cStartNew, cMaxNew);
2479: for (p = 0; p < 4; ++p) {
2480: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an interior face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
2481: }
2482: #endif
2483: }
2484: /*
2485: 2----3----3
2486: | |
2487: | B |
2488: | |
2489: 0----4--- 1
2490: | |
2491: | A |
2492: | |
2493: 0----2----1
2494: */
2495: /* Hybrid cells have 4 faces */
2496: for (c = cMax; c < cEnd; ++c) {
2497: const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2;
2498: const PetscInt *cone, *ornt;
2499: PetscInt coneNew[4], orntNew[4];
2501: DMPlexGetCone(dm, c, &cone);
2502: DMPlexGetConeOrientation(dm, c, &ornt);
2503: /* A quad */
2504: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
2505: orntNew[0] = ornt[0];
2506: coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
2507: orntNew[1] = ornt[1];
2508: coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (cone[2] - fMax);
2509: orntNew[2] = 0;
2510: coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (fEnd - fMax) + (c - cMax);
2511: orntNew[3] = 0;
2512: DMPlexSetCone(rdm, newp+0, coneNew);
2513: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
2514: #if 1
2515: if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew);
2516: for (p = 0; p < 4; ++p) {
2517: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
2518: }
2519: #endif
2520: /* B quad */
2521: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
2522: orntNew[0] = ornt[0];
2523: coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
2524: orntNew[1] = ornt[1];
2525: coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (fEnd - fMax) + (c - cMax);
2526: orntNew[2] = 0;
2527: coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (cone[3] - fMax);
2528: orntNew[3] = 0;
2529: DMPlexSetCone(rdm, newp+1, coneNew);
2530: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
2531: #if 1
2532: if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew);
2533: for (p = 0; p < 4; ++p) {
2534: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
2535: }
2536: #endif
2537: }
2538: /* Interior split faces have 2 vertices and the same cells as the parent */
2539: DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
2540: PetscMalloc1(2 + maxSupportSize*2, &supportRef);
2541: for (f = fStart; f < fMax; ++f) {
2542: const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
2544: for (r = 0; r < 2; ++r) {
2545: const PetscInt newp = fStartNew + (f - fStart)*2 + r;
2546: const PetscInt *cone, *ornt, *support;
2547: PetscInt coneNew[2], coneSize, c, supportSize, s;
2549: DMPlexGetCone(dm, f, &cone);
2550: coneNew[0] = vStartNew + (cone[0] - vStart);
2551: coneNew[1] = vStartNew + (cone[1] - vStart);
2552: coneNew[(r+1)%2] = newv;
2553: DMPlexSetCone(rdm, newp, coneNew);
2554: #if 1
2555: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2556: for (p = 0; p < 2; ++p) {
2557: if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
2558: }
2559: #endif
2560: DMPlexGetSupportSize(dm, f, &supportSize);
2561: DMPlexGetSupport(dm, f, &support);
2562: for (s = 0; s < supportSize; ++s) {
2563: if (support[s] >= cMax) {
2564: supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r;
2565: } else {
2566: DMPlexGetConeSize(dm, support[s], &coneSize);
2567: DMPlexGetCone(dm, support[s], &cone);
2568: DMPlexGetConeOrientation(dm, support[s], &ornt);
2569: for (c = 0; c < coneSize; ++c) {
2570: if (cone[c] == f) break;
2571: }
2572: supportRef[s] = cStartNew + (support[s] - cStart)*4 + (ornt[c] < 0 ? (c+1-r)%4 : (c+r)%4);
2573: }
2574: }
2575: DMPlexSetSupport(rdm, newp, supportRef);
2576: #if 1
2577: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2578: for (p = 0; p < supportSize; ++p) {
2579: if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew);
2580: }
2581: #endif
2582: }
2583: }
2584: /* Interior cell faces have 2 vertices and 2 cells */
2585: for (c = cStart; c < cMax; ++c) {
2586: const PetscInt *cone;
2588: DMPlexGetCone(dm, c, &cone);
2589: for (r = 0; r < 4; ++r) {
2590: const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + r;
2591: PetscInt coneNew[2], supportNew[2];
2593: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart);
2594: coneNew[1] = vStartNew + (vEnd - vStart) + (fMax - fStart) + (c - cStart);
2595: DMPlexSetCone(rdm, newp, coneNew);
2596: #if 1
2597: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2598: for (p = 0; p < 2; ++p) {
2599: if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
2600: }
2601: #endif
2602: supportNew[0] = (c - cStart)*4 + r;
2603: supportNew[1] = (c - cStart)*4 + (r+1)%4;
2604: DMPlexSetSupport(rdm, newp, supportNew);
2605: #if 1
2606: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2607: for (p = 0; p < 2; ++p) {
2608: if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
2609: }
2610: #endif
2611: }
2612: }
2613: /* Hybrid faces have 2 vertices and the same cells */
2614: for (f = fMax; f < fEnd; ++f) {
2615: const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (f - fMax);
2616: const PetscInt *cone, *support;
2617: PetscInt coneNew[2], supportNew[2];
2618: PetscInt size, s, r;
2620: DMPlexGetCone(dm, f, &cone);
2621: coneNew[0] = vStartNew + (cone[0] - vStart);
2622: coneNew[1] = vStartNew + (cone[1] - vStart);
2623: DMPlexSetCone(rdm, newp, coneNew);
2624: #if 1
2625: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2626: for (p = 0; p < 2; ++p) {
2627: if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
2628: }
2629: #endif
2630: DMPlexGetSupportSize(dm, f, &size);
2631: DMPlexGetSupport(dm, f, &support);
2632: for (s = 0; s < size; ++s) {
2633: DMPlexGetCone(dm, support[s], &cone);
2634: for (r = 0; r < 2; ++r) {
2635: if (cone[r+2] == f) break;
2636: }
2637: supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r;
2638: }
2639: DMPlexSetSupport(rdm, newp, supportNew);
2640: #if 1
2641: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2642: for (p = 0; p < size; ++p) {
2643: if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
2644: }
2645: #endif
2646: }
2647: /* Cell hybrid faces have 2 vertices and 2 cells */
2648: for (c = cMax; c < cEnd; ++c) {
2649: const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (fEnd - fMax) + (c - cMax);
2650: const PetscInt *cone;
2651: PetscInt coneNew[2], supportNew[2];
2653: DMPlexGetCone(dm, c, &cone);
2654: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart);
2655: coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart);
2656: DMPlexSetCone(rdm, newp, coneNew);
2657: #if 1
2658: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2659: for (p = 0; p < 2; ++p) {
2660: if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
2661: }
2662: #endif
2663: supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0;
2664: supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1;
2665: DMPlexSetSupport(rdm, newp, supportNew);
2666: #if 1
2667: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2668: for (p = 0; p < 2; ++p) {
2669: if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
2670: }
2671: #endif
2672: }
2673: /* Old vertices have identical supports */
2674: for (v = vStart; v < vEnd; ++v) {
2675: const PetscInt newp = vStartNew + (v - vStart);
2676: const PetscInt *support, *cone;
2677: PetscInt size, s;
2679: DMPlexGetSupportSize(dm, v, &size);
2680: DMPlexGetSupport(dm, v, &support);
2681: for (s = 0; s < size; ++s) {
2682: if (support[s] >= fMax) {
2683: supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (support[s] - fMax);
2684: } else {
2685: PetscInt r = 0;
2687: DMPlexGetCone(dm, support[s], &cone);
2688: if (cone[1] == v) r = 1;
2689: supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
2690: }
2691: }
2692: DMPlexSetSupport(rdm, newp, supportRef);
2693: #if 1
2694: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
2695: for (p = 0; p < size; ++p) {
2696: if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
2697: }
2698: #endif
2699: }
2700: /* Face vertices have 2 + cells supports */
2701: for (f = fStart; f < fMax; ++f) {
2702: const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
2703: const PetscInt *cone, *support;
2704: PetscInt size, s;
2706: DMPlexGetSupportSize(dm, f, &size);
2707: DMPlexGetSupport(dm, f, &support);
2708: supportRef[0] = fStartNew + (f - fStart)*2 + 0;
2709: supportRef[1] = fStartNew + (f - fStart)*2 + 1;
2710: for (s = 0; s < size; ++s) {
2711: PetscInt r = 0;
2713: DMPlexGetCone(dm, support[s], &cone);
2714: if (support[s] >= cMax) {
2715: supportRef[2+s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (fEnd - fMax) + (support[s] - cMax);
2716: } else {
2717: if (cone[1] == f) r = 1;
2718: else if (cone[2] == f) r = 2;
2719: else if (cone[3] == f) r = 3;
2720: supportRef[2+s] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*4 + r;
2721: }
2722: }
2723: DMPlexSetSupport(rdm, newp, supportRef);
2724: #if 1
2725: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
2726: for (p = 0; p < 2+size; ++p) {
2727: if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
2728: }
2729: #endif
2730: }
2731: /* Cell vertices have 4 supports */
2732: for (c = cStart; c < cMax; ++c) {
2733: const PetscInt newp = vStartNew + (vEnd - vStart) + (fMax - fStart) + (c - cStart);
2734: PetscInt supportNew[4];
2736: for (r = 0; r < 4; ++r) {
2737: supportNew[r] = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + r;
2738: }
2739: DMPlexSetSupport(rdm, newp, supportNew);
2740: }
2741: PetscFree(supportRef);
2742: break;
2743: case REFINER_SIMPLEX_3D:
2744: /* All cells have 4 faces: Tet face order is prescribed in DMPlexGetFaces_Internal() */
2745: DMPlexGetRawFaces_Internal(dm, 3, 4, cellInd, NULL, NULL, &faces);
2746: for (c = cStart; c < cEnd; ++c) {
2747: const PetscInt newp = cStartNew + (c - cStart)*8;
2748: const PetscInt *cone, *ornt;
2749: PetscInt coneNew[4], orntNew[4];
2751: DMPlexGetCone(dm, c, &cone);
2752: DMPlexGetConeOrientation(dm, c, &ornt);
2753: /* A tetrahedron: {0, a, c, d} */
2754: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 0); /* A */
2755: orntNew[0] = ornt[0];
2756: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 0); /* A */
2757: orntNew[1] = ornt[1];
2758: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 0); /* A */
2759: orntNew[2] = ornt[2];
2760: coneNew[3] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 0;
2761: orntNew[3] = 0;
2762: DMPlexSetCone(rdm, newp+0, coneNew);
2763: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
2764: #if 1
2765: if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew);
2766: for (p = 0; p < 4; ++p) {
2767: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
2768: }
2769: #endif
2770: /* B tetrahedron: {a, 1, b, e} */
2771: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 1); /* B */
2772: orntNew[0] = ornt[0];
2773: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 2); /* C */
2774: orntNew[1] = ornt[1];
2775: coneNew[2] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 1;
2776: orntNew[2] = 0;
2777: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 1); /* B */
2778: orntNew[3] = ornt[3];
2779: DMPlexSetCone(rdm, newp+1, coneNew);
2780: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
2781: #if 1
2782: if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew);
2783: for (p = 0; p < 4; ++p) {
2784: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
2785: }
2786: #endif
2787: /* C tetrahedron: {c, b, 2, f} */
2788: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 2); /* C */
2789: orntNew[0] = ornt[0];
2790: coneNew[1] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 2;
2791: orntNew[1] = 0;
2792: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 1); /* B */
2793: orntNew[2] = ornt[2];
2794: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 0); /* A */
2795: orntNew[3] = ornt[3];
2796: DMPlexSetCone(rdm, newp+2, coneNew);
2797: DMPlexSetConeOrientation(rdm, newp+2, orntNew);
2798: #if 1
2799: if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew);
2800: for (p = 0; p < 4; ++p) {
2801: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
2802: }
2803: #endif
2804: /* D tetrahedron: {d, e, f, 3} */
2805: coneNew[0] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 3;
2806: orntNew[0] = 0;
2807: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 1); /* B */
2808: orntNew[1] = ornt[1];
2809: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 2); /* C */
2810: orntNew[2] = ornt[2];
2811: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 2); /* C */
2812: orntNew[3] = ornt[3];
2813: DMPlexSetCone(rdm, newp+3, coneNew);
2814: DMPlexSetConeOrientation(rdm, newp+3, orntNew);
2815: #if 1
2816: if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew);
2817: for (p = 0; p < 4; ++p) {
2818: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
2819: }
2820: #endif
2821: /* A' tetrahedron: {c, d, a, f} */
2822: coneNew[0] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 0;
2823: orntNew[0] = -3;
2824: coneNew[1] = fStartNew + (cone[2] - fStart)*4 + 3;
2825: orntNew[1] = ornt[2] < 0 ? -(GetTriMidEdge_Static(ornt[2], 0)+1) : GetTriMidEdge_Static(ornt[2], 0);
2826: coneNew[2] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 5;
2827: orntNew[2] = 0;
2828: coneNew[3] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 4;
2829: orntNew[3] = 2;
2830: DMPlexSetCone(rdm, newp+4, coneNew);
2831: DMPlexSetConeOrientation(rdm, newp+4, orntNew);
2832: #if 1
2833: if ((newp+4 < cStartNew) || (newp+4 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+4, cStartNew, cEndNew);
2834: for (p = 0; p < 4; ++p) {
2835: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
2836: }
2837: #endif
2838: /* B' tetrahedron: {e, b, a, f} */
2839: coneNew[0] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 1;
2840: orntNew[0] = -2;
2841: coneNew[1] = fStartNew + (cone[3] - fStart)*4 + 3;
2842: orntNew[1] = ornt[3] < 0 ? -(GetTriMidEdge_Static(ornt[3], 1)+1) : GetTriMidEdge_Static(ornt[3], 1);
2843: coneNew[2] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 6;
2844: orntNew[2] = 0;
2845: coneNew[3] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 7;
2846: orntNew[3] = 0;
2847: DMPlexSetCone(rdm, newp+5, coneNew);
2848: DMPlexSetConeOrientation(rdm, newp+5, orntNew);
2849: #if 1
2850: if ((newp+5 < cStartNew) || (newp+5 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+5, cStartNew, cEndNew);
2851: for (p = 0; p < 4; ++p) {
2852: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
2853: }
2854: #endif
2855: /* C' tetrahedron: {f, a, c, b} */
2856: coneNew[0] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 5;
2857: orntNew[0] = -2;
2858: coneNew[1] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 7;
2859: orntNew[1] = -2;
2860: coneNew[2] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 2;
2861: orntNew[2] = -1;
2862: coneNew[3] = fStartNew + (cone[0] - fStart)*4 + 3;
2863: orntNew[3] = ornt[0] < 0 ? -(GetTriMidEdge_Static(ornt[0], 2)+1) : GetTriMidEdge_Static(ornt[0], 2);
2864: DMPlexSetCone(rdm, newp+6, coneNew);
2865: DMPlexSetConeOrientation(rdm, newp+6, orntNew);
2866: #if 1
2867: if ((newp+6 < cStartNew) || (newp+6 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+6, cStartNew, cEndNew);
2868: for (p = 0; p < 4; ++p) {
2869: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
2870: }
2871: #endif
2872: /* D' tetrahedron: {f, a, e, d} */
2873: coneNew[0] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 6;
2874: orntNew[0] = -2;
2875: coneNew[1] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 4;
2876: orntNew[1] = -1;
2877: coneNew[2] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 3;
2878: orntNew[2] = -2;
2879: coneNew[3] = fStartNew + (cone[1] - fStart)*4 + 3;
2880: orntNew[3] = ornt[1] < 0 ? -(GetTriMidEdge_Static(ornt[1], 1)+1) : GetTriMidEdge_Static(ornt[1], 1);
2881: DMPlexSetCone(rdm, newp+7, coneNew);
2882: DMPlexSetConeOrientation(rdm, newp+7, orntNew);
2883: #if 1
2884: if ((newp+7 < cStartNew) || (newp+7 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+7, cStartNew, cEndNew);
2885: for (p = 0; p < 4; ++p) {
2886: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
2887: }
2888: #endif
2889: }
2890: /* Split faces have 3 edges and the same cells as the parent */
2891: DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
2892: PetscMalloc1(2 + maxSupportSize*2, &supportRef);
2893: for (f = fStart; f < fEnd; ++f) {
2894: const PetscInt newp = fStartNew + (f - fStart)*4;
2895: const PetscInt *cone, *ornt, *support;
2896: PetscInt coneNew[3], orntNew[3], coneSize, supportSize, s;
2898: DMPlexGetCone(dm, f, &cone);
2899: DMPlexGetConeOrientation(dm, f, &ornt);
2900: /* A triangle */
2901: coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1 : 0);
2902: orntNew[0] = ornt[0];
2903: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 2;
2904: orntNew[1] = -2;
2905: coneNew[2] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 0 : 1);
2906: orntNew[2] = ornt[2];
2907: DMPlexSetCone(rdm, newp+0, coneNew);
2908: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
2909: #if 1
2910: if ((newp+0 < fStartNew) || (newp+0 >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+0, fStartNew, fEndNew);
2911: for (p = 0; p < 3; ++p) {
2912: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
2913: }
2914: #endif
2915: /* B triangle */
2916: coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 0 : 1);
2917: orntNew[0] = ornt[0];
2918: coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1 : 0);
2919: orntNew[1] = ornt[1];
2920: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 0;
2921: orntNew[2] = -2;
2922: DMPlexSetCone(rdm, newp+1, coneNew);
2923: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
2924: #if 1
2925: if ((newp+1 < fStartNew) || (newp+1 >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+1, fStartNew, fEndNew);
2926: for (p = 0; p < 3; ++p) {
2927: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
2928: }
2929: #endif
2930: /* C triangle */
2931: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 1;
2932: orntNew[0] = -2;
2933: coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 0 : 1);
2934: orntNew[1] = ornt[1];
2935: coneNew[2] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 1 : 0);
2936: orntNew[2] = ornt[2];
2937: DMPlexSetCone(rdm, newp+2, coneNew);
2938: DMPlexSetConeOrientation(rdm, newp+2, orntNew);
2939: #if 1
2940: if ((newp+2 < fStartNew) || (newp+2 >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+2, fStartNew, fEndNew);
2941: for (p = 0; p < 3; ++p) {
2942: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
2943: }
2944: #endif
2945: /* D triangle */
2946: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 0;
2947: orntNew[0] = 0;
2948: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 1;
2949: orntNew[1] = 0;
2950: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 2;
2951: orntNew[2] = 0;
2952: DMPlexSetCone(rdm, newp+3, coneNew);
2953: DMPlexSetConeOrientation(rdm, newp+3, orntNew);
2954: #if 1
2955: if ((newp+3 < fStartNew) || (newp+3 >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+3, fStartNew, fEndNew);
2956: for (p = 0; p < 3; ++p) {
2957: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
2958: }
2959: #endif
2960: DMPlexGetSupportSize(dm, f, &supportSize);
2961: DMPlexGetSupport(dm, f, &support);
2962: for (r = 0; r < 4; ++r) {
2963: for (s = 0; s < supportSize; ++s) {
2964: PetscInt subf;
2965: DMPlexGetConeSize(dm, support[s], &coneSize);
2966: DMPlexGetCone(dm, support[s], &cone);
2967: DMPlexGetConeOrientation(dm, support[s], &ornt);
2968: for (c = 0; c < coneSize; ++c) {
2969: if (cone[c] == f) break;
2970: }
2971: subf = GetTriSubfaceInverse_Static(ornt[c], r);
2972: supportRef[s] = cStartNew + (support[s] - cStart)*8 + (r==3 ? (c+2)%4 + 4 : faces[c*3+subf]);
2973: }
2974: DMPlexSetSupport(rdm, newp+r, supportRef);
2975: #if 1
2976: if ((newp+r < fStartNew) || (newp+r >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+r, fStartNew, fEndNew);
2977: for (p = 0; p < supportSize; ++p) {
2978: if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew);
2979: }
2980: #endif
2981: }
2982: }
2983: /* Interior faces have 3 edges and 2 cells */
2984: for (c = cStart; c < cEnd; ++c) {
2985: PetscInt newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8;
2986: const PetscInt *cone, *ornt;
2987: PetscInt coneNew[3], orntNew[3];
2988: PetscInt supportNew[2];
2990: DMPlexGetCone(dm, c, &cone);
2991: DMPlexGetConeOrientation(dm, c, &ornt);
2992: /* Face A: {c, a, d} */
2993: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 2);
2994: orntNew[0] = ornt[0] < 0 ? -2 : 0;
2995: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 2);
2996: orntNew[1] = ornt[1] < 0 ? -2 : 0;
2997: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 2);
2998: orntNew[2] = ornt[2] < 0 ? -2 : 0;
2999: DMPlexSetCone(rdm, newp, coneNew);
3000: DMPlexSetConeOrientation(rdm, newp, orntNew);
3001: #if 1
3002: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3003: for (p = 0; p < 3; ++p) {
3004: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
3005: }
3006: #endif
3007: supportNew[0] = (c - cStart)*8 + 0;
3008: supportNew[1] = (c - cStart)*8 + 0+4;
3009: DMPlexSetSupport(rdm, newp, supportNew);
3010: #if 1
3011: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3012: for (p = 0; p < 2; ++p) {
3013: if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
3014: }
3015: #endif
3016: ++newp;
3017: /* Face B: {a, b, e} */
3018: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 0);
3019: orntNew[0] = ornt[0] < 0 ? -2 : 0;
3020: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 0);
3021: orntNew[1] = ornt[3] < 0 ? -2 : 0;
3022: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 1);
3023: orntNew[2] = ornt[1] < 0 ? -2 : 0;
3024: DMPlexSetCone(rdm, newp, coneNew);
3025: DMPlexSetConeOrientation(rdm, newp, orntNew);
3026: #if 1
3027: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3028: for (p = 0; p < 3; ++p) {
3029: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
3030: }
3031: #endif
3032: supportNew[0] = (c - cStart)*8 + 1;
3033: supportNew[1] = (c - cStart)*8 + 1+4;
3034: DMPlexSetSupport(rdm, newp, supportNew);
3035: #if 1
3036: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3037: for (p = 0; p < 2; ++p) {
3038: if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
3039: }
3040: #endif
3041: ++newp;
3042: /* Face C: {c, f, b} */
3043: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 0);
3044: orntNew[0] = ornt[2] < 0 ? -2 : 0;
3045: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 2);
3046: orntNew[1] = ornt[3] < 0 ? -2 : 0;
3047: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 1);
3048: orntNew[2] = ornt[0] < 0 ? -2 : 0;
3049: DMPlexSetCone(rdm, newp, coneNew);
3050: DMPlexSetConeOrientation(rdm, newp, orntNew);
3051: #if 1
3052: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3053: for (p = 0; p < 3; ++p) {
3054: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
3055: }
3056: #endif
3057: supportNew[0] = (c - cStart)*8 + 2;
3058: supportNew[1] = (c - cStart)*8 + 2+4;
3059: DMPlexSetSupport(rdm, newp, supportNew);
3060: #if 1
3061: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3062: for (p = 0; p < 2; ++p) {
3063: if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
3064: }
3065: #endif
3066: ++newp;
3067: /* Face D: {d, e, f} */
3068: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 0);
3069: orntNew[0] = ornt[1] < 0 ? -2 : 0;
3070: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 1);
3071: orntNew[1] = ornt[3] < 0 ? -2 : 0;
3072: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 1);
3073: orntNew[2] = ornt[2] < 0 ? -2 : 0;
3074: DMPlexSetCone(rdm, newp, coneNew);
3075: DMPlexSetConeOrientation(rdm, newp, orntNew);
3076: #if 1
3077: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3078: for (p = 0; p < 3; ++p) {
3079: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
3080: }
3081: #endif
3082: supportNew[0] = (c - cStart)*8 + 3;
3083: supportNew[1] = (c - cStart)*8 + 3+4;
3084: DMPlexSetSupport(rdm, newp, supportNew);
3085: #if 1
3086: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3087: for (p = 0; p < 2; ++p) {
3088: if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
3089: }
3090: #endif
3091: ++newp;
3092: /* Face E: {d, f, a} */
3093: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 1);
3094: orntNew[0] = ornt[2] < 0 ? 0 : -2;
3095: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
3096: orntNew[1] = -2;
3097: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 2);
3098: orntNew[2] = ornt[1] < 0 ? -2 : 0;
3099: DMPlexSetCone(rdm, newp, coneNew);
3100: DMPlexSetConeOrientation(rdm, newp, orntNew);
3101: #if 1
3102: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3103: for (p = 0; p < 3; ++p) {
3104: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
3105: }
3106: #endif
3107: supportNew[0] = (c - cStart)*8 + 0+4;
3108: supportNew[1] = (c - cStart)*8 + 3+4;
3109: DMPlexSetSupport(rdm, newp, supportNew);
3110: #if 1
3111: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3112: for (p = 0; p < 2; ++p) {
3113: if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
3114: }
3115: #endif
3116: ++newp;
3117: /* Face F: {c, a, f} */
3118: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 2);
3119: orntNew[0] = ornt[0] < 0 ? -2 : 0;
3120: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
3121: orntNew[1] = 0;
3122: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 0);
3123: orntNew[2] = ornt[2] < 0 ? 0 : -2;
3124: DMPlexSetCone(rdm, newp, coneNew);
3125: DMPlexSetConeOrientation(rdm, newp, orntNew);
3126: #if 1
3127: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3128: for (p = 0; p < 3; ++p) {
3129: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
3130: }
3131: #endif
3132: supportNew[0] = (c - cStart)*8 + 0+4;
3133: supportNew[1] = (c - cStart)*8 + 2+4;
3134: DMPlexSetSupport(rdm, newp, supportNew);
3135: #if 1
3136: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3137: for (p = 0; p < 2; ++p) {
3138: if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
3139: }
3140: #endif
3141: ++newp;
3142: /* Face G: {e, a, f} */
3143: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 1);
3144: orntNew[0] = ornt[1] < 0 ? -2 : 0;
3145: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
3146: orntNew[1] = 0;
3147: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 1);
3148: orntNew[2] = ornt[3] < 0 ? 0 : -2;
3149: DMPlexSetCone(rdm, newp, coneNew);
3150: DMPlexSetConeOrientation(rdm, newp, orntNew);
3151: #if 1
3152: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3153: for (p = 0; p < 3; ++p) {
3154: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
3155: }
3156: #endif
3157: supportNew[0] = (c - cStart)*8 + 1+4;
3158: supportNew[1] = (c - cStart)*8 + 3+4;
3159: DMPlexSetSupport(rdm, newp, supportNew);
3160: #if 1
3161: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3162: for (p = 0; p < 2; ++p) {
3163: if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
3164: }
3165: #endif
3166: ++newp;
3167: /* Face H: {a, b, f} */
3168: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 0);
3169: orntNew[0] = ornt[0] < 0 ? -2 : 0;
3170: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 2);
3171: orntNew[1] = ornt[3] < 0 ? 0 : -2;
3172: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
3173: orntNew[2] = -2;
3174: DMPlexSetCone(rdm, newp, coneNew);
3175: DMPlexSetConeOrientation(rdm, newp, orntNew);
3176: #if 1
3177: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3178: for (p = 0; p < 3; ++p) {
3179: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
3180: }
3181: #endif
3182: supportNew[0] = (c - cStart)*8 + 1+4;
3183: supportNew[1] = (c - cStart)*8 + 2+4;
3184: DMPlexSetSupport(rdm, newp, supportNew);
3185: #if 1
3186: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3187: for (p = 0; p < 2; ++p) {
3188: if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
3189: }
3190: #endif
3191: ++newp;
3192: }
3193: /* Split Edges have 2 vertices and the same faces as the parent */
3194: for (e = eStart; e < eEnd; ++e) {
3195: const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);
3197: for (r = 0; r < 2; ++r) {
3198: const PetscInt newp = eStartNew + (e - eStart)*2 + r;
3199: const PetscInt *cone, *ornt, *support;
3200: PetscInt coneNew[2], coneSize, c, supportSize, s;
3202: DMPlexGetCone(dm, e, &cone);
3203: coneNew[0] = vStartNew + (cone[0] - vStart);
3204: coneNew[1] = vStartNew + (cone[1] - vStart);
3205: coneNew[(r+1)%2] = newv;
3206: DMPlexSetCone(rdm, newp, coneNew);
3207: #if 1
3208: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
3209: for (p = 0; p < 2; ++p) {
3210: if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
3211: }
3212: #endif
3213: DMPlexGetSupportSize(dm, e, &supportSize);
3214: DMPlexGetSupport(dm, e, &support);
3215: for (s = 0; s < supportSize; ++s) {
3216: DMPlexGetConeSize(dm, support[s], &coneSize);
3217: DMPlexGetCone(dm, support[s], &cone);
3218: DMPlexGetConeOrientation(dm, support[s], &ornt);
3219: for (c = 0; c < coneSize; ++c) {
3220: if (cone[c] == e) break;
3221: }
3222: supportRef[s] = fStartNew + (support[s] - fStart)*4 + (c + (ornt[c] < 0 ? 1-r : r))%3;
3223: }
3224: DMPlexSetSupport(rdm, newp, supportRef);
3225: #if 1
3226: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
3227: for (p = 0; p < supportSize; ++p) {
3228: if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
3229: }
3230: #endif
3231: }
3232: }
3233: /* Face edges have 2 vertices and 2+cells*(1/2) faces */
3234: for (f = fStart; f < fEnd; ++f) {
3235: const PetscInt *cone, *ornt, *support;
3236: PetscInt coneSize, supportSize, s;
3238: DMPlexGetSupportSize(dm, f, &supportSize);
3239: DMPlexGetSupport(dm, f, &support);
3240: for (r = 0; r < 3; ++r) {
3241: const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + r;
3242: PetscInt coneNew[2], intFaces = 0, er, eint[4] = {1, 0, 2, 0};
3243: PetscInt fint[24] = { 1, 7, -1, -1, 0, 5,
3244: -1, -1, 1, 6, 0, 4,
3245: 2, 5, 3, 4, -1, -1,
3246: -1, -1, 3, 6, 2, 7};
3248: DMPlexGetCone(dm, f, &cone);
3249: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[(r+0)%3] - eStart);
3250: coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - eStart);
3251: DMPlexSetCone(rdm, newp, coneNew);
3252: #if 1
3253: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
3254: for (p = 0; p < 2; ++p) {
3255: if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
3256: }
3257: #endif
3258: supportRef[0] = fStartNew + (f - fStart)*4 + (r+1)%3;
3259: supportRef[1] = fStartNew + (f - fStart)*4 + 3;
3260: for (s = 0; s < supportSize; ++s) {
3261: DMPlexGetConeSize(dm, support[s], &coneSize);
3262: DMPlexGetCone(dm, support[s], &cone);
3263: DMPlexGetConeOrientation(dm, support[s], &ornt);
3264: for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
3265: /* Here we want to determine whether edge newp contains a vertex which is part of the cross-tet edge */
3266: er = GetTriMidEdgeInverse_Static(ornt[c], r);
3267: if (er == eint[c]) {
3268: supportRef[2+intFaces++] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*8 + (c + 2)%4;
3269: } else {
3270: supportRef[2+intFaces++] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*8 + fint[(c*3 + er)*2 + 0];
3271: supportRef[2+intFaces++] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*8 + fint[(c*3 + er)*2 + 1];
3272: }
3273: }
3274: DMPlexSetSupport(rdm, newp, supportRef);
3275: #if 1
3276: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
3277: for (p = 0; p < intFaces; ++p) {
3278: if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
3279: }
3280: #endif
3281: }
3282: }
3283: /* Interior edges have 2 vertices and 4 faces */
3284: for (c = cStart; c < cEnd; ++c) {
3285: const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
3286: const PetscInt *cone, *ornt, *fcone;
3287: PetscInt coneNew[2], supportNew[4], find;
3289: DMPlexGetCone(dm, c, &cone);
3290: DMPlexGetConeOrientation(dm, c, &ornt);
3291: DMPlexGetCone(dm, cone[0], &fcone);
3292: find = GetTriEdge_Static(ornt[0], 0);
3293: coneNew[0] = vStartNew + (vEnd - vStart) + (fcone[find] - eStart);
3294: DMPlexGetCone(dm, cone[2], &fcone);
3295: find = GetTriEdge_Static(ornt[2], 1);
3296: coneNew[1] = vStartNew + (vEnd - vStart) + (fcone[find] - eStart);
3297: DMPlexSetCone(rdm, newp, coneNew);
3298: #if 1
3299: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
3300: for (p = 0; p < 2; ++p) {
3301: if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
3302: }
3303: #endif
3304: supportNew[0] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 4;
3305: supportNew[1] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 5;
3306: supportNew[2] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 6;
3307: supportNew[3] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 7;
3308: DMPlexSetSupport(rdm, newp, supportNew);
3309: #if 1
3310: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
3311: for (p = 0; p < 4; ++p) {
3312: if ((supportNew[p] < fStartNew) || (supportNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportNew[p], fStartNew, fEndNew);
3313: }
3314: #endif
3315: }
3316: /* Old vertices have identical supports */
3317: for (v = vStart; v < vEnd; ++v) {
3318: const PetscInt newp = vStartNew + (v - vStart);
3319: const PetscInt *support, *cone;
3320: PetscInt size, s;
3322: DMPlexGetSupportSize(dm, v, &size);
3323: DMPlexGetSupport(dm, v, &support);
3324: for (s = 0; s < size; ++s) {
3325: PetscInt r = 0;
3327: DMPlexGetCone(dm, support[s], &cone);
3328: if (cone[1] == v) r = 1;
3329: supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
3330: }
3331: DMPlexSetSupport(rdm, newp, supportRef);
3332: #if 1
3333: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
3334: for (p = 0; p < size; ++p) {
3335: if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", supportRef[p], eStartNew, eEndNew);
3336: }
3337: #endif
3338: }
3339: /* Edge vertices have 2 + face*2 + 0/1 supports */
3340: for (e = eStart; e < eEnd; ++e) {
3341: const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
3342: const PetscInt *cone, *support;
3343: PetscInt *star = NULL, starSize, cellSize = 0, coneSize, size, s;
3345: DMPlexGetSupportSize(dm, e, &size);
3346: DMPlexGetSupport(dm, e, &support);
3347: supportRef[0] = eStartNew + (e - eStart)*2 + 0;
3348: supportRef[1] = eStartNew + (e - eStart)*2 + 1;
3349: for (s = 0; s < size; ++s) {
3350: PetscInt r = 0;
3352: DMPlexGetConeSize(dm, support[s], &coneSize);
3353: DMPlexGetCone(dm, support[s], &cone);
3354: for (r = 0; r < coneSize; ++r) {if (cone[r] == e) break;}
3355: supportRef[2+s*2+0] = eStartNew + (eEnd - eStart)*2 + (support[s] - fStart)*3 + (r+0)%3;
3356: supportRef[2+s*2+1] = eStartNew + (eEnd - eStart)*2 + (support[s] - fStart)*3 + (r+2)%3;
3357: }
3358: DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
3359: for (s = 0; s < starSize*2; s += 2) {
3360: const PetscInt *cone, *ornt;
3361: PetscInt e01, e23;
3363: if ((star[s] >= cStart) && (star[s] < cEnd)) {
3364: /* Check edge 0-1 */
3365: DMPlexGetCone(dm, star[s], &cone);
3366: DMPlexGetConeOrientation(dm, star[s], &ornt);
3367: DMPlexGetCone(dm, cone[0], &cone);
3368: e01 = cone[GetTriEdge_Static(ornt[0], 0)];
3369: /* Check edge 2-3 */
3370: DMPlexGetCone(dm, star[s], &cone);
3371: DMPlexGetConeOrientation(dm, star[s], &ornt);
3372: DMPlexGetCone(dm, cone[2], &cone);
3373: e23 = cone[GetTriEdge_Static(ornt[2], 1)];
3374: if ((e01 == e) || (e23 == e)) {supportRef[2+size*2+cellSize++] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (star[s] - cStart);}
3375: }
3376: }
3377: DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
3378: DMPlexSetSupport(rdm, newp, supportRef);
3379: #if 1
3380: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
3381: for (p = 0; p < 2+size*2+cellSize; ++p) {
3382: if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", supportRef[p], eStartNew, eEndNew);
3383: }
3384: #endif
3385: }
3386: PetscFree(supportRef);
3387: DMPlexRestoreFaces_Internal(dm, 3, cStart, NULL, NULL, &faces);
3388: break;
3389: case REFINER_HYBRID_SIMPLEX_3D:
3390: DMPlexGetHybridBounds(rdm, &cMaxNew, &fMaxNew, &eMaxNew, NULL);
3391: /* Interior cells have 4 faces: Tet face order is prescribed in DMPlexGetFaces_Internal() */
3392: DMPlexGetRawFaces_Internal(dm, 3, 4, cellInd, NULL, NULL, &faces);
3393: for (c = cStart; c < cMax; ++c) {
3394: const PetscInt newp = cStartNew + (c - cStart)*8;
3395: const PetscInt *cone, *ornt;
3396: PetscInt coneNew[4], orntNew[4];
3398: DMPlexGetCone(dm, c, &cone);
3399: DMPlexGetConeOrientation(dm, c, &ornt);
3400: /* A tetrahedron: {0, a, c, d} */
3401: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 0); /* A */
3402: orntNew[0] = ornt[0];
3403: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 0); /* A */
3404: orntNew[1] = ornt[1];
3405: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 0); /* A */
3406: orntNew[2] = ornt[2];
3407: coneNew[3] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 0;
3408: orntNew[3] = 0;
3409: DMPlexSetCone(rdm, newp+0, coneNew);
3410: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
3411: #if 1
3412: if ((newp+0 < cStartNew) || (newp+0 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cMaxNew);
3413: for (p = 0; p < 4; ++p) {
3414: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
3415: }
3416: #endif
3417: /* B tetrahedron: {a, 1, b, e} */
3418: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 1); /* B */
3419: orntNew[0] = ornt[0];
3420: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 2); /* C */
3421: orntNew[1] = ornt[1];
3422: coneNew[2] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 1;
3423: orntNew[2] = 0;
3424: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 1); /* B */
3425: orntNew[3] = ornt[3];
3426: DMPlexSetCone(rdm, newp+1, coneNew);
3427: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
3428: #if 1
3429: if ((newp+1 < cStartNew) || (newp+1 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cMaxNew);
3430: for (p = 0; p < 4; ++p) {
3431: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
3432: }
3433: #endif
3434: /* C tetrahedron: {c, b, 2, f} */
3435: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 2); /* C */
3436: orntNew[0] = ornt[0];
3437: coneNew[1] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 2;
3438: orntNew[1] = 0;
3439: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 1); /* B */
3440: orntNew[2] = ornt[2];
3441: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 0); /* A */
3442: orntNew[3] = ornt[3];
3443: DMPlexSetCone(rdm, newp+2, coneNew);
3444: DMPlexSetConeOrientation(rdm, newp+2, orntNew);
3445: #if 1
3446: if ((newp+2 < cStartNew) || (newp+2 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cMaxNew);
3447: for (p = 0; p < 4; ++p) {
3448: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
3449: }
3450: #endif
3451: /* D tetrahedron: {d, e, f, 3} */
3452: coneNew[0] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 3;
3453: orntNew[0] = 0;
3454: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 1); /* B */
3455: orntNew[1] = ornt[1];
3456: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 2); /* C */
3457: orntNew[2] = ornt[2];
3458: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 2); /* C */
3459: orntNew[3] = ornt[3];
3460: DMPlexSetCone(rdm, newp+3, coneNew);
3461: DMPlexSetConeOrientation(rdm, newp+3, orntNew);
3462: #if 1
3463: if ((newp+3 < cStartNew) || (newp+3 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cMaxNew);
3464: for (p = 0; p < 4; ++p) {
3465: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
3466: }
3467: #endif
3468: /* A' tetrahedron: {d, a, c, f} */
3469: coneNew[0] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 0;
3470: orntNew[0] = -3;
3471: coneNew[1] = fStartNew + (cone[2] - fStart)*4 + 3;
3472: orntNew[1] = ornt[2] < 0 ? -(GetTriMidEdge_Static(ornt[2], 0)+1) : GetTriMidEdge_Static(ornt[2], 0);
3473: coneNew[2] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 5;
3474: orntNew[2] = 0;
3475: coneNew[3] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 4;
3476: orntNew[3] = 2;
3477: DMPlexSetCone(rdm, newp+4, coneNew);
3478: DMPlexSetConeOrientation(rdm, newp+4, orntNew);
3479: #if 1
3480: if ((newp+4 < cStartNew) || (newp+4 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+4, cStartNew, cMaxNew);
3481: for (p = 0; p < 4; ++p) {
3482: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
3483: }
3484: #endif
3485: /* B' tetrahedron: {e, b, a, f} */
3486: coneNew[0] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 1;
3487: orntNew[0] = -3;
3488: coneNew[1] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 6;
3489: orntNew[1] = 1;
3490: coneNew[2] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 7;
3491: orntNew[2] = 0;
3492: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + 3;
3493: orntNew[3] = ornt[3] < 0 ? -(GetTriMidEdge_Static(ornt[3], 0)+1) : GetTriMidEdge_Static(ornt[3], 0);
3494: DMPlexSetCone(rdm, newp+5, coneNew);
3495: DMPlexSetConeOrientation(rdm, newp+5, orntNew);
3496: #if 1
3497: if ((newp+5 < cStartNew) || (newp+5 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+5, cStartNew, cMaxNew);
3498: for (p = 0; p < 4; ++p) {
3499: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
3500: }
3501: #endif
3502: /* C' tetrahedron: {b, f, c, a} */
3503: coneNew[0] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 2;
3504: orntNew[0] = -3;
3505: coneNew[1] = fStartNew + (cone[0] - fStart)*4 + 3;
3506: orntNew[1] = ornt[0] < 0 ? -(GetTriMidEdge_Static(ornt[0], 2)+1) : GetTriMidEdge_Static(ornt[0], 2);
3507: coneNew[2] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 5;
3508: orntNew[2] = -3;
3509: coneNew[3] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 7;
3510: orntNew[3] = -2;
3511: DMPlexSetCone(rdm, newp+6, coneNew);
3512: DMPlexSetConeOrientation(rdm, newp+6, orntNew);
3513: #if 1
3514: if ((newp+6 < cStartNew) || (newp+6 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+6, cStartNew, cMaxNew);
3515: for (p = 0; p < 4; ++p) {
3516: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
3517: }
3518: #endif
3519: /* D' tetrahedron: {f, e, d, a} */
3520: coneNew[0] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 3;
3521: orntNew[0] = -3;
3522: coneNew[1] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 4;
3523: orntNew[1] = -3;
3524: coneNew[2] = fStartNew + (cone[1] - fStart)*4 + 3;
3525: orntNew[2] = ornt[1] < 0 ? -(GetTriMidEdge_Static(ornt[1], 0)+1) : GetTriMidEdge_Static(ornt[1], 0);
3526: coneNew[3] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 6;
3527: orntNew[3] = -3;
3528: DMPlexSetCone(rdm, newp+7, coneNew);
3529: DMPlexSetConeOrientation(rdm, newp+7, orntNew);
3530: #if 1
3531: if ((newp+7 < cStartNew) || (newp+7 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+7, cStartNew, cMaxNew);
3532: for (p = 0; p < 4; ++p) {
3533: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
3534: }
3535: #endif
3536: }
3537: /* Hybrid cells have 5 faces */
3538: for (c = cMax; c < cEnd; ++c) {
3539: const PetscInt newp = cStartNew + (cMax - cStart)*8 + (c - cMax)*4;
3540: const PetscInt *cone, *ornt, *fornt;
3541: PetscInt coneNew[5], orntNew[5], o, of, i;
3543: DMPlexGetCone(dm, c, &cone);
3544: DMPlexGetConeOrientation(dm, c, &ornt);
3545: DMPlexGetConeOrientation(dm, cone[0], &fornt);
3546: o = ornt[0] < 0 ? -1 : 1;
3547: for (r = 0; r < 3; ++r) {
3548: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], r);
3549: orntNew[0] = ornt[0];
3550: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], r);
3551: orntNew[1] = ornt[1];
3552: of = fornt[GetTriEdge_Static(ornt[0], r)] < 0 ? -1 : 1;
3553: i = GetTriEdgeInverse_Static(ornt[0], r) + 2;
3554: coneNew[i] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (cone[2+GetTriEdge_Static(ornt[0], r)] - fMax)*2 + (o*of < 0 ? 1 : 0);
3555: orntNew[i] = 0;
3556: i = GetTriEdgeInverse_Static(ornt[0], (r+1)%3) + 2;
3557: coneNew[i] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + GetTriSubface_Static(ornt[0], r);
3558: orntNew[i] = 0;
3559: of = fornt[GetTriEdge_Static(ornt[0], (r+2)%3)] < 0 ? -1 : 1;
3560: i = GetTriEdgeInverse_Static(ornt[0], (r+2)%3) + 2;
3561: coneNew[i] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (cone[2+GetTriEdge_Static(ornt[0], (r+2)%3)] - fMax)*2 + (o*of < 0 ? 0 : 1);
3562: orntNew[i] = 0;
3563: DMPlexSetCone(rdm, newp+r, coneNew);
3564: DMPlexSetConeOrientation(rdm, newp+r, orntNew);
3565: #if 1
3566: if ((newp+r < cMaxNew) || (newp+r >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid cell [%d, %d)", newp+r, cMaxNew, cEndNew);
3567: for (p = 0; p < 2; ++p) {
3568: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
3569: }
3570: for (p = 2; p < 5; ++p) {
3571: if ((coneNew[p] < fMaxNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", coneNew[p], fMaxNew, fEndNew);
3572: }
3573: #endif
3574: }
3575: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + 3;
3576: orntNew[0] = 0;
3577: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + 3;
3578: orntNew[1] = 0;
3579: coneNew[2] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + 1;
3580: orntNew[2] = 0;
3581: coneNew[3] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + 2;
3582: orntNew[3] = 0;
3583: coneNew[4] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + 0;
3584: orntNew[4] = 0;
3585: DMPlexSetCone(rdm, newp+3, coneNew);
3586: DMPlexSetConeOrientation(rdm, newp+3, orntNew);
3587: #if 1
3588: if ((newp+3 < cMaxNew) || (newp+3 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid cell [%d, %d)", newp+3, cMaxNew, cEndNew);
3589: for (p = 0; p < 2; ++p) {
3590: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
3591: }
3592: for (p = 2; p < 5; ++p) {
3593: if ((coneNew[p] < fMaxNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", coneNew[p], fMaxNew, fEndNew);
3594: }
3595: #endif
3596: }
3597: /* Split faces have 3 edges and the same cells as the parent */
3598: DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
3599: PetscMalloc1(2 + maxSupportSize*2, &supportRef);
3600: for (f = fStart; f < fMax; ++f) {
3601: const PetscInt newp = fStartNew + (f - fStart)*4;
3602: const PetscInt *cone, *ornt, *support;
3603: PetscInt coneNew[3], orntNew[3], coneSize, supportSize, s;
3605: DMPlexGetCone(dm, f, &cone);
3606: DMPlexGetConeOrientation(dm, f, &ornt);
3607: /* A triangle */
3608: coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1 : 0);
3609: orntNew[0] = ornt[0];
3610: coneNew[1] = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + 2;
3611: orntNew[1] = -2;
3612: coneNew[2] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 0 : 1);
3613: orntNew[2] = ornt[2];
3614: DMPlexSetCone(rdm, newp+0, coneNew);
3615: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
3616: #if 1
3617: if ((newp+0 < fStartNew) || (newp+0 >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+0, fStartNew, fMaxNew);
3618: for (p = 0; p < 3; ++p) {
3619: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
3620: }
3621: #endif
3622: /* B triangle */
3623: coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 0 : 1);
3624: orntNew[0] = ornt[0];
3625: coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1 : 0);
3626: orntNew[1] = ornt[1];
3627: coneNew[2] = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + 0;
3628: orntNew[2] = -2;
3629: DMPlexSetCone(rdm, newp+1, coneNew);
3630: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
3631: #if 1
3632: if ((newp+1 < fStartNew) || (newp+1 >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+1, fStartNew, fMaxNew);
3633: for (p = 0; p < 3; ++p) {
3634: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
3635: }
3636: #endif
3637: /* C triangle */
3638: coneNew[0] = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + 1;
3639: orntNew[0] = -2;
3640: coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 0 : 1);
3641: orntNew[1] = ornt[1];
3642: coneNew[2] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 1 : 0);
3643: orntNew[2] = ornt[2];
3644: DMPlexSetCone(rdm, newp+2, coneNew);
3645: DMPlexSetConeOrientation(rdm, newp+2, orntNew);
3646: #if 1
3647: if ((newp+2 < fStartNew) || (newp+2 >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+2, fStartNew, fMaxNew);
3648: for (p = 0; p < 3; ++p) {
3649: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
3650: }
3651: #endif
3652: /* D triangle */
3653: coneNew[0] = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + 0;
3654: orntNew[0] = 0;
3655: coneNew[1] = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + 1;
3656: orntNew[1] = 0;
3657: coneNew[2] = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + 2;
3658: orntNew[2] = 0;
3659: DMPlexSetCone(rdm, newp+3, coneNew);
3660: DMPlexSetConeOrientation(rdm, newp+3, orntNew);
3661: #if 1
3662: if ((newp+3 < fStartNew) || (newp+3 >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+3, fStartNew, fMaxNew);
3663: for (p = 0; p < 3; ++p) {
3664: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
3665: }
3666: #endif
3667: DMPlexGetSupportSize(dm, f, &supportSize);
3668: DMPlexGetSupport(dm, f, &support);
3669: for (r = 0; r < 4; ++r) {
3670: for (s = 0; s < supportSize; ++s) {
3671: PetscInt subf;
3672: DMPlexGetConeSize(dm, support[s], &coneSize);
3673: DMPlexGetCone(dm, support[s], &cone);
3674: DMPlexGetConeOrientation(dm, support[s], &ornt);
3675: for (c = 0; c < coneSize; ++c) {
3676: if (cone[c] == f) break;
3677: }
3678: subf = GetTriSubfaceInverse_Static(ornt[c], r);
3679: if (support[s] < cMax) {
3680: supportRef[s] = cStartNew + (support[s] - cStart)*8 + (r==3 ? (c+2)%4 + 4 : faces[c*3+subf]);
3681: } else {
3682: supportRef[s] = cStartNew + (cMax - cStart)*8 + (support[s] - cMax)*4 + (r==3 ? r : subf);
3683: }
3684: }
3685: DMPlexSetSupport(rdm, newp+r, supportRef);
3686: #if 1
3687: if ((newp+r < fStartNew) || (newp+r >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+r, fStartNew, fMaxNew);
3688: for (p = 0; p < supportSize; ++p) {
3689: if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an interior or hybrid cell [%d, %d)", supportRef[p], cStartNew, cEndNew);
3690: }
3691: #endif
3692: }
3693: }
3694: /* Interior cell faces have 3 edges and 2 cells */
3695: for (c = cStart; c < cMax; ++c) {
3696: PetscInt newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*8;
3697: const PetscInt *cone, *ornt;
3698: PetscInt coneNew[3], orntNew[3];
3699: PetscInt supportNew[2];
3701: DMPlexGetCone(dm, c, &cone);
3702: DMPlexGetConeOrientation(dm, c, &ornt);
3703: /* Face A: {c, a, d} */
3704: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 2);
3705: orntNew[0] = ornt[0] < 0 ? -2 : 0;
3706: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 2);
3707: orntNew[1] = ornt[1] < 0 ? -2 : 0;
3708: coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 2);
3709: orntNew[2] = ornt[2] < 0 ? -2 : 0;
3710: DMPlexSetCone(rdm, newp, coneNew);
3711: DMPlexSetConeOrientation(rdm, newp, orntNew);
3712: #if 1
3713: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3714: for (p = 0; p < 3; ++p) {
3715: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
3716: }
3717: #endif
3718: supportNew[0] = (c - cStart)*8 + 0;
3719: supportNew[1] = (c - cStart)*8 + 0+4;
3720: DMPlexSetSupport(rdm, newp, supportNew);
3721: #if 1
3722: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3723: for (p = 0; p < 2; ++p) {
3724: if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cMaxNew);
3725: }
3726: #endif
3727: ++newp;
3728: /* Face B: {a, b, e} */
3729: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 0);
3730: orntNew[0] = ornt[0] < 0 ? -2 : 0;
3731: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 0);
3732: orntNew[1] = ornt[3] < 0 ? -2 : 0;
3733: coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 1);
3734: orntNew[2] = ornt[1] < 0 ? -2 : 0;
3735: DMPlexSetCone(rdm, newp, coneNew);
3736: DMPlexSetConeOrientation(rdm, newp, orntNew);
3737: #if 1
3738: if ((newp+1 < fStartNew) || (newp+1 >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+1, fStartNew, fMaxNew);
3739: for (p = 0; p < 3; ++p) {
3740: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
3741: }
3742: #endif
3743: supportNew[0] = (c - cStart)*8 + 1;
3744: supportNew[1] = (c - cStart)*8 + 1+4;
3745: DMPlexSetSupport(rdm, newp, supportNew);
3746: #if 1
3747: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3748: for (p = 0; p < 2; ++p) {
3749: if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cMaxNew);
3750: }
3751: #endif
3752: ++newp;
3753: /* Face C: {c, f, b} */
3754: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 0);
3755: orntNew[0] = ornt[2] < 0 ? -2 : 0;
3756: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 2);
3757: orntNew[1] = ornt[3] < 0 ? -2 : 0;
3758: coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 1);
3759: orntNew[2] = ornt[0] < 0 ? -2 : 0;
3760: DMPlexSetCone(rdm, newp, coneNew);
3761: DMPlexSetConeOrientation(rdm, newp, orntNew);
3762: #if 1
3763: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3764: for (p = 0; p < 3; ++p) {
3765: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
3766: }
3767: #endif
3768: supportNew[0] = (c - cStart)*8 + 2;
3769: supportNew[1] = (c - cStart)*8 + 2+4;
3770: DMPlexSetSupport(rdm, newp, supportNew);
3771: #if 1
3772: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3773: for (p = 0; p < 2; ++p) {
3774: if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cMaxNew);
3775: }
3776: #endif
3777: ++newp;
3778: /* Face D: {d, e, f} */
3779: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 0);
3780: orntNew[0] = ornt[1] < 0 ? -2 : 0;
3781: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 1);
3782: orntNew[1] = ornt[3] < 0 ? -2 : 0;
3783: coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 1);
3784: orntNew[2] = ornt[2] < 0 ? -2 : 0;
3785: DMPlexSetCone(rdm, newp, coneNew);
3786: DMPlexSetConeOrientation(rdm, newp, orntNew);
3787: #if 1
3788: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3789: for (p = 0; p < 3; ++p) {
3790: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
3791: }
3792: #endif
3793: supportNew[0] = (c - cStart)*8 + 3;
3794: supportNew[1] = (c - cStart)*8 + 3+4;
3795: DMPlexSetSupport(rdm, newp, supportNew);
3796: #if 1
3797: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3798: for (p = 0; p < 2; ++p) {
3799: if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cMaxNew);
3800: }
3801: #endif
3802: ++newp;
3803: /* Face E: {d, f, a} */
3804: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 1);
3805: orntNew[0] = ornt[2] < 0 ? 0 : -2;
3806: coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
3807: orntNew[1] = -2;
3808: coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 2);
3809: orntNew[2] = ornt[1] < 0 ? -2 : 0;
3810: DMPlexSetCone(rdm, newp, coneNew);
3811: DMPlexSetConeOrientation(rdm, newp, orntNew);
3812: #if 1
3813: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3814: for (p = 0; p < 3; ++p) {
3815: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
3816: }
3817: #endif
3818: supportNew[0] = (c - cStart)*8 + 0+4;
3819: supportNew[1] = (c - cStart)*8 + 3+4;
3820: DMPlexSetSupport(rdm, newp, supportNew);
3821: #if 1
3822: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3823: for (p = 0; p < 2; ++p) {
3824: if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cMaxNew);
3825: }
3826: #endif
3827: ++newp;
3828: /* Face F: {c, a, f} */
3829: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 2);
3830: orntNew[0] = ornt[0] < 0 ? -2 : 0;
3831: coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
3832: orntNew[1] = 0;
3833: coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 0);
3834: orntNew[2] = ornt[2] < 0 ? 0 : -2;
3835: DMPlexSetCone(rdm, newp, coneNew);
3836: DMPlexSetConeOrientation(rdm, newp, orntNew);
3837: #if 1
3838: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3839: for (p = 0; p < 3; ++p) {
3840: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
3841: }
3842: #endif
3843: supportNew[0] = (c - cStart)*8 + 0+4;
3844: supportNew[1] = (c - cStart)*8 + 2+4;
3845: DMPlexSetSupport(rdm, newp, supportNew);
3846: #if 1
3847: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3848: for (p = 0; p < 2; ++p) {
3849: if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cMaxNew);
3850: }
3851: #endif
3852: ++newp;
3853: /* Face G: {e, a, f} */
3854: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 1);
3855: orntNew[0] = ornt[1] < 0 ? -2 : 0;
3856: coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
3857: orntNew[1] = 0;
3858: coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 1);
3859: orntNew[2] = ornt[3] < 0 ? 0 : -2;
3860: DMPlexSetCone(rdm, newp, coneNew);
3861: DMPlexSetConeOrientation(rdm, newp, orntNew);
3862: #if 1
3863: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3864: for (p = 0; p < 3; ++p) {
3865: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
3866: }
3867: #endif
3868: supportNew[0] = (c - cStart)*8 + 1+4;
3869: supportNew[1] = (c - cStart)*8 + 3+4;
3870: DMPlexSetSupport(rdm, newp, supportNew);
3871: #if 1
3872: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3873: for (p = 0; p < 2; ++p) {
3874: if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cMaxNew);
3875: }
3876: #endif
3877: ++newp;
3878: /* Face H: {a, b, f} */
3879: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 0);
3880: orntNew[0] = ornt[0] < 0 ? -2 : 0;
3881: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 2);
3882: orntNew[1] = ornt[3] < 0 ? 0 : -2;
3883: coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
3884: orntNew[2] = -2;
3885: DMPlexSetCone(rdm, newp, coneNew);
3886: DMPlexSetConeOrientation(rdm, newp, orntNew);
3887: #if 1
3888: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3889: for (p = 0; p < 3; ++p) {
3890: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
3891: }
3892: #endif
3893: supportNew[0] = (c - cStart)*8 + 1+4;
3894: supportNew[1] = (c - cStart)*8 + 2+4;
3895: DMPlexSetSupport(rdm, newp, supportNew);
3896: #if 1
3897: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3898: for (p = 0; p < 2; ++p) {
3899: if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cMaxNew);
3900: }
3901: #endif
3902: ++newp;
3903: }
3904: /* Hybrid split faces have 4 edges and same cells */
3905: for (f = fMax; f < fEnd; ++f) {
3906: const PetscInt *cone, *ornt, *support;
3907: PetscInt coneNew[4], orntNew[4];
3908: PetscInt supportNew[2], size, s, c;
3910: DMPlexGetCone(dm, f, &cone);
3911: DMPlexGetConeOrientation(dm, f, &ornt);
3912: DMPlexGetSupportSize(dm, f, &size);
3913: DMPlexGetSupport(dm, f, &support);
3914: for (r = 0; r < 2; ++r) {
3915: const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (f - fMax)*2 + r;
3917: coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1-r : r);
3918: orntNew[0] = ornt[0];
3919: coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1-r : r);
3920: orntNew[1] = ornt[1];
3921: coneNew[2+r] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (cone[2+r] - eMax);
3922: orntNew[2+r] = 0;
3923: coneNew[3-r] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (f - fMax);
3924: orntNew[3-r] = 0;
3925: DMPlexSetCone(rdm, newp, coneNew);
3926: DMPlexSetConeOrientation(rdm, newp, orntNew);
3927: #if 1
3928: if ((newp < fMaxNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", newp, fMaxNew, fEndNew);
3929: for (p = 0; p < 2; ++p) {
3930: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
3931: }
3932: for (p = 2; p < 4; ++p) {
3933: if ((coneNew[p] < eMaxNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", coneNew[p], eMaxNew, eEndNew);
3934: }
3935: #endif
3936: for (s = 0; s < size; ++s) {
3937: const PetscInt *coneCell, *orntCell, *fornt;
3938: PetscInt o, of;
3940: DMPlexGetCone(dm, support[s], &coneCell);
3941: DMPlexGetConeOrientation(dm, support[s], &orntCell);
3942: o = orntCell[0] < 0 ? -1 : 1;
3943: for (c = 2; c < 5; ++c) if (coneCell[c] == f) break;
3944: if (c >= 5) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find face %d in cone of cell %d", f, support[s]);
3945: DMPlexGetConeOrientation(dm, coneCell[0], &fornt);
3946: of = fornt[c-2] < 0 ? -1 : 1;
3947: supportNew[s] = cStartNew + (cMax - cStart)*8 + (support[s] - cMax)*4 + (GetTriEdgeInverse_Static(orntCell[0], c-2) + (o*of < 0 ? 1-r : r))%3;
3948: }
3949: DMPlexSetSupport(rdm, newp, supportNew);
3950: #if 1
3951: if ((newp < fMaxNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", newp, fMaxNew, fEndNew);
3952: for (p = 0; p < size; ++p) {
3953: if ((supportNew[p] < cMaxNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid cell [%d, %d)", supportNew[p], cMaxNew, cEndNew);
3954: }
3955: #endif
3956: }
3957: }
3958: /* Hybrid cell faces have 4 edges and 2 cells */
3959: for (c = cMax; c < cEnd; ++c) {
3960: PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3;
3961: const PetscInt *cone, *ornt;
3962: PetscInt coneNew[4], orntNew[4];
3963: PetscInt supportNew[2];
3965: DMPlexGetCone(dm, c, &cone);
3966: DMPlexGetConeOrientation(dm, c, &ornt);
3967: for (r = 0; r < 3; ++r) {
3968: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + (r+2)%3;
3969: orntNew[0] = 0;
3970: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + (r+2)%3;
3971: orntNew[1] = 0;
3972: coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (cone[2+(r+2)%3] - fMax);
3973: orntNew[2] = 0;
3974: coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (cone[2+r] - fMax);
3975: orntNew[3] = 0;
3976: DMPlexSetCone(rdm, newp+r, coneNew);
3977: DMPlexSetConeOrientation(rdm, newp+r, orntNew);
3978: #if 1
3979: if ((newp+r < fMaxNew) || (newp+r >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", newp+r, fMaxNew, fEndNew);
3980: for (p = 0; p < 2; ++p) {
3981: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
3982: }
3983: for (p = 2; p < 4; ++p) {
3984: if ((coneNew[p] < eMaxNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", coneNew[p], eMaxNew, eEndNew);
3985: }
3986: #endif
3987: supportNew[0] = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + GetTriSubface_Static(ornt[0], r);
3988: supportNew[1] = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + 3;
3989: DMPlexSetSupport(rdm, newp+r, supportNew);
3990: #if 1
3991: if ((newp+r < fMaxNew) || (newp+r >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", newp+r, fMaxNew, fEndNew);
3992: for (p = 0; p < 2; ++p) {
3993: if ((supportNew[p] < cMaxNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid cell [%d, %d)", supportNew[p], cMaxNew, cEndNew);
3994: }
3995: #endif
3996: }
3997: }
3998: /* Interior split edges have 2 vertices and the same faces as the parent */
3999: for (e = eStart; e < eMax; ++e) {
4000: const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);
4002: for (r = 0; r < 2; ++r) {
4003: const PetscInt newp = eStartNew + (e - eStart)*2 + r;
4004: const PetscInt *cone, *ornt, *support;
4005: PetscInt coneNew[2], coneSize, c, supportSize, s;
4007: DMPlexGetCone(dm, e, &cone);
4008: coneNew[0] = vStartNew + (cone[0] - vStart);
4009: coneNew[1] = vStartNew + (cone[1] - vStart);
4010: coneNew[(r+1)%2] = newv;
4011: DMPlexSetCone(rdm, newp, coneNew);
4012: #if 1
4013: if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
4014: for (p = 0; p < 2; ++p) {
4015: if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
4016: }
4017: #endif
4018: DMPlexGetSupportSize(dm, e, &supportSize);
4019: DMPlexGetSupport(dm, e, &support);
4020: for (s = 0; s < supportSize; ++s) {
4021: DMPlexGetConeSize(dm, support[s], &coneSize);
4022: DMPlexGetCone(dm, support[s], &cone);
4023: DMPlexGetConeOrientation(dm, support[s], &ornt);
4024: for (c = 0; c < coneSize; ++c) if (cone[c] == e) break;
4025: if (support[s] < fMax) {
4026: supportRef[s] = fStartNew + (support[s] - fStart)*4 + (c + (ornt[c] < 0 ? 1-r : r))%3;
4027: } else {
4028: supportRef[s] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (support[s] - fMax)*2 + (ornt[c] < 0 ? 1-r : r);
4029: }
4030: }
4031: DMPlexSetSupport(rdm, newp, supportRef);
4032: #if 1
4033: if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
4034: for (p = 0; p < supportSize; ++p) {
4035: if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an interior or hybrid face [%d, %d)", supportRef[p], fStartNew, fEndNew);
4036: }
4037: #endif
4038: }
4039: }
4040: /* Interior face edges have 2 vertices and 2+cells*(1/2) faces */
4041: for (f = fStart; f < fMax; ++f) {
4042: const PetscInt *cone, *ornt, *support;
4043: PetscInt coneSize, supportSize, s;
4045: DMPlexGetSupportSize(dm, f, &supportSize);
4046: DMPlexGetSupport(dm, f, &support);
4047: for (r = 0; r < 3; ++r) {
4048: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + r;
4049: PetscInt coneNew[2], intFaces = 0, er, eint[4] = {1, 0, 2, 0};
4050: PetscInt fint[24] = { 1, 7, -1, -1, 0, 5,
4051: -1, -1, 1, 6, 0, 4,
4052: 2, 5, 3, 4, -1, -1,
4053: -1, -1, 3, 6, 2, 7};
4055: DMPlexGetCone(dm, f, &cone);
4056: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[(r+0)%3] - eStart);
4057: coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - eStart);
4058: DMPlexSetCone(rdm, newp, coneNew);
4059: #if 1
4060: if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
4061: for (p = 0; p < 2; ++p) {
4062: if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
4063: }
4064: #endif
4065: supportRef[0] = fStartNew + (f - fStart)*4 + (r+1)%3;
4066: supportRef[1] = fStartNew + (f - fStart)*4 + 3;
4067: for (s = 0; s < supportSize; ++s) {
4068: DMPlexGetConeSize(dm, support[s], &coneSize);
4069: DMPlexGetCone(dm, support[s], &cone);
4070: DMPlexGetConeOrientation(dm, support[s], &ornt);
4071: for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
4072: if (support[s] < cMax) {
4073: /* Here we want to determine whether edge newp contains a vertex which is part of the cross-tet edge */
4074: er = GetTriMidEdgeInverse_Static(ornt[c], r);
4075: if (er == eint[c]) {
4076: supportRef[2+intFaces++] = fStartNew + (fMax - fStart)*4 + (support[s] - cStart)*8 + (c + 2)%4;
4077: } else {
4078: supportRef[2+intFaces++] = fStartNew + (fMax - fStart)*4 + (support[s] - cStart)*8 + fint[(c*3 + er)*2 + 0];
4079: supportRef[2+intFaces++] = fStartNew + (fMax - fStart)*4 + (support[s] - cStart)*8 + fint[(c*3 + er)*2 + 1];
4080: }
4081: } else {
4082: supportRef[2+intFaces++] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (support[s] - cMax)*3 + (r + 1)%3;
4083: }
4084: }
4085: DMPlexSetSupport(rdm, newp, supportRef);
4086: #if 1
4087: if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
4088: for (p = 0; p < intFaces; ++p) {
4089: if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an interior or hybrid face [%d, %d)", supportRef[p], fStartNew, fEndNew);
4090: }
4091: #endif
4092: }
4093: }
4094: /* Interior cell edges have 2 vertices and 4 faces */
4095: for (c = cStart; c < cMax; ++c) {
4096: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
4097: const PetscInt *cone, *ornt, *fcone;
4098: PetscInt coneNew[2], supportNew[4], find;
4100: DMPlexGetCone(dm, c, &cone);
4101: DMPlexGetConeOrientation(dm, c, &ornt);
4102: DMPlexGetCone(dm, cone[0], &fcone);
4103: find = GetTriEdge_Static(ornt[0], 0);
4104: coneNew[0] = vStartNew + (vEnd - vStart) + (fcone[find] - eStart);
4105: DMPlexGetCone(dm, cone[2], &fcone);
4106: find = GetTriEdge_Static(ornt[2], 1);
4107: coneNew[1] = vStartNew + (vEnd - vStart) + (fcone[find] - eStart);
4108: DMPlexSetCone(rdm, newp, coneNew);
4109: #if 1
4110: if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
4111: for (p = 0; p < 2; ++p) {
4112: if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
4113: }
4114: #endif
4115: supportNew[0] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 4;
4116: supportNew[1] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 5;
4117: supportNew[2] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 6;
4118: supportNew[3] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 7;
4119: DMPlexSetSupport(rdm, newp, supportNew);
4120: #if 1
4121: if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
4122: for (p = 0; p < 4; ++p) {
4123: if ((supportNew[p] < fStartNew) || (supportNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportNew[p], fStartNew, fMaxNew);
4124: }
4125: #endif
4126: }
4127: /* Hybrid edges have two vertices and the same faces */
4128: for (e = eMax; e < eEnd; ++e) {
4129: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (e - eMax);
4130: const PetscInt *cone, *support, *fcone;
4131: PetscInt coneNew[2], size, fsize, s;
4133: DMPlexGetCone(dm, e, &cone);
4134: DMPlexGetSupportSize(dm, e, &size);
4135: DMPlexGetSupport(dm, e, &support);
4136: coneNew[0] = vStartNew + (cone[0] - vStart);
4137: coneNew[1] = vStartNew + (cone[1] - vStart);
4138: DMPlexSetCone(rdm, newp, coneNew);
4139: #if 1
4140: if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
4141: for (p = 0; p < 2; ++p) {
4142: if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
4143: }
4144: #endif
4145: for (s = 0; s < size; ++s) {
4146: DMPlexGetConeSize(dm, support[s], &fsize);
4147: DMPlexGetCone(dm, support[s], &fcone);
4148: for (c = 0; c < fsize; ++c) if (fcone[c] == e) break;
4149: if ((c < 2) || (c > 3)) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge %d not found in cone of face %d", e, support[s]);
4150: supportRef[s] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (support[s] - fMax)*2 + c-2;
4151: }
4152: DMPlexSetSupport(rdm, newp, supportRef);
4153: #if 1
4154: if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
4155: for (p = 0; p < size; ++p) {
4156: if ((supportRef[p] < fMaxNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", supportRef[p], fMaxNew, fEndNew);
4157: }
4158: #endif
4159: }
4160: /* Hybrid face edges have 2 vertices and 2+2*cells faces */
4161: for (f = fMax; f < fEnd; ++f) {
4162: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (f - fMax);
4163: const PetscInt *cone, *support, *ccone, *cornt;
4164: PetscInt coneNew[2], size, csize, s;
4166: DMPlexGetCone(dm, f, &cone);
4167: DMPlexGetSupportSize(dm, f, &size);
4168: DMPlexGetSupport(dm, f, &support);
4169: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - eStart);
4170: coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - eStart);
4171: DMPlexSetCone(rdm, newp, coneNew);
4172: #if 1
4173: if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
4174: for (p = 0; p < 2; ++p) {
4175: if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
4176: }
4177: #endif
4178: supportRef[0] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (f - fMax)*2 + 0;
4179: supportRef[1] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (f - fMax)*2 + 1;
4180: for (s = 0; s < size; ++s) {
4181: DMPlexGetConeSize(dm, support[s], &csize);
4182: DMPlexGetCone(dm, support[s], &ccone);
4183: DMPlexGetConeOrientation(dm, support[s], &cornt);
4184: for (c = 0; c < csize; ++c) if (ccone[c] == f) break;
4185: if ((c < 2) || (c >= csize)) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Hybrid face %d is not in cone of hybrid cell %d", f, support[s]);
4186: supportRef[2+s*2+0] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (support[s] - cMax)*3 + c-2;
4187: supportRef[2+s*2+1] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (support[s] - cMax)*3 + (c-1)%3;
4188: }
4189: DMPlexSetSupport(rdm, newp, supportRef);
4190: #if 1
4191: if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
4192: for (p = 0; p < 2+size*2; ++p) {
4193: if ((supportRef[p] < fMaxNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", supportRef[p], fMaxNew, fEndNew);
4194: }
4195: #endif
4196: }
4197: /* Interior vertices have identical supports */
4198: for (v = vStart; v < vEnd; ++v) {
4199: const PetscInt newp = vStartNew + (v - vStart);
4200: const PetscInt *support, *cone;
4201: PetscInt size, s;
4203: DMPlexGetSupportSize(dm, v, &size);
4204: DMPlexGetSupport(dm, v, &support);
4205: for (s = 0; s < size; ++s) {
4206: PetscInt r = 0;
4208: DMPlexGetCone(dm, support[s], &cone);
4209: if (cone[1] == v) r = 1;
4210: if (support[s] < eMax) supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
4211: else supportRef[s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (support[s] - eMax);
4212: }
4213: DMPlexSetSupport(rdm, newp, supportRef);
4214: #if 1
4215: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
4216: for (p = 0; p < size; ++p) {
4217: if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an interior or hybrid edge [%d, %d)", supportRef[p], eStartNew, eEndNew);
4218: }
4219: #endif
4220: }
4221: /* Interior edge vertices have 2 + interior face*2 + hybrid face + cells*0/1 supports */
4222: for (e = eStart; e < eMax; ++e) {
4223: const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
4224: const PetscInt *cone, *support;
4225: PetscInt *star = NULL, starSize, faceSize = 0, cellSize = 0, coneSize, size, s;
4227: DMPlexGetSupportSize(dm, e, &size);
4228: DMPlexGetSupport(dm, e, &support);
4229: supportRef[0] = eStartNew + (e - eStart)*2 + 0;
4230: supportRef[1] = eStartNew + (e - eStart)*2 + 1;
4231: for (s = 0; s < size; ++s) {
4232: PetscInt r = 0;
4234: if (support[s] < fMax) {
4235: DMPlexGetConeSize(dm, support[s], &coneSize);
4236: DMPlexGetCone(dm, support[s], &cone);
4237: for (r = 0; r < coneSize; ++r) {if (cone[r] == e) break;}
4238: supportRef[2+faceSize+0] = eStartNew + (eMax - eStart)*2 + (support[s] - fStart)*3 + (r+0)%3;
4239: supportRef[2+faceSize+1] = eStartNew + (eMax - eStart)*2 + (support[s] - fStart)*3 + (r+2)%3;
4240: faceSize += 2;
4241: } else {
4242: supportRef[2+faceSize+0] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (support[s] - fMax);
4243: ++faceSize;
4244: }
4245: }
4246: DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
4247: for (s = 0; s < starSize*2; s += 2) {
4248: const PetscInt *cone, *ornt;
4249: PetscInt e01, e23;
4251: if ((star[s] >= cStart) && (star[s] < cMax)) {
4252: /* Check edge 0-1 */
4253: DMPlexGetCone(dm, star[s], &cone);
4254: DMPlexGetConeOrientation(dm, star[s], &ornt);
4255: DMPlexGetCone(dm, cone[0], &cone);
4256: e01 = cone[GetTriEdge_Static(ornt[0], 0)];
4257: /* Check edge 2-3 */
4258: DMPlexGetCone(dm, star[s], &cone);
4259: DMPlexGetConeOrientation(dm, star[s], &ornt);
4260: DMPlexGetCone(dm, cone[2], &cone);
4261: e23 = cone[GetTriEdge_Static(ornt[2], 1)];
4262: if ((e01 == e) || (e23 == e)) {supportRef[2+faceSize+cellSize++] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (star[s] - cStart);}
4263: }
4264: }
4265: DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
4266: DMPlexSetSupport(rdm, newp, supportRef);
4267: #if 1
4268: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
4269: for (p = 0; p < 2+faceSize+cellSize; ++p) {
4270: if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an interior or hybrid edge [%d, %d)", supportRef[p], eStartNew, eEndNew);
4271: }
4272: #endif
4273: }
4274: PetscFree(supportRef);
4275: DMPlexRestoreFaces_Internal(dm, 3, cStart, NULL, NULL, &faces);
4276: break;
4277: case REFINER_SIMPLEX_TO_HEX_3D:
4278: DMPlexGetRawFaces_Internal(dm, 3, 4, cellInd, NULL, NULL, &faces);
4279: /* All cells have 6 faces */
4280: for (c = cStart; c < cEnd; ++c) {
4281: const PetscInt newp = cStartNew + (c - cStart)*4;
4282: const PetscInt *cone, *ornt;
4283: PetscInt coneNew[6];
4284: PetscInt orntNew[6];
4286: DMPlexGetCone(dm, c, &cone);
4287: DMPlexGetConeOrientation(dm, c, &ornt);
4288: /* A hex */
4289: coneNew[0] = fStartNew + (cone[0] - fStart)*3 + GetTriSubface_Static(ornt[0], 0); /* B */
4290: orntNew[0] = ornt[0] < 0 ? -1 : 1;
4291: coneNew[1] = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + 3; /* T */
4292: orntNew[1] = -4;
4293: coneNew[2] = fStartNew + (cone[2] - fStart)*3 + GetTriSubface_Static(ornt[2], 0); /* F */
4294: orntNew[2] = ornt[2] < 0 ? -1 : 1;
4295: coneNew[3] = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + 0; /* K */
4296: orntNew[3] = -1;
4297: coneNew[4] = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + 2; /* R */
4298: orntNew[4] = 0;
4299: coneNew[5] = fStartNew + (cone[1] - fStart)*3 + GetTriSubface_Static(ornt[1], 0); /* L */
4300: orntNew[5] = ornt[1] < 0 ? -1 : 1;
4301: DMPlexSetCone(rdm, newp+0, coneNew);
4302: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
4303: #if 1
4304: if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew);
4305: for (p = 0; p < 6; ++p) {
4306: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
4307: }
4308: #endif
4309: /* B hex */
4310: coneNew[0] = fStartNew + (cone[0] - fStart)*3 + GetTriSubface_Static(ornt[0], 1); /* B */
4311: orntNew[0] = ornt[0] < 0 ? -2 : 0;
4312: coneNew[1] = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + 4; /* T */
4313: orntNew[1] = 0;
4314: coneNew[2] = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + 0; /* F */
4315: orntNew[2] = 0;
4316: coneNew[3] = fStartNew + (cone[3] - fStart)*3 + GetTriSubface_Static(ornt[3], 1); /* K */
4317: orntNew[3] = ornt[3] < 0 ? -2 : 0;
4318: coneNew[4] = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + 1; /* R */
4319: orntNew[4] = 0;
4320: coneNew[5] = fStartNew + (cone[1] - fStart)*3 + GetTriSubface_Static(ornt[1], 2); /* L */
4321: orntNew[5] = ornt[1] < 0 ? -4 : 2;
4322: DMPlexSetCone(rdm, newp+1, coneNew);
4323: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
4324: #if 1
4325: if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew);
4326: for (p = 0; p < 6; ++p) {
4327: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
4328: }
4329: #endif
4330: /* C hex */
4331: coneNew[0] = fStartNew + (cone[0] - fStart)*3 + GetTriSubface_Static(ornt[0], 2); /* B */
4332: orntNew[0] = ornt[0] < 0 ? -4 : 2;
4333: coneNew[1] = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + 5; /* T */
4334: orntNew[1] = -4;
4335: coneNew[2] = fStartNew + (cone[2] - fStart)*3 + GetTriSubface_Static(ornt[2], 1); /* F */
4336: orntNew[2] = ornt[2] < 0 ? -2 : 0;
4337: coneNew[3] = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + 1; /* K */
4338: orntNew[3] = -1;
4339: coneNew[4] = fStartNew + (cone[3] - fStart)*3 + GetTriSubface_Static(ornt[3], 0); /* R */
4340: orntNew[4] = ornt[3] < 0 ? -1 : 1;
4341: coneNew[5] = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + 2; /* L */
4342: orntNew[5] = -4;
4343: DMPlexSetCone(rdm, newp+2, coneNew);
4344: DMPlexSetConeOrientation(rdm, newp+2, orntNew);
4345: #if 1
4346: if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew);
4347: for (p = 0; p < 6; ++p) {
4348: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
4349: }
4350: #endif
4351: /* D hex */
4352: coneNew[0] = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + 3; /* B */
4353: orntNew[0] = 0;
4354: coneNew[1] = fStartNew + (cone[3] - fStart)*3 + GetTriSubface_Static(ornt[3], 2); /* T */
4355: orntNew[1] = ornt[3] < 0 ? -1 : 1;
4356: coneNew[2] = fStartNew + (cone[2] - fStart)*3 + GetTriSubface_Static(ornt[2], 2); /* F */
4357: orntNew[2] = ornt[2] < 0 ? -4 : 2;
4358: coneNew[3] = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + 4; /* K */
4359: orntNew[3] = -1;
4360: coneNew[4] = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + 5; /* R */
4361: orntNew[4] = 0;
4362: coneNew[5] = fStartNew + (cone[1] - fStart)*3 + GetTriSubface_Static(ornt[1], 1); /* L */
4363: orntNew[5] = ornt[1] < 0 ? -2 : 0;
4364: DMPlexSetCone(rdm, newp+3, coneNew);
4365: DMPlexSetConeOrientation(rdm, newp+3, orntNew);
4366: #if 1
4367: if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew);
4368: for (p = 0; p < 6; ++p) {
4369: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
4370: }
4371: #endif
4372: }
4373: /* Split faces have 4 edges and the same cells as the parent */
4374: DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
4375: PetscMalloc1(2 + maxSupportSize*2, &supportRef);
4376: for (f = fStart; f < fEnd; ++f) {
4377: const PetscInt newp = fStartNew + (f - fStart)*3;
4378: const PetscInt *cone, *ornt, *support;
4379: PetscInt coneNew[4], orntNew[4], coneSize, supportSize, s;
4381: DMPlexGetCone(dm, f, &cone);
4382: DMPlexGetConeOrientation(dm, f, &ornt);
4383: /* A quad */
4384: coneNew[0] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 0 : 1);
4385: orntNew[0] = ornt[2];
4386: coneNew[1] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1 : 0);
4387: orntNew[1] = ornt[0];
4388: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 0;
4389: orntNew[2] = 0;
4390: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 2;
4391: orntNew[3] = -2;
4392: DMPlexSetCone(rdm, newp+0, coneNew);
4393: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
4394: #if 1
4395: if ((newp+0 < fStartNew) || (newp+0 >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+0, fStartNew, fEndNew);
4396: for (p = 0; p < 4; ++p) {
4397: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
4398: }
4399: #endif
4400: /* B quad */
4401: coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 0 : 1);
4402: orntNew[0] = ornt[0];
4403: coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1 : 0);
4404: orntNew[1] = ornt[1];
4405: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 1;
4406: orntNew[2] = 0;
4407: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 0;
4408: orntNew[3] = -2;
4409: DMPlexSetCone(rdm, newp+1, coneNew);
4410: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
4411: #if 1
4412: if ((newp+1 < fStartNew) || (newp+1 >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+1, fStartNew, fEndNew);
4413: for (p = 0; p < 4; ++p) {
4414: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
4415: }
4416: #endif
4417: /* C quad */
4418: coneNew[0] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 0 : 1);
4419: orntNew[0] = ornt[1];
4420: coneNew[1] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 1 : 0);
4421: orntNew[1] = ornt[2];
4422: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 2;
4423: orntNew[2] = 0;
4424: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 1;
4425: orntNew[3] = -2;
4426: DMPlexSetCone(rdm, newp+2, coneNew);
4427: DMPlexSetConeOrientation(rdm, newp+2, orntNew);
4428: #if 1
4429: if ((newp+2 < fStartNew) || (newp+2 >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+2, fStartNew, fEndNew);
4430: for (p = 0; p < 4; ++p) {
4431: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
4432: }
4433: #endif
4434: DMPlexGetSupportSize(dm, f, &supportSize);
4435: DMPlexGetSupport(dm, f, &support);
4436: for (r = 0; r < 3; ++r) {
4437: for (s = 0; s < supportSize; ++s) {
4438: PetscInt subf;
4439: DMPlexGetConeSize(dm, support[s], &coneSize);
4440: DMPlexGetCone(dm, support[s], &cone);
4441: DMPlexGetConeOrientation(dm, support[s], &ornt);
4442: for (c = 0; c < coneSize; ++c) {
4443: if (cone[c] == f) break;
4444: }
4445: subf = GetTriSubfaceInverse_Static(ornt[c], r);
4446: supportRef[s] = cStartNew + (support[s] - cStart)*4 + faces[c*3+subf];
4447: }
4448: DMPlexSetSupport(rdm, newp+r, supportRef);
4449: #if 1
4450: if ((newp+r < fStartNew) || (newp+r >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+r, fStartNew, fEndNew);
4451: for (p = 0; p < supportSize; ++p) {
4452: if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew);
4453: }
4454: #endif
4455: }
4456: }
4457: /* Interior faces have 4 edges and 2 cells */
4458: for (c = cStart; c < cEnd; ++c) {
4459: PetscInt newp = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6;
4460: const PetscInt *cone, *ornt;
4461: PetscInt coneNew[4], orntNew[4];
4462: PetscInt supportNew[2];
4464: DMPlexGetCone(dm, c, &cone);
4465: DMPlexGetConeOrientation(dm, c, &ornt);
4466: /* Face {a, g, m, h} */
4467: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTriInteriorEdge_Static(ornt[0],0);
4468: orntNew[0] = 0;
4469: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 0;
4470: orntNew[1] = 0;
4471: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 1;
4472: orntNew[2] = -2;
4473: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTriInteriorEdge_Static(ornt[1],2);
4474: orntNew[3] = -2;
4475: DMPlexSetCone(rdm, newp, coneNew);
4476: DMPlexSetConeOrientation(rdm, newp, orntNew);
4477: #if 1
4478: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
4479: for (p = 0; p < 4; ++p) {
4480: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
4481: }
4482: #endif
4483: supportNew[0] = (c - cStart)*4 + 0;
4484: supportNew[1] = (c - cStart)*4 + 1;
4485: DMPlexSetSupport(rdm, newp, supportNew);
4486: #if 1
4487: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
4488: for (p = 0; p < 2; ++p) {
4489: if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
4490: }
4491: #endif
4492: ++newp;
4493: /* Face {g, b, l , m} */
4494: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTriInteriorEdge_Static(ornt[0],1);
4495: orntNew[0] = -2;
4496: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTriInteriorEdge_Static(ornt[3],0);
4497: orntNew[1] = 0;
4498: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 3;
4499: orntNew[2] = 0;
4500: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 0;
4501: orntNew[3] = -2;
4502: DMPlexSetCone(rdm, newp, coneNew);
4503: DMPlexSetConeOrientation(rdm, newp, orntNew);
4504: #if 1
4505: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
4506: for (p = 0; p < 4; ++p) {
4507: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
4508: }
4509: #endif
4510: supportNew[0] = (c - cStart)*4 + 1;
4511: supportNew[1] = (c - cStart)*4 + 2;
4512: DMPlexSetSupport(rdm, newp, supportNew);
4513: #if 1
4514: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
4515: for (p = 0; p < 2; ++p) {
4516: if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
4517: }
4518: #endif
4519: ++newp;
4520: /* Face {c, g, m, i} */
4521: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTriInteriorEdge_Static(ornt[0],2);
4522: orntNew[0] = 0;
4523: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 0;
4524: orntNew[1] = 0;
4525: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 2;
4526: orntNew[2] = -2;
4527: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTriInteriorEdge_Static(ornt[2],0);
4528: orntNew[3] = -2;
4529: DMPlexSetCone(rdm, newp, coneNew);
4530: DMPlexSetConeOrientation(rdm, newp, orntNew);
4531: #if 1
4532: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
4533: for (p = 0; p < 4; ++p) {
4534: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
4535: }
4536: #endif
4537: supportNew[0] = (c - cStart)*4 + 0;
4538: supportNew[1] = (c - cStart)*4 + 2;
4539: DMPlexSetSupport(rdm, newp, supportNew);
4540: #if 1
4541: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
4542: for (p = 0; p < 2; ++p) {
4543: if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
4544: }
4545: #endif
4546: ++newp;
4547: /* Face {d, h, m, i} */
4548: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTriInteriorEdge_Static(ornt[1],0);
4549: orntNew[0] = 0;
4550: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 1;
4551: orntNew[1] = 0;
4552: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 2;
4553: orntNew[2] = -2;
4554: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTriInteriorEdge_Static(ornt[2],2);
4555: orntNew[3] = -2;
4556: DMPlexSetCone(rdm, newp, coneNew);
4557: DMPlexSetConeOrientation(rdm, newp, orntNew);
4558: #if 1
4559: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
4560: for (p = 0; p < 4; ++p) {
4561: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
4562: }
4563: #endif
4564: supportNew[0] = (c - cStart)*4 + 0;
4565: supportNew[1] = (c - cStart)*4 + 3;
4566: DMPlexSetSupport(rdm, newp, supportNew);
4567: #if 1
4568: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
4569: for (p = 0; p < 2; ++p) {
4570: if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
4571: }
4572: #endif
4573: ++newp;
4574: /* Face {h, m, l, e} */
4575: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 1;
4576: orntNew[0] = 0;
4577: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 3;
4578: orntNew[1] = -2;
4579: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTriInteriorEdge_Static(ornt[3],1);
4580: orntNew[2] = -2;
4581: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTriInteriorEdge_Static(ornt[1],1);
4582: orntNew[3] = 0;
4583: DMPlexSetCone(rdm, newp, coneNew);
4584: DMPlexSetConeOrientation(rdm, newp, orntNew);
4585: #if 1
4586: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
4587: for (p = 0; p < 4; ++p) {
4588: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
4589: }
4590: #endif
4591: supportNew[0] = (c - cStart)*4 + 1;
4592: supportNew[1] = (c - cStart)*4 + 3;
4593: DMPlexSetSupport(rdm, newp, supportNew);
4594: #if 1
4595: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
4596: for (p = 0; p < 2; ++p) {
4597: if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
4598: }
4599: #endif
4600: ++newp;
4601: /* Face {i, m, l, f} */
4602: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 2;
4603: orntNew[0] = 0;
4604: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 3;
4605: orntNew[1] = -2;
4606: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTriInteriorEdge_Static(ornt[3],2);
4607: orntNew[2] = -2;
4608: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTriInteriorEdge_Static(ornt[2],1);
4609: orntNew[3] = 0;
4610: DMPlexSetCone(rdm, newp, coneNew);
4611: DMPlexSetConeOrientation(rdm, newp, orntNew);
4612: #if 1
4613: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
4614: for (p = 0; p < 4; ++p) {
4615: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
4616: }
4617: #endif
4618: supportNew[0] = (c - cStart)*4 + 2;
4619: supportNew[1] = (c - cStart)*4 + 3;
4620: DMPlexSetSupport(rdm, newp, supportNew);
4621: #if 1
4622: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
4623: for (p = 0; p < 2; ++p) {
4624: if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
4625: }
4626: #endif
4627: ++newp;
4628: }
4629: /* Split Edges have 2 vertices and the same faces as the parent */
4630: for (e = eStart; e < eEnd; ++e) {
4631: const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);
4633: for (r = 0; r < 2; ++r) {
4634: const PetscInt newp = eStartNew + (e - eStart)*2 + r;
4635: const PetscInt *cone, *ornt, *support;
4636: PetscInt coneNew[2], coneSize, c, supportSize, s;
4638: DMPlexGetCone(dm, e, &cone);
4639: coneNew[0] = vStartNew + (cone[0] - vStart);
4640: coneNew[1] = vStartNew + (cone[1] - vStart);
4641: coneNew[(r+1)%2] = newv;
4642: DMPlexSetCone(rdm, newp, coneNew);
4643: #if 1
4644: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
4645: for (p = 0; p < 2; ++p) {
4646: if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
4647: }
4648: #endif
4649: DMPlexGetSupportSize(dm, e, &supportSize);
4650: DMPlexGetSupport(dm, e, &support);
4651: for (s = 0; s < supportSize; ++s) {
4652: DMPlexGetConeSize(dm, support[s], &coneSize);
4653: DMPlexGetCone(dm, support[s], &cone);
4654: DMPlexGetConeOrientation(dm, support[s], &ornt);
4655: for (c = 0; c < coneSize; ++c) {
4656: if (cone[c] == e) break;
4657: }
4658: supportRef[s] = fStartNew + (support[s] - fStart)*3 + (c + (ornt[c] < 0 ? 1-r : r))%3;
4659: }
4660: DMPlexSetSupport(rdm, newp, supportRef);
4661: #if 1
4662: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
4663: for (p = 0; p < supportSize; ++p) {
4664: if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
4665: }
4666: #endif
4667: }
4668: }
4669: /* Face edges have 2 vertices and 2 + cell faces supports */
4670: for (f = fStart; f < fEnd; ++f) {
4671: const PetscInt *cone, *ornt, *support;
4672: PetscInt coneSize, supportSize, s;
4674: DMPlexGetSupportSize(dm, f, &supportSize);
4675: DMPlexGetSupport(dm, f, &support);
4676: for (r = 0; r < 3; ++r) {
4677: const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + r;
4678: PetscInt coneNew[2];
4679: PetscInt fint[4][3] = { {0, 1, 2},
4680: {3, 4, 0},
4681: {2, 5, 3},
4682: {1, 4, 5} };
4684: DMPlexGetCone(dm, f, &cone);
4685: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - eStart);
4686: coneNew[1] = vStartNew + (vEnd - vStart) + (eEnd - eStart) + f - fStart;
4687: DMPlexSetCone(rdm, newp, coneNew);
4688: #if 1
4689: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
4690: for (p = 0; p < 2; ++p) {
4691: if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
4692: }
4693: #endif
4694: supportRef[0] = fStartNew + (f - fStart)*3 + (r+0)%3;
4695: supportRef[1] = fStartNew + (f - fStart)*3 + (r+1)%3;
4696: for (s = 0; s < supportSize; ++s) {
4697: PetscInt er;
4698: DMPlexGetConeSize(dm, support[s], &coneSize);
4699: DMPlexGetCone(dm, support[s], &cone);
4700: DMPlexGetConeOrientation(dm, support[s], &ornt);
4701: for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
4702: er = GetTriInteriorEdgeInverse_Static(ornt[c], r);
4703: supportRef[2+s] = fStartNew + (fEnd - fStart)*3 + (support[s] - cStart)*6 + fint[c][er];
4704: }
4705: DMPlexSetSupport(rdm, newp, supportRef);
4706: #if 1
4707: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
4708: for (p = 0; p < supportSize + 2; ++p) {
4709: if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
4710: }
4711: #endif
4712: }
4713: }
4714: /* Interior cell edges have 2 vertices and 3 faces */
4715: for (c = cStart; c < cEnd; ++c) {
4716: const PetscInt *cone;
4717: PetscInt fint[4][3] = { {0,1,2},
4718: {0,3,4},
4719: {2,3,5},
4720: {1,4,5} } ;
4722: DMPlexGetCone(dm, c, &cone);
4723: for (r = 0; r < 4; r++) {
4724: PetscInt coneNew[2], supportNew[3];
4725: const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + r;
4727: coneNew[0] = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (cone[r] - fStart);
4728: coneNew[1] = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd -fStart) + c - cStart;
4729: DMPlexSetCone(rdm, newp, coneNew);
4730: #if 1
4731: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
4732: for (p = 0; p < 2; ++p) {
4733: if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
4734: }
4735: #endif
4736: supportNew[0] = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + fint[r][0];
4737: supportNew[1] = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + fint[r][1];
4738: supportNew[2] = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + fint[r][2];
4739: DMPlexSetSupport(rdm, newp, supportNew);
4740: #if 1
4741: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
4742: for (p = 0; p < 3; ++p) {
4743: if ((supportNew[p] < fStartNew) || (supportNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportNew[p], fStartNew, fEndNew);
4744: }
4745: #endif
4746: }
4747: }
4748: /* Old vertices have identical supports */
4749: for (v = vStart; v < vEnd; ++v) {
4750: const PetscInt newp = vStartNew + (v - vStart);
4751: const PetscInt *support, *cone;
4752: PetscInt size, s;
4754: DMPlexGetSupportSize(dm, v, &size);
4755: DMPlexGetSupport(dm, v, &support);
4756: for (s = 0; s < size; ++s) {
4757: PetscInt r = 0;
4759: DMPlexGetCone(dm, support[s], &cone);
4760: if (cone[1] == v) r = 1;
4761: supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
4762: }
4763: DMPlexSetSupport(rdm, newp, supportRef);
4764: #if 1
4765: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
4766: for (p = 0; p < size; ++p) {
4767: if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", supportRef[p], eStartNew, eEndNew);
4768: }
4769: #endif
4770: }
4771: /* Edge vertices have 2 + faces supports */
4772: for (e = eStart; e < eEnd; ++e) {
4773: const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
4774: const PetscInt *cone, *support;
4775: PetscInt size, s;
4777: DMPlexGetSupportSize(dm, e, &size);
4778: DMPlexGetSupport(dm, e, &support);
4779: supportRef[0] = eStartNew + (e - eStart)*2 + 0;
4780: supportRef[1] = eStartNew + (e - eStart)*2 + 1;
4781: for (s = 0; s < size; ++s) {
4782: PetscInt r = 0, coneSize;
4784: DMPlexGetConeSize(dm, support[s], &coneSize);
4785: DMPlexGetCone(dm, support[s], &cone);
4786: for (r = 0; r < coneSize; ++r) {if (cone[r] == e) break;}
4787: supportRef[2+s] = eStartNew + (eEnd - eStart)*2 + (support[s] - fStart)*3 + r;
4788: }
4789: DMPlexSetSupport(rdm, newp, supportRef);
4790: #if 1
4791: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
4792: for (p = 0; p < 2+size; ++p) {
4793: if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", supportRef[p], eStartNew, eEndNew);
4794: }
4795: #endif
4796: }
4797: /* Face vertices have 3 + cells supports */
4798: for (f = fStart; f < fEnd; ++f) {
4799: const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (f - fStart);
4800: const PetscInt *cone, *support;
4801: PetscInt size, s;
4803: DMPlexGetSupportSize(dm, f, &size);
4804: DMPlexGetSupport(dm, f, &support);
4805: supportRef[0] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 0;
4806: supportRef[1] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 1;
4807: supportRef[2] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 2;
4808: for (s = 0; s < size; ++s) {
4809: PetscInt r = 0, coneSize;
4811: DMPlexGetConeSize(dm, support[s], &coneSize);
4812: DMPlexGetCone(dm, support[s], &cone);
4813: for (r = 0; r < coneSize; ++r) {if (cone[r] == f) break;}
4814: supportRef[3+s] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (support[s] - cStart)*4 + r;
4815: }
4816: DMPlexSetSupport(rdm, newp, supportRef);
4817: #if 1
4818: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
4819: for (p = 0; p < 3+size; ++p) {
4820: if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", supportRef[p], eStartNew, eEndNew);
4821: }
4822: #endif
4823: }
4824: /* Interior cell vertices have 4 supports */
4825: for (c = cStart; c < cEnd; ++c) {
4826: const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + c - cStart;
4827: supportRef[0] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 0;
4828: supportRef[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 1;
4829: supportRef[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 2;
4830: supportRef[3] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 3;
4831: DMPlexSetSupport(rdm, newp, supportRef);
4832: #if 1
4833: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
4834: for (p = 0; p < 4; ++p) {
4835: if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", supportRef[p], eStartNew, eEndNew);
4836: }
4837: #endif
4838: }
4839: PetscFree(supportRef);
4840: DMPlexRestoreFaces_Internal(dm, 3, cStart, NULL, NULL, &faces);
4841: break;
4842: case REFINER_HEX_3D:
4843: /*
4844: Bottom (viewed from top) Top
4845: 1---------2---------2 7---------2---------6
4846: | | | | | |
4847: | B 2 C | | H 2 G |
4848: | | | | | |
4849: 3----3----0----1----1 3----3----0----1----1
4850: | | | | | |
4851: | A 0 D | | E 0 F |
4852: | | | | | |
4853: 0---------0---------3 4---------0---------5
4854: */
4855: /* All cells have 6 faces: Bottom, Top, Front, Back, Right, Left */
4856: for (c = cStart; c < cEnd; ++c) {
4857: const PetscInt newp = (c - cStart)*8;
4858: const PetscInt *cone, *ornt;
4859: PetscInt coneNew[6], orntNew[6];
4861: DMPlexGetCone(dm, c, &cone);
4862: DMPlexGetConeOrientation(dm, c, &ornt);
4863: /* A hex */
4864: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 0);
4865: orntNew[0] = ornt[0];
4866: coneNew[1] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 8; /* AE */
4867: orntNew[1] = 0;
4868: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 0);
4869: orntNew[2] = ornt[2];
4870: coneNew[3] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 3; /* AB */
4871: orntNew[3] = 0;
4872: coneNew[4] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 0; /* AD */
4873: orntNew[4] = 0;
4874: coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 0);
4875: orntNew[5] = ornt[5];
4876: DMPlexSetCone(rdm, newp+0, coneNew);
4877: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
4878: #if 1
4879: if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew);
4880: for (p = 0; p < 6; ++p) {
4881: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
4882: }
4883: #endif
4884: /* B hex */
4885: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 1);
4886: orntNew[0] = ornt[0];
4887: coneNew[1] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 11; /* BH */
4888: orntNew[1] = 0;
4889: coneNew[2] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 3; /* AB */
4890: orntNew[2] = -1;
4891: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 1);
4892: orntNew[3] = ornt[3];
4893: coneNew[4] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 2; /* BC */
4894: orntNew[4] = 0;
4895: coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 3);
4896: orntNew[5] = ornt[5];
4897: DMPlexSetCone(rdm, newp+1, coneNew);
4898: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
4899: #if 1
4900: if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew);
4901: for (p = 0; p < 6; ++p) {
4902: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
4903: }
4904: #endif
4905: /* C hex */
4906: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 2);
4907: orntNew[0] = ornt[0];
4908: coneNew[1] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 10; /* CG */
4909: orntNew[1] = 0;
4910: coneNew[2] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 1; /* CD */
4911: orntNew[2] = -1;
4912: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 0);
4913: orntNew[3] = ornt[3];
4914: coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 1);
4915: orntNew[4] = ornt[4];
4916: coneNew[5] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 2; /* BC */
4917: orntNew[5] = -4;
4918: DMPlexSetCone(rdm, newp+2, coneNew);
4919: DMPlexSetConeOrientation(rdm, newp+2, orntNew);
4920: #if 1
4921: if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew);
4922: for (p = 0; p < 6; ++p) {
4923: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
4924: }
4925: #endif
4926: /* D hex */
4927: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 3);
4928: orntNew[0] = ornt[0];
4929: coneNew[1] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 9; /* DF */
4930: orntNew[1] = 0;
4931: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 1);
4932: orntNew[2] = ornt[2];
4933: coneNew[3] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 1; /* CD */
4934: orntNew[3] = 0;
4935: coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 0);
4936: orntNew[4] = ornt[4];
4937: coneNew[5] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 0; /* AD */
4938: orntNew[5] = -4;
4939: DMPlexSetCone(rdm, newp+3, coneNew);
4940: DMPlexSetConeOrientation(rdm, newp+3, orntNew);
4941: #if 1
4942: if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew);
4943: for (p = 0; p < 6; ++p) {
4944: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
4945: }
4946: #endif
4947: /* E hex */
4948: coneNew[0] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 8; /* AE */
4949: orntNew[0] = -4;
4950: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 0);
4951: orntNew[1] = ornt[1];
4952: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 3);
4953: orntNew[2] = ornt[2];
4954: coneNew[3] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 7; /* EH */
4955: orntNew[3] = 0;
4956: coneNew[4] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 4; /* EF */
4957: orntNew[4] = -1;
4958: coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 1);
4959: orntNew[5] = ornt[5];
4960: DMPlexSetCone(rdm, newp+4, coneNew);
4961: DMPlexSetConeOrientation(rdm, newp+4, orntNew);
4962: #if 1
4963: if ((newp+4 < cStartNew) || (newp+4 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+4, cStartNew, cEndNew);
4964: for (p = 0; p < 6; ++p) {
4965: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
4966: }
4967: #endif
4968: /* F hex */
4969: coneNew[0] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 9; /* DF */
4970: orntNew[0] = -4;
4971: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 1);
4972: orntNew[1] = ornt[1];
4973: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 2);
4974: orntNew[2] = ornt[2];
4975: coneNew[3] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 5; /* FG */
4976: orntNew[3] = -1;
4977: coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 3);
4978: orntNew[4] = ornt[4];
4979: coneNew[5] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 4; /* EF */
4980: orntNew[5] = 1;
4981: DMPlexSetCone(rdm, newp+5, coneNew);
4982: DMPlexSetConeOrientation(rdm, newp+5, orntNew);
4983: #if 1
4984: if ((newp+5 < cStartNew) || (newp+5 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+5, cStartNew, cEndNew);
4985: for (p = 0; p < 6; ++p) {
4986: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
4987: }
4988: #endif
4989: /* G hex */
4990: coneNew[0] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 10; /* CG */
4991: orntNew[0] = -4;
4992: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 2);
4993: orntNew[1] = ornt[1];
4994: coneNew[2] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 5; /* FG */
4995: orntNew[2] = 0;
4996: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 3);
4997: orntNew[3] = ornt[3];
4998: coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 2);
4999: orntNew[4] = ornt[4];
5000: coneNew[5] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 6; /* GH */
5001: orntNew[5] = -3;
5002: DMPlexSetCone(rdm, newp+6, coneNew);
5003: DMPlexSetConeOrientation(rdm, newp+6, orntNew);
5004: #if 1
5005: if ((newp+6 < cStartNew) || (newp+6 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+6, cStartNew, cEndNew);
5006: for (p = 0; p < 6; ++p) {
5007: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
5008: }
5009: #endif
5010: /* H hex */
5011: coneNew[0] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 11; /* BH */
5012: orntNew[0] = -4;
5013: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 3);
5014: orntNew[1] = ornt[1];
5015: coneNew[2] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 7; /* EH */
5016: orntNew[2] = -1;
5017: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 2);
5018: orntNew[3] = ornt[3];
5019: coneNew[4] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 6; /* GH */
5020: orntNew[4] = 3;
5021: coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 2);
5022: orntNew[5] = ornt[5];
5023: DMPlexSetCone(rdm, newp+7, coneNew);
5024: DMPlexSetConeOrientation(rdm, newp+7, orntNew);
5025: #if 1
5026: if ((newp+7 < cStartNew) || (newp+7 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+7, cStartNew, cEndNew);
5027: for (p = 0; p < 6; ++p) {
5028: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
5029: }
5030: #endif
5031: }
5032: /* Split faces have 4 edges and the same cells as the parent */
5033: DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
5034: PetscMalloc1(4 + maxSupportSize*2, &supportRef);
5035: for (f = fStart; f < fEnd; ++f) {
5036: for (r = 0; r < 4; ++r) {
5037: /* TODO: This can come from GetFaces_Internal() */
5038: const PetscInt newCells[24] = {0, 1, 2, 3, 4, 5, 6, 7, 0, 3, 5, 4, 2, 1, 7, 6, 3, 2, 6, 5, 0, 4, 7, 1};
5039: const PetscInt newp = fStartNew + (f - fStart)*4 + r;
5040: const PetscInt *cone, *ornt, *support;
5041: PetscInt coneNew[4], orntNew[4], coneSize, c, supportSize, s;
5043: DMPlexGetCone(dm, f, &cone);
5044: DMPlexGetConeOrientation(dm, f, &ornt);
5045: coneNew[(r+3)%4] = eStartNew + (cone[(r+3)%4] - eStart)*2 + (ornt[(r+3)%4] < 0 ? 0 : 1);
5046: orntNew[(r+3)%4] = ornt[(r+3)%4];
5047: coneNew[(r+0)%4] = eStartNew + (cone[r] - eStart)*2 + (ornt[r] < 0 ? 1 : 0);
5048: orntNew[(r+0)%4] = ornt[r];
5049: coneNew[(r+1)%4] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + r;
5050: orntNew[(r+1)%4] = 0;
5051: coneNew[(r+2)%4] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + (r+3)%4;
5052: orntNew[(r+2)%4] = -2;
5053: DMPlexSetCone(rdm, newp, coneNew);
5054: DMPlexSetConeOrientation(rdm, newp, orntNew);
5055: #if 1
5056: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
5057: for (p = 0; p < 4; ++p) {
5058: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
5059: }
5060: #endif
5061: DMPlexGetSupportSize(dm, f, &supportSize);
5062: DMPlexGetSupport(dm, f, &support);
5063: for (s = 0; s < supportSize; ++s) {
5064: DMPlexGetConeSize(dm, support[s], &coneSize);
5065: DMPlexGetCone(dm, support[s], &cone);
5066: DMPlexGetConeOrientation(dm, support[s], &ornt);
5067: for (c = 0; c < coneSize; ++c) {
5068: if (cone[c] == f) break;
5069: }
5070: supportRef[s] = cStartNew + (support[s] - cStart)*8 + newCells[c*4+GetQuadSubfaceInverse_Static(ornt[c], r)];
5071: }
5072: DMPlexSetSupport(rdm, newp, supportRef);
5073: #if 1
5074: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
5075: for (p = 0; p < supportSize; ++p) {
5076: if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew);
5077: }
5078: #endif
5079: }
5080: }
5081: /* Interior faces have 4 edges and 2 cells */
5082: for (c = cStart; c < cEnd; ++c) {
5083: const PetscInt newCells[24] = {0, 3, 2, 3, 1, 2, 0, 1, 4, 5, 5, 6, 6, 7, 4, 7, 0, 4, 3, 5, 2, 6, 1, 7};
5084: const PetscInt *cone, *ornt;
5085: PetscInt newp, coneNew[4], orntNew[4], supportNew[2];
5087: DMPlexGetCone(dm, c, &cone);
5088: DMPlexGetConeOrientation(dm, c, &ornt);
5089: /* A-D face */
5090: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 0;
5091: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 3);
5092: orntNew[0] = 0;
5093: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 0;
5094: orntNew[1] = 0;
5095: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 2;
5096: orntNew[2] = -2;
5097: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 0);
5098: orntNew[3] = -2;
5099: DMPlexSetCone(rdm, newp, coneNew);
5100: DMPlexSetConeOrientation(rdm, newp, orntNew);
5101: #if 1
5102: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
5103: for (p = 0; p < 4; ++p) {
5104: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
5105: }
5106: #endif
5107: /* C-D face */
5108: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 1;
5109: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 2);
5110: orntNew[0] = 0;
5111: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 0;
5112: orntNew[1] = 0;
5113: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 4;
5114: orntNew[2] = -2;
5115: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 0);
5116: orntNew[3] = -2;
5117: DMPlexSetCone(rdm, newp, coneNew);
5118: DMPlexSetConeOrientation(rdm, newp, orntNew);
5119: #if 1
5120: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
5121: for (p = 0; p < 4; ++p) {
5122: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
5123: }
5124: #endif
5125: /* B-C face */
5126: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 2;
5127: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 1);
5128: orntNew[0] = -2;
5129: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 0);
5130: orntNew[1] = 0;
5131: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 3;
5132: orntNew[2] = 0;
5133: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 0;
5134: orntNew[3] = -2;
5135: DMPlexSetCone(rdm, newp, coneNew);
5136: DMPlexSetConeOrientation(rdm, newp, orntNew);
5137: #if 1
5138: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
5139: for (p = 0; p < 4; ++p) {
5140: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
5141: }
5142: #endif
5143: /* A-B face */
5144: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 3;
5145: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 0);
5146: orntNew[0] = -2;
5147: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 3);
5148: orntNew[1] = 0;
5149: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 5;
5150: orntNew[2] = 0;
5151: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 0;
5152: orntNew[3] = -2;
5153: DMPlexSetCone(rdm, newp, coneNew);
5154: DMPlexSetConeOrientation(rdm, newp, orntNew);
5155: #if 1
5156: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
5157: for (p = 0; p < 4; ++p) {
5158: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
5159: }
5160: #endif
5161: /* E-F face */
5162: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 4;
5163: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 2;
5164: orntNew[0] = -2;
5165: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 2);
5166: orntNew[1] = -2;
5167: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 0);
5168: orntNew[2] = 0;
5169: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 1;
5170: orntNew[3] = 0;
5171: DMPlexSetCone(rdm, newp, coneNew);
5172: DMPlexSetConeOrientation(rdm, newp, orntNew);
5173: #if 1
5174: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
5175: for (p = 0; p < 4; ++p) {
5176: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
5177: }
5178: #endif
5179: /* F-G face */
5180: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 5;
5181: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 4;
5182: orntNew[0] = -2;
5183: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 2);
5184: orntNew[1] = -2;
5185: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 1);
5186: orntNew[2] = 0;
5187: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 1;
5188: orntNew[3] = 0;
5189: DMPlexSetCone(rdm, newp, coneNew);
5190: DMPlexSetConeOrientation(rdm, newp, orntNew);
5191: #if 1
5192: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
5193: for (p = 0; p < 4; ++p) {
5194: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
5195: }
5196: #endif
5197: /* G-H face */
5198: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 6;
5199: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 2);
5200: orntNew[0] = -2;
5201: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 2);
5202: orntNew[1] = 0;
5203: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 1;
5204: orntNew[2] = 0;
5205: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 3;
5206: orntNew[3] = -2;
5207: DMPlexSetCone(rdm, newp, coneNew);
5208: DMPlexSetConeOrientation(rdm, newp, orntNew);
5209: #if 1
5210: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
5211: for (p = 0; p < 4; ++p) {
5212: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
5213: }
5214: #endif
5215: /* E-H face */
5216: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 7;
5217: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 5;
5218: orntNew[0] = -2;
5219: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 1);
5220: orntNew[1] = -2;
5221: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 3);
5222: orntNew[2] = 0;
5223: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 1;
5224: orntNew[3] = 0;
5225: DMPlexSetCone(rdm, newp, coneNew);
5226: DMPlexSetConeOrientation(rdm, newp, orntNew);
5227: #if 1
5228: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
5229: for (p = 0; p < 4; ++p) {
5230: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
5231: }
5232: #endif
5233: /* A-E face */
5234: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 8;
5235: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 3);
5236: orntNew[0] = 0;
5237: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 2;
5238: orntNew[1] = 0;
5239: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 5;
5240: orntNew[2] = -2;
5241: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 0);
5242: orntNew[3] = -2;
5243: DMPlexSetCone(rdm, newp, coneNew);
5244: DMPlexSetConeOrientation(rdm, newp, orntNew);
5245: #if 1
5246: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
5247: for (p = 0; p < 4; ++p) {
5248: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
5249: }
5250: #endif
5251: /* D-F face */
5252: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 9;
5253: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 1);
5254: orntNew[0] = -2;
5255: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 3);
5256: orntNew[1] = 0;
5257: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 4;
5258: orntNew[2] = 0;
5259: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 2;
5260: orntNew[3] = -2;
5261: DMPlexSetCone(rdm, newp, coneNew);
5262: DMPlexSetConeOrientation(rdm, newp, orntNew);
5263: #if 1
5264: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
5265: for (p = 0; p < 4; ++p) {
5266: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
5267: }
5268: #endif
5269: /* C-G face */
5270: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 10;
5271: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 4;
5272: orntNew[0] = -2;
5273: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 1);
5274: orntNew[1] = -2;
5275: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 3);
5276: orntNew[2] = 0;
5277: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 3;
5278: orntNew[3] = 0;
5279: DMPlexSetCone(rdm, newp, coneNew);
5280: DMPlexSetConeOrientation(rdm, newp, orntNew);
5281: #if 1
5282: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
5283: for (p = 0; p < 4; ++p) {
5284: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
5285: }
5286: #endif
5287: /* B-H face */
5288: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 11;
5289: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 5;
5290: orntNew[0] = 0;
5291: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 3;
5292: orntNew[1] = -2;
5293: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 1);
5294: orntNew[2] = -2;
5295: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 2);
5296: orntNew[3] = 0;
5297: DMPlexSetCone(rdm, newp, coneNew);
5298: DMPlexSetConeOrientation(rdm, newp, orntNew);
5299: #if 1
5300: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
5301: for (p = 0; p < 4; ++p) {
5302: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
5303: }
5304: #endif
5305: for (r = 0; r < 12; ++r) {
5306: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + r;
5307: supportNew[0] = cStartNew + (c - cStart)*8 + newCells[r*2+0];
5308: supportNew[1] = cStartNew + (c - cStart)*8 + newCells[r*2+1];
5309: DMPlexSetSupport(rdm, newp, supportNew);
5310: #if 1
5311: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
5312: for (p = 0; p < 2; ++p) {
5313: if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
5314: }
5315: #endif
5316: }
5317: }
5318: /* Split edges have 2 vertices and the same faces as the parent */
5319: DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
5320: for (e = eStart; e < eEnd; ++e) {
5321: const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);
5323: for (r = 0; r < 2; ++r) {
5324: const PetscInt newp = eStartNew + (e - eStart)*2 + r;
5325: const PetscInt *cone, *ornt, *support;
5326: PetscInt coneNew[2], coneSize, c, supportSize, s;
5328: DMPlexGetCone(dm, e, &cone);
5329: coneNew[0] = vStartNew + (cone[0] - vStart);
5330: coneNew[1] = vStartNew + (cone[1] - vStart);
5331: coneNew[(r+1)%2] = newv;
5332: DMPlexSetCone(rdm, newp, coneNew);
5333: #if 1
5334: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
5335: for (p = 0; p < 2; ++p) {
5336: if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
5337: }
5338: #endif
5339: DMPlexGetSupportSize(dm, e, &supportSize);
5340: DMPlexGetSupport(dm, e, &support);
5341: for (s = 0; s < supportSize; ++s) {
5342: DMPlexGetConeSize(dm, support[s], &coneSize);
5343: DMPlexGetCone(dm, support[s], &cone);
5344: DMPlexGetConeOrientation(dm, support[s], &ornt);
5345: for (c = 0; c < coneSize; ++c) {
5346: if (cone[c] == e) break;
5347: }
5348: supportRef[s] = fStartNew + (support[s] - fStart)*4 + (ornt[c] < 0 ? (c+1-r)%4 : (c+r)%4);
5349: }
5350: DMPlexSetSupport(rdm, newp, supportRef);
5351: #if 1
5352: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
5353: for (p = 0; p < supportSize; ++p) {
5354: if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
5355: }
5356: #endif
5357: }
5358: }
5359: /* Face edges have 2 vertices and 2+cells faces */
5360: for (f = fStart; f < fEnd; ++f) {
5361: const PetscInt newFaces[24] = {3, 2, 1, 0, 4, 5, 6, 7, 0, 9, 4, 8, 2, 11, 6, 10, 1, 10, 5, 9, 8, 7, 11, 3};
5362: const PetscInt newv = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (f - fStart);
5363: const PetscInt *cone, *coneCell, *orntCell, *support;
5364: PetscInt coneNew[2], coneSize, c, supportSize, s;
5366: DMPlexGetCone(dm, f, &cone);
5367: for (r = 0; r < 4; ++r) {
5368: const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + r;
5370: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - eStart);
5371: coneNew[1] = newv;
5372: DMPlexSetCone(rdm, newp, coneNew);
5373: #if 1
5374: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
5375: for (p = 0; p < 2; ++p) {
5376: if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
5377: }
5378: #endif
5379: DMPlexGetSupportSize(dm, f, &supportSize);
5380: DMPlexGetSupport(dm, f, &support);
5381: supportRef[0] = fStartNew + (f - fStart)*4 + r;
5382: supportRef[1] = fStartNew + (f - fStart)*4 + (r+1)%4;
5383: for (s = 0; s < supportSize; ++s) {
5384: DMPlexGetConeSize(dm, support[s], &coneSize);
5385: DMPlexGetCone(dm, support[s], &coneCell);
5386: DMPlexGetConeOrientation(dm, support[s], &orntCell);
5387: for (c = 0; c < coneSize; ++c) if (coneCell[c] == f) break;
5388: supportRef[2+s] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*12 + newFaces[c*4 + GetQuadEdgeInverse_Static(orntCell[c], r)];
5389: }
5390: DMPlexSetSupport(rdm, newp, supportRef);
5391: #if 1
5392: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
5393: for (p = 0; p < 2+supportSize; ++p) {
5394: if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
5395: }
5396: #endif
5397: }
5398: }
5399: /* Cell edges have 2 vertices and 4 faces */
5400: for (c = cStart; c < cEnd; ++c) {
5401: const PetscInt newFaces[24] = {0, 1, 2, 3, 4, 5, 6, 7, 0, 9, 4, 8, 2, 11, 6, 10, 1, 10, 5, 9, 3, 8, 7, 11};
5402: const PetscInt newv = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (c - cStart);
5403: const PetscInt *cone;
5404: PetscInt coneNew[2], supportNew[4];
5406: DMPlexGetCone(dm, c, &cone);
5407: for (r = 0; r < 6; ++r) {
5408: const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + r;
5410: coneNew[0] = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (cone[r] - fStart);
5411: coneNew[1] = newv;
5412: DMPlexSetCone(rdm, newp, coneNew);
5413: #if 1
5414: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
5415: for (p = 0; p < 2; ++p) {
5416: if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
5417: }
5418: #endif
5419: for (f = 0; f < 4; ++f) supportNew[f] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + newFaces[r*4+f];
5420: DMPlexSetSupport(rdm, newp, supportNew);
5421: #if 1
5422: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
5423: for (p = 0; p < 4; ++p) {
5424: if ((supportNew[p] < fStartNew) || (supportNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportNew[p], fStartNew, fEndNew);
5425: }
5426: #endif
5427: }
5428: }
5429: /* Old vertices have identical supports */
5430: for (v = vStart; v < vEnd; ++v) {
5431: const PetscInt newp = vStartNew + (v - vStart);
5432: const PetscInt *support, *cone;
5433: PetscInt size, s;
5435: DMPlexGetSupportSize(dm, v, &size);
5436: DMPlexGetSupport(dm, v, &support);
5437: for (s = 0; s < size; ++s) {
5438: PetscInt r = 0;
5440: DMPlexGetCone(dm, support[s], &cone);
5441: if (cone[1] == v) r = 1;
5442: supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
5443: }
5444: DMPlexSetSupport(rdm, newp, supportRef);
5445: #if 1
5446: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
5447: for (p = 0; p < size; ++p) {
5448: if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", supportRef[p], eStartNew, eEndNew);
5449: }
5450: #endif
5451: }
5452: /* Edge vertices have 2 + faces supports */
5453: for (e = eStart; e < eEnd; ++e) {
5454: const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
5455: const PetscInt *cone, *support;
5456: PetscInt size, s;
5458: DMPlexGetSupportSize(dm, e, &size);
5459: DMPlexGetSupport(dm, e, &support);
5460: supportRef[0] = eStartNew + (e - eStart)*2 + 0;
5461: supportRef[1] = eStartNew + (e - eStart)*2 + 1;
5462: for (s = 0; s < size; ++s) {
5463: PetscInt r;
5465: DMPlexGetCone(dm, support[s], &cone);
5466: for (r = 0; r < 4; ++r) if (cone[r] == e) break;
5467: supportRef[2+s] = eStartNew + (eEnd - eStart)*2 + (support[s] - fStart)*4 + r;
5468: }
5469: DMPlexSetSupport(rdm, newp, supportRef);
5470: #if 1
5471: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
5472: for (p = 0; p < 2+size; ++p) {
5473: if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", supportRef[p], eStartNew, eEndNew);
5474: }
5475: #endif
5476: }
5477: /* Face vertices have 4 + cells supports */
5478: for (f = fStart; f < fEnd; ++f) {
5479: const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (f - fStart);
5480: const PetscInt *cone, *support;
5481: PetscInt size, s;
5483: DMPlexGetSupportSize(dm, f, &size);
5484: DMPlexGetSupport(dm, f, &support);
5485: for (r = 0; r < 4; ++r) supportRef[r] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + r;
5486: for (s = 0; s < size; ++s) {
5487: PetscInt r;
5489: DMPlexGetCone(dm, support[s], &cone);
5490: for (r = 0; r < 6; ++r) if (cone[r] == f) break;
5491: supportRef[4+s] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (support[s] - cStart)*6 + r;
5492: }
5493: DMPlexSetSupport(rdm, newp, supportRef);
5494: #if 1
5495: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
5496: for (p = 0; p < 4+size; ++p) {
5497: if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", supportRef[p], eStartNew, eEndNew);
5498: }
5499: #endif
5500: }
5501: /* Cell vertices have 6 supports */
5502: for (c = cStart; c < cEnd; ++c) {
5503: const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (c - cStart);
5504: PetscInt supportNew[6];
5506: for (r = 0; r < 6; ++r) {
5507: supportNew[r] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + r;
5508: }
5509: DMPlexSetSupport(rdm, newp, supportNew);
5510: }
5511: PetscFree(supportRef);
5512: break;
5513: case REFINER_HYBRID_HEX_3D:
5514: DMPlexGetHybridBounds(rdm, &cMaxNew, &fMaxNew, &eMaxNew, NULL);
5515: /*
5516: Bottom (viewed from top) Top
5517: 1---------2---------2 7---------2---------6
5518: | | | | | |
5519: | B 2 C | | H 2 G |
5520: | | | | | |
5521: 3----3----0----1----1 3----3----0----1----1
5522: | | | | | |
5523: | A 0 D | | E 0 F |
5524: | | | | | |
5525: 0---------0---------3 4---------0---------5
5526: */
5527: /* Interior cells have 6 faces: Bottom, Top, Front, Back, Right, Left */
5528: for (c = cStart; c < cMax; ++c) {
5529: const PetscInt newp = (c - cStart)*8;
5530: const PetscInt *cone, *ornt;
5531: PetscInt coneNew[6], orntNew[6];
5533: DMPlexGetCone(dm, c, &cone);
5534: DMPlexGetConeOrientation(dm, c, &ornt);
5535: /* A hex */
5536: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 0);
5537: orntNew[0] = ornt[0];
5538: coneNew[1] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 8; /* AE */
5539: orntNew[1] = 0;
5540: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 0);
5541: orntNew[2] = ornt[2];
5542: coneNew[3] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 3; /* AB */
5543: orntNew[3] = 0;
5544: coneNew[4] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 0; /* AD */
5545: orntNew[4] = 0;
5546: coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 0);
5547: orntNew[5] = ornt[5];
5548: DMPlexSetCone(rdm, newp+0, coneNew);
5549: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
5550: #if 1
5551: if ((newp+0 < cStartNew) || (newp+0 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cMaxNew);
5552: for (p = 0; p < 6; ++p) {
5553: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
5554: }
5555: #endif
5556: /* B hex */
5557: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 1);
5558: orntNew[0] = ornt[0];
5559: coneNew[1] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 11; /* BH */
5560: orntNew[1] = 0;
5561: coneNew[2] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 3; /* AB */
5562: orntNew[2] = -1;
5563: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 1);
5564: orntNew[3] = ornt[3];
5565: coneNew[4] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 2; /* BC */
5566: orntNew[4] = 0;
5567: coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 3);
5568: orntNew[5] = ornt[5];
5569: DMPlexSetCone(rdm, newp+1, coneNew);
5570: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
5571: #if 1
5572: if ((newp+1 < cStartNew) || (newp+1 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cMaxNew);
5573: for (p = 0; p < 6; ++p) {
5574: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
5575: }
5576: #endif
5577: /* C hex */
5578: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 2);
5579: orntNew[0] = ornt[0];
5580: coneNew[1] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 10; /* CG */
5581: orntNew[1] = 0;
5582: coneNew[2] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 1; /* CD */
5583: orntNew[2] = -1;
5584: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 0);
5585: orntNew[3] = ornt[3];
5586: coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 1);
5587: orntNew[4] = ornt[4];
5588: coneNew[5] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 2; /* BC */
5589: orntNew[5] = -4;
5590: DMPlexSetCone(rdm, newp+2, coneNew);
5591: DMPlexSetConeOrientation(rdm, newp+2, orntNew);
5592: #if 1
5593: if ((newp+2 < cStartNew) || (newp+2 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cMaxNew);
5594: for (p = 0; p < 6; ++p) {
5595: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
5596: }
5597: #endif
5598: /* D hex */
5599: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 3);
5600: orntNew[0] = ornt[0];
5601: coneNew[1] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 9; /* DF */
5602: orntNew[1] = 0;
5603: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 1);
5604: orntNew[2] = ornt[2];
5605: coneNew[3] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 1; /* CD */
5606: orntNew[3] = 0;
5607: coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 0);
5608: orntNew[4] = ornt[4];
5609: coneNew[5] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 0; /* AD */
5610: orntNew[5] = -4;
5611: DMPlexSetCone(rdm, newp+3, coneNew);
5612: DMPlexSetConeOrientation(rdm, newp+3, orntNew);
5613: #if 1
5614: if ((newp+3 < cStartNew) || (newp+3 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cMaxNew);
5615: for (p = 0; p < 6; ++p) {
5616: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
5617: }
5618: #endif
5619: /* E hex */
5620: coneNew[0] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 8; /* AE */
5621: orntNew[0] = -4;
5622: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 0);
5623: orntNew[1] = ornt[1];
5624: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 3);
5625: orntNew[2] = ornt[2];
5626: coneNew[3] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 7; /* EH */
5627: orntNew[3] = 0;
5628: coneNew[4] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 4; /* EF */
5629: orntNew[4] = -1;
5630: coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 1);
5631: orntNew[5] = ornt[5];
5632: DMPlexSetCone(rdm, newp+4, coneNew);
5633: DMPlexSetConeOrientation(rdm, newp+4, orntNew);
5634: #if 1
5635: if ((newp+4 < cStartNew) || (newp+4 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+4, cStartNew, cMaxNew);
5636: for (p = 0; p < 6; ++p) {
5637: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
5638: }
5639: #endif
5640: /* F hex */
5641: coneNew[0] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 9; /* DF */
5642: orntNew[0] = -4;
5643: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 1);
5644: orntNew[1] = ornt[1];
5645: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 2);
5646: orntNew[2] = ornt[2];
5647: coneNew[3] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 5; /* FG */
5648: orntNew[3] = -1;
5649: coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 3);
5650: orntNew[4] = ornt[4];
5651: coneNew[5] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 4; /* EF */
5652: orntNew[5] = 1;
5653: DMPlexSetCone(rdm, newp+5, coneNew);
5654: DMPlexSetConeOrientation(rdm, newp+5, orntNew);
5655: #if 1
5656: if ((newp+5 < cStartNew) || (newp+5 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+5, cStartNew, cMaxNew);
5657: for (p = 0; p < 6; ++p) {
5658: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
5659: }
5660: #endif
5661: /* G hex */
5662: coneNew[0] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 10; /* CG */
5663: orntNew[0] = -4;
5664: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 2);
5665: orntNew[1] = ornt[1];
5666: coneNew[2] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 5; /* FG */
5667: orntNew[2] = 0;
5668: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 3);
5669: orntNew[3] = ornt[3];
5670: coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 2);
5671: orntNew[4] = ornt[4];
5672: coneNew[5] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 6; /* GH */
5673: orntNew[5] = -3;
5674: DMPlexSetCone(rdm, newp+6, coneNew);
5675: DMPlexSetConeOrientation(rdm, newp+6, orntNew);
5676: #if 1
5677: if ((newp+6 < cStartNew) || (newp+6 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+6, cStartNew, cMaxNew);
5678: for (p = 0; p < 6; ++p) {
5679: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
5680: }
5681: #endif
5682: /* H hex */
5683: coneNew[0] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 11; /* BH */
5684: orntNew[0] = -4;
5685: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 3);
5686: orntNew[1] = ornt[1];
5687: coneNew[2] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 7; /* EH */
5688: orntNew[2] = -1;
5689: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 2);
5690: orntNew[3] = ornt[3];
5691: coneNew[4] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 6; /* GH */
5692: orntNew[4] = 3;
5693: coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 2);
5694: orntNew[5] = ornt[5];
5695: DMPlexSetCone(rdm, newp+7, coneNew);
5696: DMPlexSetConeOrientation(rdm, newp+7, orntNew);
5697: #if 1
5698: if ((newp+7 < cStartNew) || (newp+7 >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+7, cStartNew, cMaxNew);
5699: for (p = 0; p < 6; ++p) {
5700: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
5701: }
5702: #endif
5703: }
5704: /* Hybrid cells have 6 faces: Front, Back, Sides */
5705: /*
5706: 3---------2---------2
5707: | | |
5708: | D 2 C |
5709: | | |
5710: 3----3----0----1----1
5711: | | |
5712: | A 0 B |
5713: | | |
5714: 0---------0---------1
5715: */
5716: for (c = cMax; c < cEnd; ++c) {
5717: const PetscInt newp = (cMax - cStart)*8 + (c - cMax)*4;
5718: const PetscInt *cone, *ornt, *fornt;
5719: PetscInt coneNew[6], orntNew[6], o, of, i;
5721: DMPlexGetCone(dm, c, &cone);
5722: DMPlexGetConeOrientation(dm, c, &ornt);
5723: DMPlexGetConeOrientation(dm, cone[0], &fornt);
5724: o = ornt[0] < 0 ? -1 : 1;
5725: for (r = 0; r < 4; ++r) {
5726: PetscInt subfA = GetQuadSubface_Static(ornt[0], r);
5727: PetscInt edgeA = GetQuadEdge_Static(ornt[0], r);
5728: PetscInt edgeB = GetQuadEdge_Static(ornt[0], (r+3)%4);
5729: if (ornt[0] != ornt[1]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Inconsistent ordering for matching ends of hybrid cell %d: %d != %d", c, ornt[0], ornt[1]);
5730: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + subfA;
5731: orntNew[0] = ornt[0];
5732: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + subfA;
5733: orntNew[1] = ornt[0];
5734: of = fornt[edgeA] < 0 ? -1 : 1;
5735: i = GetQuadEdgeInverse_Static(ornt[0], r) + 2;
5736: coneNew[i] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (cone[2+edgeA] - fMax)*2 + (o*of < 0 ? 1 : 0);
5737: orntNew[i] = ornt[edgeA];
5738: i = GetQuadEdgeInverse_Static(ornt[0], (r+1)%4) + 2;
5739: coneNew[i] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + edgeA;
5740: orntNew[i] = 0;
5741: i = GetQuadEdgeInverse_Static(ornt[0], (r+2)%4) + 2;
5742: coneNew[i] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + edgeB;
5743: orntNew[i] = -2;
5744: of = fornt[edgeB] < 0 ? -1 : 1;
5745: i = GetQuadEdgeInverse_Static(ornt[0], (r+3)%4) + 2;
5746: coneNew[i] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (cone[2+edgeB] - fMax)*2 + (o*of < 0 ? 0 : 1);
5747: orntNew[i] = ornt[edgeB];
5748: DMPlexSetCone(rdm, newp+r, coneNew);
5749: DMPlexSetConeOrientation(rdm, newp+r, orntNew);
5750: #if 1
5751: if ((newp+r < cMaxNew) || (newp+r >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid cell [%d, %d)", newp+r, cMaxNew, cEndNew);
5752: for (p = 0; p < 2; ++p) {
5753: if ((coneNew[p] < fStartNew) || (coneNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fMaxNew);
5754: }
5755: for (p = 2; p < 6; ++p) {
5756: if ((coneNew[p] < fMaxNew) || (coneNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", coneNew[p], fMaxNew, fEndNew);
5757: }
5758: #endif
5759: }
5760: }
5761: /* Interior split faces have 4 edges and the same cells as the parent */
5762: DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
5763: PetscMalloc1(4 + maxSupportSize*2, &supportRef);
5764: for (f = fStart; f < fMax; ++f) {
5765: for (r = 0; r < 4; ++r) {
5766: /* TODO: This can come from GetFaces_Internal() */
5767: const PetscInt newCells[24] = {0, 1, 2, 3, 4, 5, 6, 7, 0, 3, 5, 4, 2, 1, 7, 6, 3, 2, 6, 5, 0, 4, 7, 1};
5768: const PetscInt newp = fStartNew + (f - fStart)*4 + r;
5769: const PetscInt *cone, *ornt, *support;
5770: PetscInt coneNew[4], orntNew[4], coneSize, c, supportSize, s;
5772: DMPlexGetCone(dm, f, &cone);
5773: DMPlexGetConeOrientation(dm, f, &ornt);
5774: coneNew[(r+3)%4] = eStartNew + (cone[(r+3)%4] - eStart)*2 + (ornt[(r+3)%4] < 0 ? 0 : 1);
5775: orntNew[(r+3)%4] = ornt[(r+3)%4];
5776: coneNew[(r+0)%4] = eStartNew + (cone[r] - eStart)*2 + (ornt[r] < 0 ? 1 : 0);
5777: orntNew[(r+0)%4] = ornt[r];
5778: coneNew[(r+1)%4] = eStartNew + (eMax - eStart)*2 + (f - fStart)*4 + r;
5779: orntNew[(r+1)%4] = 0;
5780: coneNew[(r+2)%4] = eStartNew + (eMax - eStart)*2 + (f - fStart)*4 + (r+3)%4;
5781: orntNew[(r+2)%4] = -2;
5782: DMPlexSetCone(rdm, newp, coneNew);
5783: DMPlexSetConeOrientation(rdm, newp, orntNew);
5784: #if 1
5785: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
5786: for (p = 0; p < 4; ++p) {
5787: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
5788: }
5789: #endif
5790: DMPlexGetSupportSize(dm, f, &supportSize);
5791: DMPlexGetSupport(dm, f, &support);
5792: for (s = 0; s < supportSize; ++s) {
5793: PetscInt subf;
5794: DMPlexGetConeSize(dm, support[s], &coneSize);
5795: DMPlexGetCone(dm, support[s], &cone);
5796: DMPlexGetConeOrientation(dm, support[s], &ornt);
5797: for (c = 0; c < coneSize; ++c) {
5798: if (cone[c] == f) break;
5799: }
5800: subf = GetQuadSubfaceInverse_Static(ornt[c], r);
5801: if (support[s] < cMax) {
5802: supportRef[s] = cStartNew + (support[s] - cStart)*8 + newCells[c*4+subf];
5803: } else {
5804: supportRef[s] = cStartNew + (cMax - cStart)*8 + (support[s] - cMax)*4 + subf;
5805: }
5806: }
5807: DMPlexSetSupport(rdm, newp, supportRef);
5808: #if 1
5809: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
5810: for (p = 0; p < supportSize; ++p) {
5811: if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew);
5812: }
5813: #endif
5814: }
5815: }
5816: /* Interior cell faces have 4 edges and 2 cells */
5817: for (c = cStart; c < cMax; ++c) {
5818: const PetscInt newCells[24] = {0, 3, 2, 3, 1, 2, 0, 1, 4, 5, 5, 6, 6, 7, 4, 7, 0, 4, 3, 5, 2, 6, 1, 7};
5819: const PetscInt *cone, *ornt;
5820: PetscInt newp, coneNew[4], orntNew[4], supportNew[2];
5822: DMPlexGetCone(dm, c, &cone);
5823: DMPlexGetConeOrientation(dm, c, &ornt);
5824: /* A-D face */
5825: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 0;
5826: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 3);
5827: orntNew[0] = 0;
5828: coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 0;
5829: orntNew[1] = 0;
5830: coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 2;
5831: orntNew[2] = -2;
5832: coneNew[3] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 0);
5833: orntNew[3] = -2;
5834: DMPlexSetCone(rdm, newp, coneNew);
5835: DMPlexSetConeOrientation(rdm, newp, orntNew);
5836: #if 1
5837: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
5838: for (p = 0; p < 4; ++p) {
5839: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
5840: }
5841: #endif
5842: /* C-D face */
5843: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 1;
5844: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 2);
5845: orntNew[0] = 0;
5846: coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 0;
5847: orntNew[1] = 0;
5848: coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 4;
5849: orntNew[2] = -2;
5850: coneNew[3] = eStartNew + (eMax - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 0);
5851: orntNew[3] = -2;
5852: DMPlexSetCone(rdm, newp, coneNew);
5853: DMPlexSetConeOrientation(rdm, newp, orntNew);
5854: #if 1
5855: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
5856: for (p = 0; p < 4; ++p) {
5857: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
5858: }
5859: #endif
5860: /* B-C face */
5861: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 2;
5862: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 1);
5863: orntNew[0] = -2;
5864: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 0);
5865: orntNew[1] = 0;
5866: coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 3;
5867: orntNew[2] = 0;
5868: coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 0;
5869: orntNew[3] = -2;
5870: DMPlexSetCone(rdm, newp, coneNew);
5871: DMPlexSetConeOrientation(rdm, newp, orntNew);
5872: #if 1
5873: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
5874: for (p = 0; p < 4; ++p) {
5875: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
5876: }
5877: #endif
5878: /* A-B face */
5879: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 3;
5880: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 0);
5881: orntNew[0] = -2;
5882: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 3);
5883: orntNew[1] = 0;
5884: coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 5;
5885: orntNew[2] = 0;
5886: coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 0;
5887: orntNew[3] = -2;
5888: DMPlexSetCone(rdm, newp, coneNew);
5889: DMPlexSetConeOrientation(rdm, newp, orntNew);
5890: #if 1
5891: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
5892: for (p = 0; p < 4; ++p) {
5893: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
5894: }
5895: #endif
5896: /* E-F face */
5897: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 4;
5898: coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 2;
5899: orntNew[0] = -2;
5900: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 2);
5901: orntNew[1] = -2;
5902: coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 0);
5903: orntNew[2] = 0;
5904: coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 1;
5905: orntNew[3] = 0;
5906: DMPlexSetCone(rdm, newp, coneNew);
5907: DMPlexSetConeOrientation(rdm, newp, orntNew);
5908: #if 1
5909: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
5910: for (p = 0; p < 4; ++p) {
5911: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
5912: }
5913: #endif
5914: /* F-G face */
5915: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 5;
5916: coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 4;
5917: orntNew[0] = -2;
5918: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 2);
5919: orntNew[1] = -2;
5920: coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 1);
5921: orntNew[2] = 0;
5922: coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 1;
5923: orntNew[3] = 0;
5924: DMPlexSetCone(rdm, newp, coneNew);
5925: DMPlexSetConeOrientation(rdm, newp, orntNew);
5926: #if 1
5927: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
5928: for (p = 0; p < 4; ++p) {
5929: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
5930: }
5931: #endif
5932: /* G-H face */
5933: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 6;
5934: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 2);
5935: orntNew[0] = -2;
5936: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 2);
5937: orntNew[1] = 0;
5938: coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 1;
5939: orntNew[2] = 0;
5940: coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 3;
5941: orntNew[3] = -2;
5942: DMPlexSetCone(rdm, newp, coneNew);
5943: DMPlexSetConeOrientation(rdm, newp, orntNew);
5944: #if 1
5945: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
5946: for (p = 0; p < 4; ++p) {
5947: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
5948: }
5949: #endif
5950: /* E-H face */
5951: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 7;
5952: coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 5;
5953: orntNew[0] = -2;
5954: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 1);
5955: orntNew[1] = -2;
5956: coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 3);
5957: orntNew[2] = 0;
5958: coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 1;
5959: orntNew[3] = 0;
5960: DMPlexSetCone(rdm, newp, coneNew);
5961: DMPlexSetConeOrientation(rdm, newp, orntNew);
5962: #if 1
5963: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
5964: for (p = 0; p < 4; ++p) {
5965: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
5966: }
5967: #endif
5968: /* A-E face */
5969: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 8;
5970: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 3);
5971: orntNew[0] = 0;
5972: coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 2;
5973: orntNew[1] = 0;
5974: coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 5;
5975: orntNew[2] = -2;
5976: coneNew[3] = eStartNew + (eMax - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 0);
5977: orntNew[3] = -2;
5978: DMPlexSetCone(rdm, newp, coneNew);
5979: DMPlexSetConeOrientation(rdm, newp, orntNew);
5980: #if 1
5981: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
5982: for (p = 0; p < 4; ++p) {
5983: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
5984: }
5985: #endif
5986: /* D-F face */
5987: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 9;
5988: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 1);
5989: orntNew[0] = -2;
5990: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 3);
5991: orntNew[1] = 0;
5992: coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 4;
5993: orntNew[2] = 0;
5994: coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 2;
5995: orntNew[3] = -2;
5996: DMPlexSetCone(rdm, newp, coneNew);
5997: DMPlexSetConeOrientation(rdm, newp, orntNew);
5998: #if 1
5999: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
6000: for (p = 0; p < 4; ++p) {
6001: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
6002: }
6003: #endif
6004: /* C-G face */
6005: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 10;
6006: coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 4;
6007: orntNew[0] = -2;
6008: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 1);
6009: orntNew[1] = -2;
6010: coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 3);
6011: orntNew[2] = 0;
6012: coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 3;
6013: orntNew[3] = 0;
6014: DMPlexSetCone(rdm, newp, coneNew);
6015: DMPlexSetConeOrientation(rdm, newp, orntNew);
6016: #if 1
6017: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
6018: for (p = 0; p < 4; ++p) {
6019: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
6020: }
6021: #endif
6022: /* B-H face */
6023: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 11;
6024: coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 5;
6025: orntNew[0] = 0;
6026: coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 3;
6027: orntNew[1] = -2;
6028: coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 1);
6029: orntNew[2] = -2;
6030: coneNew[3] = eStartNew + (eMax - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 2);
6031: orntNew[3] = 0;
6032: DMPlexSetCone(rdm, newp, coneNew);
6033: DMPlexSetConeOrientation(rdm, newp, orntNew);
6034: #if 1
6035: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
6036: for (p = 0; p < 4; ++p) {
6037: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
6038: }
6039: #endif
6040: for (r = 0; r < 12; ++r) {
6041: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + r;
6042: supportNew[0] = cStartNew + (c - cStart)*8 + newCells[r*2+0];
6043: supportNew[1] = cStartNew + (c - cStart)*8 + newCells[r*2+1];
6044: DMPlexSetSupport(rdm, newp, supportNew);
6045: #if 1
6046: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
6047: for (p = 0; p < 2; ++p) {
6048: if ((supportNew[p] < cStartNew) || (supportNew[p] >= cMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cMaxNew);
6049: }
6050: #endif
6051: }
6052: }
6053: /* Hybrid split faces have 4 edges and same cells */
6054: for (f = fMax; f < fEnd; ++f) {
6055: const PetscInt *cone, *ornt, *support;
6056: PetscInt coneNew[4], orntNew[4];
6057: PetscInt supportNew[2], size, s, c;
6059: DMPlexGetCone(dm, f, &cone);
6060: DMPlexGetConeOrientation(dm, f, &ornt);
6061: DMPlexGetSupportSize(dm, f, &size);
6062: DMPlexGetSupport(dm, f, &support);
6063: for (r = 0; r < 2; ++r) {
6064: const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (f - fMax)*2 + r;
6066: coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1-r : r);
6067: orntNew[0] = ornt[0];
6068: coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1-r : r);
6069: orntNew[1] = ornt[1];
6070: coneNew[2+r] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (cone[2+r] - eMax);
6071: orntNew[2+r] = 0;
6072: coneNew[3-r] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (f - fMax);
6073: orntNew[3-r] = 0;
6074: DMPlexSetCone(rdm, newp, coneNew);
6075: DMPlexSetConeOrientation(rdm, newp, orntNew);
6076: #if 1
6077: if ((newp < fMaxNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", newp, fMaxNew, fEndNew);
6078: for (p = 0; p < 2; ++p) {
6079: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
6080: }
6081: for (p = 2; p < 4; ++p) {
6082: if ((coneNew[p] < eMaxNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", coneNew[p], eMaxNew, eEndNew);
6083: }
6084: #endif
6085: for (s = 0; s < size; ++s) {
6086: const PetscInt *coneCell, *orntCell, *fornt;
6087: PetscInt o, of;
6089: DMPlexGetCone(dm, support[s], &coneCell);
6090: DMPlexGetConeOrientation(dm, support[s], &orntCell);
6091: o = orntCell[0] < 0 ? -1 : 1;
6092: for (c = 2; c < 6; ++c) if (coneCell[c] == f) break;
6093: if (c >= 6) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find face %d in cone of cell %d", f, support[s]);
6094: DMPlexGetConeOrientation(dm, coneCell[0], &fornt);
6095: of = fornt[c-2] < 0 ? -1 : 1;
6096: supportNew[s] = cStartNew + (cMax - cStart)*8 + (support[s] - cMax)*4 + (GetQuadEdgeInverse_Static(orntCell[0], c-2) + (o*of < 0 ? 1-r : r))%4;
6097: }
6098: DMPlexSetSupport(rdm, newp, supportNew);
6099: #if 1
6100: if ((newp < fMaxNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", newp, fMaxNew, fEndNew);
6101: for (p = 0; p < size; ++p) {
6102: if ((supportNew[p] < cMaxNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid cell [%d, %d)", supportNew[p], cMaxNew, cEndNew);
6103: }
6104: #endif
6105: }
6106: }
6107: /* Hybrid cell faces have 4 edges and 2 cells */
6108: for (c = cMax; c < cEnd; ++c) {
6109: PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4;
6110: const PetscInt *cone, *ornt;
6111: PetscInt coneNew[4], orntNew[4];
6112: PetscInt supportNew[2];
6114: DMPlexGetCone(dm, c, &cone);
6115: DMPlexGetConeOrientation(dm, c, &ornt);
6116: for (r = 0; r < 4; ++r) {
6117: #if 0
6118: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], r);
6119: orntNew[0] = 0;
6120: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], r);
6121: orntNew[1] = 0;
6122: coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (cone[2+GetQuadEdge_Static(ornt[0], r)] - fMax);
6123: orntNew[2] = 0;
6124: coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (fEnd - fMax) + (c - cMax);
6125: orntNew[3] = 0;
6126: #else
6127: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + r;
6128: orntNew[0] = 0;
6129: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + r;
6130: orntNew[1] = 0;
6131: coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (cone[2+r] - fMax);
6132: orntNew[2] = 0;
6133: coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (fEnd - fMax) + (c - cMax);
6134: orntNew[3] = 0;
6135: #endif
6136: DMPlexSetCone(rdm, newp+r, coneNew);
6137: DMPlexSetConeOrientation(rdm, newp+r, orntNew);
6138: #if 1
6139: if ((newp+r < fMaxNew) || (newp+r >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", newp+r, fMaxNew, fEndNew);
6140: for (p = 0; p < 2; ++p) {
6141: if ((coneNew[p] < eStartNew) || (coneNew[p] >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eMaxNew);
6142: }
6143: for (p = 2; p < 4; ++p) {
6144: if ((coneNew[p] < eMaxNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", coneNew[p], eMaxNew, eEndNew);
6145: }
6146: #endif
6147: supportNew[0] = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + GetQuadSubface_Static(ornt[0], r);
6148: supportNew[1] = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + GetQuadSubface_Static(ornt[0], (r+1)%4);
6149: DMPlexSetSupport(rdm, newp+r, supportNew);
6150: #if 1
6151: if ((newp+r < fMaxNew) || (newp+r >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", newp+r, fMaxNew, fEndNew);
6152: for (p = 0; p < 2; ++p) {
6153: if ((supportNew[p] < cMaxNew) || (supportNew[p] >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid cell [%d, %d)", supportNew[p], cMaxNew, cEndNew);
6154: }
6155: #endif
6156: }
6157: }
6158: /* Interior split edges have 2 vertices and the same faces as the parent */
6159: DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
6160: for (e = eStart; e < eMax; ++e) {
6161: const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);
6163: for (r = 0; r < 2; ++r) {
6164: const PetscInt newp = eStartNew + (e - eStart)*2 + r;
6165: const PetscInt *cone, *ornt, *support;
6166: PetscInt coneNew[2], coneSize, c, supportSize, s;
6168: DMPlexGetCone(dm, e, &cone);
6169: coneNew[0] = vStartNew + (cone[0] - vStart);
6170: coneNew[1] = vStartNew + (cone[1] - vStart);
6171: coneNew[(r+1)%2] = newv;
6172: DMPlexSetCone(rdm, newp, coneNew);
6173: #if 1
6174: if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
6175: for (p = 0; p < 2; ++p) {
6176: if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
6177: }
6178: #endif
6179: DMPlexGetSupportSize(dm, e, &supportSize);
6180: DMPlexGetSupport(dm, e, &support);
6181: for (s = 0; s < supportSize; ++s) {
6182: DMPlexGetConeSize(dm, support[s], &coneSize);
6183: DMPlexGetCone(dm, support[s], &cone);
6184: DMPlexGetConeOrientation(dm, support[s], &ornt);
6185: for (c = 0; c < coneSize; ++c) {
6186: if (cone[c] == e) break;
6187: }
6188: if (support[s] < fMax) {
6189: supportRef[s] = fStartNew + (support[s] - fStart)*4 + (c + (ornt[c] < 0 ? 1-r : r))%4;
6190: } else {
6191: supportRef[s] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (support[s] - fMax)*2 + (ornt[c] < 0 ? 1-r : r);
6192: }
6193: }
6194: DMPlexSetSupport(rdm, newp, supportRef);
6195: #if 1
6196: if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
6197: for (p = 0; p < supportSize; ++p) {
6198: if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
6199: }
6200: #endif
6201: }
6202: }
6203: /* Interior face edges have 2 vertices and 2+cells faces */
6204: for (f = fStart; f < fMax; ++f) {
6205: const PetscInt newFaces[24] = {3, 2, 1, 0, 4, 5, 6, 7, 0, 9, 4, 8, 2, 11, 6, 10, 1, 10, 5, 9, 8, 7, 11, 3};
6206: const PetscInt newv = vStartNew + (vEnd - vStart) + (eMax - eStart) + (f - fStart);
6207: const PetscInt *cone, *coneCell, *orntCell, *support;
6208: PetscInt coneNew[2], coneSize, c, supportSize, s;
6210: DMPlexGetCone(dm, f, &cone);
6211: for (r = 0; r < 4; ++r) {
6212: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (f - fStart)*4 + r;
6214: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - eStart);
6215: coneNew[1] = newv;
6216: DMPlexSetCone(rdm, newp, coneNew);
6217: #if 1
6218: if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
6219: for (p = 0; p < 2; ++p) {
6220: if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
6221: }
6222: #endif
6223: DMPlexGetSupportSize(dm, f, &supportSize);
6224: DMPlexGetSupport(dm, f, &support);
6225: supportRef[0] = fStartNew + (f - fStart)*4 + r;
6226: supportRef[1] = fStartNew + (f - fStart)*4 + (r+1)%4;
6227: for (s = 0; s < supportSize; ++s) {
6228: DMPlexGetConeSize(dm, support[s], &coneSize);
6229: DMPlexGetCone(dm, support[s], &coneCell);
6230: DMPlexGetConeOrientation(dm, support[s], &orntCell);
6231: for (c = 0; c < coneSize; ++c) if (coneCell[c] == f) break;
6232: if (support[s] < cMax) {
6233: supportRef[2+s] = fStartNew + (fMax - fStart)*4 + (support[s] - cStart)*12 + newFaces[c*4 + GetQuadEdgeInverse_Static(orntCell[c], r)];
6234: } else {
6235: supportRef[2+s] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (support[s] - cMax)*4 + r;
6236: }
6237: }
6238: DMPlexSetSupport(rdm, newp, supportRef);
6239: #if 1
6240: if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
6241: for (p = 0; p < 2+supportSize; ++p) {
6242: if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
6243: }
6244: #endif
6245: }
6246: }
6247: /* Interior cell edges have 2 vertices and 4 faces */
6248: for (c = cStart; c < cMax; ++c) {
6249: const PetscInt newFaces[24] = {0, 1, 2, 3, 4, 5, 6, 7, 0, 9, 4, 8, 2, 11, 6, 10, 1, 10, 5, 9, 3, 8, 7, 11};
6250: const PetscInt newv = vStartNew + (vEnd - vStart) + (eMax - eStart) + (fMax - fStart) + (c - cStart);
6251: const PetscInt *cone;
6252: PetscInt coneNew[2], supportNew[4];
6254: DMPlexGetCone(dm, c, &cone);
6255: for (r = 0; r < 6; ++r) {
6256: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + r;
6258: coneNew[0] = vStartNew + (vEnd - vStart) + (eMax - eStart) + (cone[r] - fStart);
6259: coneNew[1] = newv;
6260: DMPlexSetCone(rdm, newp, coneNew);
6261: #if 1
6262: if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
6263: for (p = 0; p < 2; ++p) {
6264: if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
6265: }
6266: #endif
6267: for (f = 0; f < 4; ++f) supportNew[f] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + newFaces[r*4+f];
6268: DMPlexSetSupport(rdm, newp, supportNew);
6269: #if 1
6270: if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
6271: for (p = 0; p < 4; ++p) {
6272: if ((supportNew[p] < fStartNew) || (supportNew[p] >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportNew[p], fStartNew, fMaxNew);
6273: }
6274: #endif
6275: }
6276: }
6277: /* Hybrid edges have two vertices and the same faces */
6278: for (e = eMax; e < eEnd; ++e) {
6279: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (e - eMax);
6280: const PetscInt *cone, *support, *fcone;
6281: PetscInt coneNew[2], size, fsize, s;
6283: DMPlexGetCone(dm, e, &cone);
6284: DMPlexGetSupportSize(dm, e, &size);
6285: DMPlexGetSupport(dm, e, &support);
6286: coneNew[0] = vStartNew + (cone[0] - vStart);
6287: coneNew[1] = vStartNew + (cone[1] - vStart);
6288: DMPlexSetCone(rdm, newp, coneNew);
6289: #if 1
6290: if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
6291: for (p = 0; p < 2; ++p) {
6292: if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
6293: }
6294: #endif
6295: for (s = 0; s < size; ++s) {
6296: DMPlexGetConeSize(dm, support[s], &fsize);
6297: DMPlexGetCone(dm, support[s], &fcone);
6298: for (c = 0; c < fsize; ++c) if (fcone[c] == e) break;
6299: if ((c < 2) || (c > 3)) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge %d not found in cone of face %d", e, support[s]);
6300: supportRef[s] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (support[s] - fMax)*2 + c-2;
6301: }
6302: DMPlexSetSupport(rdm, newp, supportRef);
6303: #if 1
6304: if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
6305: for (p = 0; p < size; ++p) {
6306: if ((supportRef[p] < fMaxNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", supportRef[p], fMaxNew, fEndNew);
6307: }
6308: #endif
6309: }
6310: /* Hybrid face edges have 2 vertices and 2+cells faces */
6311: for (f = fMax; f < fEnd; ++f) {
6312: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (f - fMax);
6313: const PetscInt *cone, *support, *ccone, *cornt;
6314: PetscInt coneNew[2], size, csize, s;
6316: DMPlexGetCone(dm, f, &cone);
6317: DMPlexGetSupportSize(dm, f, &size);
6318: DMPlexGetSupport(dm, f, &support);
6319: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - eStart);
6320: coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - eStart);
6321: DMPlexSetCone(rdm, newp, coneNew);
6322: #if 1
6323: if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
6324: for (p = 0; p < 2; ++p) {
6325: if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
6326: }
6327: #endif
6328: supportRef[0] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (f - fMax)*2 + 0;
6329: supportRef[1] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (f - fMax)*2 + 1;
6330: for (s = 0; s < size; ++s) {
6331: DMPlexGetConeSize(dm, support[s], &csize);
6332: DMPlexGetCone(dm, support[s], &ccone);
6333: DMPlexGetConeOrientation(dm, support[s], &cornt);
6334: for (c = 0; c < csize; ++c) if (ccone[c] == f) break;
6335: if ((c < 2) || (c >= csize)) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Hybrid face %d is not in cone of hybrid cell %d", f, support[s]);
6336: supportRef[2+s] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (support[s] - cMax)*4 + c-2;
6337: }
6338: DMPlexSetSupport(rdm, newp, supportRef);
6339: #if 1
6340: if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
6341: for (p = 0; p < 2+size; ++p) {
6342: if ((supportRef[p] < fMaxNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", supportRef[p], fMaxNew, fEndNew);
6343: }
6344: #endif
6345: }
6346: /* Hybrid cell edges have 2 vertices and 4 faces */
6347: for (c = cMax; c < cEnd; ++c) {
6348: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (fEnd - fMax) + (c - cMax);
6349: const PetscInt *cone, *support;
6350: PetscInt coneNew[2], size;
6352: DMPlexGetCone(dm, c, &cone);
6353: DMPlexGetSupportSize(dm, c, &size);
6354: DMPlexGetSupport(dm, c, &support);
6355: coneNew[0] = vStartNew + (vEnd - vStart) + (eMax - eStart) + (cone[0] - fStart);
6356: coneNew[1] = vStartNew + (vEnd - vStart) + (eMax - eStart) + (cone[1] - fStart);
6357: DMPlexSetCone(rdm, newp, coneNew);
6358: #if 1
6359: if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
6360: for (p = 0; p < 2; ++p) {
6361: if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
6362: }
6363: #endif
6364: supportRef[0] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + 0;
6365: supportRef[1] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + 1;
6366: supportRef[2] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + 2;
6367: supportRef[3] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + 3;
6368: DMPlexSetSupport(rdm, newp, supportRef);
6369: #if 1
6370: if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
6371: for (p = 0; p < 4; ++p) {
6372: if ((supportRef[p] < fMaxNew) || (supportRef[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", supportRef[p], fMaxNew, fEndNew);
6373: }
6374: #endif
6375: }
6376: /* Interior vertices have identical supports */
6377: for (v = vStart; v < vEnd; ++v) {
6378: const PetscInt newp = vStartNew + (v - vStart);
6379: const PetscInt *support, *cone;
6380: PetscInt size, s;
6382: DMPlexGetSupportSize(dm, v, &size);
6383: DMPlexGetSupport(dm, v, &support);
6384: for (s = 0; s < size; ++s) {
6385: PetscInt r = 0;
6387: DMPlexGetCone(dm, support[s], &cone);
6388: if (cone[1] == v) r = 1;
6389: if (support[s] < eMax) supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
6390: else supportRef[s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (support[s] - eMax);
6391: }
6392: DMPlexSetSupport(rdm, newp, supportRef);
6393: #if 1
6394: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
6395: for (p = 0; p < size; ++p) {
6396: if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", supportRef[p], eStartNew, eEndNew);
6397: }
6398: #endif
6399: }
6400: /* Interior edge vertices have 2 + faces supports */
6401: for (e = eStart; e < eMax; ++e) {
6402: const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
6403: const PetscInt *cone, *support;
6404: PetscInt size, s;
6406: DMPlexGetSupportSize(dm, e, &size);
6407: DMPlexGetSupport(dm, e, &support);
6408: supportRef[0] = eStartNew + (e - eStart)*2 + 0;
6409: supportRef[1] = eStartNew + (e - eStart)*2 + 1;
6410: for (s = 0; s < size; ++s) {
6411: PetscInt r;
6413: DMPlexGetCone(dm, support[s], &cone);
6414: for (r = 0; r < 4; ++r) if (cone[r] == e) break;
6415: if (support[s] < fMax) {
6416: supportRef[2+s] = eStartNew + (eMax - eStart)*2 + (support[s] - fStart)*4 + r;
6417: } else {
6418: supportRef[2+s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (support[s] - fMax);
6419: }
6420: }
6421: DMPlexSetSupport(rdm, newp, supportRef);
6422: #if 1
6423: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
6424: for (p = 0; p < 2+size; ++p) {
6425: if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", supportRef[p], eStartNew, eEndNew);
6426: }
6427: #endif
6428: }
6429: /* Interior face vertices have 4 + cells supports */
6430: for (f = fStart; f < fMax; ++f) {
6431: const PetscInt newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (f - fStart);
6432: const PetscInt *cone, *support;
6433: PetscInt size, s;
6435: DMPlexGetSupportSize(dm, f, &size);
6436: DMPlexGetSupport(dm, f, &support);
6437: for (r = 0; r < 4; ++r) supportRef[r] = eStartNew + (eMax - eStart)*2 + (f - fStart)*4 + r;
6438: for (s = 0; s < size; ++s) {
6439: PetscInt r;
6441: DMPlexGetCone(dm, support[s], &cone);
6442: for (r = 0; r < 6; ++r) if (cone[r] == f) break;
6443: if (support[s] < cMax) {
6444: supportRef[4+s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (support[s] - cStart)*6 + r;
6445: } else {
6446: supportRef[4+s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (fEnd - fMax) + (support[s] - cMax);
6447: }
6448: }
6449: DMPlexSetSupport(rdm, newp, supportRef);
6450: #if 1
6451: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
6452: for (p = 0; p < 4+size; ++p) {
6453: if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", supportRef[p], eStartNew, eEndNew);
6454: }
6455: #endif
6456: }
6457: /* Cell vertices have 6 supports */
6458: for (c = cStart; c < cMax; ++c) {
6459: const PetscInt newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (fMax - fStart) + (c - cStart);
6460: PetscInt supportNew[6];
6462: for (r = 0; r < 6; ++r) {
6463: supportNew[r] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + r;
6464: }
6465: DMPlexSetSupport(rdm, newp, supportNew);
6466: }
6467: PetscFree(supportRef);
6468: break;
6469: default:
6470: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
6471: }
6472: return(0);
6473: }
6475: static PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
6476: {
6477: PetscSection coordSection, coordSectionNew;
6478: Vec coordinates, coordinatesNew;
6479: PetscScalar *coords, *coordsNew;
6480: const PetscInt numVertices = depthSize ? depthSize[0] : 0;
6481: PetscInt dim, spaceDim, depth, bs, coordSizeNew, cStart, cEnd, cMax;
6482: PetscInt c, vStart, vStartNew, vEnd, v, eStart, eEnd, eMax, e, fStart, fEnd, fMax, f;
6483: PetscInt cStartNew, cEndNew, vEndNew, *parentId = NULL;
6484: VecType vtype;
6485: PetscBool isperiodic, localize = PETSC_FALSE, needcoords = PETSC_FALSE;
6486: const PetscReal *maxCell, *L;
6487: const DMBoundaryType *bd;
6488: PetscErrorCode ierr;
6491: DMGetDimension(dm, &dim);
6492: DMPlexGetDepth(dm, &depth);
6493: DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
6494: DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);
6495: DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
6496: DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);
6497: DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, NULL);
6498: GetDepthStart_Private(depth, depthSize, &cStartNew, NULL, NULL, &vStartNew);
6499: GetDepthEnd_Private(depth, depthSize, &cEndNew, NULL, NULL, &vEndNew);
6500: DMGetPeriodicity(dm, &isperiodic, &maxCell, &L, &bd);
6501: /* Determine if we need to localize coordinates when generating them */
6502: if (isperiodic && !maxCell) {
6503: DMGetCoordinatesLocalized(dm, &localize);
6504: if (!localize) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Cannot refine if coordinates have not been localized");
6505: }
6506: if (isperiodic) {
6507: PetscOptionsBegin(PetscObjectComm((PetscObject)dm),((PetscObject)dm)->prefix,"DMPlex coords refinement options","DM");
6508: PetscOptionsBool("-dm_plex_refine_localize","Automatically localize from parent cells",NULL,localize,&localize,NULL);
6509: PetscOptionsEnd();
6510: if (localize) {
6511: DMLocalizeCoordinates(dm);
6512: }
6513: }
6514: DMSetPeriodicity(rdm, isperiodic, maxCell, L, bd);
6516: DMGetCoordinateSection(dm, &coordSection);
6517: PetscSectionGetFieldComponents(coordSection, 0, &spaceDim);
6518: PetscSectionCreate(PetscObjectComm((PetscObject)dm), &coordSectionNew);
6519: PetscSectionSetNumFields(coordSectionNew, 1);
6520: PetscSectionSetFieldComponents(coordSectionNew, 0, spaceDim);
6522: if (localize) {
6523: PetscInt p, r, newp, *pi;
6525: /* New coordinates will be already localized on the cell */
6526: PetscSectionSetChart(coordSectionNew, 0, vStartNew+numVertices);
6528: /* We need the parentId to properly localize coordinates */
6529: PetscMalloc1(cEndNew-cStartNew,&pi);
6530: switch (refiner) {
6531: case REFINER_NOOP:
6532: break;
6533: case REFINER_SIMPLEX_1D:
6534: for (p = cStart; p < cEnd; ++p) {
6535: for (r = 0; r < 2; ++r) {
6536: newp = (p - cStart)*2 + r;
6537: pi[newp] = p;
6538: }
6539: }
6540: break;
6541: case REFINER_SIMPLEX_2D:
6542: for (p = cStart; p < cEnd; ++p) {
6543: for (r = 0; r < 4; ++r) {
6544: newp = (p - cStart)*4 + r;
6545: pi[newp] = p;
6546: }
6547: }
6548: break;
6549: case REFINER_HEX_2D:
6550: for (p = cStart; p < cEnd; ++p) {
6551: for (r = 0; r < 4; ++r) {
6552: newp = (p - cStart)*4 + r;
6553: pi[newp] = p;
6554: }
6555: }
6556: break;
6557: case REFINER_SIMPLEX_TO_HEX_2D:
6558: for (p = cStart; p < cEnd; ++p) {
6559: for (r = 0; r < 3; ++r) {
6560: newp = (p - cStart)*3 + r;
6561: pi[newp] = p;
6562: }
6563: }
6564: break;
6565: case REFINER_HYBRID_SIMPLEX_2D:
6566: for (p = cStart; p < cMax; ++p) {
6567: for (r = 0; r < 4; ++r) {
6568: newp = (p - cStart)*4 + r;
6569: pi[newp] = p;
6570: }
6571: }
6572: for (p = cMax; p < cEnd; ++p) {
6573: for (r = 0; r < 2; ++r) {
6574: newp = (cMax - cStart)*4 + (p - cMax)*2 + r;
6575: pi[newp] = p;
6576: }
6577: }
6578: break;
6579: case REFINER_HYBRID_HEX_2D:
6580: for (p = cStart; p < cMax; ++p) {
6581: for (r = 0; r < 4; ++r) {
6582: newp = (p - cStart)*4 + r;
6583: pi[newp] = p;
6584: }
6585: }
6586: for (p = cMax; p < cEnd; ++p) {
6587: for (r = 0; r < 2; ++r) {
6588: newp = (cMax - cStart)*4 + (p - cMax)*2 + r;
6589: pi[newp] = p;
6590: }
6591: }
6592: break;
6593: case REFINER_SIMPLEX_3D:
6594: for (p = cStart; p < cEnd; ++p) {
6595: for (r = 0; r < 8; ++r) {
6596: newp = (p - cStart)*8 + r;
6597: pi[newp] = p;
6598: }
6599: }
6600: break;
6601: case REFINER_HYBRID_SIMPLEX_3D:
6602: for (p = cStart; p < cMax; ++p) {
6603: for (r = 0; r < 8; ++r) {
6604: newp = (p - cStart)*8 + r;
6605: pi[newp] = p;
6606: }
6607: }
6608: for (p = cMax; p < cEnd; ++p) {
6609: for (r = 0; r < 4; ++r) {
6610: newp = (cMax - cStart)*8 + (p - cMax)*4 + r;
6611: pi[newp] = p;
6612: }
6613: }
6614: break;
6615: case REFINER_SIMPLEX_TO_HEX_3D:
6616: for (p = cStart; p < cEnd; ++p) {
6617: for (r = 0; r < 4; ++r) {
6618: newp = (p - cStart)*4 + r;
6619: pi[newp] = p;
6620: }
6621: }
6622: break;
6623: case REFINER_HEX_3D:
6624: for (p = cStart; p < cEnd; ++p) {
6625: for (r = 0; r < 8; ++r) {
6626: newp = (p - cStart)*8 + r;
6627: pi[newp] = p;
6628: }
6629: }
6630: break;
6631: case REFINER_HYBRID_HEX_3D:
6632: for (p = cStart; p < cMax; ++p) {
6633: for (r = 0; r < 8; ++r) {
6634: newp = (p - cStart)*8 + r;
6635: pi[newp] = p;
6636: }
6637: }
6638: for (p = cMax; p < cEnd; ++p) {
6639: for (r = 0; r < 4; ++r) {
6640: newp = (cMax - cStart)*8 + (p - cMax)*4 + r;
6641: pi[newp] = p;
6642: }
6643: }
6644: break;
6645: default:
6646: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
6647: }
6648: parentId = pi;
6649: } else {
6650: PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+numVertices);
6651: }
6652: if (cMax < 0) cMax = cEnd;
6653: if (fMax < 0) fMax = fEnd;
6654: if (eMax < 0) eMax = eEnd;
6656: /* All vertices have the spaceDim coordinates */
6657: if (localize) {
6658: PetscInt c;
6660: for (c = cStartNew; c < cEndNew; ++c) {
6661: PetscInt *cone = NULL;
6662: PetscInt closureSize, coneSize = 0, p, pdof;
6664: PetscSectionGetDof(coordSection, parentId[c], &pdof);
6665: if (pdof) { /* localize on all cells that are refinement of a localized parent cell */
6666: DMPlexGetTransitiveClosure(rdm, c, PETSC_TRUE, &closureSize, &cone);
6667: for (p = 0; p < closureSize*2; p += 2) {
6668: const PetscInt point = cone[p];
6669: if ((point >= vStartNew) && (point < vEndNew)) coneSize++;
6670: }
6671: DMPlexRestoreTransitiveClosure(rdm, c, PETSC_TRUE, &closureSize, &cone);
6672: PetscSectionSetDof(coordSectionNew, c, coneSize*spaceDim);
6673: PetscSectionSetFieldDof(coordSectionNew, c, 0, coneSize*spaceDim);
6674: }
6675: }
6676: }
6677: for (v = vStartNew; v < vStartNew+numVertices; ++v) {
6678: PetscSectionSetDof(coordSectionNew, v, spaceDim);
6679: PetscSectionSetFieldDof(coordSectionNew, v, 0, spaceDim);
6680: }
6681: PetscSectionSetUp(coordSectionNew);
6682: DMSetCoordinateSection(rdm, PETSC_DETERMINE, coordSectionNew);
6683: DMGetCoordinatesLocal(dm, &coordinates);
6684: PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);
6685: VecCreate(PETSC_COMM_SELF, &coordinatesNew);
6686: PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");
6687: VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);
6688: VecGetBlockSize(coordinates, &bs);
6689: VecSetBlockSize(coordinatesNew, bs);
6690: VecGetType(coordinates, &vtype);
6691: VecSetType(coordinatesNew, vtype);
6692: VecGetArray(coordinates, &coords);
6693: VecGetArray(coordinatesNew, &coordsNew);
6695: switch (refiner) {
6696: case REFINER_NOOP: break;
6697: case REFINER_SIMPLEX_TO_HEX_3D:
6698: case REFINER_HEX_3D:
6699: case REFINER_HYBRID_HEX_3D:
6700: /* Face vertices have the average of corner coordinates */
6701: for (f = fStart; f < fMax; ++f) {
6702: const PetscInt newv = vStartNew + (vEnd - vStart) + (eMax - eStart) + (f - fStart);
6703: PetscInt *cone = NULL;
6704: PetscInt closureSize, coneSize = 0, off[8], offnew, p, d;
6706: DMPlexGetTransitiveClosure(dm, f, PETSC_TRUE, &closureSize, &cone);
6707: for (p = 0; p < closureSize*2; p += 2) {
6708: const PetscInt point = cone[p];
6709: if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point;
6710: }
6711: if (localize) {
6712: const PetscInt *support = NULL;
6713: PetscInt *rStar = NULL;
6714: PetscInt supportSize, rStarSize, coff, s, ccoff[8];
6715: PetscBool cellfound = PETSC_FALSE;
6717: DMPlexGetTransitiveClosure(rdm, newv, PETSC_FALSE, &rStarSize, &rStar);
6718: DMPlexGetSupportSize(dm,f,&supportSize);
6719: DMPlexGetSupport(dm,f,&support);
6720: /* Compute average of coordinates for each cell sharing the face */
6721: for (s = 0; s < supportSize; ++s) {
6722: PetscScalar coordsNewAux[3] = { 0.0, 0.0, 0.0 };
6723: PetscInt *cellCone = NULL;
6724: PetscInt cellClosureSize, cellConeSize = 0, cdof;
6725: const PetscInt cell = support[s];
6726: PetscBool copyoff = PETSC_FALSE;
6728: DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &cellClosureSize, &cellCone);
6729: for (p = 0; p < cellClosureSize*2; p += 2) {
6730: const PetscInt point = cellCone[p];
6731: if ((point >= vStart) && (point < vEnd)) cellCone[cellConeSize++] = point;
6732: }
6733: PetscSectionGetDof(coordSection, cell, &cdof);
6734: if (!cdof) { /* the parent cell does not have localized coordinates */
6735: cellfound = PETSC_TRUE;
6736: for (v = 0; v < coneSize; ++v) {
6737: PetscSectionGetOffset(coordSection, cone[v], &off[v]);
6738: for (d = 0; d < spaceDim; ++d) coordsNewAux[d] += coords[off[v]+d];
6739: }
6740: for (d = 0; d < spaceDim; ++d) coordsNewAux[d] /= coneSize;
6741: } else {
6742: PetscSectionGetOffset(coordSection, cell, &coff);
6743: for (p = 0; p < coneSize; ++p) {
6744: const PetscInt tv = cone[p];
6745: PetscInt cv, voff;
6746: PetscBool locv = PETSC_TRUE;
6748: for (cv = 0; cv < cellConeSize; ++cv) {
6749: if (cellCone[cv] == tv) {
6750: ccoff[p] = spaceDim*cv + coff;
6751: break;
6752: }
6753: }
6754: if (cv == cellConeSize) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unable to map vertex %D\n",tv);
6756: PetscSectionGetOffset(coordSection, cone[p], &voff);
6757: for (d = 0; d < spaceDim; ++d) {
6758: coordsNewAux[d] += coords[ccoff[p]+d];
6759: if (!cellfound && coords[voff+d] != coords[ccoff[p]+d]) locv = PETSC_FALSE;
6760: }
6761: if (locv && !cellfound) {
6762: cellfound = PETSC_TRUE;
6763: copyoff = PETSC_TRUE;
6764: }
6765: }
6766: for (d = 0; d < spaceDim; ++d) coordsNewAux[d] /= coneSize;
6768: /* Found a valid face for the "vertex" part of the Section (physical space)
6769: i.e., a face that has at least one corner in the physical space */
6770: if (copyoff) for (p = 0; p < coneSize; ++p) off[p] = ccoff[p];
6771: }
6773: /* Localize new coordinates on each refined cell */
6774: for (v = 0; v < rStarSize*2; v += 2) {
6775: if ((rStar[v] >= cStartNew) && (rStar[v] < cEndNew) && parentId[rStar[v]-cStartNew] == cell) {
6776: PetscInt *rcone = NULL, rclosureSize, lid, rcdof, rcoff;
6777: const PetscInt rcell = rStar[v];
6779: PetscSectionGetDof(coordSectionNew, rcell, &rcdof);
6780: if (!rcdof) continue;
6781: PetscSectionGetOffset(coordSectionNew, rcell, &rcoff);
6782: DMPlexGetTransitiveClosure(rdm, rcell, PETSC_TRUE, &rclosureSize, &rcone);
6783: for (p = 0, lid = 0; p < rclosureSize*2; p += 2) {
6784: if (rcone[p] == newv) {
6785: for (d = 0; d < spaceDim; d++) coordsNew[rcoff + lid*spaceDim + d] = coordsNewAux[d];
6786: break;
6787: }
6788: if (rcone[p] >= vStartNew && rcone[p] < vEndNew) lid++;
6789: }
6790: DMPlexRestoreTransitiveClosure(rdm, rcell, PETSC_TRUE, &rclosureSize, &rcone);
6791: if (p == closureSize*2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unable to map new vertex %D\n",newv);
6792: }
6793: }
6794: DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &cellClosureSize, &cellCone);
6795: }
6796: DMPlexRestoreTransitiveClosure(rdm, newv, PETSC_FALSE, &rStarSize, &rStar);
6797: if (!cellfound) {
6798: /* Could not find a valid face for the vertex part, we will get this vertex later (final reduction) */
6799: needcoords = PETSC_TRUE;
6800: coneSize = 0;
6801: }
6802: } else {
6803: for (v = 0; v < coneSize; ++v) {
6804: PetscSectionGetOffset(coordSection, cone[v], &off[v]);
6805: }
6806: }
6807: PetscSectionGetOffset(coordSectionNew, newv, &offnew);
6808: if (coneSize) {
6809: for (d = 0; d < spaceDim; ++d) coordsNew[offnew+d] = 0.0;
6810: for (v = 0; v < coneSize; ++v) {DMLocalizeAddCoordinate_Internal(dm, spaceDim, &coords[off[0]], &coords[off[v]], &coordsNew[offnew]);}
6811: for (d = 0; d < spaceDim; ++d) coordsNew[offnew+d] /= coneSize;
6812: } else {
6813: for (d = 0; d < spaceDim; ++d) coordsNew[offnew+d] = PETSC_MIN_REAL;
6814: }
6815: DMPlexRestoreTransitiveClosure(dm, f, PETSC_TRUE, &closureSize, &cone);
6816: }
6817: case REFINER_SIMPLEX_TO_HEX_2D:
6818: case REFINER_HEX_2D:
6819: case REFINER_HYBRID_HEX_2D:
6820: case REFINER_SIMPLEX_1D:
6821: /* Cell vertices have the average of corner coordinates */
6822: for (c = cStart; c < cMax; ++c) {
6823: const PetscInt newv = vStartNew + (vEnd - vStart) + (dim > 1 ? (eMax - eStart) : 0) + (c - cStart) + (dim > 2 ? (fMax - fStart) : 0);
6824: PetscInt *cone = NULL;
6825: PetscInt closureSize, coneSize = 0, off[8], offnew, p, d, cdof = 0;
6827: DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);
6828: for (p = 0; p < closureSize*2; p += 2) {
6829: const PetscInt point = cone[p];
6830: if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point;
6831: }
6832: if (localize) {
6833: PetscSectionGetDof(coordSection, c, &cdof);
6834: }
6835: if (cdof) {
6836: PetscInt coff;
6838: PetscSectionGetOffset(coordSection, c, &coff);
6839: for (v = 0; v < coneSize; ++v) off[v] = spaceDim*v + coff;
6840: } else {
6841: for (v = 0; v < coneSize; ++v) {
6842: PetscSectionGetOffset(coordSection, cone[v], &off[v]);
6843: }
6844: }
6845: PetscSectionGetOffset(coordSectionNew, newv, &offnew);
6846: for (d = 0; d < spaceDim; ++d) coordsNew[offnew+d] = 0.0;
6847: for (v = 0; v < coneSize; ++v) {DMLocalizeAddCoordinate_Internal(dm, spaceDim, &coords[off[0]], &coords[off[v]], &coordsNew[offnew]);}
6848: for (d = 0; d < spaceDim; ++d) coordsNew[offnew+d] /= coneSize;
6849: DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);
6851: /* Localize new coordinates on each refined cell */
6852: if (cdof) {
6853: PetscInt *rStar = NULL, rStarSize;
6855: DMPlexGetTransitiveClosure(rdm, newv, PETSC_FALSE, &rStarSize, &rStar);
6856: for (v = 0; v < rStarSize*2; v += 2) {
6857: if ((rStar[v] >= cStartNew) && (rStar[v] < cEndNew)) {
6858: PetscInt *cone = NULL, closureSize, lid, coff, rc, rcdof;
6860: rc = rStar[v];
6861: PetscSectionGetDof(coordSectionNew, rc, &rcdof);
6862: if (!rcdof) continue;
6863: PetscSectionGetOffset(coordSectionNew, rc, &coff);
6864: DMPlexGetTransitiveClosure(rdm, rc, PETSC_TRUE, &closureSize, &cone);
6865: for (p = 0, lid = 0; p < closureSize*2; p += 2) {
6866: if (cone[p] == newv) {
6867: for (d = 0; d < spaceDim; d++) coordsNew[coff + lid*spaceDim + d] = coordsNew[offnew + d];
6868: break;
6869: }
6870: if (cone[p] >= vStartNew && cone[p] < vEndNew) lid++;
6871: }
6872: if (p == closureSize*2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unable to map new vertex %D\n",newv);
6873: DMPlexRestoreTransitiveClosure(rdm, rc, PETSC_TRUE, &closureSize, &cone);
6874: }
6875: }
6876: DMPlexRestoreTransitiveClosure(rdm, newv, PETSC_FALSE, &rStarSize, &rStar);
6877: }
6878: }
6879: case REFINER_SIMPLEX_2D:
6880: case REFINER_HYBRID_SIMPLEX_2D:
6881: case REFINER_SIMPLEX_3D:
6882: case REFINER_HYBRID_SIMPLEX_3D:
6883: /* Edge vertices have the average of endpoint coordinates */
6884: for (e = eStart; e < eMax; ++e) {
6885: const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);
6886: const PetscInt *cone;
6887: PetscInt coneSize, offA, offB, offnew, d;
6889: DMPlexGetConeSize(dm, e, &coneSize);
6890: if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %d cone should have two vertices, not %d", e, coneSize);
6891: DMPlexGetCone(dm, e, &cone);
6892: if (localize) {
6893: PetscInt coff, toffA = -1, toffB = -1, voffA, voffB;
6894: PetscInt *eStar = NULL, eStarSize;
6895: PetscInt *rStar = NULL, rStarSize;
6896: PetscBool cellfound = PETSC_FALSE;
6898: offA = offB = -1;
6899: PetscSectionGetOffset(coordSection, cone[0], &voffA);
6900: PetscSectionGetOffset(coordSection, cone[1], &voffB);
6901: DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &eStarSize, &eStar);
6902: DMPlexGetTransitiveClosure(rdm, newv, PETSC_FALSE, &rStarSize, &rStar);
6903: for (v = 0; v < eStarSize*2; v += 2) {
6904: if ((eStar[v] >= cStart) && (eStar[v] < cEnd)) {
6905: PetscScalar coordsNewAux[3];
6906: PetscInt *cellCone = NULL;
6907: PetscInt cellClosureSize, s, cv, cdof;
6908: PetscBool locvA = PETSC_TRUE, locvB = PETSC_TRUE;
6909: const PetscInt cell = eStar[v];
6911: PetscSectionGetDof(coordSection, cell, &cdof);
6912: if (!cdof) {
6913: /* Found a valid edge for the "vertex" part of the Section */
6914: offA = voffA;
6915: offB = voffB;
6916: cellfound = PETSC_TRUE;
6917: } else {
6918: PetscSectionGetOffset(coordSection, cell, &coff);
6919: DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &cellClosureSize, &cellCone);
6920: for (s = 0, cv = 0; s < cellClosureSize*2; s += 2) {
6921: const PetscInt point = cellCone[s];
6922: if ((point >= vStart) && (point < vEnd)) {
6923: if (point == cone[0]) toffA = spaceDim*cv + coff;
6924: else if (point == cone[1]) toffB = spaceDim*cv + coff;
6925: cv++;
6926: }
6927: }
6928: DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &cellClosureSize, &cellCone);
6929: for (d = 0; d < spaceDim; ++d) {
6930: coordsNewAux[d] = 0.5*(coords[toffA+d] + coords[toffB+d]);
6931: if (coords[toffA+d] != coords[voffA+d]) locvA = PETSC_FALSE;
6932: if (coords[toffB+d] != coords[voffB+d]) locvB = PETSC_FALSE;
6933: }
6934: /* Found a valid edge for the "vertex" part of the Section */
6935: if (!cellfound && (locvA || locvB)) {
6936: cellfound = PETSC_TRUE;
6937: offA = toffA;
6938: offB = toffB;
6939: }
6940: }
6942: /* Localize new coordinates on each refined cell */
6943: for (s = 0; s < rStarSize*2; s += 2) {
6944: if ((rStar[s] >= cStartNew) && (rStar[s] < cEndNew) && parentId[rStar[s]-cStartNew] == cell) {
6945: PetscInt *rcone = NULL, rclosureSize, lid, p, rcdof;
6946: const PetscInt rcell = rStar[s];
6948: PetscSectionGetDof(coordSectionNew, rcell, &rcdof);
6949: if (!rcdof) continue;
6950: PetscSectionGetOffset(coordSectionNew, rcell, &coff);
6951: DMPlexGetTransitiveClosure(rdm, rcell, PETSC_TRUE, &rclosureSize, &rcone);
6952: for (p = 0, lid = 0; p < rclosureSize*2; p += 2) {
6953: if (rcone[p] == newv) {
6954: for (d = 0; d < spaceDim; d++) coordsNew[coff + lid*spaceDim + d] = coordsNewAux[d];
6955: break;
6956: }
6957: if (rcone[p] >= vStartNew && rcone[p] < vEndNew) lid++;
6958: }
6959: DMPlexRestoreTransitiveClosure(rdm, rcell, PETSC_TRUE, &rclosureSize, &rcone);
6960: if (p == rclosureSize*2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unable to map new vertex %D\n",newv);
6961: }
6962: }
6963: }
6964: }
6965: DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &eStarSize, &eStar);
6966: DMPlexRestoreTransitiveClosure(rdm, newv, PETSC_FALSE, &rStarSize, &rStar);
6967: if (!cellfound) {
6968: /* Could not find a valid edge for the vertex part, we will get this vertex later (final reduction) */
6969: needcoords = PETSC_TRUE;
6970: }
6971: } else {
6972: PetscSectionGetOffset(coordSection, cone[0], &offA);
6973: PetscSectionGetOffset(coordSection, cone[1], &offB);
6974: }
6975: PetscSectionGetOffset(coordSectionNew, newv, &offnew);
6976: if (offA != -1 && offB != -1) {
6977: DMLocalizeCoordinate_Internal(dm, spaceDim, &coords[offA], &coords[offB], &coordsNew[offnew]);
6978: for (d = 0; d < spaceDim; ++d) {
6979: coordsNew[offnew+d] = 0.5*(coords[offA+d] + coordsNew[offnew+d]);
6980: }
6981: } else {
6982: for (d = 0; d < spaceDim; ++d) coordsNew[offnew+d] = PETSC_MIN_REAL;
6983: }
6984: }
6985: /* Old vertices have the same coordinates */
6986: for (v = vStart; v < vEnd; ++v) {
6987: const PetscInt newv = vStartNew + (v - vStart);
6988: PetscInt off, offnew, d;
6990: PetscSectionGetOffset(coordSection, v, &off);
6991: PetscSectionGetOffset(coordSectionNew, newv, &offnew);
6992: for (d = 0; d < spaceDim; ++d) {
6993: coordsNew[offnew+d] = coords[off+d];
6994: }
6996: /* Localize new coordinates on each refined cell */
6997: if (localize) {
6998: PetscInt p;
6999: PetscInt *rStar = NULL, rStarSize;
7001: DMPlexGetTransitiveClosure(rdm, newv, PETSC_FALSE, &rStarSize, &rStar);
7002: for (p = 0; p < rStarSize*2; p += 2) {
7003: if ((rStar[p] >= cStartNew) && (rStar[p] < cEndNew)) {
7004: PetscScalar ocoords[3];
7005: PetscInt *cone = NULL, closureSize, lid, coff, s, oc, cdof;
7007: c = rStar[p];
7008: oc = parentId[c-cStartNew];
7009: PetscSectionGetDof(coordSectionNew, c, &cdof);
7010: if (!cdof) continue;
7011: PetscSectionGetDof(coordSection, oc, &cdof);
7012: if (!cdof) continue;
7013: PetscSectionGetOffset(coordSection, oc, &coff);
7014: DMPlexGetTransitiveClosure(dm, oc, PETSC_TRUE, &closureSize, &cone);
7015: for (s = 0, lid = 0; s < closureSize*2; s += 2) {
7016: if (cone[s] == v) {
7017: for (d = 0; d < spaceDim; d++) ocoords[d] = coords[coff + lid*spaceDim + d];
7018: break;
7019: }
7020: if (cone[s] >= vStart && cone[s] < vEnd) lid++;
7021: }
7022: if (s == closureSize*2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unable to map old vertex %D\n",v);
7023: DMPlexRestoreTransitiveClosure(dm, oc, PETSC_TRUE, &closureSize, &cone);
7025: PetscSectionGetOffset(coordSectionNew, c, &coff);
7026: DMPlexGetTransitiveClosure(rdm, c, PETSC_TRUE, &closureSize, &cone);
7027: for (s = 0, lid = 0; s < closureSize*2; s += 2) {
7028: if (cone[s] == newv) {
7029: for (d = 0; d < spaceDim; d++) coordsNew[coff + lid*spaceDim + d] = ocoords[d];
7030: break;
7031: }
7032: if (cone[s] >= vStartNew && cone[s] < vEndNew) lid++;
7033: }
7034: if (s == closureSize*2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unable to map new vertex %D\n",newv);
7035: DMPlexRestoreTransitiveClosure(rdm, c, PETSC_TRUE, &closureSize, &cone);
7036: }
7037: }
7038: DMPlexRestoreTransitiveClosure(rdm, newv, PETSC_FALSE, &rStarSize, &rStar);
7039: }
7040: }
7041: break;
7042: default:
7043: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
7044: }
7045: VecRestoreArray(coordinates, &coords);
7046: VecRestoreArray(coordinatesNew, &coordsNew);
7047: DMSetCoordinatesLocal(rdm, coordinatesNew);
7049: /* Final reduction (if needed) if we are localizing */
7050: if (localize) {
7051: PetscBool gred;
7053: MPIU_Allreduce(&needcoords, &gred, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)rdm));
7054: if (gred) {
7055: DM cdm;
7056: Vec aux;
7057: PetscSF sf;
7058: const PetscScalar *lArray;
7059: PetscScalar *gArray;
7061: DMGetCoordinateDM(rdm, &cdm);
7062: DMCreateGlobalVector(cdm, &aux);
7063: DMGetDefaultSF(cdm, &sf);
7064: VecGetArrayRead(coordinatesNew, &lArray);
7065: VecSet(aux, PETSC_MIN_REAL);
7066: VecGetArray(aux, &gArray);
7067: PetscSFReduceBegin(sf, MPIU_SCALAR, lArray, gArray, MPIU_MAX);
7068: PetscSFReduceEnd(sf, MPIU_SCALAR, lArray, gArray, MPIU_MAX);
7069: VecRestoreArrayRead(coordinatesNew, &lArray);
7070: VecRestoreArray(aux, &gArray);
7071: DMGlobalToLocalBegin(cdm, aux, INSERT_VALUES, coordinatesNew);
7072: DMGlobalToLocalEnd(cdm, aux, INSERT_VALUES, coordinatesNew);
7073: VecDestroy(&aux);
7074: }
7075: }
7076: VecDestroy(&coordinatesNew);
7077: PetscSectionDestroy(&coordSectionNew);
7078: PetscFree(parentId);
7079: return(0);
7080: }
7082: /*@
7083: DMPlexCreateProcessSF - Create an SF which just has process connectivity
7085: Collective on DM
7087: Input Parameters:
7088: + dm - The DM
7089: - sfPoint - The PetscSF which encodes point connectivity
7091: Output Parameters:
7092: + processRanks - A list of process neighbors, or NULL
7093: - sfProcess - An SF encoding the process connectivity, or NULL
7095: Level: developer
7097: .seealso: PetscSFCreate(), DMPlexCreateTwoSidedProcessSF()
7098: @*/
7099: PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess)
7100: {
7101: PetscInt numRoots, numLeaves, l;
7102: const PetscInt *localPoints;
7103: const PetscSFNode *remotePoints;
7104: PetscInt *localPointsNew;
7105: PetscSFNode *remotePointsNew;
7106: PetscInt *ranks, *ranksNew;
7107: PetscMPIInt size;
7108: PetscErrorCode ierr;
7115: MPI_Comm_size(PetscObjectComm((PetscObject) dm), &size);
7116: PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);
7117: PetscMalloc1(numLeaves, &ranks);
7118: for (l = 0; l < numLeaves; ++l) {
7119: ranks[l] = remotePoints[l].rank;
7120: }
7121: PetscSortRemoveDupsInt(&numLeaves, ranks);
7122: PetscMalloc1(numLeaves, &ranksNew);
7123: PetscMalloc1(numLeaves, &localPointsNew);
7124: PetscMalloc1(numLeaves, &remotePointsNew);
7125: for (l = 0; l < numLeaves; ++l) {
7126: ranksNew[l] = ranks[l];
7127: localPointsNew[l] = l;
7128: remotePointsNew[l].index = 0;
7129: remotePointsNew[l].rank = ranksNew[l];
7130: }
7131: PetscFree(ranks);
7132: if (processRanks) {ISCreateGeneral(PetscObjectComm((PetscObject)dm), numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);}
7133: else {PetscFree(ranksNew);}
7134: if (sfProcess) {
7135: PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess);
7136: PetscObjectSetName((PetscObject) *sfProcess, "Process SF");
7137: PetscSFSetFromOptions(*sfProcess);
7138: PetscSFSetGraph(*sfProcess, size, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);
7139: }
7140: return(0);
7141: }
7143: static PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
7144: {
7145: PetscSF sf, sfNew, sfProcess;
7146: IS processRanks;
7147: MPI_Datatype depthType;
7148: PetscInt numRoots, numLeaves, numLeavesNew = 0, l, m;
7149: const PetscInt *localPoints, *neighbors;
7150: const PetscSFNode *remotePoints;
7151: PetscInt *localPointsNew;
7152: PetscSFNode *remotePointsNew;
7153: PetscInt *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew;
7154: PetscInt ldepth, depth, numNeighbors, pStartNew, pEndNew, cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax, r, n;
7155: PetscInt cStartNew = 0, vStartNew = 0, fStartNew = 0, eStartNew = 0;
7156: PetscErrorCode ierr;
7159: DMPlexGetChart(rdm, &pStartNew, &pEndNew);
7160: DMPlexGetDepth(dm, &ldepth);
7161: MPIU_Allreduce(&ldepth, &depth, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject) dm));
7162: if ((ldepth >= 0) && (depth != ldepth)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Inconsistent Plex depth %d != %d", ldepth, depth);
7163: DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
7164: DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);
7165: DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
7166: DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);
7167: DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);
7168: cMax = cMax < 0 ? cEnd : cMax;
7169: fMax = fMax < 0 ? fEnd : fMax;
7170: eMax = eMax < 0 ? eEnd : eMax;
7171: if (refiner) {GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);}
7172: DMGetPointSF(dm, &sf);
7173: DMGetPointSF(rdm, &sfNew);
7174: /* Calculate size of new SF */
7175: PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);
7176: if (numRoots < 0) return(0);
7177: for (l = 0; l < numLeaves; ++l) {
7178: const PetscInt p = localPoints[l];
7180: switch (refiner) {
7181: case REFINER_SIMPLEX_1D:
7182: if ((p >= vStart) && (p < vEnd)) {
7183: /* Interior vertices stay the same */
7184: ++numLeavesNew;
7185: } else if ((p >= cStart && p < cMax)) {
7186: /* Interior cells add new cells and interior vertices */
7187: numLeavesNew += 2 + 1;
7188: }
7189: break;
7190: case REFINER_SIMPLEX_2D:
7191: case REFINER_HYBRID_SIMPLEX_2D:
7192: if ((p >= vStart) && (p < vEnd)) {
7193: /* Interior vertices stay the same */
7194: ++numLeavesNew;
7195: } else if ((p >= fStart) && (p < fMax)) {
7196: /* Interior faces add new faces and vertex */
7197: numLeavesNew += 2 + 1;
7198: } else if ((p >= fMax) && (p < fEnd)) {
7199: /* Hybrid faces stay the same */
7200: ++numLeavesNew;
7201: } else if ((p >= cStart) && (p < cMax)) {
7202: /* Interior cells add new cells and interior faces */
7203: numLeavesNew += 4 + 3;
7204: } else if ((p >= cMax) && (p < cEnd)) {
7205: /* Hybrid cells add new cells and hybrid face */
7206: numLeavesNew += 2 + 1;
7207: }
7208: break;
7209: case REFINER_SIMPLEX_TO_HEX_2D:
7210: if ((p >= vStart) && (p < vEnd)) {
7211: /* Interior vertices stay the same */
7212: ++numLeavesNew;
7213: } else if ((p >= fStart) && (p < fEnd)) {
7214: /* Interior faces add new faces and vertex */
7215: numLeavesNew += 2 + 1;
7216: } else if ((p >= cStart) && (p < cEnd)) {
7217: /* Interior cells add new cells, interior faces, and vertex */
7218: numLeavesNew += 3 + 3 + 1;
7219: }
7220: break;
7221: case REFINER_HEX_2D:
7222: case REFINER_HYBRID_HEX_2D:
7223: if ((p >= vStart) && (p < vEnd)) {
7224: /* Interior vertices stay the same */
7225: ++numLeavesNew;
7226: } else if ((p >= fStart) && (p < fMax)) {
7227: /* Interior faces add new faces and vertex */
7228: numLeavesNew += 2 + 1;
7229: } else if ((p >= fMax) && (p < fEnd)) {
7230: /* Hybrid faces stay the same */
7231: ++numLeavesNew;
7232: } else if ((p >= cStart) && (p < cMax)) {
7233: /* Interior cells add new cells, interior faces, and vertex */
7234: numLeavesNew += 4 + 4 + 1;
7235: } else if ((p >= cMax) && (p < cEnd)) {
7236: /* Hybrid cells add new cells and hybrid face */
7237: numLeavesNew += 2 + 1;
7238: }
7239: break;
7240: case REFINER_SIMPLEX_3D:
7241: case REFINER_HYBRID_SIMPLEX_3D:
7242: if ((p >= vStart) && (p < vEnd)) {
7243: /* Interior vertices stay the same */
7244: ++numLeavesNew;
7245: } else if ((p >= eStart) && (p < eMax)) {
7246: /* Interior edges add new edges and vertex */
7247: numLeavesNew += 2 + 1;
7248: } else if ((p >= eMax) && (p < eEnd)) {
7249: /* Hybrid edges stay the same */
7250: ++numLeavesNew;
7251: } else if ((p >= fStart) && (p < fMax)) {
7252: /* Interior faces add new faces and edges */
7253: numLeavesNew += 4 + 3;
7254: } else if ((p >= fMax) && (p < fEnd)) {
7255: /* Hybrid faces add new faces and edges */
7256: numLeavesNew += 2 + 1;
7257: } else if ((p >= cStart) && (p < cMax)) {
7258: /* Interior cells add new cells, faces, and edges */
7259: numLeavesNew += 8 + 8 + 1;
7260: } else if ((p >= cMax) && (p < cEnd)) {
7261: /* Hybrid cells add new cells and faces */
7262: numLeavesNew += 4 + 3;
7263: }
7264: break;
7265: case REFINER_SIMPLEX_TO_HEX_3D:
7266: if ((p >= vStart) && (p < vEnd)) {
7267: /* Interior vertices stay the same */
7268: ++numLeavesNew;
7269: } else if ((p >= eStart) && (p < eEnd)) {
7270: /* Interior edges add new edges and vertex */
7271: numLeavesNew += 2 + 1;
7272: } else if ((p >= fStart) && (p < fEnd)) {
7273: /* Interior faces add new faces, edges and a vertex */
7274: numLeavesNew += 3 + 3 + 1;
7275: } else if ((p >= cStart) && (p < cEnd)) {
7276: /* Interior cells add new cells, faces, edges and a vertex */
7277: numLeavesNew += 4 + 6 + 4 + 1;
7278: }
7279: break;
7280: case REFINER_HEX_3D:
7281: case REFINER_HYBRID_HEX_3D:
7282: if ((p >= vStart) && (p < vEnd)) {
7283: /* Old vertices stay the same */
7284: ++numLeavesNew;
7285: } else if ((p >= eStart) && (p < eMax)) {
7286: /* Interior edges add new edges, and vertex */
7287: numLeavesNew += 2 + 1;
7288: } else if ((p >= eMax) && (p < eEnd)) {
7289: /* Hybrid edges stay the same */
7290: ++numLeavesNew;
7291: } else if ((p >= fStart) && (p < fMax)) {
7292: /* Interior faces add new faces, edges, and vertex */
7293: numLeavesNew += 4 + 4 + 1;
7294: } else if ((p >= fMax) && (p < fEnd)) {
7295: /* Hybrid faces add new faces and edges */
7296: numLeavesNew += 2 + 1;
7297: } else if ((p >= cStart) && (p < cMax)) {
7298: /* Interior cells add new cells, faces, edges, and vertex */
7299: numLeavesNew += 8 + 12 + 6 + 1;
7300: } else if ((p >= cStart) && (p < cEnd)) {
7301: /* Hybrid cells add new cells, faces, and edges */
7302: numLeavesNew += 4 + 4 + 1;
7303: }
7304: break;
7305: default:
7306: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
7307: }
7308: }
7309: /* Communicate depthSizes for each remote rank */
7310: DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);
7311: ISGetLocalSize(processRanks, &numNeighbors);
7312: PetscMalloc5((depth+1)*numNeighbors,&rdepthSize,numNeighbors,&rvStartNew,numNeighbors,&reStartNew,numNeighbors,&rfStartNew,numNeighbors,&rcStartNew);
7313: PetscMalloc7(depth+1,&depthSizeOld,(depth+1)*numNeighbors,&rdepthSizeOld,(depth+1)*numNeighbors,&rdepthMaxOld,numNeighbors,&rvStart,numNeighbors,&reStart,numNeighbors,&rfStart,numNeighbors,&rcStart);
7314: MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);
7315: MPI_Type_commit(&depthType);
7316: PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);
7317: PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);
7318: for (n = 0; n < numNeighbors; ++n) {
7319: GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);
7320: }
7321: depthSizeOld[depth] = cMax;
7322: depthSizeOld[0] = vMax;
7323: depthSizeOld[depth-1] = fMax;
7324: depthSizeOld[1] = eMax;
7326: PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);
7327: PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);
7329: depthSizeOld[depth] = cEnd - cStart;
7330: depthSizeOld[0] = vEnd - vStart;
7331: depthSizeOld[depth-1] = fEnd - fStart;
7332: depthSizeOld[1] = eEnd - eStart;
7334: PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);
7335: PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);
7336: for (n = 0; n < numNeighbors; ++n) {
7337: GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);
7338: rdepthMaxOld[n*(depth+1)+depth] = rdepthMaxOld[n*(depth+1)+depth] < 0 ? rdepthSizeOld[n*(depth+1)+depth] +rcStart[n]: rdepthMaxOld[n*(depth+1)+depth];
7339: rdepthMaxOld[n*(depth+1)+depth-1] = rdepthMaxOld[n*(depth+1)+depth-1] < 0 ? rdepthSizeOld[n*(depth+1)+depth-1]+rfStart[n]: rdepthMaxOld[n*(depth+1)+depth-1];
7340: rdepthMaxOld[n*(depth+1)+1] = rdepthMaxOld[n*(depth+1)+1] < 0 ? rdepthSizeOld[n*(depth+1)+1] +reStart[n]: rdepthMaxOld[n*(depth+1)+1];
7341: }
7342: MPI_Type_free(&depthType);
7343: PetscSFDestroy(&sfProcess);
7344: /* Calculate new point SF */
7345: PetscMalloc1(numLeavesNew, &localPointsNew);
7346: PetscMalloc1(numLeavesNew, &remotePointsNew);
7347: ISGetIndices(processRanks, &neighbors);
7348: for (l = 0, m = 0; l < numLeaves; ++l) {
7349: PetscInt p = localPoints[l];
7350: PetscInt rp = remotePoints[l].index, n;
7351: PetscMPIInt rrank = remotePoints[l].rank;
7353: PetscFindInt(rrank, numNeighbors, neighbors, &n);
7354: if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank);
7355: switch (refiner) {
7356: case REFINER_SIMPLEX_1D:
7357: if ((p >= vStart) && (p < vEnd)) {
7358: /* Old vertices stay the same */
7359: localPointsNew[m] = vStartNew + (p - vStart);
7360: remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
7361: remotePointsNew[m].rank = rrank;
7362: ++m;
7363: } else if ((p >= cStart) && (p < cMax)) {
7364: /* Old interior cells add new cells and vertex */
7365: for (r = 0; r < 2; ++r, ++m) {
7366: localPointsNew[m] = cStartNew + (p - cStart)*2 + r;
7367: remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*2 + r;
7368: remotePointsNew[m].rank = rrank;
7369: }
7370: localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - cStart);
7371: remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rcStart[n]);
7372: remotePointsNew[m].rank = rrank;
7373: ++m;
7374: }
7375: break;
7376: case REFINER_SIMPLEX_2D:
7377: case REFINER_HYBRID_SIMPLEX_2D:
7378: if ((p >= vStart) && (p < vEnd)) {
7379: /* Old vertices stay the same */
7380: localPointsNew[m] = vStartNew + (p - vStart);
7381: remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
7382: remotePointsNew[m].rank = rrank;
7383: ++m;
7384: } else if ((p >= fStart) && (p < fMax)) {
7385: /* Old interior faces add new faces and vertex */
7386: for (r = 0; r < 2; ++r, ++m) {
7387: localPointsNew[m] = fStartNew + (p - fStart)*2 + r;
7388: remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
7389: remotePointsNew[m].rank = rrank;
7390: }
7391: localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart);
7392: remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
7393: remotePointsNew[m].rank = rrank;
7394: ++m;
7395: } else if ((p >= fMax) && (p < fEnd)) {
7396: /* Old hybrid faces stay the same */
7397: localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - fMax);
7398: remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]);
7399: remotePointsNew[m].rank = rrank;
7400: ++m;
7401: } else if ((p >= cStart) && (p < cMax)) {
7402: /* Old interior cells add new cells and interior faces */
7403: for (r = 0; r < 4; ++r, ++m) {
7404: localPointsNew[m] = cStartNew + (p - cStart)*4 + r;
7405: remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
7406: remotePointsNew[m].rank = rrank;
7407: }
7408: for (r = 0; r < 3; ++r, ++m) {
7409: localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - cStart)*3 + r;
7410: remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r;
7411: remotePointsNew[m].rank = rrank;
7412: }
7413: } else if ((p >= cMax) && (p < cEnd)) {
7414: /* Old hybrid cells add new cells and hybrid face */
7415: for (r = 0; r < 2; ++r, ++m) {
7416: localPointsNew[m] = cStartNew + (p - cStart)*4 + r;
7417: remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
7418: remotePointsNew[m].rank = rrank;
7419: }
7420: localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax);
7421: remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*3 + (rp - rdepthMaxOld[n*(depth+1)+depth]);
7422: remotePointsNew[m].rank = rrank;
7423: ++m;
7424: }
7425: break;
7426: case REFINER_SIMPLEX_TO_HEX_2D:
7427: if ((p >= vStart) && (p < vEnd)) {
7428: /* Old vertices stay the same */
7429: localPointsNew[m] = vStartNew + (p - vStart);
7430: remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
7431: remotePointsNew[m].rank = rrank;
7432: ++m;
7433: } else if ((p >= fStart) && (p < fEnd)) {
7434: /* Old interior faces add new faces and vertex */
7435: for (r = 0; r < 2; ++r, ++m) {
7436: localPointsNew[m] = fStartNew + (p - fStart)*2 + r;
7437: remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
7438: remotePointsNew[m].rank = rrank;
7439: }
7440: localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart);
7441: remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
7442: remotePointsNew[m].rank = rrank;
7443: ++m;
7444: } else if ((p >= cStart) && (p < cEnd)) {
7445: /* Old interior cells add new cells, interior faces, and a vertex */
7446: for (r = 0; r < 3; ++r, ++m) {
7447: localPointsNew[m] = cStartNew + (p - cStart)*3 + r;
7448: remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*3 + r;
7449: remotePointsNew[m].rank = rrank;
7450: }
7451: for (r = 0; r < 3; ++r, ++m) {
7452: localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r;
7453: remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r;
7454: remotePointsNew[m].rank = rrank;
7455: }
7456: localPointsNew[m] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart);
7457: remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + rdepthSizeOld[n*(depth+1)+depth-1] + (rp - rcStart[n]);
7458: remotePointsNew[m].rank = rrank;
7459: ++m;
7460: }
7461: break;
7462: case REFINER_HEX_2D:
7463: case REFINER_HYBRID_HEX_2D:
7464: if ((p >= vStart) && (p < vEnd)) {
7465: /* Old vertices stay the same */
7466: localPointsNew[m] = vStartNew + (p - vStart);
7467: remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
7468: remotePointsNew[m].rank = rrank;
7469: ++m;
7470: } else if ((p >= fStart) && (p < fMax)) {
7471: /* Old interior faces add new faces and vertex */
7472: for (r = 0; r < 2; ++r, ++m) {
7473: localPointsNew[m] = fStartNew + (p - fStart)*2 + r;
7474: remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
7475: remotePointsNew[m].rank = rrank;
7476: }
7477: localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart);
7478: remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
7479: remotePointsNew[m].rank = rrank;
7480: ++m;
7481: } else if ((p >= fMax) && (p < fEnd)) {
7482: /* Old hybrid faces stay the same */
7483: localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - fMax);
7484: remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]);
7485: remotePointsNew[m].rank = rrank;
7486: ++m;
7487: } else if ((p >= cStart) && (p < cMax)) {
7488: /* Old interior cells add new cells, interior faces, and vertex */
7489: for (r = 0; r < 4; ++r, ++m) {
7490: localPointsNew[m] = cStartNew + (p - cStart)*4 + r;
7491: remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
7492: remotePointsNew[m].rank = rrank;
7493: }
7494: for (r = 0; r < 4; ++r, ++m) {
7495: localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - cStart)*4 + r;
7496: remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*4 + r;
7497: remotePointsNew[m].rank = rrank;
7498: }
7499: localPointsNew[m] = vStartNew + (vEnd - vStart) + (fMax - fStart) + (p - cStart);
7500: remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n]) + (rp - rcStart[n]);
7501: remotePointsNew[m].rank = rrank;
7502: ++m;
7503: } else if ((p >= cStart) && (p < cMax)) {
7504: /* Old hybrid cells add new cells and hybrid face */
7505: for (r = 0; r < 2; ++r, ++m) {
7506: localPointsNew[m] = cStartNew + (p - cStart)*4 + r;
7507: remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
7508: remotePointsNew[m].rank = rrank;
7509: }
7510: localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (p - cMax);
7511: remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*4 + (rp - rdepthMaxOld[n*(depth+1)+depth]);
7512: remotePointsNew[m].rank = rrank;
7513: ++m;
7514: }
7515: break;
7516: case REFINER_SIMPLEX_3D:
7517: case REFINER_HYBRID_SIMPLEX_3D:
7518: if ((p >= vStart) && (p < vEnd)) {
7519: /* Interior vertices stay the same */
7520: localPointsNew[m] = vStartNew + (p - vStart);
7521: remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
7522: remotePointsNew[m].rank = rrank;
7523: ++m;
7524: } else if ((p >= eStart) && (p < eMax)) {
7525: /* Interior edges add new edges and vertex */
7526: for (r = 0; r < 2; ++r, ++m) {
7527: localPointsNew[m] = eStartNew + (p - eStart)*2 + r;
7528: remotePointsNew[m].index = reStartNew[n] + (rp - reStart[n])*2 + r;
7529: remotePointsNew[m].rank = rrank;
7530: }
7531: localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - eStart);
7532: remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - reStart[n]);
7533: remotePointsNew[m].rank = rrank;
7534: ++m;
7535: } else if ((p >= eMax) && (p < eEnd)) {
7536: /* Hybrid edges stay the same */
7537: localPointsNew[m] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (p - eMax);
7538: remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*3 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n]) + (rp - rdepthMaxOld[n*(depth+1)+1]);
7539: remotePointsNew[m].rank = rrank;
7540: ++m;
7541: } else if ((p >= fStart) && (p < fMax)) {
7542: /* Interior faces add new faces and edges */
7543: for (r = 0; r < 4; ++r, ++m) {
7544: localPointsNew[m] = fStartNew + (p - fStart)*4 + r;
7545: remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*4 + r;
7546: remotePointsNew[m].rank = rrank;
7547: }
7548: for (r = 0; r < 3; ++r, ++m) {
7549: localPointsNew[m] = eStartNew + (eMax - eStart)*2 + (p - fStart)*3 + r;
7550: remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rp - rfStart[n])*3 + r;
7551: remotePointsNew[m].rank = rrank;
7552: }
7553: } else if ((p >= fMax) && (p < fEnd)) {
7554: /* Hybrid faces add new faces and edges */
7555: for (r = 0; r < 2; ++r, ++m) {
7556: localPointsNew[m] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (p - fMax)*2 + r;
7557: remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*8 + (rp - rdepthMaxOld[n*(depth+1)+depth-1])*2 + r;
7558: remotePointsNew[m].rank = rrank;
7559: }
7560: localPointsNew[m] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (p - fMax);
7561: remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*3 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n]) + (rdepthSizeOld[n*(depth+1)+1]+reStart[n] - rdepthMaxOld[n*(depth+1)+1]) + (rp - rdepthMaxOld[n*(depth+1)+depth-1]);
7562: remotePointsNew[m].rank = rrank;
7563: ++m;
7564: } else if ((p >= cStart) && (p < cMax)) {
7565: /* Interior cells add new cells, faces, and edges */
7566: for (r = 0; r < 8; ++r, ++m) {
7567: localPointsNew[m] = cStartNew + (p - cStart)*8 + r;
7568: remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*8 + r;
7569: remotePointsNew[m].rank = rrank;
7570: }
7571: for (r = 0; r < 8; ++r, ++m) {
7572: localPointsNew[m] = fStartNew + (fMax - fStart)*4 + (p - cStart)*8 + r;
7573: remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rp - rcStart[n])*8 + r;
7574: remotePointsNew[m].rank = rrank;
7575: }
7576: localPointsNew[m] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (p - cStart)*1 + 0;
7577: remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*3 + (rp - rcStart[n])*1 + 0;
7578: remotePointsNew[m].rank = rrank;
7579: ++m;
7580: } else if ((p >= cMax) && (p < cEnd)) {
7581: /* Hybrid cells add new cells and faces */
7582: for (r = 0; r < 4; ++r, ++m) {
7583: localPointsNew[m] = cStartNew + (cMax - cStart)*8 + (p - cMax)*4 + r;
7584: remotePointsNew[m].index = rcStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*8 + (rp - rdepthMaxOld[n*(depth+1)+depth])*4 + r;
7585: remotePointsNew[m].rank = rrank;
7586: }
7587: for (r = 0; r < 3; ++r, ++m) {
7588: localPointsNew[m] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (p - cMax)*3 + r;
7589: remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*8 + (rdepthSizeOld[n*(depth+1)+depth-1]+rfStart[n] - rdepthMaxOld[n*(depth+1)+depth-1])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth])*3 + r;
7590: remotePointsNew[m].rank = rrank;
7591: }
7592: }
7593: break;
7594: case REFINER_SIMPLEX_TO_HEX_3D:
7595: if ((p >= vStart) && (p < vEnd)) {
7596: /* Interior vertices stay the same */
7597: localPointsNew[m] = vStartNew + (p - vStart);
7598: remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
7599: remotePointsNew[m].rank = rrank;
7600: ++m;
7601: } else if ((p >= eStart) && (p < eEnd)) {
7602: /* Interior edges add new edges and vertex */
7603: for (r = 0; r < 2; ++r, ++m) {
7604: localPointsNew[m] = eStartNew + (p - eStart)*2 + r;
7605: remotePointsNew[m].index = reStartNew[n] + (rp - reStart[n])*2 + r;
7606: remotePointsNew[m].rank = rrank;
7607: }
7608: localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - eStart);
7609: remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - reStart[n]);
7610: remotePointsNew[m].rank = rrank;
7611: ++m;
7612: } else if ((p >= fStart) && (p < fEnd)) {
7613: /* Interior faces add new faces, edges and a vertex */
7614: for (r = 0; r < 3; ++r, ++m) {
7615: localPointsNew[m] = fStartNew + (p - fStart)*3 + r;
7616: remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*3 + r;
7617: remotePointsNew[m].rank = rrank;
7618: }
7619: for (r = 0; r < 3; ++r, ++m) {
7620: localPointsNew[m] = eStartNew + (eEnd - eStart)*2 + (p - fStart)*3 + r;
7621: remotePointsNew[m].index = reStartNew[n] + (rdepthSizeOld[n*(depth+1)+1])*2 + (rp - rfStart[n])*3 + r;
7622: remotePointsNew[m].rank = rrank;
7623: }
7624: localPointsNew[m] = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (p - fStart);
7625: remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + rdepthSizeOld[n*(depth+1)+1] + (rp - rfStart[n]);
7626: remotePointsNew[m].rank = rrank;
7627: ++m;
7628: } else if ((p >= cStart) && (p < cEnd)) {
7629: /* Interior cells add new cells, faces, edges, and a vertex */
7630: for (r = 0; r < 4; ++r, ++m) {
7631: localPointsNew[m] = cStartNew + (p - cStart)*4 + r;
7632: remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
7633: remotePointsNew[m].rank = rrank;
7634: }
7635: for (r = 0; r < 6; ++r, ++m) {
7636: localPointsNew[m] = fStartNew + (fEnd - fStart)*3 + (p - cStart)*6 + r;
7637: remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*3 + (rp - rcStart[n])*6 + r;
7638: remotePointsNew[m].rank = rrank;
7639: }
7640: for (r = 0; r < 4; ++r, ++m) {
7641: localPointsNew[m] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (p - cStart)*4 + r;
7642: remotePointsNew[m].index = reStartNew[n] + rdepthSizeOld[n*(depth+1)+1]*2 + rdepthSizeOld[n*(depth+1)+depth-1]*3 + (rp - rcStart[n])*4 + r;
7643: remotePointsNew[m].rank = rrank;
7644: }
7645: localPointsNew[m] = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (p - cStart);
7646: remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + rdepthSizeOld[n*(depth+1)+1] + rdepthSizeOld[n*(depth+1)+depth-1] + (rp - rcStart[n]);
7647: remotePointsNew[m].rank = rrank;
7648: ++m;
7649: }
7650: break;
7651: case REFINER_HEX_3D:
7652: case REFINER_HYBRID_HEX_3D:
7653: if ((p >= vStart) && (p < vEnd)) {
7654: /* Interior vertices stay the same */
7655: localPointsNew[m] = vStartNew + (p - vStart);
7656: remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
7657: remotePointsNew[m].rank = rrank;
7658: ++m;
7659: } else if ((p >= eStart) && (p < eMax)) {
7660: /* Interior edges add new edges and vertex */
7661: for (r = 0; r < 2; ++r, ++m) {
7662: localPointsNew[m] = eStartNew + (p - eStart)*2 + r;
7663: remotePointsNew[m].index = reStartNew[n] + (rp - reStart[n])*2 + r;
7664: remotePointsNew[m].rank = rrank;
7665: }
7666: localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - eStart);
7667: remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - reStart[n]);
7668: remotePointsNew[m].rank = rrank;
7669: ++m;
7670: } else if ((p >= eMax) && (p < eEnd)) {
7671: /* Hybrid edges stay the same */
7672: localPointsNew[m] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (p - eMax);
7673: remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*6 + (rp - rdepthMaxOld[n*(depth+1)+1]);
7674: remotePointsNew[m].rank = rrank;
7675: ++m;
7676: } else if ((p >= fStart) && (p < fMax)) {
7677: /* Interior faces add new faces, edges, and vertex */
7678: for (r = 0; r < 4; ++r, ++m) {
7679: localPointsNew[m] = fStartNew + (p - fStart)*4 + r;
7680: remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*4 + r;
7681: remotePointsNew[m].rank = rrank;
7682: }
7683: for (r = 0; r < 4; ++r, ++m) {
7684: localPointsNew[m] = eStartNew + (eMax - eStart)*2 + (p - fStart)*4 + r;
7685: remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rp - rfStart[n])*4 + r;
7686: remotePointsNew[m].rank = rrank;
7687: }
7688: localPointsNew[m] = vStartNew + (vEnd - vStart) + (eMax - eStart) + (p - fStart);
7689: remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n]) + (rp - rfStart[n]);
7690: remotePointsNew[m].rank = rrank;
7691: ++m;
7692: } else if ((p >= fMax) && (p < fEnd)) {
7693: /* Hybrid faces add new faces and edges */
7694: for (r = 0; r < 2; ++r, ++m) {
7695: localPointsNew[m] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (p - fMax)*2 + r;
7696: remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*12 + (rp - rdepthMaxOld[n*(depth+1)+depth-1])*2 + r;
7697: remotePointsNew[m].rank = rrank;
7698: }
7699: localPointsNew[m] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (p - fMax);
7700: remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*6 + (rdepthSizeOld[n*(depth+1)+1]+reStart[n] - rdepthMaxOld[n*(depth+1)+1]) + (rp - rdepthMaxOld[n*(depth+1)+depth-1]);
7701: remotePointsNew[m].rank = rrank;
7702: ++m;
7703: } else if ((p >= cStart) && (p < cMax)) {
7704: /* Interior cells add new cells, faces, edges, and vertex */
7705: for (r = 0; r < 8; ++r, ++m) {
7706: localPointsNew[m] = cStartNew + (p - cStart)*8 + r;
7707: remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*8 + r;
7708: remotePointsNew[m].rank = rrank;
7709: }
7710: for (r = 0; r < 12; ++r, ++m) {
7711: localPointsNew[m] = fStartNew + (fMax - fStart)*4 + (p - cStart)*12 + r;
7712: remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rp - rcStart[n])*12 + r;
7713: remotePointsNew[m].rank = rrank;
7714: }
7715: for (r = 0; r < 6; ++r, ++m) {
7716: localPointsNew[m] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (p - cStart)*6 + r;
7717: remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rp - rcStart[n])*6 + r;
7718: remotePointsNew[m].rank = rrank;
7719: }
7720: for (r = 0; r < 1; ++r, ++m) {
7721: localPointsNew[m] = vStartNew + (eMax - eStart) + (fMax - fStart) + (p - cStart) + r;
7722: remotePointsNew[m].index = rvStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n]) + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n]) + (rp - rcStart[n]) + r;
7723: remotePointsNew[m].rank = rrank;
7724: }
7725: } else if ((p >= cMax) && (p < cEnd)) {
7726: /* Hybrid cells add new cells, faces, and edges */
7727: for (r = 0; r < 4; ++r, ++m) {
7728: localPointsNew[m] = cStartNew + (cMax - cStart)*8 + (p - cMax)*4 + r;
7729: remotePointsNew[m].index = rcStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*8 + (rp - rdepthMaxOld[n*(depth+1)+depth])*4 + r;
7730: remotePointsNew[m].rank = rrank;
7731: }
7732: for (r = 0; r < 4; ++r, ++m) {
7733: localPointsNew[m] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (p - cMax)*4 + r;
7734: remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*12 + (rdepthSizeOld[n*(depth+1)+depth-1]+rfStart[n] - rdepthMaxOld[n*(depth+1)+depth-1])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth])*4 + r;
7735: remotePointsNew[m].rank = rrank;
7736: }
7737: localPointsNew[m] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (fEnd - fMax) + (p - cMax);
7738: remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*6 + (rdepthSizeOld[n*(depth+1)+1]+reStart[n] - rdepthMaxOld[n*(depth+1)+1]) + (rdepthSizeOld[n*(depth+1)+depth-1]+rfStart[n] - rdepthMaxOld[n*(depth+1)+depth-1]) + (rp - rdepthMaxOld[n*(depth+1)+depth]);
7739: remotePointsNew[m].rank = rrank;
7740: ++m;
7741: }
7742: break;
7743: default:
7744: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
7745: }
7746: }
7747: if (m != numLeavesNew) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of leaf point %d should be %d", m, numLeavesNew);
7748: ISRestoreIndices(processRanks, &neighbors);
7749: ISDestroy(&processRanks);
7750: {
7751: PetscSFNode *rp, *rtmp;
7752: PetscInt *lp, *idx, *ltmp, i;
7754: /* SF needs sorted leaves to correct calculate Gather */
7755: PetscMalloc1(numLeavesNew,&idx);
7756: PetscMalloc1(numLeavesNew, &lp);
7757: PetscMalloc1(numLeavesNew, &rp);
7758: for (i = 0; i < numLeavesNew; ++i) {
7759: 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);
7760: idx[i] = i;
7761: }
7762: PetscSortIntWithPermutation(numLeavesNew, localPointsNew, idx);
7763: for (i = 0; i < numLeavesNew; ++i) {
7764: lp[i] = localPointsNew[idx[i]];
7765: rp[i] = remotePointsNew[idx[i]];
7766: }
7767: ltmp = localPointsNew;
7768: localPointsNew = lp;
7769: rtmp = remotePointsNew;
7770: remotePointsNew = rp;
7771: PetscFree(idx);
7772: PetscFree(ltmp);
7773: PetscFree(rtmp);
7774: }
7775: PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);
7776: PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);
7777: PetscFree7(depthSizeOld,rdepthSizeOld,rdepthMaxOld,rvStart,reStart,rfStart,rcStart);
7778: return(0);
7779: }
7781: static PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
7782: {
7783: PetscInt numLabels, l;
7784: PetscInt depth, newp, cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax, r;
7785: PetscInt cStartNew = 0, vStartNew = 0, fStartNew = 0, eStartNew = 0;
7789: DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
7790: DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);
7791: DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
7792: DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);
7793: DMPlexGetDepth(dm, &depth);
7794: if (refiner) {GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);}
7795: DMGetNumLabels(dm, &numLabels);
7796: DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);
7797: switch (refiner) {
7798: case REFINER_NOOP:
7799: case REFINER_SIMPLEX_1D:
7800: case REFINER_SIMPLEX_2D:
7801: case REFINER_SIMPLEX_TO_HEX_2D:
7802: case REFINER_HEX_2D:
7803: case REFINER_SIMPLEX_3D:
7804: case REFINER_HEX_3D:
7805: case REFINER_SIMPLEX_TO_HEX_3D:
7806: break;
7807: case REFINER_HYBRID_SIMPLEX_3D:
7808: case REFINER_HYBRID_HEX_3D:
7809: if (eMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No edge maximum specified in hybrid mesh");
7810: case REFINER_HYBRID_SIMPLEX_2D:
7811: case REFINER_HYBRID_HEX_2D:
7812: if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
7813: if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
7814: break;
7815: default:
7816: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
7817: }
7818: for (l = 0; l < numLabels; ++l) {
7819: DMLabel label, labelNew;
7820: const char *lname;
7821: PetscBool isDepth;
7822: IS valueIS;
7823: const PetscInt *values;
7824: PetscInt defVal;
7825: PetscInt numValues, val;
7827: DMGetLabelName(dm, l, &lname);
7828: PetscStrcmp(lname, "depth", &isDepth);
7829: if (isDepth) continue;
7830: DMCreateLabel(rdm, lname);
7831: DMGetLabel(dm, lname, &label);
7832: DMGetLabel(rdm, lname, &labelNew);
7833: DMLabelGetDefaultValue(label,&defVal);
7834: DMLabelSetDefaultValue(labelNew,defVal);
7835: DMLabelGetValueIS(label, &valueIS);
7836: ISGetLocalSize(valueIS, &numValues);
7837: ISGetIndices(valueIS, &values);
7838: for (val = 0; val < numValues; ++val) {
7839: IS pointIS;
7840: const PetscInt *points;
7841: PetscInt numPoints, n;
7843: DMLabelGetStratumIS(label, values[val], &pointIS);
7844: ISGetLocalSize(pointIS, &numPoints);
7845: ISGetIndices(pointIS, &points);
7846: /* Ensure refined label is created with same number of strata as
7847: * original (even if no entries here). */
7848: DMLabelAddStratum(labelNew, values[val]);
7849: for (n = 0; n < numPoints; ++n) {
7850: const PetscInt p = points[n];
7851: switch (refiner) {
7852: case REFINER_SIMPLEX_1D:
7853: if ((p >= vStart) && (p < vEnd)) {
7854: /* Old vertices stay the same */
7855: newp = vStartNew + (p - vStart);
7856: DMLabelSetValue(labelNew, newp, values[val]);
7857: } else if ((p >= cStart) && (p < cEnd)) {
7858: /* Old cells add new cells and vertex */
7859: newp = vStartNew + (vEnd - vStart) + (p - cStart);
7860: DMLabelSetValue(labelNew, newp, values[val]);
7861: for (r = 0; r < 2; ++r) {
7862: newp = cStartNew + (p - cStart)*2 + r;
7863: DMLabelSetValue(labelNew, newp, values[val]);
7864: }
7865: }
7866: break;
7867: case REFINER_SIMPLEX_2D:
7868: if ((p >= vStart) && (p < vEnd)) {
7869: /* Old vertices stay the same */
7870: newp = vStartNew + (p - vStart);
7871: DMLabelSetValue(labelNew, newp, values[val]);
7872: } else if ((p >= fStart) && (p < fEnd)) {
7873: /* Old faces add new faces and vertex */
7874: newp = vStartNew + (vEnd - vStart) + (p - fStart);
7875: DMLabelSetValue(labelNew, newp, values[val]);
7876: for (r = 0; r < 2; ++r) {
7877: newp = fStartNew + (p - fStart)*2 + r;
7878: DMLabelSetValue(labelNew, newp, values[val]);
7879: }
7880: } else if ((p >= cStart) && (p < cEnd)) {
7881: /* Old cells add new cells and interior faces */
7882: for (r = 0; r < 4; ++r) {
7883: newp = cStartNew + (p - cStart)*4 + r;
7884: DMLabelSetValue(labelNew, newp, values[val]);
7885: }
7886: for (r = 0; r < 3; ++r) {
7887: newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r;
7888: DMLabelSetValue(labelNew, newp, values[val]);
7889: }
7890: }
7891: break;
7892: case REFINER_SIMPLEX_TO_HEX_2D:
7893: if ((p >= vStart) && (p < vEnd)) {
7894: /* Old vertices stay the same */
7895: newp = vStartNew + (p - vStart);
7896: DMLabelSetValue(labelNew, newp, values[val]);
7897: } else if ((p >= fStart) && (p < fEnd)) {
7898: /* Old faces add new faces and vertex */
7899: newp = vStartNew + (vEnd - vStart) + (p - fStart);
7900: DMLabelSetValue(labelNew, newp, values[val]);
7901: for (r = 0; r < 2; ++r) {
7902: newp = fStartNew + (p - fStart)*2 + r;
7903: DMLabelSetValue(labelNew, newp, values[val]);
7904: }
7905: } else if ((p >= cStart) && (p < cEnd)) {
7906: /* Old cells add new cells, interior faces, and a vertex */
7907: for (r = 0; r < 3; ++r) {
7908: newp = cStartNew + (p - cStart)*3 + r;
7909: DMLabelSetValue(labelNew, newp, values[val]);
7910: }
7911: for (r = 0; r < 3; ++r) {
7912: newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r;
7913: DMLabelSetValue(labelNew, newp, values[val]);
7914: }
7915: newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + p;
7916: DMLabelSetValue(labelNew, newp, values[val]);
7917: }
7918: break;
7919: case REFINER_HEX_2D:
7920: if ((p >= vStart) && (p < vEnd)) {
7921: /* Old vertices stay the same */
7922: newp = vStartNew + (p - vStart);
7923: DMLabelSetValue(labelNew, newp, values[val]);
7924: } else if ((p >= fStart) && (p < fEnd)) {
7925: /* Old faces add new faces and vertex */
7926: newp = vStartNew + (vEnd - vStart) + (p - fStart);
7927: DMLabelSetValue(labelNew, newp, values[val]);
7928: for (r = 0; r < 2; ++r) {
7929: newp = fStartNew + (p - fStart)*2 + r;
7930: DMLabelSetValue(labelNew, newp, values[val]);
7931: }
7932: } else if ((p >= cStart) && (p < cEnd)) {
7933: /* Old cells add new cells and interior faces and vertex */
7934: for (r = 0; r < 4; ++r) {
7935: newp = cStartNew + (p - cStart)*4 + r;
7936: DMLabelSetValue(labelNew, newp, values[val]);
7937: }
7938: for (r = 0; r < 4; ++r) {
7939: newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r;
7940: DMLabelSetValue(labelNew, newp, values[val]);
7941: }
7942: newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart);
7943: DMLabelSetValue(labelNew, newp, values[val]);
7944: }
7945: break;
7946: case REFINER_HYBRID_SIMPLEX_2D:
7947: if ((p >= vStart) && (p < vEnd)) {
7948: /* Old vertices stay the same */
7949: newp = vStartNew + (p - vStart);
7950: DMLabelSetValue(labelNew, newp, values[val]);
7951: } else if ((p >= fStart) && (p < fMax)) {
7952: /* Old interior faces add new faces and vertex */
7953: newp = vStartNew + (vEnd - vStart) + (p - fStart);
7954: DMLabelSetValue(labelNew, newp, values[val]);
7955: for (r = 0; r < 2; ++r) {
7956: newp = fStartNew + (p - fStart)*2 + r;
7957: DMLabelSetValue(labelNew, newp, values[val]);
7958: }
7959: } else if ((p >= fMax) && (p < fEnd)) {
7960: /* Old hybrid faces stay the same */
7961: newp = fStartNew + (fMax - fStart)*2 + (p - fMax);
7962: DMLabelSetValue(labelNew, newp, values[val]);
7963: } else if ((p >= cStart) && (p < cMax)) {
7964: /* Old interior cells add new cells and interior faces */
7965: for (r = 0; r < 4; ++r) {
7966: newp = cStartNew + (p - cStart)*4 + r;
7967: DMLabelSetValue(labelNew, newp, values[val]);
7968: }
7969: for (r = 0; r < 3; ++r) {
7970: newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r;
7971: DMLabelSetValue(labelNew, newp, values[val]);
7972: }
7973: } else if ((p >= cMax) && (p < cEnd)) {
7974: /* Old hybrid cells add new cells and hybrid face */
7975: for (r = 0; r < 2; ++r) {
7976: newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r;
7977: DMLabelSetValue(labelNew, newp, values[val]);
7978: }
7979: newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax);
7980: DMLabelSetValue(labelNew, newp, values[val]);
7981: }
7982: break;
7983: case REFINER_HYBRID_HEX_2D:
7984: if ((p >= vStart) && (p < vEnd)) {
7985: /* Old vertices stay the same */
7986: newp = vStartNew + (p - vStart);
7987: DMLabelSetValue(labelNew, newp, values[val]);
7988: } else if ((p >= fStart) && (p < fMax)) {
7989: /* Old interior faces add new faces and vertex */
7990: newp = vStartNew + (vEnd - vStart) + (p - fStart);
7991: DMLabelSetValue(labelNew, newp, values[val]);
7992: for (r = 0; r < 2; ++r) {
7993: newp = fStartNew + (p - fStart)*2 + r;
7994: DMLabelSetValue(labelNew, newp, values[val]);
7995: }
7996: } else if ((p >= fMax) && (p < fEnd)) {
7997: /* Old hybrid faces stay the same */
7998: newp = fStartNew + (fMax - fStart)*2 + (p - fMax);
7999: DMLabelSetValue(labelNew, newp, values[val]);
8000: } else if ((p >= cStart) && (p < cMax)) {
8001: /* Old interior cells add new cells, interior faces, and vertex */
8002: for (r = 0; r < 4; ++r) {
8003: newp = cStartNew + (p - cStart)*4 + r;
8004: DMLabelSetValue(labelNew, newp, values[val]);
8005: }
8006: for (r = 0; r < 4; ++r) {
8007: newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r;
8008: DMLabelSetValue(labelNew, newp, values[val]);
8009: }
8010: newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart);
8011: DMLabelSetValue(labelNew, newp, values[val]);
8012: } else if ((p >= cMax) && (p < cEnd)) {
8013: /* Old hybrid cells add new cells and hybrid face */
8014: for (r = 0; r < 2; ++r) {
8015: newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r;
8016: DMLabelSetValue(labelNew, newp, values[val]);
8017: }
8018: newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (p - cMax);
8019: DMLabelSetValue(labelNew, newp, values[val]);
8020: }
8021: break;
8022: case REFINER_SIMPLEX_3D:
8023: if ((p >= vStart) && (p < vEnd)) {
8024: /* Old vertices stay the same */
8025: newp = vStartNew + (p - vStart);
8026: DMLabelSetValue(labelNew, newp, values[val]);
8027: } else if ((p >= eStart) && (p < eEnd)) {
8028: /* Old edges add new edges and vertex */
8029: for (r = 0; r < 2; ++r) {
8030: newp = eStartNew + (p - eStart)*2 + r;
8031: DMLabelSetValue(labelNew, newp, values[val]);
8032: }
8033: newp = vStartNew + (vEnd - vStart) + (p - eStart);
8034: DMLabelSetValue(labelNew, newp, values[val]);
8035: } else if ((p >= fStart) && (p < fEnd)) {
8036: /* Old faces add new faces and edges */
8037: for (r = 0; r < 4; ++r) {
8038: newp = fStartNew + (p - fStart)*4 + r;
8039: DMLabelSetValue(labelNew, newp, values[val]);
8040: }
8041: for (r = 0; r < 3; ++r) {
8042: newp = eStartNew + (eEnd - eStart)*2 + (p - fStart)*3 + r;
8043: DMLabelSetValue(labelNew, newp, values[val]);
8044: }
8045: } else if ((p >= cStart) && (p < cEnd)) {
8046: /* Old cells add new cells and interior faces and edges */
8047: for (r = 0; r < 8; ++r) {
8048: newp = cStartNew + (p - cStart)*8 + r;
8049: DMLabelSetValue(labelNew, newp, values[val]);
8050: }
8051: for (r = 0; r < 8; ++r) {
8052: newp = fStartNew + (fEnd - fStart)*4 + (p - cStart)*8 + r;
8053: DMLabelSetValue(labelNew, newp, values[val]);
8054: }
8055: for (r = 0; r < 1; ++r) {
8056: newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (p - cStart)*1 + r;
8057: DMLabelSetValue(labelNew, newp, values[val]);
8058: }
8059: }
8060: break;
8061: case REFINER_SIMPLEX_TO_HEX_3D:
8062: if ((p >= vStart) && (p < vEnd)) {
8063: /* Old vertices stay the same */
8064: newp = vStartNew + (p - vStart);
8065: DMLabelSetValue(labelNew, newp, values[val]);
8066: } else if ((p >= eStart) && (p < eEnd)) {
8067: /* Old edges add new edges and vertex */
8068: for (r = 0; r < 2; ++r) {
8069: newp = eStartNew + (p - eStart)*2 + r;
8070: DMLabelSetValue(labelNew, newp, values[val]);
8071: }
8072: newp = vStartNew + (vEnd - vStart) + (p - eStart);
8073: DMLabelSetValue(labelNew, newp, values[val]);
8074: } else if ((p >= fStart) && (p < fEnd)) {
8075: /* Old faces add new faces, edges and a vertex */
8076: for (r = 0; r < 3; ++r) {
8077: newp = fStartNew + (p - fStart)*3 + r;
8078: DMLabelSetValue(labelNew, newp, values[val]);
8079: }
8080: for (r = 0; r < 3; ++r) {
8081: newp = eStartNew + (eEnd - eStart)*2 + (p - fStart)*3 + r;
8082: DMLabelSetValue(labelNew, newp, values[val]);
8083: }
8084: } else if ((p >= cStart) && (p < cEnd)) {
8085: /* Old cells add new cells and interior faces and edges and a vertex */
8086: for (r = 0; r < 4; ++r) {
8087: newp = cStartNew + (p - cStart)*4 + r;
8088: DMLabelSetValue(labelNew, newp, values[val]);
8089: }
8090: for (r = 0; r < 6; ++r) {
8091: newp = fStartNew + (fEnd - fStart)*3 + (p - cStart)*6 + r;
8092: DMLabelSetValue(labelNew, newp, values[val]);
8093: }
8094: for (r = 0; r < 4; ++r) {
8095: newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (p - cStart)*4 + r;
8096: DMLabelSetValue(labelNew, newp, values[val]);
8097: }
8098: newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + p - cStart;
8099: DMLabelSetValue(labelNew, newp, values[val]);
8100: }
8101: break;
8102: case REFINER_HYBRID_SIMPLEX_3D:
8103: if ((p >= vStart) && (p < vEnd)) {
8104: /* Interior vertices stay the same */
8105: newp = vStartNew + (p - vStart);
8106: DMLabelSetValue(labelNew, newp, values[val]);
8107: } else if ((p >= eStart) && (p < eMax)) {
8108: /* Interior edges add new edges and vertex */
8109: for (r = 0; r < 2; ++r) {
8110: newp = eStartNew + (p - eStart)*2 + r;
8111: DMLabelSetValue(labelNew, newp, values[val]);
8112: }
8113: newp = vStartNew + (vEnd - vStart) + (p - eStart);
8114: DMLabelSetValue(labelNew, newp, values[val]);
8115: } else if ((p >= eMax) && (p < eEnd)) {
8116: /* Hybrid edges stay the same */
8117: newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (p - eMax);
8118: DMLabelSetValue(labelNew, newp, values[val]);
8119: } else if ((p >= fStart) && (p < fMax)) {
8120: /* Interior faces add new faces and edges */
8121: for (r = 0; r < 4; ++r) {
8122: newp = fStartNew + (p - fStart)*4 + r;
8123: DMLabelSetValue(labelNew, newp, values[val]);
8124: }
8125: for (r = 0; r < 3; ++r) {
8126: newp = eStartNew + (eMax - eStart)*2 + (p - fStart)*3 + r;
8127: DMLabelSetValue(labelNew, newp, values[val]);
8128: }
8129: } else if ((p >= fMax) && (p < fEnd)) {
8130: /* Hybrid faces add new faces and edges */
8131: for (r = 0; r < 2; ++r) {
8132: newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (p - fMax)*2 + r;
8133: DMLabelSetValue(labelNew, newp, values[val]);
8134: }
8135: newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (p - fMax);
8136: DMLabelSetValue(labelNew, newp, values[val]);
8137: } else if ((p >= cStart) && (p < cMax)) {
8138: /* Interior cells add new cells, faces, and edges */
8139: for (r = 0; r < 8; ++r) {
8140: newp = cStartNew + (p - cStart)*8 + r;
8141: DMLabelSetValue(labelNew, newp, values[val]);
8142: }
8143: for (r = 0; r < 8; ++r) {
8144: newp = fStartNew + (fMax - fStart)*4 + (p - cStart)*8 + r;
8145: DMLabelSetValue(labelNew, newp, values[val]);
8146: }
8147: newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (p - cStart);
8148: DMLabelSetValue(labelNew, newp, values[val]);
8149: } else if ((p >= cMax) && (p < cEnd)) {
8150: /* Hybrid cells add new cells and faces */
8151: for (r = 0; r < 4; ++r) {
8152: newp = cStartNew + (cMax - cStart)*8 + (p - cMax)*4 + r;
8153: DMLabelSetValue(labelNew, newp, values[val]);
8154: }
8155: for (r = 0; r < 3; ++r) {
8156: newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (p - cMax)*3 + r;
8157: DMLabelSetValue(labelNew, newp, values[val]);
8158: }
8159: }
8160: break;
8161: case REFINER_HEX_3D:
8162: if ((p >= vStart) && (p < vEnd)) {
8163: /* Old vertices stay the same */
8164: newp = vStartNew + (p - vStart);
8165: DMLabelSetValue(labelNew, newp, values[val]);
8166: } else if ((p >= eStart) && (p < eEnd)) {
8167: /* Old edges add new edges and vertex */
8168: for (r = 0; r < 2; ++r) {
8169: newp = eStartNew + (p - eStart)*2 + r;
8170: DMLabelSetValue(labelNew, newp, values[val]);
8171: }
8172: newp = vStartNew + (vEnd - vStart) + (p - eStart);
8173: DMLabelSetValue(labelNew, newp, values[val]);
8174: } else if ((p >= fStart) && (p < fEnd)) {
8175: /* Old faces add new faces, edges, and vertex */
8176: for (r = 0; r < 4; ++r) {
8177: newp = fStartNew + (p - fStart)*4 + r;
8178: DMLabelSetValue(labelNew, newp, values[val]);
8179: }
8180: for (r = 0; r < 4; ++r) {
8181: newp = eStartNew + (eEnd - eStart)*2 + (p - fStart)*4 + r;
8182: DMLabelSetValue(labelNew, newp, values[val]);
8183: }
8184: newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (p - fStart);
8185: DMLabelSetValue(labelNew, newp, values[val]);
8186: } else if ((p >= cStart) && (p < cEnd)) {
8187: /* Old cells add new cells, faces, edges, and vertex */
8188: for (r = 0; r < 8; ++r) {
8189: newp = cStartNew + (p - cStart)*8 + r;
8190: DMLabelSetValue(labelNew, newp, values[val]);
8191: }
8192: for (r = 0; r < 12; ++r) {
8193: newp = fStartNew + (fEnd - fStart)*4 + (p - cStart)*12 + r;
8194: DMLabelSetValue(labelNew, newp, values[val]);
8195: }
8196: for (r = 0; r < 6; ++r) {
8197: newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (p - cStart)*6 + r;
8198: DMLabelSetValue(labelNew, newp, values[val]);
8199: }
8200: newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (p - cStart);
8201: DMLabelSetValue(labelNew, newp, values[val]);
8202: }
8203: break;
8204: case REFINER_HYBRID_HEX_3D:
8205: if ((p >= vStart) && (p < vEnd)) {
8206: /* Interior vertices stay the same */
8207: newp = vStartNew + (p - vStart);
8208: DMLabelSetValue(labelNew, newp, values[val]);
8209: } else if ((p >= eStart) && (p < eMax)) {
8210: /* Interior edges add new edges and vertex */
8211: for (r = 0; r < 2; ++r) {
8212: newp = eStartNew + (p - eStart)*2 + r;
8213: DMLabelSetValue(labelNew, newp, values[val]);
8214: }
8215: newp = vStartNew + (vEnd - vStart) + (p - eStart);
8216: DMLabelSetValue(labelNew, newp, values[val]);
8217: } else if ((p >= eMax) && (p < eEnd)) {
8218: /* Hybrid edges stay the same */
8219: newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (p - eMax);
8220: DMLabelSetValue(labelNew, newp, values[val]);
8221: } else if ((p >= fStart) && (p < fMax)) {
8222: /* Interior faces add new faces, edges, and vertex */
8223: for (r = 0; r < 4; ++r) {
8224: newp = fStartNew + (p - fStart)*4 + r;
8225: DMLabelSetValue(labelNew, newp, values[val]);
8226: }
8227: for (r = 0; r < 4; ++r) {
8228: newp = eStartNew + (eMax - eStart)*2 + (p - fStart)*4 + r;
8229: DMLabelSetValue(labelNew, newp, values[val]);
8230: }
8231: newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (p - fStart);
8232: DMLabelSetValue(labelNew, newp, values[val]);
8233: } else if ((p >= fMax) && (p < fEnd)) {
8234: /* Hybrid faces add new faces and edges */
8235: for (r = 0; r < 2; ++r) {
8236: newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (p - fMax)*2 + r;
8237: DMLabelSetValue(labelNew, newp, values[val]);
8238: }
8239: newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (p - fMax);
8240: DMLabelSetValue(labelNew, newp, values[val]);
8241: } else if ((p >= cStart) && (p < cMax)) {
8242: /* Interior cells add new cells, faces, edges, and vertex */
8243: for (r = 0; r < 8; ++r) {
8244: newp = cStartNew + (p - cStart)*8 + r;
8245: DMLabelSetValue(labelNew, newp, values[val]);
8246: }
8247: for (r = 0; r < 12; ++r) {
8248: newp = fStartNew + (fMax - fStart)*4 + (p - cStart)*12 + r;
8249: DMLabelSetValue(labelNew, newp, values[val]);
8250: }
8251: for (r = 0; r < 6; ++r) {
8252: newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (p - cStart)*6 + r;
8253: DMLabelSetValue(labelNew, newp, values[val]);
8254: }
8255: newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (fMax - fStart) + (p - cStart);
8256: DMLabelSetValue(labelNew, newp, values[val]);
8257: } else if ((p >= cMax) && (p < cEnd)) {
8258: /* Hybrid cells add new cells, faces, and edges */
8259: for (r = 0; r < 4; ++r) {
8260: newp = cStartNew + (cMax - cStart)*8 + (p - cMax)*4 + r;
8261: DMLabelSetValue(labelNew, newp, values[val]);
8262: }
8263: for (r = 0; r < 4; ++r) {
8264: newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (p - cMax)*4 + r;
8265: DMLabelSetValue(labelNew, newp, values[val]);
8266: }
8267: newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (fEnd - fMax) + (p - cMax);
8268: DMLabelSetValue(labelNew, newp, values[val]);
8269: }
8270: break;
8271: default:
8272: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
8273: }
8274: }
8275: ISRestoreIndices(pointIS, &points);
8276: ISDestroy(&pointIS);
8277: }
8278: ISRestoreIndices(valueIS, &values);
8279: ISDestroy(&valueIS);
8280: if (0) {
8281: DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);
8282: }
8283: }
8284: return(0);
8285: }
8287: /* This will only work for interpolated meshes */
8288: PetscErrorCode DMPlexRefineUniform_Internal(DM dm, CellRefiner cellRefiner, DM *dmRefined)
8289: {
8290: DM rdm;
8291: PetscInt *depthSize;
8292: PetscInt dim, depth = 0, d, pStart = 0, pEnd = 0;
8296: DMCreate(PetscObjectComm((PetscObject)dm), &rdm);
8297: DMSetType(rdm, DMPLEX);
8298: DMGetDimension(dm, &dim);
8299: DMSetDimension(rdm, dim);
8300: /* Calculate number of new points of each depth */
8301: DMPlexGetDepth(dm, &depth);
8302: if (depth >= 0 && dim != depth) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Mesh must be interpolated for regular refinement");
8303: PetscMalloc1(depth+1, &depthSize);
8304: PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));
8305: CellRefinerGetSizes(cellRefiner, dm, depthSize);
8306: /* Step 1: Set chart */
8307: for (d = 0; d <= depth; ++d) pEnd += depthSize[d];
8308: DMPlexSetChart(rdm, pStart, pEnd);
8309: /* Step 2: Set cone/support sizes */
8310: CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);
8311: /* Step 3: Setup refined DM */
8312: DMSetUp(rdm);
8313: /* Step 4: Set cones and supports */
8314: CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);
8315: /* Step 5: Stratify */
8316: DMPlexStratify(rdm);
8317: /* Step 6: Create pointSF */
8318: CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);
8319: /* Step 7: Create labels */
8320: CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);
8321: /* Step 8: Set coordinates */
8322: CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);
8323: PetscFree(depthSize);
8325: *dmRefined = rdm;
8326: return(0);
8327: }
8329: /*@
8330: DMPlexCreateCoarsePointIS - Creates an IS covering the coarse DM chart with the fine points as data
8332: Input Parameter:
8333: . dm - The coarse DM
8335: Output Parameter:
8336: . fpointIS - The IS of all the fine points which exist in the original coarse mesh
8338: Level: developer
8340: .seealso: DMRefine(), DMPlexSetRefinementUniform(), DMPlexCreateSubpointIS()
8341: @*/
8342: PetscErrorCode DMPlexCreateCoarsePointIS(DM dm, IS *fpointIS)
8343: {
8344: CellRefiner cellRefiner;
8345: PetscInt *depthSize, *fpoints;
8346: PetscInt cStartNew = 0, vStartNew = 0, fStartNew = 0, eStartNew = 0;
8347: PetscInt depth, pStart, pEnd, p, vStart, vEnd, v;
8351: DMPlexGetDepth(dm, &depth);
8352: DMPlexGetChart(dm, &pStart, &pEnd);
8353: DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
8354: DMPlexGetCellRefiner_Internal(dm, &cellRefiner);
8355: PetscMalloc1(depth+1, &depthSize);
8356: CellRefinerGetSizes(cellRefiner, dm, depthSize);
8357: if (cellRefiner) {GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);}
8358: PetscMalloc1(pEnd-pStart,&fpoints);
8359: for (p = 0; p < pEnd-pStart; ++p) fpoints[p] = -1;
8360: switch (cellRefiner) {
8361: case REFINER_SIMPLEX_1D:
8362: case REFINER_SIMPLEX_2D:
8363: case REFINER_HYBRID_SIMPLEX_2D:
8364: case REFINER_HEX_2D:
8365: case REFINER_HYBRID_HEX_2D:
8366: case REFINER_SIMPLEX_3D:
8367: case REFINER_HYBRID_SIMPLEX_3D:
8368: case REFINER_HEX_3D:
8369: case REFINER_HYBRID_HEX_3D:
8370: for (v = vStart; v < vEnd; ++v) fpoints[v-pStart] = vStartNew + (v - vStart);
8371: break;
8372: default:
8373: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", cellRefiner);
8374: }
8375: ISCreateGeneral(PETSC_COMM_SELF, pEnd-pStart, fpoints, PETSC_OWN_POINTER, fpointIS);
8376: PetscFree(depthSize);
8377: return(0);
8378: }
8380: /*@
8381: DMPlexSetRefinementUniform - Set the flag for uniform refinement
8383: Input Parameters:
8384: + dm - The DM
8385: - refinementUniform - The flag for uniform refinement
8387: Level: developer
8389: .seealso: DMRefine(), DMPlexGetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
8390: @*/
8391: PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform)
8392: {
8393: DM_Plex *mesh = (DM_Plex*) dm->data;
8397: mesh->refinementUniform = refinementUniform;
8398: return(0);
8399: }
8401: /*@
8402: DMPlexGetRefinementUniform - Retrieve the flag for uniform refinement
8404: Input Parameter:
8405: . dm - The DM
8407: Output Parameter:
8408: . refinementUniform - The flag for uniform refinement
8410: Level: developer
8412: .seealso: DMRefine(), DMPlexSetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
8413: @*/
8414: PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform)
8415: {
8416: DM_Plex *mesh = (DM_Plex*) dm->data;
8421: *refinementUniform = mesh->refinementUniform;
8422: return(0);
8423: }
8425: /*@
8426: DMPlexSetRefinementLimit - Set the maximum cell volume for refinement
8428: Input Parameters:
8429: + dm - The DM
8430: - refinementLimit - The maximum cell volume in the refined mesh
8432: Level: developer
8434: .seealso: DMRefine(), DMPlexGetRefinementLimit(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform()
8435: @*/
8436: PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit)
8437: {
8438: DM_Plex *mesh = (DM_Plex*) dm->data;
8442: mesh->refinementLimit = refinementLimit;
8443: return(0);
8444: }
8446: /*@
8447: DMPlexGetRefinementLimit - Retrieve the maximum cell volume for refinement
8449: Input Parameter:
8450: . dm - The DM
8452: Output Parameter:
8453: . refinementLimit - The maximum cell volume in the refined mesh
8455: Level: developer
8457: .seealso: DMRefine(), DMPlexSetRefinementLimit(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform()
8458: @*/
8459: PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit)
8460: {
8461: DM_Plex *mesh = (DM_Plex*) dm->data;
8466: /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */
8467: *refinementLimit = mesh->refinementLimit;
8468: return(0);
8469: }
8471: /*@
8472: DMPlexSetRefinementFunction - Set the function giving the maximum cell volume for refinement
8474: Input Parameters:
8475: + dm - The DM
8476: - refinementFunc - Function giving the maximum cell volume in the refined mesh
8478: Note: The calling sequence is refinementFunc(coords, limit)
8479: $ coords - Coordinates of the current point, usually a cell centroid
8480: $ limit - The maximum cell volume for a cell containing this point
8482: Level: developer
8484: .seealso: DMRefine(), DMPlexGetRefinementFunction(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
8485: @*/
8486: PetscErrorCode DMPlexSetRefinementFunction(DM dm, PetscErrorCode (*refinementFunc)(const PetscReal [], PetscReal *))
8487: {
8488: DM_Plex *mesh = (DM_Plex*) dm->data;
8492: mesh->refinementFunc = refinementFunc;
8493: return(0);
8494: }
8496: /*@
8497: DMPlexGetRefinementFunction - Get the function giving the maximum cell volume for refinement
8499: Input Parameter:
8500: . dm - The DM
8502: Output Parameter:
8503: . refinementFunc - Function giving the maximum cell volume in the refined mesh
8505: Note: The calling sequence is refinementFunc(coords, limit)
8506: $ coords - Coordinates of the current point, usually a cell centroid
8507: $ limit - The maximum cell volume for a cell containing this point
8509: Level: developer
8511: .seealso: DMRefine(), DMPlexSetRefinementFunction(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
8512: @*/
8513: PetscErrorCode DMPlexGetRefinementFunction(DM dm, PetscErrorCode (**refinementFunc)(const PetscReal [], PetscReal *))
8514: {
8515: DM_Plex *mesh = (DM_Plex*) dm->data;
8520: *refinementFunc = mesh->refinementFunc;
8521: return(0);
8522: }
8524: PetscErrorCode DMPlexGetCellRefiner_Internal(DM dm, CellRefiner *cellRefiner)
8525: {
8526: PetscInt dim, cStart, cEnd, coneSize, cMax, fMax;
8530: DMGetDimension(dm, &dim);
8531: DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
8532: if (cEnd <= cStart) {*cellRefiner = REFINER_NOOP; return(0);}
8533: DMPlexGetConeSize(dm, cStart, &coneSize);
8534: DMPlexGetHybridBounds(dm, &cMax, &fMax, NULL, NULL);
8535: switch (dim) {
8536: case 1:
8537: switch (coneSize) {
8538: case 2:
8539: *cellRefiner = REFINER_SIMPLEX_1D;
8540: break;
8541: default:
8542: SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim);
8543: }
8544: break;
8545: case 2:
8546: switch (coneSize) {
8547: case 3:
8548: if (cMax >= 0) *cellRefiner = REFINER_HYBRID_SIMPLEX_2D;
8549: else *cellRefiner = REFINER_SIMPLEX_2D;
8550: break;
8551: case 4:
8552: if (cMax >= 0 && fMax >= 0) *cellRefiner = REFINER_HYBRID_HEX_2D;
8553: else *cellRefiner = REFINER_HEX_2D;
8554: break;
8555: default:
8556: SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim);
8557: }
8558: break;
8559: case 3:
8560: switch (coneSize) {
8561: case 4:
8562: if (cMax >= 0) *cellRefiner = REFINER_HYBRID_SIMPLEX_3D;
8563: else *cellRefiner = REFINER_SIMPLEX_3D;
8564: break;
8565: case 6:
8566: if (cMax >= 0) *cellRefiner = REFINER_HYBRID_HEX_3D;
8567: else *cellRefiner = REFINER_HEX_3D;
8568: break;
8569: default:
8570: SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim);
8571: }
8572: break;
8573: default:
8574: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim);
8575: }
8576: return(0);
8577: }
8579: PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined)
8580: {
8581: PetscBool isUniform;
8585: DMPlexGetRefinementUniform(dm, &isUniform);
8586: if (isUniform) {
8587: CellRefiner cellRefiner;
8588: PetscBool localized;
8590: DMGetCoordinatesLocalized(dm, &localized);
8591: DMPlexGetCellRefiner_Internal(dm, &cellRefiner);
8592: DMPlexRefineUniform_Internal(dm, cellRefiner, dmRefined);
8593: DMCopyBoundary(dm, *dmRefined);
8594: if (localized) {DMLocalizeCoordinates(*dmRefined);}
8595: } else {
8596: DMPlexRefine_Internal(dm, NULL, dmRefined);
8597: }
8598: return(0);
8599: }
8601: PetscErrorCode DMRefineHierarchy_Plex(DM dm, PetscInt nlevels, DM dmRefined[])
8602: {
8603: DM cdm = dm;
8604: PetscInt r;
8605: PetscBool isUniform, localized;
8609: DMPlexGetRefinementUniform(dm, &isUniform);
8610: DMGetCoordinatesLocalized(dm, &localized);
8611: if (isUniform) {
8612: for (r = 0; r < nlevels; ++r) {
8613: CellRefiner cellRefiner;
8615: DMPlexGetCellRefiner_Internal(cdm, &cellRefiner);
8616: DMPlexRefineUniform_Internal(cdm, cellRefiner, &dmRefined[r]);
8617: DMCopyBoundary(cdm, dmRefined[r]);
8618: if (localized) {DMLocalizeCoordinates(dmRefined[r]);}
8619: DMSetCoarseDM(dmRefined[r], cdm);
8620: DMPlexSetRegularRefinement(dmRefined[r], PETSC_TRUE);
8621: cdm = dmRefined[r];
8622: }
8623: } else {
8624: for (r = 0; r < nlevels; ++r) {
8625: DMRefine(cdm, PetscObjectComm((PetscObject) dm), &dmRefined[r]);
8626: DMCopyBoundary(cdm, dmRefined[r]);
8627: if (localized) {DMLocalizeCoordinates(dmRefined[r]);}
8628: DMSetCoarseDM(dmRefined[r], cdm);
8629: cdm = dmRefined[r];
8630: }
8631: }
8632: return(0);
8633: }