Actual source code: plexrefine.c
petsc-3.8.4 2018-03-24
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: default:
115: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
116: }
117: if (v0) {*v0 = v; *jac = j; *invjac = invj;}
118: return(0);
119: }
121: PetscErrorCode CellRefinerRestoreAffineTransforms_Internal(CellRefiner refiner, PetscInt *numSubcells, PetscReal *v0[], PetscReal *jac[], PetscReal *invjac[])
122: {
126: PetscFree3(*v0,*jac,*invjac);
127: return(0);
128: }
130: /* Should this be here or in the DualSpace somehow? */
131: PetscErrorCode CellRefinerInCellTest_Internal(CellRefiner refiner, const PetscReal point[], PetscBool *inside)
132: {
133: PetscReal sum = 0.0;
134: PetscInt d;
137: *inside = PETSC_TRUE;
138: switch (refiner) {
139: case REFINER_NOOP: break;
140: case REFINER_SIMPLEX_2D:
141: for (d = 0; d < 2; ++d) {
142: if (point[d] < -1.0) {*inside = PETSC_FALSE; break;}
143: sum += point[d];
144: }
145: if (sum > 1.0e-10) {*inside = PETSC_FALSE; break;}
146: break;
147: case REFINER_HEX_2D:
148: for (d = 0; d < 2; ++d) if ((point[d] < -1.00000000001) || (point[d] > 1.000000000001)) {*inside = PETSC_FALSE; break;}
149: break;
150: default:
151: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
152: }
153: return(0);
154: }
156: static PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[])
157: {
158: PetscInt cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax;
162: DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
163: DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);
164: DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
165: DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);
166: DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);
167: switch (refiner) {
168: case REFINER_NOOP:
169: break;
170: case REFINER_SIMPLEX_1D:
171: depthSize[0] = vEnd - vStart + cEnd - cStart; /* Add a vertex on every cell. */
172: depthSize[1] = 2*(cEnd - cStart); /* Split every cell in 2. */
173: break;
174: case REFINER_SIMPLEX_2D:
175: depthSize[0] = vEnd - vStart + fEnd - fStart; /* Add a vertex on every face */
176: depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */
177: depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */
178: break;
179: case REFINER_HYBRID_SIMPLEX_2D:
180: if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
181: if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
182: depthSize[0] = vEnd - vStart + fMax - fStart; /* Add a vertex on every face, but not hybrid faces */
183: 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 */
184: depthSize[2] = 4*(cMax - cStart) + 2*(cEnd - cMax); /* Interior cells split into 4 cells, Hybrid cells split into 2 cells */
185: break;
186: case REFINER_SIMPLEX_TO_HEX_2D:
187: depthSize[0] = vEnd - vStart + fEnd - fStart + cEnd - cStart; /* Add a vertex on every face and cell */
188: depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */
189: depthSize[2] = 3*(cEnd - cStart); /* Every cell split into 3 cells */
190: break;
191: case REFINER_HEX_2D:
192: depthSize[0] = vEnd - vStart + fEnd - fStart + cEnd - cStart; /* Add a vertex on every face and cell */
193: depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart); /* Every face is split into 2 faces and 4 faces are added for each cell */
194: depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */
195: break;
196: case REFINER_HYBRID_HEX_2D:
197: if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
198: if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
199: /* Quadrilateral */
200: depthSize[0] = vEnd - vStart + fMax - fStart + cMax - cStart; /* Add a vertex on every face and cell */
201: depthSize[1] = 2*(fMax - fStart) + 4*(cMax - cStart); /* Every face is split into 2 faces, and 4 faces are added for each cell */
202: depthSize[2] = 4*(cMax - cStart); /* Every cell split into 4 cells */
203: /* Segment Prisms */
204: depthSize[0] += 0; /* No hybrid vertices */
205: depthSize[1] += (fEnd - fMax) + (cEnd - cMax); /* Every hybrid face remains and 1 faces is added for each hybrid cell */
206: depthSize[2] += 2*(cEnd - cMax); /* Every hybrid cell split into 2 cells */
207: break;
208: case REFINER_SIMPLEX_3D:
209: depthSize[0] = vEnd - vStart + eEnd - eStart; /* Add a vertex on every edge */
210: 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 */
211: depthSize[2] = 4*(fEnd - fStart) + 8*(cEnd - cStart); /* Every face split into 4 faces and 8 faces are added for each cell */
212: depthSize[3] = 8*(cEnd - cStart); /* Every cell split into 8 cells */
213: break;
214: case REFINER_HYBRID_SIMPLEX_3D:
215: if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
216: if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
217: if (eMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No edge maximum specified in hybrid mesh");
218: /* Tetrahedra */
219: depthSize[0] = vEnd - vStart + eMax - eStart; /* Add a vertex on every interior edge */
220: 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 */
221: depthSize[2] = 4*(fMax - fStart) + 8*(cMax - cStart); /* Every interior face split into 4 faces, 8 faces added for each interior cell */
222: depthSize[3] = 8*(cMax - cStart); /* Every interior cell split into 8 cells */
223: /* Triangular Prisms */
224: depthSize[0] += 0; /* No hybrid vertices */
225: depthSize[1] += (eEnd - eMax) + (fEnd - fMax); /* Every hybrid edge remains, 1 edge for every hybrid face */
226: depthSize[2] += 2*(fEnd - fMax) + 3*(cEnd - cMax); /* Every hybrid face split into 2 faces and 3 faces are added for each hybrid cell */
227: depthSize[3] += 4*(cEnd - cMax); /* Every hybrid cell split into 4 cells */
228: break;
229: case REFINER_SIMPLEX_TO_HEX_3D:
230: depthSize[0] = vEnd - vStart + fEnd - fStart + eEnd - eStart + cEnd - cStart; /* Add a vertex on every face, edge and cell */
231: 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 */
232: depthSize[2] = 3*(fEnd - fStart) + 6*(cEnd - cStart); /* Every face is split into 3 faces and 6 faces are added for each cell */
233: depthSize[3] = 4*(cEnd - cStart); /* Every cell split into 4 cells */
234: break;
235: case REFINER_HEX_3D:
236: depthSize[0] = vEnd - vStart + eEnd - eStart + fEnd - fStart + cEnd - cStart; /* Add a vertex on every edge, face and cell */
237: 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 */
238: depthSize[2] = 4*(fEnd - fStart) + 12*(cEnd - cStart); /* Every face is split into 4 faces, and 12 faces are added for each cell */
239: depthSize[3] = 8*(cEnd - cStart); /* Every cell split into 8 cells */
240: break;
241: case REFINER_HYBRID_HEX_3D:
242: if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
243: if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
244: if (eMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No edge maximum specified in hybrid mesh");
245: /* Hexahedra */
246: depthSize[0] = vEnd - vStart + eMax - eStart + fMax - fStart + cMax - cStart; /* Add a vertex on every edge, face and cell */
247: 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 */
248: depthSize[2] = 4*(fMax - fStart) + 12*(cMax - cStart); /* Every face is split into 4 faces, and 12 faces are added for each cell */
249: depthSize[3] = 8*(cMax - cStart); /* Every cell split into 8 cells */
250: /* Quadrilateral Prisms */
251: depthSize[0] += 0; /* No hybrid vertices */
252: depthSize[1] += (eEnd - eMax) + (fEnd - fMax) + (cEnd - cMax); /* Every hybrid edge remains, 1 edge for every hybrid face and hybrid cell */
253: depthSize[2] += 2*(fEnd - fMax) + 4*(cEnd - cMax); /* Every hybrid face split into 2 faces and 4 faces are added for each hybrid cell */
254: depthSize[3] += 4*(cEnd - cMax); /* Every hybrid cell split into 4 cells */
255: break;
256: default:
257: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
258: }
259: return(0);
260: }
262: /* Return triangle edge for orientation o, if it is r for o == 0 */
263: PETSC_STATIC_INLINE PetscInt GetTriEdge_Static(PetscInt o, PetscInt r) {
264: return (o < 0 ? 2-(o+r) : o+r)%3;
265: }
266: PETSC_STATIC_INLINE PetscInt GetTriEdgeInverse_Static(PetscInt o, PetscInt s) {
267: return (o < 0 ? 2-(o+s) : 3+s-o)%3;
268: }
270: /* Return triangle subface for orientation o, if it is r for o == 0 */
271: PETSC_STATIC_INLINE PetscInt GetTriSubface_Static(PetscInt o, PetscInt r) {
272: return (o < 0 ? 3-(o+r) : o+r)%3;
273: }
274: PETSC_STATIC_INLINE PetscInt GetTriSubfaceInverse_Static(PetscInt o, PetscInt s) {
275: return (o < 0 ? 3-(o+s) : 3+s-o)%3;
276: }
278: /* Return the interior edge number connecting the midpoints of the triangle edges r
279: and r+1 in the transitive closure for triangle orientation o */
280: PETSC_STATIC_INLINE PetscInt GetTriMidEdge_Static(PetscInt o, PetscInt r) {
281: return (o < 0 ? 1-(o+r) : o+r)%3;
282: }
283: PETSC_STATIC_INLINE PetscInt GetTriMidEdgeInverse_Static(PetscInt o, PetscInt s) {
284: return (o < 0 ? 1-(o+s) : 3+s-o)%3;
285: }
287: /* Return the interior edge number connecting the midpoint of the triangle edge r
288: (in the transitive closure) and the vertex in the interior of the face for triangle orientation o */
289: PETSC_STATIC_INLINE PetscInt GetTriInteriorEdge_Static(PetscInt o, PetscInt r) {
290: return (o < 0 ? 2-(o+r) : o+r)%3;
291: }
292: PETSC_STATIC_INLINE PetscInt GetTriInteriorEdgeInverse_Static(PetscInt o, PetscInt s) {
293: return (o < 0 ? 2-(o+s) : 3+s-o)%3;
294: }
296: /* Return quad edge for orientation o, if it is r for o == 0 */
297: PETSC_STATIC_INLINE PetscInt GetQuadEdge_Static(PetscInt o, PetscInt r) {
298: return (o < 0 ? 3-(o+r) : o+r)%4;
299: }
300: PETSC_STATIC_INLINE PetscInt GetQuadEdgeInverse_Static(PetscInt o, PetscInt s) {
301: return (o < 0 ? 3-(o+s) : 4+s-o)%4;
302: }
304: /* Return quad subface for orientation o, if it is r for o == 0 */
305: PETSC_STATIC_INLINE PetscInt GetQuadSubface_Static(PetscInt o, PetscInt r) {
306: return (o < 0 ? 4-(o+r) : o+r)%4;
307: }
308: PETSC_STATIC_INLINE PetscInt GetQuadSubfaceInverse_Static(PetscInt o, PetscInt s) {
309: return (o < 0 ? 4-(o+s) : 4+s-o)%4;
310: }
312: static PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
313: {
314: PetscInt depth, cStart, cStartNew, cEnd, cMax, c, vStart, vStartNew, vEnd, vMax, v, fStart, fStartNew, fEnd, fMax, f, eStart, eStartNew, eEnd, eMax, e, r;
318: if (!refiner) return(0);
319: DMPlexGetDepth(dm, &depth);
320: DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
321: DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);
322: DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
323: DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);
324: DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);
325: GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);
326: switch (refiner) {
327: case REFINER_SIMPLEX_1D:
328: /* All cells have 2 vertices */
329: for (c = cStart; c < cEnd; ++c) {
330: for (r = 0; r < 2; ++r) {
331: const PetscInt newp = cStartNew + (c - cStart)*2 + r;
333: DMPlexSetConeSize(rdm, newp, 2);
334: }
335: }
336: /* Old vertices have identical supports */
337: for (v = vStart; v < vEnd; ++v) {
338: const PetscInt newp = vStartNew + (v - vStart);
339: PetscInt size;
341: DMPlexGetSupportSize(dm, v, &size);
342: DMPlexSetSupportSize(rdm, newp, size);
343: }
344: /* Cell vertices have support 2 */
345: for (c = cStart; c < cEnd; ++c) {
346: const PetscInt newp = vStartNew + (vEnd - vStart) + (c - cStart);
348: DMPlexSetSupportSize(rdm, newp, 2);
349: }
350: break;
351: case REFINER_SIMPLEX_2D:
352: /* All cells have 3 faces */
353: for (c = cStart; c < cEnd; ++c) {
354: for (r = 0; r < 4; ++r) {
355: const PetscInt newp = (c - cStart)*4 + r;
357: DMPlexSetConeSize(rdm, newp, 3);
358: }
359: }
360: /* Split faces have 2 vertices and the same cells as the parent */
361: for (f = fStart; f < fEnd; ++f) {
362: for (r = 0; r < 2; ++r) {
363: const PetscInt newp = fStartNew + (f - fStart)*2 + r;
364: PetscInt size;
366: DMPlexSetConeSize(rdm, newp, 2);
367: DMPlexGetSupportSize(dm, f, &size);
368: DMPlexSetSupportSize(rdm, newp, size);
369: }
370: }
371: /* Interior faces have 2 vertices and 2 cells */
372: for (c = cStart; c < cEnd; ++c) {
373: for (r = 0; r < 3; ++r) {
374: const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r;
376: DMPlexSetConeSize(rdm, newp, 2);
377: DMPlexSetSupportSize(rdm, newp, 2);
378: }
379: }
380: /* Old vertices have identical supports */
381: for (v = vStart; v < vEnd; ++v) {
382: const PetscInt newp = vStartNew + (v - vStart);
383: PetscInt size;
385: DMPlexGetSupportSize(dm, v, &size);
386: DMPlexSetSupportSize(rdm, newp, size);
387: }
388: /* Face vertices have 2 + cells*2 supports */
389: for (f = fStart; f < fEnd; ++f) {
390: const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
391: PetscInt size;
393: DMPlexGetSupportSize(dm, f, &size);
394: DMPlexSetSupportSize(rdm, newp, 2 + size*2);
395: }
396: break;
397: case REFINER_SIMPLEX_TO_HEX_2D:
398: /* All cells have 4 faces */
399: for (c = cStart; c < cEnd; ++c) {
400: for (r = 0; r < 3; ++r) {
401: const PetscInt newp = (c - cStart)*3 + r;
403: DMPlexSetConeSize(rdm, newp, 4);
404: }
405: }
406: /* Split faces have 2 vertices and the same cells as the parent */
407: for (f = fStart; f < fEnd; ++f) {
408: for (r = 0; r < 2; ++r) {
409: const PetscInt newp = fStartNew + (f - fStart)*2 + r;
410: PetscInt size;
412: DMPlexSetConeSize(rdm, newp, 2);
413: DMPlexGetSupportSize(dm, f, &size);
414: DMPlexSetSupportSize(rdm, newp, size);
415: }
416: }
417: /* Interior faces have 2 vertices and 2 cells */
418: for (c = cStart; c < cEnd; ++c) {
419: for (r = 0; r < 3; ++r) {
420: const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r;
422: DMPlexSetConeSize(rdm, newp, 2);
423: DMPlexSetSupportSize(rdm, newp, 2);
424: }
425: }
426: /* Old vertices have identical supports */
427: for (v = vStart; v < vEnd; ++v) {
428: const PetscInt newp = vStartNew + (v - vStart);
429: PetscInt size;
431: DMPlexGetSupportSize(dm, v, &size);
432: DMPlexSetSupportSize(rdm, newp, size);
433: }
434: /* Split-face vertices have cells + 2 supports */
435: for (f = fStart; f < fEnd; ++f) {
436: const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
437: PetscInt size;
439: DMPlexGetSupportSize(dm, f, &size);
440: DMPlexSetSupportSize(rdm, newp, size + 2);
441: }
442: /* Interior vertices have 3 supports */
443: for (c = cStart; c < cEnd; ++c) {
444: const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + c - cStart;
446: DMPlexSetSupportSize(rdm, newp, 3);
447: }
448: break;
449: case REFINER_HEX_2D:
450: /* All cells have 4 faces */
451: for (c = cStart; c < cEnd; ++c) {
452: for (r = 0; r < 4; ++r) {
453: const PetscInt newp = cStartNew + (c - cStart)*4 + r;
455: DMPlexSetConeSize(rdm, newp, 4);
456: }
457: }
458: /* Split faces have 2 vertices and the same cells as the parent */
459: for (f = fStart; f < fEnd; ++f) {
460: for (r = 0; r < 2; ++r) {
461: const PetscInt newp = fStartNew + (f - fStart)*2 + r;
462: PetscInt size;
464: DMPlexSetConeSize(rdm, newp, 2);
465: DMPlexGetSupportSize(dm, f, &size);
466: DMPlexSetSupportSize(rdm, newp, size);
467: }
468: }
469: /* Interior faces have 2 vertices and 2 cells */
470: for (c = cStart; c < cEnd; ++c) {
471: for (r = 0; r < 4; ++r) {
472: const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r;
474: DMPlexSetConeSize(rdm, newp, 2);
475: DMPlexSetSupportSize(rdm, newp, 2);
476: }
477: }
478: /* Old vertices have identical supports */
479: for (v = vStart; v < vEnd; ++v) {
480: const PetscInt newp = vStartNew + (v - vStart);
481: PetscInt size;
483: DMPlexGetSupportSize(dm, v, &size);
484: DMPlexSetSupportSize(rdm, newp, size);
485: }
486: /* Face vertices have 2 + cells supports */
487: for (f = fStart; f < fEnd; ++f) {
488: const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
489: PetscInt size;
491: DMPlexGetSupportSize(dm, f, &size);
492: DMPlexSetSupportSize(rdm, newp, 2 + size);
493: }
494: /* Cell vertices have 4 supports */
495: for (c = cStart; c < cEnd; ++c) {
496: const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart);
498: DMPlexSetSupportSize(rdm, newp, 4);
499: }
500: break;
501: case REFINER_HYBRID_SIMPLEX_2D:
502: if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
503: cMax = PetscMin(cEnd, cMax);
504: if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
505: fMax = PetscMin(fEnd, fMax);
506: DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);
507: /* Interior cells have 3 faces */
508: for (c = cStart; c < cMax; ++c) {
509: for (r = 0; r < 4; ++r) {
510: const PetscInt newp = cStartNew + (c - cStart)*4 + r;
512: DMPlexSetConeSize(rdm, newp, 3);
513: }
514: }
515: /* Hybrid cells have 4 faces */
516: for (c = cMax; c < cEnd; ++c) {
517: for (r = 0; r < 2; ++r) {
518: const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r;
520: DMPlexSetConeSize(rdm, newp, 4);
521: }
522: }
523: /* Interior split faces have 2 vertices and the same cells as the parent */
524: for (f = fStart; f < fMax; ++f) {
525: for (r = 0; r < 2; ++r) {
526: const PetscInt newp = fStartNew + (f - fStart)*2 + r;
527: PetscInt size;
529: DMPlexSetConeSize(rdm, newp, 2);
530: DMPlexGetSupportSize(dm, f, &size);
531: DMPlexSetSupportSize(rdm, newp, size);
532: }
533: }
534: /* Interior cell faces have 2 vertices and 2 cells */
535: for (c = cStart; c < cMax; ++c) {
536: for (r = 0; r < 3; ++r) {
537: const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r;
539: DMPlexSetConeSize(rdm, newp, 2);
540: DMPlexSetSupportSize(rdm, newp, 2);
541: }
542: }
543: /* Hybrid faces have 2 vertices and the same cells */
544: for (f = fMax; f < fEnd; ++f) {
545: const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax);
546: PetscInt size;
548: DMPlexSetConeSize(rdm, newp, 2);
549: DMPlexGetSupportSize(dm, f, &size);
550: DMPlexSetSupportSize(rdm, newp, size);
551: }
552: /* Hybrid cell faces have 2 vertices and 2 cells */
553: for (c = cMax; c < cEnd; ++c) {
554: const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax);
556: DMPlexSetConeSize(rdm, newp, 2);
557: DMPlexSetSupportSize(rdm, newp, 2);
558: }
559: /* Old vertices have identical supports */
560: for (v = vStart; v < vEnd; ++v) {
561: const PetscInt newp = vStartNew + (v - vStart);
562: PetscInt size;
564: DMPlexGetSupportSize(dm, v, &size);
565: DMPlexSetSupportSize(rdm, newp, size);
566: }
567: /* Face vertices have 2 + (2 interior, 1 hybrid) supports */
568: for (f = fStart; f < fMax; ++f) {
569: const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
570: const PetscInt *support;
571: PetscInt size, newSize = 2, s;
573: DMPlexGetSupportSize(dm, f, &size);
574: DMPlexGetSupport(dm, f, &support);
575: for (s = 0; s < size; ++s) {
576: if (support[s] >= cMax) newSize += 1;
577: else newSize += 2;
578: }
579: DMPlexSetSupportSize(rdm, newp, newSize);
580: }
581: break;
582: case REFINER_HYBRID_HEX_2D:
583: if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
584: cMax = PetscMin(cEnd, cMax);
585: if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
586: fMax = PetscMin(fEnd, fMax);
587: DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4, PETSC_DETERMINE, PETSC_DETERMINE);
588: /* Interior cells have 4 faces */
589: for (c = cStart; c < cMax; ++c) {
590: for (r = 0; r < 4; ++r) {
591: const PetscInt newp = cStartNew + (c - cStart)*4 + r;
593: DMPlexSetConeSize(rdm, newp, 4);
594: }
595: }
596: /* Hybrid cells have 4 faces */
597: for (c = cMax; c < cEnd; ++c) {
598: for (r = 0; r < 2; ++r) {
599: const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r;
601: DMPlexSetConeSize(rdm, newp, 4);
602: }
603: }
604: /* Interior split faces have 2 vertices and the same cells as the parent */
605: for (f = fStart; f < fMax; ++f) {
606: for (r = 0; r < 2; ++r) {
607: const PetscInt newp = fStartNew + (f - fStart)*2 + r;
608: PetscInt size;
610: DMPlexSetConeSize(rdm, newp, 2);
611: DMPlexGetSupportSize(dm, f, &size);
612: DMPlexSetSupportSize(rdm, newp, size);
613: }
614: }
615: /* Interior cell faces have 2 vertices and 2 cells */
616: for (c = cStart; c < cMax; ++c) {
617: for (r = 0; r < 4; ++r) {
618: const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + r;
620: DMPlexSetConeSize(rdm, newp, 2);
621: DMPlexSetSupportSize(rdm, newp, 2);
622: }
623: }
624: /* Hybrid faces have 2 vertices and the same cells */
625: for (f = fMax; f < fEnd; ++f) {
626: const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (f - fMax);
627: PetscInt size;
629: DMPlexSetConeSize(rdm, newp, 2);
630: DMPlexGetSupportSize(dm, f, &size);
631: DMPlexSetSupportSize(rdm, newp, size);
632: }
633: /* Hybrid cell faces have 2 vertices and 2 cells */
634: for (c = cMax; c < cEnd; ++c) {
635: const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (fEnd - fMax) + (c - cMax);
637: DMPlexSetConeSize(rdm, newp, 2);
638: DMPlexSetSupportSize(rdm, newp, 2);
639: }
640: /* Old vertices have identical supports */
641: for (v = vStart; v < vEnd; ++v) {
642: const PetscInt newp = vStartNew + (v - vStart);
643: PetscInt size;
645: DMPlexGetSupportSize(dm, v, &size);
646: DMPlexSetSupportSize(rdm, newp, size);
647: }
648: /* Face vertices have 2 + cells supports */
649: for (f = fStart; f < fMax; ++f) {
650: const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
651: PetscInt size;
653: DMPlexGetSupportSize(dm, f, &size);
654: DMPlexSetSupportSize(rdm, newp, 2 + size);
655: }
656: /* Cell vertices have 4 supports */
657: for (c = cStart; c < cMax; ++c) {
658: const PetscInt newp = vStartNew + (vEnd - vStart) + (fMax - fStart) + (c - cStart);
660: DMPlexSetSupportSize(rdm, newp, 4);
661: }
662: break;
663: case REFINER_SIMPLEX_3D:
664: /* All cells have 4 faces */
665: for (c = cStart; c < cEnd; ++c) {
666: for (r = 0; r < 8; ++r) {
667: const PetscInt newp = cStartNew + (c - cStart)*8 + r;
669: DMPlexSetConeSize(rdm, newp, 4);
670: }
671: }
672: /* Split faces have 3 edges and the same cells as the parent */
673: for (f = fStart; f < fEnd; ++f) {
674: for (r = 0; r < 4; ++r) {
675: const PetscInt newp = fStartNew + (f - fStart)*4 + r;
676: PetscInt size;
678: DMPlexSetConeSize(rdm, newp, 3);
679: DMPlexGetSupportSize(dm, f, &size);
680: DMPlexSetSupportSize(rdm, newp, size);
681: }
682: }
683: /* Interior cell faces have 3 edges and 2 cells */
684: for (c = cStart; c < cEnd; ++c) {
685: for (r = 0; r < 8; ++r) {
686: const PetscInt newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + r;
688: DMPlexSetConeSize(rdm, newp, 3);
689: DMPlexSetSupportSize(rdm, newp, 2);
690: }
691: }
692: /* Split edges have 2 vertices and the same faces */
693: for (e = eStart; e < eEnd; ++e) {
694: for (r = 0; r < 2; ++r) {
695: const PetscInt newp = eStartNew + (e - eStart)*2 + r;
696: PetscInt size;
698: DMPlexSetConeSize(rdm, newp, 2);
699: DMPlexGetSupportSize(dm, e, &size);
700: DMPlexSetSupportSize(rdm, newp, size);
701: }
702: }
703: /* Face edges have 2 vertices and 2+cells*(1/2) faces */
704: for (f = fStart; f < fEnd; ++f) {
705: for (r = 0; r < 3; ++r) {
706: const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + r;
707: const PetscInt *cone, *ornt, *support, eint[4] = {1, 0, 2, 0};
708: PetscInt coneSize, c, supportSize, s, er, intFaces = 0;
710: DMPlexSetConeSize(rdm, newp, 2);
711: DMPlexGetSupportSize(dm, f, &supportSize);
712: DMPlexGetSupport(dm, f, &support);
713: for (s = 0; s < supportSize; ++s) {
714: DMPlexGetConeSize(dm, support[s], &coneSize);
715: DMPlexGetCone(dm, support[s], &cone);
716: DMPlexGetConeOrientation(dm, support[s], &ornt);
717: for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
718: /* Here we want to determine whether edge newp contains a vertex which is part of the cross-tet edge */
719: er = GetTriMidEdgeInverse_Static(ornt[c], r);
720: if (er == eint[c]) {
721: intFaces += 1;
722: } else {
723: intFaces += 2;
724: }
725: }
726: DMPlexSetSupportSize(rdm, newp, 2+intFaces);
727: }
728: }
729: /* Interior cell edges have 2 vertices and 4 faces */
730: for (c = cStart; c < cEnd; ++c) {
731: const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
733: DMPlexSetConeSize(rdm, newp, 2);
734: DMPlexSetSupportSize(rdm, newp, 4);
735: }
736: /* Old vertices have identical supports */
737: for (v = vStart; v < vEnd; ++v) {
738: const PetscInt newp = vStartNew + (v - vStart);
739: PetscInt size;
741: DMPlexGetSupportSize(dm, v, &size);
742: DMPlexSetSupportSize(rdm, newp, size);
743: }
744: /* Edge vertices have 2 + faces*2 + cells*0/1 supports */
745: for (e = eStart; e < eEnd; ++e) {
746: const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
747: PetscInt size, *star = NULL, starSize, s, cellSize = 0;
749: DMPlexGetSupportSize(dm, e, &size);
750: DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
751: for (s = 0; s < starSize*2; s += 2) {
752: const PetscInt *cone, *ornt;
753: PetscInt e01, e23;
755: if ((star[s] >= cStart) && (star[s] < cEnd)) {
756: /* Check edge 0-1 */
757: DMPlexGetCone(dm, star[s], &cone);
758: DMPlexGetConeOrientation(dm, star[s], &ornt);
759: DMPlexGetCone(dm, cone[0], &cone);
760: e01 = cone[GetTriEdge_Static(ornt[0], 0)];
761: /* Check edge 2-3 */
762: DMPlexGetCone(dm, star[s], &cone);
763: DMPlexGetConeOrientation(dm, star[s], &ornt);
764: DMPlexGetCone(dm, cone[2], &cone);
765: e23 = cone[GetTriEdge_Static(ornt[2], 1)];
766: if ((e01 == e) || (e23 == e)) ++cellSize;
767: }
768: }
769: DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
770: DMPlexSetSupportSize(rdm, newp, 2 + size*2 + cellSize);
771: }
772: break;
773: case REFINER_HYBRID_SIMPLEX_3D:
774: DMPlexSetHybridBounds(rdm, cStartNew + 8*(cMax-cStart), fStartNew + 4*(fMax - fStart) + 8*(cMax - cStart),
775: eStartNew + 2*(eMax - eStart) + 3*(fMax - fStart) + (cMax - cStart), PETSC_DETERMINE);
776: /* Interior cells have 4 faces */
777: for (c = cStart; c < cMax; ++c) {
778: for (r = 0; r < 8; ++r) {
779: const PetscInt newp = cStartNew + (c - cStart)*8 + r;
781: DMPlexSetConeSize(rdm, newp, 4);
782: }
783: }
784: /* Hybrid cells have 5 faces */
785: for (c = cMax; c < cEnd; ++c) {
786: for (r = 0; r < 4; ++r) {
787: const PetscInt newp = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + r;
789: DMPlexSetConeSize(rdm, newp, 5);
790: }
791: }
792: /* Interior split faces have 3 edges and the same cells as the parent */
793: for (f = fStart; f < fMax; ++f) {
794: for (r = 0; r < 4; ++r) {
795: const PetscInt newp = fStartNew + (f - fStart)*4 + r;
796: PetscInt size;
798: DMPlexSetConeSize(rdm, newp, 3);
799: DMPlexGetSupportSize(dm, f, &size);
800: DMPlexSetSupportSize(rdm, newp, size);
801: }
802: }
803: /* Interior cell faces have 3 edges and 2 cells */
804: for (c = cStart; c < cMax; ++c) {
805: for (r = 0; r < 8; ++r) {
806: const PetscInt newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + r;
808: DMPlexSetConeSize(rdm, newp, 3);
809: DMPlexSetSupportSize(rdm, newp, 2);
810: }
811: }
812: /* Hybrid split faces have 4 edges and the same cells as the parent */
813: for (f = fMax; f < fEnd; ++f) {
814: for (r = 0; r < 2; ++r) {
815: const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (f - fMax)*2 + r;
816: PetscInt size;
818: DMPlexSetConeSize(rdm, newp, 4);
819: DMPlexGetSupportSize(dm, f, &size);
820: DMPlexSetSupportSize(rdm, newp, size);
821: }
822: }
823: /* Hybrid cells faces have 4 edges and 2 cells */
824: for (c = cMax; c < cEnd; ++c) {
825: for (r = 0; r < 3; ++r) {
826: const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + r;
828: DMPlexSetConeSize(rdm, newp, 4);
829: DMPlexSetSupportSize(rdm, newp, 2);
830: }
831: }
832: /* Interior split edges have 2 vertices and the same faces */
833: for (e = eStart; e < eMax; ++e) {
834: for (r = 0; r < 2; ++r) {
835: const PetscInt newp = eStartNew + (e - eStart)*2 + r;
836: PetscInt size;
838: DMPlexSetConeSize(rdm, newp, 2);
839: DMPlexGetSupportSize(dm, e, &size);
840: DMPlexSetSupportSize(rdm, newp, size);
841: }
842: }
843: /* Interior face edges have 2 vertices and 2+cells*(1/2) faces */
844: for (f = fStart; f < fMax; ++f) {
845: for (r = 0; r < 3; ++r) {
846: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + r;
847: const PetscInt *cone, *ornt, *support, eint[4] = {1, 0, 2, 0};
848: PetscInt coneSize, c, supportSize, s, er, intFaces = 0;
850: DMPlexSetConeSize(rdm, newp, 2);
851: DMPlexGetSupportSize(dm, f, &supportSize);
852: DMPlexGetSupport(dm, f, &support);
853: for (s = 0; s < supportSize; ++s) {
854: DMPlexGetConeSize(dm, support[s], &coneSize);
855: DMPlexGetCone(dm, support[s], &cone);
856: DMPlexGetConeOrientation(dm, support[s], &ornt);
857: for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
858: if (support[s] < cMax) {
859: /* Here we want to determine whether edge newp contains a vertex which is part of the cross-tet edge */
860: er = GetTriMidEdgeInverse_Static(ornt[c], r);
861: if (er == eint[c]) {
862: intFaces += 1;
863: } else {
864: intFaces += 2;
865: }
866: } else {
867: intFaces += 1;
868: }
869: }
870: DMPlexSetSupportSize(rdm, newp, 2+intFaces);
871: }
872: }
873: /* Interior cell edges have 2 vertices and 4 faces */
874: for (c = cStart; c < cMax; ++c) {
875: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
877: DMPlexSetConeSize(rdm, newp, 2);
878: DMPlexSetSupportSize(rdm, newp, 4);
879: }
880: /* Hybrid edges have 2 vertices and the same faces */
881: for (e = eMax; e < eEnd; ++e) {
882: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (e - eMax);
883: PetscInt size;
885: DMPlexSetConeSize(rdm, newp, 2);
886: DMPlexGetSupportSize(dm, e, &size);
887: DMPlexSetSupportSize(rdm, newp, size);
888: }
889: /* Hybrid face edges have 2 vertices and 2+2*cells faces */
890: for (f = fMax; f < fEnd; ++f) {
891: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (f - fMax);
892: PetscInt size;
894: DMPlexSetConeSize(rdm, newp, 2);
895: DMPlexGetSupportSize(dm, f, &size);
896: DMPlexSetSupportSize(rdm, newp, 2+2*size);
897: }
898: /* Interior vertices have identical supports */
899: for (v = vStart; v < vEnd; ++v) {
900: const PetscInt newp = vStartNew + (v - vStart);
901: PetscInt size;
903: DMPlexGetSupportSize(dm, v, &size);
904: DMPlexSetSupportSize(rdm, newp, size);
905: }
906: /* Interior edge vertices have 2 + interior face*2 + hybrid face + cells*0/1 supports */
907: for (e = eStart; e < eMax; ++e) {
908: const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
909: const PetscInt *support;
910: PetscInt size, *star = NULL, starSize, s, faceSize = 0, cellSize = 0;
912: DMPlexGetSupportSize(dm, e, &size);
913: DMPlexGetSupport(dm, e, &support);
914: for (s = 0; s < size; ++s) {
915: if (support[s] < fMax) faceSize += 2;
916: else faceSize += 1;
917: }
918: DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
919: for (s = 0; s < starSize*2; s += 2) {
920: const PetscInt *cone, *ornt;
921: PetscInt e01, e23;
923: if ((star[s] >= cStart) && (star[s] < cMax)) {
924: /* Check edge 0-1 */
925: DMPlexGetCone(dm, star[s], &cone);
926: DMPlexGetConeOrientation(dm, star[s], &ornt);
927: DMPlexGetCone(dm, cone[0], &cone);
928: e01 = cone[GetTriEdge_Static(ornt[0], 0)];
929: /* Check edge 2-3 */
930: DMPlexGetCone(dm, star[s], &cone);
931: DMPlexGetConeOrientation(dm, star[s], &ornt);
932: DMPlexGetCone(dm, cone[2], &cone);
933: e23 = cone[GetTriEdge_Static(ornt[2], 1)];
934: if ((e01 == e) || (e23 == e)) ++cellSize;
935: }
936: }
937: DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
938: DMPlexSetSupportSize(rdm, newp, 2 + faceSize + cellSize);
939: }
940: break;
941: case REFINER_SIMPLEX_TO_HEX_3D:
942: /* All cells have 6 faces */
943: for (c = cStart; c < cEnd; ++c) {
944: for (r = 0; r < 4; ++r) {
945: const PetscInt newp = cStartNew + (c - cStart)*4 + r;
947: DMPlexSetConeSize(rdm, newp, 6);
948: }
949: }
950: /* Split faces have 4 edges and the same cells as the parent */
951: for (f = fStart; f < fEnd; ++f) {
952: for (r = 0; r < 3; ++r) {
953: const PetscInt newp = fStartNew + (f - fStart)*3 + r;
954: PetscInt size;
956: DMPlexSetConeSize(rdm, newp, 4);
957: DMPlexGetSupportSize(dm, f, &size);
958: DMPlexSetSupportSize(rdm, newp, size);
959: }
960: }
961: /* Interior cell faces have 4 edges and 2 cells */
962: for (c = cStart; c < cEnd; ++c) {
963: for (r = 0; r < 6; ++r) {
964: const PetscInt newp = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + r;
966: DMPlexSetConeSize(rdm, newp, 4);
967: DMPlexSetSupportSize(rdm, newp, 2);
968: }
969: }
970: /* Split edges have 2 vertices and the same faces */
971: for (e = eStart; e < eEnd; ++e) {
972: for (r = 0; r < 2; ++r) {
973: const PetscInt newp = eStartNew + (e - eStart)*2 + r;
974: PetscInt size;
976: DMPlexSetConeSize(rdm, newp, 2);
977: DMPlexGetSupportSize(dm, e, &size);
978: DMPlexSetSupportSize(rdm, newp, size);
979: }
980: }
981: /* Face edges have 2 vertices and 2 + cell faces supports */
982: for (f = fStart; f < fEnd; ++f) {
983: for (r = 0; r < 3; ++r) {
984: const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + r;
985: PetscInt size;
987: DMPlexSetConeSize(rdm, newp, 2);
988: DMPlexGetSupportSize(dm, f, &size);
989: DMPlexSetSupportSize(rdm, newp, 2+size);
990: }
991: }
992: /* Interior cell edges have 2 vertices and 3 faces */
993: for (c = cStart; c < cEnd; ++c) {
994: for (r = 0; r < 4; ++r) {
995: const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + r;
997: DMPlexSetConeSize(rdm, newp, 2);
998: DMPlexSetSupportSize(rdm, newp, 3);
999: }
1000: }
1001: /* Old vertices have identical supports */
1002: for (v = vStart; v < vEnd; ++v) {
1003: const PetscInt newp = vStartNew + (v - vStart);
1004: PetscInt size;
1006: DMPlexGetSupportSize(dm, v, &size);
1007: DMPlexSetSupportSize(rdm, newp, size);
1008: }
1009: /* Edge vertices have 2 + faces supports */
1010: for (e = eStart; e < eEnd; ++e) {
1011: const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
1012: PetscInt size;
1014: DMPlexGetSupportSize(dm, e, &size);
1015: DMPlexSetSupportSize(rdm, newp, 2 + size);
1016: }
1017: /* Face vertices have 3 + cells supports */
1018: for (f = fStart; f < fEnd; ++f) {
1019: const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + f - fStart;
1020: PetscInt size;
1022: DMPlexGetSupportSize(dm, f, &size);
1023: DMPlexSetSupportSize(rdm, newp, 3 + size);
1024: }
1025: /* Interior cell vertices have 4 supports */
1026: for (c = cStart; c < cEnd; ++c) {
1027: const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + fEnd - fStart + c - cStart;
1029: DMPlexSetSupportSize(rdm, newp, 4);
1030: }
1031: break;
1032: case REFINER_HEX_3D:
1033: /* All cells have 6 faces */
1034: for (c = cStart; c < cEnd; ++c) {
1035: for (r = 0; r < 8; ++r) {
1036: const PetscInt newp = (c - cStart)*8 + r;
1038: DMPlexSetConeSize(rdm, newp, 6);
1039: }
1040: }
1041: /* Split faces have 4 edges and the same cells as the parent */
1042: for (f = fStart; f < fEnd; ++f) {
1043: for (r = 0; r < 4; ++r) {
1044: const PetscInt newp = fStartNew + (f - fStart)*4 + r;
1045: PetscInt size;
1047: DMPlexSetConeSize(rdm, newp, 4);
1048: DMPlexGetSupportSize(dm, f, &size);
1049: DMPlexSetSupportSize(rdm, newp, size);
1050: }
1051: }
1052: /* Interior faces have 4 edges and 2 cells */
1053: for (c = cStart; c < cEnd; ++c) {
1054: for (r = 0; r < 12; ++r) {
1055: const PetscInt newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + r;
1057: DMPlexSetConeSize(rdm, newp, 4);
1058: DMPlexSetSupportSize(rdm, newp, 2);
1059: }
1060: }
1061: /* Split edges have 2 vertices and the same faces as the parent */
1062: for (e = eStart; e < eEnd; ++e) {
1063: for (r = 0; r < 2; ++r) {
1064: const PetscInt newp = eStartNew + (e - eStart)*2 + r;
1065: PetscInt size;
1067: DMPlexSetConeSize(rdm, newp, 2);
1068: DMPlexGetSupportSize(dm, e, &size);
1069: DMPlexSetSupportSize(rdm, newp, size);
1070: }
1071: }
1072: /* Face edges have 2 vertices and 2+cells faces */
1073: for (f = fStart; f < fEnd; ++f) {
1074: for (r = 0; r < 4; ++r) {
1075: const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + r;
1076: PetscInt size;
1078: DMPlexSetConeSize(rdm, newp, 2);
1079: DMPlexGetSupportSize(dm, f, &size);
1080: DMPlexSetSupportSize(rdm, newp, 2+size);
1081: }
1082: }
1083: /* Cell edges have 2 vertices and 4 faces */
1084: for (c = cStart; c < cEnd; ++c) {
1085: for (r = 0; r < 6; ++r) {
1086: const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + r;
1088: DMPlexSetConeSize(rdm, newp, 2);
1089: DMPlexSetSupportSize(rdm, newp, 4);
1090: }
1091: }
1092: /* Old vertices have identical supports */
1093: for (v = vStart; v < vEnd; ++v) {
1094: const PetscInt newp = vStartNew + (v - vStart);
1095: PetscInt size;
1097: DMPlexGetSupportSize(dm, v, &size);
1098: DMPlexSetSupportSize(rdm, newp, size);
1099: }
1100: /* Edge vertices have 2 + faces supports */
1101: for (e = eStart; e < eEnd; ++e) {
1102: const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
1103: PetscInt size;
1105: DMPlexGetSupportSize(dm, e, &size);
1106: DMPlexSetSupportSize(rdm, newp, 2 + size);
1107: }
1108: /* Face vertices have 4 + cells supports */
1109: for (f = fStart; f < fEnd; ++f) {
1110: const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (f - fStart);
1111: PetscInt size;
1113: DMPlexGetSupportSize(dm, f, &size);
1114: DMPlexSetSupportSize(rdm, newp, 4 + size);
1115: }
1116: /* Cell vertices have 6 supports */
1117: for (c = cStart; c < cEnd; ++c) {
1118: const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (c - cStart);
1120: DMPlexSetSupportSize(rdm, newp, 6);
1121: }
1122: break;
1123: case REFINER_HYBRID_HEX_3D:
1124: DMPlexSetHybridBounds(rdm, cStartNew + 8*(cMax-cStart), fStartNew + 4*(fMax - fStart) + 12*(cMax - cStart),
1125: eStartNew + 2*(eMax - eStart) + 4*(fMax - fStart) + 6*(cMax - cStart), PETSC_DETERMINE);
1126: /* Interior cells have 6 faces */
1127: for (c = cStart; c < cMax; ++c) {
1128: for (r = 0; r < 8; ++r) {
1129: const PetscInt newp = cStartNew + (c - cStart)*8 + r;
1131: DMPlexSetConeSize(rdm, newp, 6);
1132: }
1133: }
1134: /* Hybrid cells have 6 faces */
1135: for (c = cMax; c < cEnd; ++c) {
1136: for (r = 0; r < 4; ++r) {
1137: const PetscInt newp = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + r;
1139: DMPlexSetConeSize(rdm, newp, 6);
1140: }
1141: }
1142: /* Interior split faces have 4 edges and the same cells as the parent */
1143: for (f = fStart; f < fMax; ++f) {
1144: for (r = 0; r < 4; ++r) {
1145: const PetscInt newp = fStartNew + (f - fStart)*4 + r;
1146: PetscInt size;
1148: DMPlexSetConeSize(rdm, newp, 4);
1149: DMPlexGetSupportSize(dm, f, &size);
1150: DMPlexSetSupportSize(rdm, newp, size);
1151: }
1152: }
1153: /* Interior cell faces have 4 edges and 2 cells */
1154: for (c = cStart; c < cMax; ++c) {
1155: for (r = 0; r < 12; ++r) {
1156: const PetscInt newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + r;
1158: DMPlexSetConeSize(rdm, newp, 4);
1159: DMPlexSetSupportSize(rdm, newp, 2);
1160: }
1161: }
1162: /* Hybrid split faces have 4 edges and the same cells as the parent */
1163: for (f = fMax; f < fEnd; ++f) {
1164: for (r = 0; r < 2; ++r) {
1165: const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (f - fMax)*2 + r;
1166: PetscInt size;
1168: DMPlexSetConeSize(rdm, newp, 4);
1169: DMPlexGetSupportSize(dm, f, &size);
1170: DMPlexSetSupportSize(rdm, newp, size);
1171: }
1172: }
1173: /* Hybrid cells faces have 4 edges and 2 cells */
1174: for (c = cMax; c < cEnd; ++c) {
1175: for (r = 0; r < 4; ++r) {
1176: const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + r;
1178: DMPlexSetConeSize(rdm, newp, 4);
1179: DMPlexSetSupportSize(rdm, newp, 2);
1180: }
1181: }
1182: /* Interior split edges have 2 vertices and the same faces as the parent */
1183: for (e = eStart; e < eMax; ++e) {
1184: for (r = 0; r < 2; ++r) {
1185: const PetscInt newp = eStartNew + (e - eStart)*2 + r;
1186: PetscInt size;
1188: DMPlexSetConeSize(rdm, newp, 2);
1189: DMPlexGetSupportSize(dm, e, &size);
1190: DMPlexSetSupportSize(rdm, newp, size);
1191: }
1192: }
1193: /* Interior face edges have 2 vertices and 2+cells faces */
1194: for (f = fStart; f < fMax; ++f) {
1195: for (r = 0; r < 4; ++r) {
1196: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (f - fStart)*4 + r;
1197: PetscInt size;
1199: DMPlexSetConeSize(rdm, newp, 2);
1200: DMPlexGetSupportSize(dm, f, &size);
1201: DMPlexSetSupportSize(rdm, newp, 2+size);
1202: }
1203: }
1204: /* Interior cell edges have 2 vertices and 4 faces */
1205: for (c = cStart; c < cMax; ++c) {
1206: for (r = 0; r < 6; ++r) {
1207: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + r;
1209: DMPlexSetConeSize(rdm, newp, 2);
1210: DMPlexSetSupportSize(rdm, newp, 4);
1211: }
1212: }
1213: /* Hybrid edges have 2 vertices and the same faces */
1214: for (e = eMax; e < eEnd; ++e) {
1215: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (e - eMax);
1216: PetscInt size;
1218: DMPlexSetConeSize(rdm, newp, 2);
1219: DMPlexGetSupportSize(dm, e, &size);
1220: DMPlexSetSupportSize(rdm, newp, size);
1221: }
1222: /* Hybrid face edges have 2 vertices and 2+cells faces */
1223: for (f = fMax; f < fEnd; ++f) {
1224: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (f - fMax);
1225: PetscInt size;
1227: DMPlexSetConeSize(rdm, newp, 2);
1228: DMPlexGetSupportSize(dm, f, &size);
1229: DMPlexSetSupportSize(rdm, newp, 2+size);
1230: }
1231: /* Hybrid cell edges have 2 vertices and 4 faces */
1232: for (c = cMax; c < cEnd; ++c) {
1233: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (fEnd - fMax) + (c - cMax);
1235: DMPlexSetConeSize(rdm, newp, 2);
1236: DMPlexSetSupportSize(rdm, newp, 4);
1237: }
1238: /* Interior vertices have identical supports */
1239: for (v = vStart; v < vEnd; ++v) {
1240: const PetscInt newp = vStartNew + (v - vStart);
1241: PetscInt size;
1243: DMPlexGetSupportSize(dm, v, &size);
1244: DMPlexSetSupportSize(rdm, newp, size);
1245: }
1246: /* Interior edge vertices have 2 + faces supports */
1247: for (e = eStart; e < eMax; ++e) {
1248: const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
1249: PetscInt size;
1251: DMPlexGetSupportSize(dm, e, &size);
1252: DMPlexSetSupportSize(rdm, newp, 2 + size);
1253: }
1254: /* Interior face vertices have 4 + cells supports */
1255: for (f = fStart; f < fMax; ++f) {
1256: const PetscInt newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (f - fStart);
1257: PetscInt size;
1259: DMPlexGetSupportSize(dm, f, &size);
1260: DMPlexSetSupportSize(rdm, newp, 4 + size);
1261: }
1262: /* Interior cell vertices have 6 supports */
1263: for (c = cStart; c < cMax; ++c) {
1264: const PetscInt newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (fMax - fStart) + (c - cStart);
1266: DMPlexSetSupportSize(rdm, newp, 6);
1267: }
1268: break;
1269: default:
1270: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
1271: }
1272: return(0);
1273: }
1275: static PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
1276: {
1277: const PetscInt *faces, cellInd[4] = {0, 1, 2, 3};
1278: PetscInt cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax;
1279: PetscInt cStartNew, cEndNew, cMaxNew, vStartNew, vEndNew, fStartNew, fEndNew, fMaxNew, eStartNew, eEndNew, eMaxNew;
1280: PetscInt depth, maxSupportSize, *supportRef, c, f, e, v, r, p;
1281: PetscErrorCode ierr;
1284: if (!refiner) return(0);
1285: DMPlexGetDepth(dm, &depth);
1286: DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
1287: DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);
1288: DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
1289: DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);
1290: DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);
1291: GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);
1292: GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);
1293: switch (refiner) {
1294: case REFINER_SIMPLEX_1D:
1295: /* Max support size of refined mesh is 2 */
1296: PetscMalloc1(2, &supportRef);
1297: /* All cells have 2 vertices */
1298: for (c = cStart; c < cEnd; ++c) {
1299: const PetscInt newv = vStartNew + (vEnd - vStart) + (c - cStart);
1301: for (r = 0; r < 2; ++r) {
1302: const PetscInt newp = cStartNew + (c - cStart)*2 + r;
1303: const PetscInt *cone;
1304: PetscInt coneNew[2];
1306: DMPlexGetCone(dm, c, &cone);
1307: coneNew[0] = vStartNew + (cone[0] - vStart);
1308: coneNew[1] = vStartNew + (cone[1] - vStart);
1309: coneNew[(r+1)%2] = newv;
1310: DMPlexSetCone(rdm, newp, coneNew);
1311: #if 1
1312: if ((newp < cStartNew) || (newp >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp, cStartNew, cEndNew);
1313: for (p = 0; p < 2; ++p) {
1314: 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);
1315: }
1316: #endif
1317: }
1318: }
1319: /* Old vertices have identical supports */
1320: for (v = vStart; v < vEnd; ++v) {
1321: const PetscInt newp = vStartNew + (v - vStart);
1322: const PetscInt *support, *cone;
1323: PetscInt size, s;
1325: DMPlexGetSupportSize(dm, v, &size);
1326: DMPlexGetSupport(dm, v, &support);
1327: for (s = 0; s < size; ++s) {
1328: PetscInt r = 0;
1330: DMPlexGetCone(dm, support[s], &cone);
1331: if (cone[1] == v) r = 1;
1332: supportRef[s] = cStartNew + (support[s] - cStart)*2 + r;
1333: }
1334: DMPlexSetSupport(rdm, newp, supportRef);
1335: #if 1
1336: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
1337: for (p = 0; p < size; ++p) {
1338: 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);
1339: }
1340: #endif
1341: }
1342: /* Cell vertices have support of 2 cells */
1343: for (c = cStart; c < cEnd; ++c) {
1344: const PetscInt newp = vStartNew + (vEnd - vStart) + (c - cStart);
1346: supportRef[0] = cStartNew + (c - cStart)*2 + 0;
1347: supportRef[1] = cStartNew + (c - cStart)*2 + 1;
1348: DMPlexSetSupport(rdm, newp, supportRef);
1349: #if 1
1350: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
1351: for (p = 0; p < 2; ++p) {
1352: 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);
1353: }
1354: #endif
1355: }
1356: PetscFree(supportRef);
1357: break;
1358: case REFINER_SIMPLEX_2D:
1359: /*
1360: 2
1361: |\
1362: | \
1363: | \
1364: | \
1365: | C \
1366: | \
1367: | \
1368: 2---1---1
1369: |\ D / \
1370: | 2 0 \
1371: |A \ / B \
1372: 0---0-------1
1373: */
1374: /* All cells have 3 faces */
1375: for (c = cStart; c < cEnd; ++c) {
1376: const PetscInt newp = cStartNew + (c - cStart)*4;
1377: const PetscInt *cone, *ornt;
1378: PetscInt coneNew[3], orntNew[3];
1380: DMPlexGetCone(dm, c, &cone);
1381: DMPlexGetConeOrientation(dm, c, &ornt);
1382: /* A triangle */
1383: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
1384: orntNew[0] = ornt[0];
1385: coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2;
1386: orntNew[1] = -2;
1387: coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
1388: orntNew[2] = ornt[2];
1389: DMPlexSetCone(rdm, newp+0, coneNew);
1390: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
1391: #if 1
1392: 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);
1393: for (p = 0; p < 3; ++p) {
1394: 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);
1395: }
1396: #endif
1397: /* B triangle */
1398: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
1399: orntNew[0] = ornt[0];
1400: coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
1401: orntNew[1] = ornt[1];
1402: coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0;
1403: orntNew[2] = -2;
1404: DMPlexSetCone(rdm, newp+1, coneNew);
1405: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
1406: #if 1
1407: 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);
1408: for (p = 0; p < 3; ++p) {
1409: 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);
1410: }
1411: #endif
1412: /* C triangle */
1413: coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1;
1414: orntNew[0] = -2;
1415: coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
1416: orntNew[1] = ornt[1];
1417: coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
1418: orntNew[2] = ornt[2];
1419: DMPlexSetCone(rdm, newp+2, coneNew);
1420: DMPlexSetConeOrientation(rdm, newp+2, orntNew);
1421: #if 1
1422: 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);
1423: for (p = 0; p < 3; ++p) {
1424: 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);
1425: }
1426: #endif
1427: /* D triangle */
1428: coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0;
1429: orntNew[0] = 0;
1430: coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1;
1431: orntNew[1] = 0;
1432: coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2;
1433: orntNew[2] = 0;
1434: DMPlexSetCone(rdm, newp+3, coneNew);
1435: DMPlexSetConeOrientation(rdm, newp+3, orntNew);
1436: #if 1
1437: 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);
1438: for (p = 0; p < 3; ++p) {
1439: 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);
1440: }
1441: #endif
1442: }
1443: /* Split faces have 2 vertices and the same cells as the parent */
1444: DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
1445: PetscMalloc1(2 + maxSupportSize*2, &supportRef);
1446: for (f = fStart; f < fEnd; ++f) {
1447: const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
1449: for (r = 0; r < 2; ++r) {
1450: const PetscInt newp = fStartNew + (f - fStart)*2 + r;
1451: const PetscInt *cone, *ornt, *support;
1452: PetscInt coneNew[2], coneSize, c, supportSize, s;
1454: DMPlexGetCone(dm, f, &cone);
1455: coneNew[0] = vStartNew + (cone[0] - vStart);
1456: coneNew[1] = vStartNew + (cone[1] - vStart);
1457: coneNew[(r+1)%2] = newv;
1458: DMPlexSetCone(rdm, newp, coneNew);
1459: #if 1
1460: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1461: for (p = 0; p < 2; ++p) {
1462: 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);
1463: }
1464: #endif
1465: DMPlexGetSupportSize(dm, f, &supportSize);
1466: DMPlexGetSupport(dm, f, &support);
1467: for (s = 0; s < supportSize; ++s) {
1468: DMPlexGetConeSize(dm, support[s], &coneSize);
1469: DMPlexGetCone(dm, support[s], &cone);
1470: DMPlexGetConeOrientation(dm, support[s], &ornt);
1471: for (c = 0; c < coneSize; ++c) {
1472: if (cone[c] == f) break;
1473: }
1474: supportRef[s] = cStartNew + (support[s] - cStart)*4 + (ornt[c] < 0 ? (c+1-r)%3 : (c+r)%3);
1475: }
1476: DMPlexSetSupport(rdm, newp, supportRef);
1477: #if 1
1478: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1479: for (p = 0; p < supportSize; ++p) {
1480: 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);
1481: }
1482: #endif
1483: }
1484: }
1485: /* Interior faces have 2 vertices and 2 cells */
1486: for (c = cStart; c < cEnd; ++c) {
1487: const PetscInt *cone;
1489: DMPlexGetCone(dm, c, &cone);
1490: for (r = 0; r < 3; ++r) {
1491: const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r;
1492: PetscInt coneNew[2];
1493: PetscInt supportNew[2];
1495: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart);
1496: coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart);
1497: DMPlexSetCone(rdm, newp, coneNew);
1498: #if 1
1499: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1500: for (p = 0; p < 2; ++p) {
1501: 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);
1502: }
1503: #endif
1504: supportNew[0] = (c - cStart)*4 + (r+1)%3;
1505: supportNew[1] = (c - cStart)*4 + 3;
1506: DMPlexSetSupport(rdm, newp, supportNew);
1507: #if 1
1508: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1509: for (p = 0; p < 2; ++p) {
1510: 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);
1511: }
1512: #endif
1513: }
1514: }
1515: /* Old vertices have identical supports */
1516: for (v = vStart; v < vEnd; ++v) {
1517: const PetscInt newp = vStartNew + (v - vStart);
1518: const PetscInt *support, *cone;
1519: PetscInt size, s;
1521: DMPlexGetSupportSize(dm, v, &size);
1522: DMPlexGetSupport(dm, v, &support);
1523: for (s = 0; s < size; ++s) {
1524: PetscInt r = 0;
1526: DMPlexGetCone(dm, support[s], &cone);
1527: if (cone[1] == v) r = 1;
1528: supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
1529: }
1530: DMPlexSetSupport(rdm, newp, supportRef);
1531: #if 1
1532: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
1533: for (p = 0; p < size; ++p) {
1534: 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);
1535: }
1536: #endif
1537: }
1538: /* Face vertices have 2 + cells*2 supports */
1539: for (f = fStart; f < fEnd; ++f) {
1540: const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
1541: const PetscInt *cone, *support;
1542: PetscInt size, s;
1544: DMPlexGetSupportSize(dm, f, &size);
1545: DMPlexGetSupport(dm, f, &support);
1546: supportRef[0] = fStartNew + (f - fStart)*2 + 0;
1547: supportRef[1] = fStartNew + (f - fStart)*2 + 1;
1548: for (s = 0; s < size; ++s) {
1549: PetscInt r = 0;
1551: DMPlexGetCone(dm, support[s], &cone);
1552: if (cone[1] == f) r = 1;
1553: else if (cone[2] == f) r = 2;
1554: supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3;
1555: supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r;
1556: }
1557: DMPlexSetSupport(rdm, newp, supportRef);
1558: #if 1
1559: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
1560: for (p = 0; p < 2+size*2; ++p) {
1561: 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);
1562: }
1563: #endif
1564: }
1565: PetscFree(supportRef);
1566: break;
1567: case REFINER_SIMPLEX_TO_HEX_2D:
1568: /*
1569: 2
1570: |\
1571: | \
1572: | \
1573: | \
1574: | C \
1575: | \
1576: 2 1
1577: |\ / \
1578: | 2 1 \
1579: | \/ \
1580: | | \
1581: |A | B \
1582: | 0 \
1583: | | \
1584: 0---0----------1
1585: */
1586: /* All cells have 4 faces */
1587: for (c = cStart; c < cEnd; ++c) {
1588: const PetscInt newp = cStartNew + (c - cStart)*3;
1589: const PetscInt *cone, *ornt;
1590: PetscInt coneNew[4], orntNew[4];
1592: DMPlexGetCone(dm, c, &cone);
1593: DMPlexGetConeOrientation(dm, c, &ornt);
1594: /* A quad */
1595: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
1596: orntNew[0] = ornt[0];
1597: coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0;
1598: orntNew[1] = 0;
1599: coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2;
1600: orntNew[2] = -2;
1601: coneNew[3] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
1602: orntNew[3] = ornt[2];
1603: DMPlexSetCone(rdm, newp+0, coneNew);
1604: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
1605: #if 1
1606: 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);
1607: for (p = 0; p < 4; ++p) {
1608: 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);
1609: }
1610: #endif
1611: /* B quad */
1612: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
1613: orntNew[0] = ornt[0];
1614: coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
1615: orntNew[1] = ornt[1];
1616: coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1;
1617: orntNew[2] = 0;
1618: coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0;
1619: orntNew[3] = -2;
1620: DMPlexSetCone(rdm, newp+1, coneNew);
1621: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
1622: #if 1
1623: 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);
1624: for (p = 0; p < 4; ++p) {
1625: 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);
1626: }
1627: #endif
1628: /* C quad */
1629: coneNew[0] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
1630: orntNew[0] = ornt[1];
1631: coneNew[1] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
1632: orntNew[1] = ornt[2];
1633: coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2;
1634: orntNew[2] = 0;
1635: coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1;
1636: orntNew[3] = -2;
1637: DMPlexSetCone(rdm, newp+2, coneNew);
1638: DMPlexSetConeOrientation(rdm, newp+2, orntNew);
1639: #if 1
1640: 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);
1641: for (p = 0; p < 4; ++p) {
1642: 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);
1643: }
1644: #endif
1645: }
1646: /* Split faces have 2 vertices and the same cells as the parent */
1647: DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
1648: PetscMalloc1(2 + maxSupportSize*2, &supportRef);
1649: for (f = fStart; f < fEnd; ++f) {
1650: const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
1652: for (r = 0; r < 2; ++r) {
1653: const PetscInt newp = fStartNew + (f - fStart)*2 + r;
1654: const PetscInt *cone, *ornt, *support;
1655: PetscInt coneNew[2], coneSize, c, supportSize, s;
1657: DMPlexGetCone(dm, f, &cone);
1658: coneNew[0] = vStartNew + (cone[0] - vStart);
1659: coneNew[1] = vStartNew + (cone[1] - vStart);
1660: coneNew[(r+1)%2] = newv;
1661: DMPlexSetCone(rdm, newp, coneNew);
1662: #if 1
1663: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1664: for (p = 0; p < 2; ++p) {
1665: 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);
1666: }
1667: #endif
1668: DMPlexGetSupportSize(dm, f, &supportSize);
1669: DMPlexGetSupport(dm, f, &support);
1670: for (s = 0; s < supportSize; ++s) {
1671: DMPlexGetConeSize(dm, support[s], &coneSize);
1672: DMPlexGetCone(dm, support[s], &cone);
1673: DMPlexGetConeOrientation(dm, support[s], &ornt);
1674: for (c = 0; c < coneSize; ++c) {
1675: if (cone[c] == f) break;
1676: }
1677: supportRef[s] = cStartNew + (support[s] - cStart)*3 + (ornt[c] < 0 ? (c+1-r)%3 : (c+r)%3);
1678: }
1679: DMPlexSetSupport(rdm, newp, supportRef);
1680: #if 1
1681: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1682: for (p = 0; p < supportSize; ++p) {
1683: 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);
1684: }
1685: #endif
1686: }
1687: }
1688: /* Interior faces have 2 vertices and 2 cells */
1689: for (c = cStart; c < cEnd; ++c) {
1690: const PetscInt *cone;
1692: DMPlexGetCone(dm, c, &cone);
1693: for (r = 0; r < 3; ++r) {
1694: const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r;
1695: PetscInt coneNew[2];
1696: PetscInt supportNew[2];
1698: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart);
1699: coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart);
1700: DMPlexSetCone(rdm, newp, coneNew);
1701: #if 1
1702: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1703: for (p = 0; p < 2; ++p) {
1704: 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);
1705: }
1706: #endif
1707: supportNew[0] = (c - cStart)*3 + r%3;
1708: supportNew[1] = (c - cStart)*3 + (r+1)%3;
1709: DMPlexSetSupport(rdm, newp, supportNew);
1710: #if 1
1711: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1712: for (p = 0; p < 2; ++p) {
1713: 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);
1714: }
1715: #endif
1716: }
1717: }
1718: /* Old vertices have identical supports */
1719: for (v = vStart; v < vEnd; ++v) {
1720: const PetscInt newp = vStartNew + (v - vStart);
1721: const PetscInt *support, *cone;
1722: PetscInt size, s;
1724: DMPlexGetSupportSize(dm, v, &size);
1725: DMPlexGetSupport(dm, v, &support);
1726: for (s = 0; s < size; ++s) {
1727: PetscInt r = 0;
1729: DMPlexGetCone(dm, support[s], &cone);
1730: if (cone[1] == v) r = 1;
1731: supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
1732: }
1733: DMPlexSetSupport(rdm, newp, supportRef);
1734: #if 1
1735: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
1736: for (p = 0; p < size; ++p) {
1737: 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);
1738: }
1739: #endif
1740: }
1741: /* Split-face vertices have cells + 2 supports */
1742: for (f = fStart; f < fEnd; ++f) {
1743: const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
1744: const PetscInt *cone, *support;
1745: PetscInt size, s;
1747: DMPlexGetSupportSize(dm, f, &size);
1748: DMPlexGetSupport(dm, f, &support);
1749: supportRef[0] = fStartNew + (f - fStart)*2 + 0;
1750: supportRef[1] = fStartNew + (f - fStart)*2 + 1;
1751: for (s = 0; s < size; ++s) {
1752: PetscInt r = 0;
1754: DMPlexGetCone(dm, support[s], &cone);
1755: if (cone[1] == f) r = 1;
1756: else if (cone[2] == f) r = 2;
1757: supportRef[2+s+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r;
1758: }
1759: DMPlexSetSupport(rdm, newp, supportRef);
1760: #if 1
1761: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
1762: for (p = 0; p < 2+size; ++p) {
1763: 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);
1764: }
1765: #endif
1766: }
1767: /* Interior vertices vertices have 3 supports */
1768: for (c = cStart; c < cEnd; ++c) {
1769: const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + c - cStart;
1771: supportRef[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0;
1772: supportRef[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1;
1773: supportRef[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2;
1774: DMPlexSetSupport(rdm, newp, supportRef);
1775: }
1776: PetscFree(supportRef);
1777: break;
1778: case REFINER_HEX_2D:
1779: /*
1780: 3---------2---------2
1781: | | |
1782: | D 2 C |
1783: | | |
1784: 3----3----0----1----1
1785: | | |
1786: | A 0 B |
1787: | | |
1788: 0---------0---------1
1789: */
1790: /* All cells have 4 faces */
1791: for (c = cStart; c < cEnd; ++c) {
1792: const PetscInt newp = (c - cStart)*4;
1793: const PetscInt *cone, *ornt;
1794: PetscInt coneNew[4], orntNew[4];
1796: DMPlexGetCone(dm, c, &cone);
1797: DMPlexGetConeOrientation(dm, c, &ornt);
1798: /* A quad */
1799: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
1800: orntNew[0] = ornt[0];
1801: coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0;
1802: orntNew[1] = 0;
1803: coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3;
1804: orntNew[2] = -2;
1805: coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1);
1806: orntNew[3] = ornt[3];
1807: DMPlexSetCone(rdm, newp+0, coneNew);
1808: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
1809: #if 1
1810: 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);
1811: for (p = 0; p < 4; ++p) {
1812: 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);
1813: }
1814: #endif
1815: /* B quad */
1816: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
1817: orntNew[0] = ornt[0];
1818: coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
1819: orntNew[1] = ornt[1];
1820: coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1;
1821: orntNew[2] = -2;
1822: coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0;
1823: orntNew[3] = -2;
1824: DMPlexSetCone(rdm, newp+1, coneNew);
1825: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
1826: #if 1
1827: 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);
1828: for (p = 0; p < 4; ++p) {
1829: 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);
1830: }
1831: #endif
1832: /* C quad */
1833: coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1;
1834: orntNew[0] = 0;
1835: coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
1836: orntNew[1] = ornt[1];
1837: coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
1838: orntNew[2] = ornt[2];
1839: coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2;
1840: orntNew[3] = -2;
1841: DMPlexSetCone(rdm, newp+2, coneNew);
1842: DMPlexSetConeOrientation(rdm, newp+2, orntNew);
1843: #if 1
1844: 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);
1845: for (p = 0; p < 4; ++p) {
1846: 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);
1847: }
1848: #endif
1849: /* D quad */
1850: coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3;
1851: orntNew[0] = 0;
1852: coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2;
1853: orntNew[1] = 0;
1854: coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
1855: orntNew[2] = ornt[2];
1856: coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0);
1857: orntNew[3] = ornt[3];
1858: DMPlexSetCone(rdm, newp+3, coneNew);
1859: DMPlexSetConeOrientation(rdm, newp+3, orntNew);
1860: #if 1
1861: 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);
1862: for (p = 0; p < 4; ++p) {
1863: 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);
1864: }
1865: #endif
1866: }
1867: /* Split faces have 2 vertices and the same cells as the parent */
1868: DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
1869: PetscMalloc1(2 + maxSupportSize*2, &supportRef);
1870: for (f = fStart; f < fEnd; ++f) {
1871: const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
1873: for (r = 0; r < 2; ++r) {
1874: const PetscInt newp = fStartNew + (f - fStart)*2 + r;
1875: const PetscInt *cone, *ornt, *support;
1876: PetscInt coneNew[2], coneSize, c, supportSize, s;
1878: DMPlexGetCone(dm, f, &cone);
1879: coneNew[0] = vStartNew + (cone[0] - vStart);
1880: coneNew[1] = vStartNew + (cone[1] - vStart);
1881: coneNew[(r+1)%2] = newv;
1882: DMPlexSetCone(rdm, newp, coneNew);
1883: #if 1
1884: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1885: for (p = 0; p < 2; ++p) {
1886: 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);
1887: }
1888: #endif
1889: DMPlexGetSupportSize(dm, f, &supportSize);
1890: DMPlexGetSupport(dm, f, &support);
1891: for (s = 0; s < supportSize; ++s) {
1892: DMPlexGetConeSize(dm, support[s], &coneSize);
1893: DMPlexGetCone(dm, support[s], &cone);
1894: DMPlexGetConeOrientation(dm, support[s], &ornt);
1895: for (c = 0; c < coneSize; ++c) {
1896: if (cone[c] == f) break;
1897: }
1898: supportRef[s] = cStartNew + (support[s] - cStart)*4 + (ornt[c] < 0 ? (c+1-r)%4 : (c+r)%4);
1899: }
1900: DMPlexSetSupport(rdm, newp, supportRef);
1901: #if 1
1902: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1903: for (p = 0; p < supportSize; ++p) {
1904: 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);
1905: }
1906: #endif
1907: }
1908: }
1909: /* Interior faces have 2 vertices and 2 cells */
1910: for (c = cStart; c < cEnd; ++c) {
1911: const PetscInt *cone;
1912: PetscInt coneNew[2], supportNew[2];
1914: DMPlexGetCone(dm, c, &cone);
1915: for (r = 0; r < 4; ++r) {
1916: const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r;
1918: if (r==1 || r==2) {
1919: coneNew[0] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart);
1920: coneNew[1] = vStartNew + (vEnd - vStart) + (cone[r] - fStart);
1921: } else {
1922: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart);
1923: coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart);
1924: }
1925: DMPlexSetCone(rdm, newp, coneNew);
1926: #if 1
1927: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1928: for (p = 0; p < 2; ++p) {
1929: 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);
1930: }
1931: #endif
1932: supportNew[0] = (c - cStart)*4 + r;
1933: supportNew[1] = (c - cStart)*4 + (r+1)%4;
1934: DMPlexSetSupport(rdm, newp, supportNew);
1935: #if 1
1936: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1937: for (p = 0; p < 2; ++p) {
1938: 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);
1939: }
1940: #endif
1941: }
1942: }
1943: /* Old vertices have identical supports */
1944: for (v = vStart; v < vEnd; ++v) {
1945: const PetscInt newp = vStartNew + (v - vStart);
1946: const PetscInt *support, *cone;
1947: PetscInt size, s;
1949: DMPlexGetSupportSize(dm, v, &size);
1950: DMPlexGetSupport(dm, v, &support);
1951: for (s = 0; s < size; ++s) {
1952: PetscInt r = 0;
1954: DMPlexGetCone(dm, support[s], &cone);
1955: if (cone[1] == v) r = 1;
1956: supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
1957: }
1958: DMPlexSetSupport(rdm, newp, supportRef);
1959: #if 1
1960: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
1961: for (p = 0; p < size; ++p) {
1962: 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);
1963: }
1964: #endif
1965: }
1966: /* Face vertices have 2 + cells supports */
1967: for (f = fStart; f < fEnd; ++f) {
1968: const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
1969: const PetscInt *cone, *support;
1970: PetscInt size, s;
1972: DMPlexGetSupportSize(dm, f, &size);
1973: DMPlexGetSupport(dm, f, &support);
1974: supportRef[0] = fStartNew + (f - fStart)*2 + 0;
1975: supportRef[1] = fStartNew + (f - fStart)*2 + 1;
1976: for (s = 0; s < size; ++s) {
1977: PetscInt r = 0;
1979: DMPlexGetCone(dm, support[s], &cone);
1980: if (cone[1] == f) r = 1;
1981: else if (cone[2] == f) r = 2;
1982: else if (cone[3] == f) r = 3;
1983: supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r;
1984: }
1985: DMPlexSetSupport(rdm, newp, supportRef);
1986: #if 1
1987: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
1988: for (p = 0; p < 2+size; ++p) {
1989: 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);
1990: }
1991: #endif
1992: }
1993: /* Cell vertices have 4 supports */
1994: for (c = cStart; c < cEnd; ++c) {
1995: const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart);
1996: PetscInt supportNew[4];
1998: for (r = 0; r < 4; ++r) {
1999: supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r;
2000: }
2001: DMPlexSetSupport(rdm, newp, supportNew);
2002: }
2003: PetscFree(supportRef);
2004: break;
2005: case REFINER_HYBRID_SIMPLEX_2D:
2006: if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
2007: cMax = PetscMin(cEnd, cMax);
2008: if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
2009: fMax = PetscMin(fEnd, fMax);
2010: DMPlexGetHybridBounds(rdm, &cMaxNew, &fMaxNew, NULL, NULL);
2011: /* Interior cells have 3 faces */
2012: for (c = cStart; c < cMax; ++c) {
2013: const PetscInt newp = cStartNew + (c - cStart)*4;
2014: const PetscInt *cone, *ornt;
2015: PetscInt coneNew[3], orntNew[3];
2017: DMPlexGetCone(dm, c, &cone);
2018: DMPlexGetConeOrientation(dm, c, &ornt);
2019: /* A triangle */
2020: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
2021: orntNew[0] = ornt[0];
2022: coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2;
2023: orntNew[1] = -2;
2024: coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
2025: orntNew[2] = ornt[2];
2026: DMPlexSetCone(rdm, newp+0, coneNew);
2027: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
2028: #if 1
2029: 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);
2030: for (p = 0; p < 3; ++p) {
2031: 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);
2032: }
2033: #endif
2034: /* B triangle */
2035: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
2036: orntNew[0] = ornt[0];
2037: coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
2038: orntNew[1] = ornt[1];
2039: coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0;
2040: orntNew[2] = -2;
2041: DMPlexSetCone(rdm, newp+1, coneNew);
2042: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
2043: #if 1
2044: 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);
2045: for (p = 0; p < 3; ++p) {
2046: 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);
2047: }
2048: #endif
2049: /* C triangle */
2050: coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1;
2051: orntNew[0] = -2;
2052: coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
2053: orntNew[1] = ornt[1];
2054: coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
2055: orntNew[2] = ornt[2];
2056: DMPlexSetCone(rdm, newp+2, coneNew);
2057: DMPlexSetConeOrientation(rdm, newp+2, orntNew);
2058: #if 1
2059: 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);
2060: for (p = 0; p < 3; ++p) {
2061: 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);
2062: }
2063: #endif
2064: /* D triangle */
2065: coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0;
2066: orntNew[0] = 0;
2067: coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1;
2068: orntNew[1] = 0;
2069: coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2;
2070: orntNew[2] = 0;
2071: DMPlexSetCone(rdm, newp+3, coneNew);
2072: DMPlexSetConeOrientation(rdm, newp+3, orntNew);
2073: #if 1
2074: 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);
2075: for (p = 0; p < 3; ++p) {
2076: 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);
2077: }
2078: #endif
2079: }
2080: /*
2081: 2----3----3
2082: | |
2083: | B |
2084: | |
2085: 0----4--- 1
2086: | |
2087: | A |
2088: | |
2089: 0----2----1
2090: */
2091: /* Hybrid cells have 4 faces */
2092: for (c = cMax; c < cEnd; ++c) {
2093: const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2;
2094: const PetscInt *cone, *ornt;
2095: PetscInt coneNew[4], orntNew[4], r;
2097: DMPlexGetCone(dm, c, &cone);
2098: DMPlexGetConeOrientation(dm, c, &ornt);
2099: r = (ornt[0] < 0 ? 1 : 0);
2100: /* A quad */
2101: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + r;
2102: orntNew[0] = ornt[0];
2103: coneNew[1] = fStartNew + (cone[1] - fStart)*2 + r;
2104: orntNew[1] = ornt[1];
2105: coneNew[2+r] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[2+r] - fMax);
2106: orntNew[2+r] = 0;
2107: coneNew[3-r] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax);
2108: orntNew[3-r] = 0;
2109: DMPlexSetCone(rdm, newp+0, coneNew);
2110: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
2111: #if 1
2112: 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);
2113: for (p = 0; p < 4; ++p) {
2114: 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);
2115: }
2116: #endif
2117: /* B quad */
2118: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + 1-r;
2119: orntNew[0] = ornt[0];
2120: coneNew[1] = fStartNew + (cone[1] - fStart)*2 + 1-r;
2121: orntNew[1] = ornt[1];
2122: coneNew[2+r] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax);
2123: orntNew[2+r] = 0;
2124: coneNew[3-r] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[3-r] - fMax);
2125: orntNew[3-r] = 0;
2126: DMPlexSetCone(rdm, newp+1, coneNew);
2127: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
2128: #if 1
2129: 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);
2130: for (p = 0; p < 4; ++p) {
2131: 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);
2132: }
2133: #endif
2134: }
2135: /* Interior split faces have 2 vertices and the same cells as the parent */
2136: DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
2137: PetscMalloc1(2 + maxSupportSize*2, &supportRef);
2138: for (f = fStart; f < fMax; ++f) {
2139: const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
2141: for (r = 0; r < 2; ++r) {
2142: const PetscInt newp = fStartNew + (f - fStart)*2 + r;
2143: const PetscInt *cone, *ornt, *support;
2144: PetscInt coneNew[2], coneSize, c, supportSize, s;
2146: DMPlexGetCone(dm, f, &cone);
2147: coneNew[0] = vStartNew + (cone[0] - vStart);
2148: coneNew[1] = vStartNew + (cone[1] - vStart);
2149: coneNew[(r+1)%2] = newv;
2150: DMPlexSetCone(rdm, newp, coneNew);
2151: #if 1
2152: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2153: for (p = 0; p < 2; ++p) {
2154: 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);
2155: }
2156: #endif
2157: DMPlexGetSupportSize(dm, f, &supportSize);
2158: DMPlexGetSupport(dm, f, &support);
2159: for (s = 0; s < supportSize; ++s) {
2160: DMPlexGetConeSize(dm, support[s], &coneSize);
2161: DMPlexGetCone(dm, support[s], &cone);
2162: DMPlexGetConeOrientation(dm, support[s], &ornt);
2163: for (c = 0; c < coneSize; ++c) if (cone[c] == f) break;
2164: if (support[s] >= cMax) {
2165: supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + (ornt[c] < 0 ? 1-r : r);
2166: } else {
2167: supportRef[s] = cStartNew + (support[s] - cStart)*4 + (ornt[c] < 0 ? (c+1-r)%3 : (c+r)%3);
2168: }
2169: }
2170: DMPlexSetSupport(rdm, newp, supportRef);
2171: #if 1
2172: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2173: for (p = 0; p < supportSize; ++p) {
2174: 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);
2175: }
2176: #endif
2177: }
2178: }
2179: /* Interior cell faces have 2 vertices and 2 cells */
2180: for (c = cStart; c < cMax; ++c) {
2181: const PetscInt *cone;
2183: DMPlexGetCone(dm, c, &cone);
2184: for (r = 0; r < 3; ++r) {
2185: const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r;
2186: PetscInt coneNew[2];
2187: PetscInt supportNew[2];
2189: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart);
2190: coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart);
2191: DMPlexSetCone(rdm, newp, coneNew);
2192: #if 1
2193: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2194: for (p = 0; p < 2; ++p) {
2195: 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);
2196: }
2197: #endif
2198: supportNew[0] = (c - cStart)*4 + (r+1)%3;
2199: supportNew[1] = (c - cStart)*4 + 3;
2200: DMPlexSetSupport(rdm, newp, supportNew);
2201: #if 1
2202: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2203: for (p = 0; p < 2; ++p) {
2204: 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);
2205: }
2206: #endif
2207: }
2208: }
2209: /* Interior hybrid faces have 2 vertices and the same cells */
2210: for (f = fMax; f < fEnd; ++f) {
2211: const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax);
2212: const PetscInt *cone, *ornt;
2213: const PetscInt *support;
2214: PetscInt coneNew[2];
2215: PetscInt supportNew[2];
2216: PetscInt size, s, r;
2218: DMPlexGetCone(dm, f, &cone);
2219: coneNew[0] = vStartNew + (cone[0] - vStart);
2220: coneNew[1] = vStartNew + (cone[1] - vStart);
2221: DMPlexSetCone(rdm, newp, coneNew);
2222: #if 1
2223: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2224: for (p = 0; p < 2; ++p) {
2225: 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);
2226: }
2227: #endif
2228: DMPlexGetSupportSize(dm, f, &size);
2229: DMPlexGetSupport(dm, f, &support);
2230: for (s = 0; s < size; ++s) {
2231: DMPlexGetCone(dm, support[s], &cone);
2232: DMPlexGetConeOrientation(dm, support[s], &ornt);
2233: for (r = 0; r < 2; ++r) {
2234: if (cone[r+2] == f) break;
2235: }
2236: supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + (ornt[0] < 0 ? 1-r : r);
2237: }
2238: DMPlexSetSupport(rdm, newp, supportNew);
2239: #if 1
2240: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2241: for (p = 0; p < size; ++p) {
2242: 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);
2243: }
2244: #endif
2245: }
2246: /* Cell hybrid faces have 2 vertices and 2 cells */
2247: for (c = cMax; c < cEnd; ++c) {
2248: const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax);
2249: const PetscInt *cone;
2250: PetscInt coneNew[2];
2251: PetscInt supportNew[2];
2253: DMPlexGetCone(dm, c, &cone);
2254: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart);
2255: coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart);
2256: DMPlexSetCone(rdm, newp, coneNew);
2257: #if 1
2258: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2259: for (p = 0; p < 2; ++p) {
2260: 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);
2261: }
2262: #endif
2263: supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0;
2264: supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1;
2265: DMPlexSetSupport(rdm, newp, supportNew);
2266: #if 1
2267: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2268: for (p = 0; p < 2; ++p) {
2269: 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);
2270: }
2271: #endif
2272: }
2273: /* Old vertices have identical supports */
2274: for (v = vStart; v < vEnd; ++v) {
2275: const PetscInt newp = vStartNew + (v - vStart);
2276: const PetscInt *support, *cone;
2277: PetscInt size, s;
2279: DMPlexGetSupportSize(dm, v, &size);
2280: DMPlexGetSupport(dm, v, &support);
2281: for (s = 0; s < size; ++s) {
2282: if (support[s] >= fMax) {
2283: supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax);
2284: } else {
2285: PetscInt r = 0;
2287: DMPlexGetCone(dm, support[s], &cone);
2288: if (cone[1] == v) r = 1;
2289: supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
2290: }
2291: }
2292: DMPlexSetSupport(rdm, newp, supportRef);
2293: #if 1
2294: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
2295: for (p = 0; p < size; ++p) {
2296: 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);
2297: }
2298: #endif
2299: }
2300: /* Face vertices have 2 + (2 interior, 1 hybrid) supports */
2301: for (f = fStart; f < fMax; ++f) {
2302: const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
2303: const PetscInt *cone, *support;
2304: PetscInt size, newSize = 2, s;
2306: DMPlexGetSupportSize(dm, f, &size);
2307: DMPlexGetSupport(dm, f, &support);
2308: supportRef[0] = fStartNew + (f - fStart)*2 + 0;
2309: supportRef[1] = fStartNew + (f - fStart)*2 + 1;
2310: for (s = 0; s < size; ++s) {
2311: PetscInt r = 0;
2313: DMPlexGetCone(dm, support[s], &cone);
2314: if (support[s] >= cMax) {
2315: supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (support[s] - cMax);
2317: newSize += 1;
2318: } else {
2319: if (cone[1] == f) r = 1;
2320: else if (cone[2] == f) r = 2;
2321: supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3;
2322: supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r;
2324: newSize += 2;
2325: }
2326: }
2327: DMPlexSetSupport(rdm, newp, supportRef);
2328: #if 1
2329: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
2330: for (p = 0; p < newSize; ++p) {
2331: 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);
2332: }
2333: #endif
2334: }
2335: PetscFree(supportRef);
2336: break;
2337: case REFINER_HYBRID_HEX_2D:
2338: /* Hybrid Hex 2D */
2339: if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
2340: cMax = PetscMin(cEnd, cMax);
2341: if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
2342: fMax = PetscMin(fEnd, fMax);
2343: DMPlexGetHybridBounds(rdm, &cMaxNew, &fMaxNew, NULL, NULL);
2344: /* Interior cells have 4 faces */
2345: for (c = cStart; c < cMax; ++c) {
2346: const PetscInt newp = cStartNew + (c - cStart)*4;
2347: const PetscInt *cone, *ornt;
2348: PetscInt coneNew[4], orntNew[4];
2350: DMPlexGetCone(dm, c, &cone);
2351: DMPlexGetConeOrientation(dm, c, &ornt);
2352: /* A quad */
2353: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
2354: orntNew[0] = ornt[0];
2355: coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + 0;
2356: orntNew[1] = 0;
2357: coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + 3;
2358: orntNew[2] = -2;
2359: coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1);
2360: orntNew[3] = ornt[3];
2361: DMPlexSetCone(rdm, newp+0, coneNew);
2362: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
2363: #if 1
2364: 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);
2365: for (p = 0; p < 4; ++p) {
2366: 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);
2367: }
2368: #endif
2369: /* B quad */
2370: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
2371: orntNew[0] = ornt[0];
2372: coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
2373: orntNew[1] = ornt[1];
2374: coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + 1;
2375: orntNew[2] = 0;
2376: coneNew[3] = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + 0;
2377: orntNew[3] = -2;
2378: DMPlexSetCone(rdm, newp+1, coneNew);
2379: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
2380: #if 1
2381: 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);
2382: for (p = 0; p < 4; ++p) {
2383: 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);
2384: }
2385: #endif
2386: /* C quad */
2387: coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + 1;
2388: orntNew[0] = -2;
2389: coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
2390: orntNew[1] = ornt[1];
2391: coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
2392: orntNew[2] = ornt[2];
2393: coneNew[3] = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + 2;
2394: orntNew[3] = 0;
2395: DMPlexSetCone(rdm, newp+2, coneNew);
2396: DMPlexSetConeOrientation(rdm, newp+2, orntNew);
2397: #if 1
2398: 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);
2399: for (p = 0; p < 4; ++p) {
2400: 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);
2401: }
2402: #endif
2403: /* D quad */
2404: coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + 3;
2405: orntNew[0] = 0;
2406: coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + 2;
2407: orntNew[1] = -2;
2408: coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
2409: orntNew[2] = ornt[2];
2410: coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0);
2411: orntNew[3] = ornt[3];
2412: DMPlexSetCone(rdm, newp+3, coneNew);
2413: DMPlexSetConeOrientation(rdm, newp+3, orntNew);
2414: #if 1
2415: 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);
2416: for (p = 0; p < 4; ++p) {
2417: 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);
2418: }
2419: #endif
2420: }
2421: /*
2422: 2----3----3
2423: | |
2424: | B |
2425: | |
2426: 0----4--- 1
2427: | |
2428: | A |
2429: | |
2430: 0----2----1
2431: */
2432: /* Hybrid cells have 4 faces */
2433: for (c = cMax; c < cEnd; ++c) {
2434: const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2;
2435: const PetscInt *cone, *ornt;
2436: PetscInt coneNew[4], orntNew[4];
2438: DMPlexGetCone(dm, c, &cone);
2439: DMPlexGetConeOrientation(dm, c, &ornt);
2440: /* A quad */
2441: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
2442: orntNew[0] = ornt[0];
2443: coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
2444: orntNew[1] = ornt[1];
2445: coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (cone[2] - fMax);
2446: orntNew[2] = 0;
2447: coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (fEnd - fMax) + (c - cMax);
2448: orntNew[3] = 0;
2449: DMPlexSetCone(rdm, newp+0, coneNew);
2450: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
2451: #if 1
2452: 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);
2453: for (p = 0; p < 4; ++p) {
2454: 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);
2455: }
2456: #endif
2457: /* B quad */
2458: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
2459: orntNew[0] = ornt[0];
2460: coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
2461: orntNew[1] = ornt[1];
2462: coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (fEnd - fMax) + (c - cMax);
2463: orntNew[2] = 0;
2464: coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (cone[3] - fMax);
2465: orntNew[3] = 0;
2466: DMPlexSetCone(rdm, newp+1, coneNew);
2467: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
2468: #if 1
2469: 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);
2470: for (p = 0; p < 4; ++p) {
2471: 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);
2472: }
2473: #endif
2474: }
2475: /* Interior split faces have 2 vertices and the same cells as the parent */
2476: DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
2477: PetscMalloc1(2 + maxSupportSize*2, &supportRef);
2478: for (f = fStart; f < fMax; ++f) {
2479: const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
2481: for (r = 0; r < 2; ++r) {
2482: const PetscInt newp = fStartNew + (f - fStart)*2 + r;
2483: const PetscInt *cone, *ornt, *support;
2484: PetscInt coneNew[2], coneSize, c, supportSize, s;
2486: DMPlexGetCone(dm, f, &cone);
2487: coneNew[0] = vStartNew + (cone[0] - vStart);
2488: coneNew[1] = vStartNew + (cone[1] - vStart);
2489: coneNew[(r+1)%2] = newv;
2490: DMPlexSetCone(rdm, newp, coneNew);
2491: #if 1
2492: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2493: for (p = 0; p < 2; ++p) {
2494: 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);
2495: }
2496: #endif
2497: DMPlexGetSupportSize(dm, f, &supportSize);
2498: DMPlexGetSupport(dm, f, &support);
2499: for (s = 0; s < supportSize; ++s) {
2500: if (support[s] >= cMax) {
2501: supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r;
2502: } else {
2503: DMPlexGetConeSize(dm, support[s], &coneSize);
2504: DMPlexGetCone(dm, support[s], &cone);
2505: DMPlexGetConeOrientation(dm, support[s], &ornt);
2506: for (c = 0; c < coneSize; ++c) {
2507: if (cone[c] == f) break;
2508: }
2509: supportRef[s] = cStartNew + (support[s] - cStart)*4 + (ornt[c] < 0 ? (c+1-r)%4 : (c+r)%4);
2510: }
2511: }
2512: DMPlexSetSupport(rdm, newp, supportRef);
2513: #if 1
2514: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2515: for (p = 0; p < supportSize; ++p) {
2516: 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);
2517: }
2518: #endif
2519: }
2520: }
2521: /* Interior cell faces have 2 vertices and 2 cells */
2522: for (c = cStart; c < cMax; ++c) {
2523: const PetscInt *cone;
2525: DMPlexGetCone(dm, c, &cone);
2526: for (r = 0; r < 4; ++r) {
2527: const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + r;
2528: PetscInt coneNew[2], supportNew[2];
2530: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart);
2531: coneNew[1] = vStartNew + (vEnd - vStart) + (fMax - fStart) + (c - cStart);
2532: DMPlexSetCone(rdm, newp, coneNew);
2533: #if 1
2534: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2535: for (p = 0; p < 2; ++p) {
2536: 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);
2537: }
2538: #endif
2539: supportNew[0] = (c - cStart)*4 + r;
2540: supportNew[1] = (c - cStart)*4 + (r+1)%4;
2541: DMPlexSetSupport(rdm, newp, supportNew);
2542: #if 1
2543: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2544: for (p = 0; p < 2; ++p) {
2545: 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);
2546: }
2547: #endif
2548: }
2549: }
2550: /* Hybrid faces have 2 vertices and the same cells */
2551: for (f = fMax; f < fEnd; ++f) {
2552: const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (f - fMax);
2553: const PetscInt *cone, *support;
2554: PetscInt coneNew[2], supportNew[2];
2555: PetscInt size, s, r;
2557: DMPlexGetCone(dm, f, &cone);
2558: coneNew[0] = vStartNew + (cone[0] - vStart);
2559: coneNew[1] = vStartNew + (cone[1] - vStart);
2560: DMPlexSetCone(rdm, newp, coneNew);
2561: #if 1
2562: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2563: for (p = 0; p < 2; ++p) {
2564: 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);
2565: }
2566: #endif
2567: DMPlexGetSupportSize(dm, f, &size);
2568: DMPlexGetSupport(dm, f, &support);
2569: for (s = 0; s < size; ++s) {
2570: DMPlexGetCone(dm, support[s], &cone);
2571: for (r = 0; r < 2; ++r) {
2572: if (cone[r+2] == f) break;
2573: }
2574: supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r;
2575: }
2576: DMPlexSetSupport(rdm, newp, supportNew);
2577: #if 1
2578: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2579: for (p = 0; p < size; ++p) {
2580: 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);
2581: }
2582: #endif
2583: }
2584: /* Cell hybrid faces have 2 vertices and 2 cells */
2585: for (c = cMax; c < cEnd; ++c) {
2586: const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (fEnd - fMax) + (c - cMax);
2587: const PetscInt *cone;
2588: PetscInt coneNew[2], supportNew[2];
2590: DMPlexGetCone(dm, c, &cone);
2591: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart);
2592: coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart);
2593: DMPlexSetCone(rdm, newp, coneNew);
2594: #if 1
2595: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2596: for (p = 0; p < 2; ++p) {
2597: 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);
2598: }
2599: #endif
2600: supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0;
2601: supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1;
2602: DMPlexSetSupport(rdm, newp, supportNew);
2603: #if 1
2604: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2605: for (p = 0; p < 2; ++p) {
2606: 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);
2607: }
2608: #endif
2609: }
2610: /* Old vertices have identical supports */
2611: for (v = vStart; v < vEnd; ++v) {
2612: const PetscInt newp = vStartNew + (v - vStart);
2613: const PetscInt *support, *cone;
2614: PetscInt size, s;
2616: DMPlexGetSupportSize(dm, v, &size);
2617: DMPlexGetSupport(dm, v, &support);
2618: for (s = 0; s < size; ++s) {
2619: if (support[s] >= fMax) {
2620: supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (support[s] - fMax);
2621: } else {
2622: PetscInt r = 0;
2624: DMPlexGetCone(dm, support[s], &cone);
2625: if (cone[1] == v) r = 1;
2626: supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
2627: }
2628: }
2629: DMPlexSetSupport(rdm, newp, supportRef);
2630: #if 1
2631: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
2632: for (p = 0; p < size; ++p) {
2633: 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);
2634: }
2635: #endif
2636: }
2637: /* Face vertices have 2 + cells supports */
2638: for (f = fStart; f < fMax; ++f) {
2639: const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
2640: const PetscInt *cone, *support;
2641: PetscInt size, s;
2643: DMPlexGetSupportSize(dm, f, &size);
2644: DMPlexGetSupport(dm, f, &support);
2645: supportRef[0] = fStartNew + (f - fStart)*2 + 0;
2646: supportRef[1] = fStartNew + (f - fStart)*2 + 1;
2647: for (s = 0; s < size; ++s) {
2648: PetscInt r = 0;
2650: DMPlexGetCone(dm, support[s], &cone);
2651: if (support[s] >= cMax) {
2652: supportRef[2+s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (fEnd - fMax) + (support[s] - cMax);
2653: } else {
2654: if (cone[1] == f) r = 1;
2655: else if (cone[2] == f) r = 2;
2656: else if (cone[3] == f) r = 3;
2657: supportRef[2+s] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*4 + r;
2658: }
2659: }
2660: DMPlexSetSupport(rdm, newp, supportRef);
2661: #if 1
2662: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
2663: for (p = 0; p < 2+size; ++p) {
2664: 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);
2665: }
2666: #endif
2667: }
2668: /* Cell vertices have 4 supports */
2669: for (c = cStart; c < cMax; ++c) {
2670: const PetscInt newp = vStartNew + (vEnd - vStart) + (fMax - fStart) + (c - cStart);
2671: PetscInt supportNew[4];
2673: for (r = 0; r < 4; ++r) {
2674: supportNew[r] = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + r;
2675: }
2676: DMPlexSetSupport(rdm, newp, supportNew);
2677: }
2678: PetscFree(supportRef);
2679: break;
2680: case REFINER_SIMPLEX_3D:
2681: /* All cells have 4 faces: Tet face order is prescribed in DMPlexGetFaces_Internal() */
2682: DMPlexGetRawFaces_Internal(dm, 3, 4, cellInd, NULL, NULL, &faces);
2683: for (c = cStart; c < cEnd; ++c) {
2684: const PetscInt newp = cStartNew + (c - cStart)*8;
2685: const PetscInt *cone, *ornt;
2686: PetscInt coneNew[4], orntNew[4];
2688: DMPlexGetCone(dm, c, &cone);
2689: DMPlexGetConeOrientation(dm, c, &ornt);
2690: /* A tetrahedron: {0, a, c, d} */
2691: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 0); /* A */
2692: orntNew[0] = ornt[0];
2693: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 0); /* A */
2694: orntNew[1] = ornt[1];
2695: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 0); /* A */
2696: orntNew[2] = ornt[2];
2697: coneNew[3] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 0;
2698: orntNew[3] = 0;
2699: DMPlexSetCone(rdm, newp+0, coneNew);
2700: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
2701: #if 1
2702: 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);
2703: for (p = 0; p < 4; ++p) {
2704: 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);
2705: }
2706: #endif
2707: /* B tetrahedron: {a, 1, b, e} */
2708: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 1); /* B */
2709: orntNew[0] = ornt[0];
2710: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 2); /* C */
2711: orntNew[1] = ornt[1];
2712: coneNew[2] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 1;
2713: orntNew[2] = 0;
2714: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 1); /* B */
2715: orntNew[3] = ornt[3];
2716: DMPlexSetCone(rdm, newp+1, coneNew);
2717: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
2718: #if 1
2719: 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);
2720: for (p = 0; p < 4; ++p) {
2721: 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);
2722: }
2723: #endif
2724: /* C tetrahedron: {c, b, 2, f} */
2725: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 2); /* C */
2726: orntNew[0] = ornt[0];
2727: coneNew[1] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 2;
2728: orntNew[1] = 0;
2729: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 1); /* B */
2730: orntNew[2] = ornt[2];
2731: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 0); /* A */
2732: orntNew[3] = ornt[3];
2733: DMPlexSetCone(rdm, newp+2, coneNew);
2734: DMPlexSetConeOrientation(rdm, newp+2, orntNew);
2735: #if 1
2736: 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);
2737: for (p = 0; p < 4; ++p) {
2738: 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);
2739: }
2740: #endif
2741: /* D tetrahedron: {d, e, f, 3} */
2742: coneNew[0] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 3;
2743: orntNew[0] = 0;
2744: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 1); /* B */
2745: orntNew[1] = ornt[1];
2746: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 2); /* C */
2747: orntNew[2] = ornt[2];
2748: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 2); /* C */
2749: orntNew[3] = ornt[3];
2750: DMPlexSetCone(rdm, newp+3, coneNew);
2751: DMPlexSetConeOrientation(rdm, newp+3, orntNew);
2752: #if 1
2753: 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);
2754: for (p = 0; p < 4; ++p) {
2755: 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);
2756: }
2757: #endif
2758: /* A' tetrahedron: {c, d, a, f} */
2759: coneNew[0] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 0;
2760: orntNew[0] = -3;
2761: coneNew[1] = fStartNew + (cone[2] - fStart)*4 + 3;
2762: orntNew[1] = ornt[2] < 0 ? -(GetTriMidEdge_Static(ornt[2], 0)+1) : GetTriMidEdge_Static(ornt[2], 0);
2763: coneNew[2] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 5;
2764: orntNew[2] = 0;
2765: coneNew[3] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 4;
2766: orntNew[3] = 2;
2767: DMPlexSetCone(rdm, newp+4, coneNew);
2768: DMPlexSetConeOrientation(rdm, newp+4, orntNew);
2769: #if 1
2770: 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);
2771: for (p = 0; p < 4; ++p) {
2772: 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);
2773: }
2774: #endif
2775: /* B' tetrahedron: {e, b, a, f} */
2776: coneNew[0] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 1;
2777: orntNew[0] = -2;
2778: coneNew[1] = fStartNew + (cone[3] - fStart)*4 + 3;
2779: orntNew[1] = ornt[3] < 0 ? -(GetTriMidEdge_Static(ornt[3], 1)+1) : GetTriMidEdge_Static(ornt[3], 1);
2780: coneNew[2] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 6;
2781: orntNew[2] = 0;
2782: coneNew[3] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 7;
2783: orntNew[3] = 0;
2784: DMPlexSetCone(rdm, newp+5, coneNew);
2785: DMPlexSetConeOrientation(rdm, newp+5, orntNew);
2786: #if 1
2787: 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);
2788: for (p = 0; p < 4; ++p) {
2789: 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);
2790: }
2791: #endif
2792: /* C' tetrahedron: {f, a, c, b} */
2793: coneNew[0] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 5;
2794: orntNew[0] = -2;
2795: coneNew[1] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 7;
2796: orntNew[1] = -2;
2797: coneNew[2] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 2;
2798: orntNew[2] = -1;
2799: coneNew[3] = fStartNew + (cone[0] - fStart)*4 + 3;
2800: orntNew[3] = ornt[0] < 0 ? -(GetTriMidEdge_Static(ornt[0], 2)+1) : GetTriMidEdge_Static(ornt[0], 2);
2801: DMPlexSetCone(rdm, newp+6, coneNew);
2802: DMPlexSetConeOrientation(rdm, newp+6, orntNew);
2803: #if 1
2804: 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);
2805: for (p = 0; p < 4; ++p) {
2806: 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);
2807: }
2808: #endif
2809: /* D' tetrahedron: {f, a, e, d} */
2810: coneNew[0] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 6;
2811: orntNew[0] = -2;
2812: coneNew[1] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 4;
2813: orntNew[1] = -1;
2814: coneNew[2] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 3;
2815: orntNew[2] = -2;
2816: coneNew[3] = fStartNew + (cone[1] - fStart)*4 + 3;
2817: orntNew[3] = ornt[1] < 0 ? -(GetTriMidEdge_Static(ornt[1], 1)+1) : GetTriMidEdge_Static(ornt[1], 1);
2818: DMPlexSetCone(rdm, newp+7, coneNew);
2819: DMPlexSetConeOrientation(rdm, newp+7, orntNew);
2820: #if 1
2821: 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);
2822: for (p = 0; p < 4; ++p) {
2823: 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);
2824: }
2825: #endif
2826: }
2827: /* Split faces have 3 edges and the same cells as the parent */
2828: DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
2829: PetscMalloc1(2 + maxSupportSize*2, &supportRef);
2830: for (f = fStart; f < fEnd; ++f) {
2831: const PetscInt newp = fStartNew + (f - fStart)*4;
2832: const PetscInt *cone, *ornt, *support;
2833: PetscInt coneNew[3], orntNew[3], coneSize, supportSize, s;
2835: DMPlexGetCone(dm, f, &cone);
2836: DMPlexGetConeOrientation(dm, f, &ornt);
2837: /* A triangle */
2838: coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1 : 0);
2839: orntNew[0] = ornt[0];
2840: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 2;
2841: orntNew[1] = -2;
2842: coneNew[2] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 0 : 1);
2843: orntNew[2] = ornt[2];
2844: DMPlexSetCone(rdm, newp+0, coneNew);
2845: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
2846: #if 1
2847: 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);
2848: for (p = 0; p < 3; ++p) {
2849: 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);
2850: }
2851: #endif
2852: /* B triangle */
2853: coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 0 : 1);
2854: orntNew[0] = ornt[0];
2855: coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1 : 0);
2856: orntNew[1] = ornt[1];
2857: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 0;
2858: orntNew[2] = -2;
2859: DMPlexSetCone(rdm, newp+1, coneNew);
2860: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
2861: #if 1
2862: 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);
2863: for (p = 0; p < 3; ++p) {
2864: 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);
2865: }
2866: #endif
2867: /* C triangle */
2868: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 1;
2869: orntNew[0] = -2;
2870: coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 0 : 1);
2871: orntNew[1] = ornt[1];
2872: coneNew[2] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 1 : 0);
2873: orntNew[2] = ornt[2];
2874: DMPlexSetCone(rdm, newp+2, coneNew);
2875: DMPlexSetConeOrientation(rdm, newp+2, orntNew);
2876: #if 1
2877: 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);
2878: for (p = 0; p < 3; ++p) {
2879: 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);
2880: }
2881: #endif
2882: /* D triangle */
2883: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 0;
2884: orntNew[0] = 0;
2885: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 1;
2886: orntNew[1] = 0;
2887: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 2;
2888: orntNew[2] = 0;
2889: DMPlexSetCone(rdm, newp+3, coneNew);
2890: DMPlexSetConeOrientation(rdm, newp+3, orntNew);
2891: #if 1
2892: 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);
2893: for (p = 0; p < 3; ++p) {
2894: 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);
2895: }
2896: #endif
2897: DMPlexGetSupportSize(dm, f, &supportSize);
2898: DMPlexGetSupport(dm, f, &support);
2899: for (r = 0; r < 4; ++r) {
2900: for (s = 0; s < supportSize; ++s) {
2901: PetscInt subf;
2902: DMPlexGetConeSize(dm, support[s], &coneSize);
2903: DMPlexGetCone(dm, support[s], &cone);
2904: DMPlexGetConeOrientation(dm, support[s], &ornt);
2905: for (c = 0; c < coneSize; ++c) {
2906: if (cone[c] == f) break;
2907: }
2908: subf = GetTriSubfaceInverse_Static(ornt[c], r);
2909: supportRef[s] = cStartNew + (support[s] - cStart)*8 + (r==3 ? (c+2)%4 + 4 : faces[c*3+subf]);
2910: }
2911: DMPlexSetSupport(rdm, newp+r, supportRef);
2912: #if 1
2913: 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);
2914: for (p = 0; p < supportSize; ++p) {
2915: 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);
2916: }
2917: #endif
2918: }
2919: }
2920: /* Interior faces have 3 edges and 2 cells */
2921: for (c = cStart; c < cEnd; ++c) {
2922: PetscInt newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8;
2923: const PetscInt *cone, *ornt;
2924: PetscInt coneNew[3], orntNew[3];
2925: PetscInt supportNew[2];
2927: DMPlexGetCone(dm, c, &cone);
2928: DMPlexGetConeOrientation(dm, c, &ornt);
2929: /* Face A: {c, a, d} */
2930: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 2);
2931: orntNew[0] = ornt[0] < 0 ? -2 : 0;
2932: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 2);
2933: orntNew[1] = ornt[1] < 0 ? -2 : 0;
2934: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 2);
2935: orntNew[2] = ornt[2] < 0 ? -2 : 0;
2936: DMPlexSetCone(rdm, newp, coneNew);
2937: DMPlexSetConeOrientation(rdm, newp, orntNew);
2938: #if 1
2939: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2940: for (p = 0; p < 3; ++p) {
2941: 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);
2942: }
2943: #endif
2944: supportNew[0] = (c - cStart)*8 + 0;
2945: supportNew[1] = (c - cStart)*8 + 0+4;
2946: DMPlexSetSupport(rdm, newp, supportNew);
2947: #if 1
2948: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2949: for (p = 0; p < 2; ++p) {
2950: 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);
2951: }
2952: #endif
2953: ++newp;
2954: /* Face B: {a, b, e} */
2955: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 0);
2956: orntNew[0] = ornt[0] < 0 ? -2 : 0;
2957: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 0);
2958: orntNew[1] = ornt[3] < 0 ? -2 : 0;
2959: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 1);
2960: orntNew[2] = ornt[1] < 0 ? -2 : 0;
2961: DMPlexSetCone(rdm, newp, coneNew);
2962: DMPlexSetConeOrientation(rdm, newp, orntNew);
2963: #if 1
2964: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2965: for (p = 0; p < 3; ++p) {
2966: 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);
2967: }
2968: #endif
2969: supportNew[0] = (c - cStart)*8 + 1;
2970: supportNew[1] = (c - cStart)*8 + 1+4;
2971: DMPlexSetSupport(rdm, newp, supportNew);
2972: #if 1
2973: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2974: for (p = 0; p < 2; ++p) {
2975: 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);
2976: }
2977: #endif
2978: ++newp;
2979: /* Face C: {c, f, b} */
2980: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 0);
2981: orntNew[0] = ornt[2] < 0 ? -2 : 0;
2982: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 2);
2983: orntNew[1] = ornt[3] < 0 ? -2 : 0;
2984: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 1);
2985: orntNew[2] = ornt[0] < 0 ? -2 : 0;
2986: DMPlexSetCone(rdm, newp, coneNew);
2987: DMPlexSetConeOrientation(rdm, newp, orntNew);
2988: #if 1
2989: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2990: for (p = 0; p < 3; ++p) {
2991: 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);
2992: }
2993: #endif
2994: supportNew[0] = (c - cStart)*8 + 2;
2995: supportNew[1] = (c - cStart)*8 + 2+4;
2996: DMPlexSetSupport(rdm, newp, supportNew);
2997: #if 1
2998: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2999: for (p = 0; p < 2; ++p) {
3000: 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);
3001: }
3002: #endif
3003: ++newp;
3004: /* Face D: {d, e, f} */
3005: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 0);
3006: orntNew[0] = ornt[1] < 0 ? -2 : 0;
3007: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 1);
3008: orntNew[1] = ornt[3] < 0 ? -2 : 0;
3009: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 1);
3010: orntNew[2] = ornt[2] < 0 ? -2 : 0;
3011: DMPlexSetCone(rdm, newp, coneNew);
3012: DMPlexSetConeOrientation(rdm, newp, orntNew);
3013: #if 1
3014: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3015: for (p = 0; p < 3; ++p) {
3016: 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);
3017: }
3018: #endif
3019: supportNew[0] = (c - cStart)*8 + 3;
3020: supportNew[1] = (c - cStart)*8 + 3+4;
3021: DMPlexSetSupport(rdm, newp, supportNew);
3022: #if 1
3023: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3024: for (p = 0; p < 2; ++p) {
3025: 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);
3026: }
3027: #endif
3028: ++newp;
3029: /* Face E: {d, f, a} */
3030: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 1);
3031: orntNew[0] = ornt[2] < 0 ? 0 : -2;
3032: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
3033: orntNew[1] = -2;
3034: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 2);
3035: orntNew[2] = ornt[1] < 0 ? -2 : 0;
3036: DMPlexSetCone(rdm, newp, coneNew);
3037: DMPlexSetConeOrientation(rdm, newp, orntNew);
3038: #if 1
3039: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3040: for (p = 0; p < 3; ++p) {
3041: 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);
3042: }
3043: #endif
3044: supportNew[0] = (c - cStart)*8 + 0+4;
3045: supportNew[1] = (c - cStart)*8 + 3+4;
3046: DMPlexSetSupport(rdm, newp, supportNew);
3047: #if 1
3048: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3049: for (p = 0; p < 2; ++p) {
3050: 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);
3051: }
3052: #endif
3053: ++newp;
3054: /* Face F: {c, a, f} */
3055: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 2);
3056: orntNew[0] = ornt[0] < 0 ? -2 : 0;
3057: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
3058: orntNew[1] = 0;
3059: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 0);
3060: orntNew[2] = ornt[2] < 0 ? 0 : -2;
3061: DMPlexSetCone(rdm, newp, coneNew);
3062: DMPlexSetConeOrientation(rdm, newp, orntNew);
3063: #if 1
3064: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3065: for (p = 0; p < 3; ++p) {
3066: 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);
3067: }
3068: #endif
3069: supportNew[0] = (c - cStart)*8 + 0+4;
3070: supportNew[1] = (c - cStart)*8 + 2+4;
3071: DMPlexSetSupport(rdm, newp, supportNew);
3072: #if 1
3073: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3074: for (p = 0; p < 2; ++p) {
3075: 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);
3076: }
3077: #endif
3078: ++newp;
3079: /* Face G: {e, a, f} */
3080: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 1);
3081: orntNew[0] = ornt[1] < 0 ? -2 : 0;
3082: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
3083: orntNew[1] = 0;
3084: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 1);
3085: orntNew[2] = ornt[3] < 0 ? 0 : -2;
3086: DMPlexSetCone(rdm, newp, coneNew);
3087: DMPlexSetConeOrientation(rdm, newp, orntNew);
3088: #if 1
3089: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3090: for (p = 0; p < 3; ++p) {
3091: 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);
3092: }
3093: #endif
3094: supportNew[0] = (c - cStart)*8 + 1+4;
3095: supportNew[1] = (c - cStart)*8 + 3+4;
3096: DMPlexSetSupport(rdm, newp, supportNew);
3097: #if 1
3098: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3099: for (p = 0; p < 2; ++p) {
3100: 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);
3101: }
3102: #endif
3103: ++newp;
3104: /* Face H: {a, b, f} */
3105: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 0);
3106: orntNew[0] = ornt[0] < 0 ? -2 : 0;
3107: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 2);
3108: orntNew[1] = ornt[3] < 0 ? 0 : -2;
3109: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
3110: orntNew[2] = -2;
3111: DMPlexSetCone(rdm, newp, coneNew);
3112: DMPlexSetConeOrientation(rdm, newp, orntNew);
3113: #if 1
3114: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3115: for (p = 0; p < 3; ++p) {
3116: 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);
3117: }
3118: #endif
3119: supportNew[0] = (c - cStart)*8 + 1+4;
3120: supportNew[1] = (c - cStart)*8 + 2+4;
3121: DMPlexSetSupport(rdm, newp, supportNew);
3122: #if 1
3123: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
3124: for (p = 0; p < 2; ++p) {
3125: 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);
3126: }
3127: #endif
3128: ++newp;
3129: }
3130: /* Split Edges have 2 vertices and the same faces as the parent */
3131: for (e = eStart; e < eEnd; ++e) {
3132: const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);
3134: for (r = 0; r < 2; ++r) {
3135: const PetscInt newp = eStartNew + (e - eStart)*2 + r;
3136: const PetscInt *cone, *ornt, *support;
3137: PetscInt coneNew[2], coneSize, c, supportSize, s;
3139: DMPlexGetCone(dm, e, &cone);
3140: coneNew[0] = vStartNew + (cone[0] - vStart);
3141: coneNew[1] = vStartNew + (cone[1] - vStart);
3142: coneNew[(r+1)%2] = newv;
3143: DMPlexSetCone(rdm, newp, coneNew);
3144: #if 1
3145: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
3146: for (p = 0; p < 2; ++p) {
3147: 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);
3148: }
3149: #endif
3150: DMPlexGetSupportSize(dm, e, &supportSize);
3151: DMPlexGetSupport(dm, e, &support);
3152: for (s = 0; s < supportSize; ++s) {
3153: DMPlexGetConeSize(dm, support[s], &coneSize);
3154: DMPlexGetCone(dm, support[s], &cone);
3155: DMPlexGetConeOrientation(dm, support[s], &ornt);
3156: for (c = 0; c < coneSize; ++c) {
3157: if (cone[c] == e) break;
3158: }
3159: supportRef[s] = fStartNew + (support[s] - fStart)*4 + (c + (ornt[c] < 0 ? 1-r : r))%3;
3160: }
3161: DMPlexSetSupport(rdm, newp, supportRef);
3162: #if 1
3163: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
3164: for (p = 0; p < supportSize; ++p) {
3165: 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);
3166: }
3167: #endif
3168: }
3169: }
3170: /* Face edges have 2 vertices and 2+cells*(1/2) faces */
3171: for (f = fStart; f < fEnd; ++f) {
3172: const PetscInt *cone, *ornt, *support;
3173: PetscInt coneSize, supportSize, s;
3175: DMPlexGetSupportSize(dm, f, &supportSize);
3176: DMPlexGetSupport(dm, f, &support);
3177: for (r = 0; r < 3; ++r) {
3178: const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + r;
3179: PetscInt coneNew[2], intFaces = 0, er, eint[4] = {1, 0, 2, 0};
3180: PetscInt fint[24] = { 1, 7, -1, -1, 0, 5,
3181: -1, -1, 1, 6, 0, 4,
3182: 2, 5, 3, 4, -1, -1,
3183: -1, -1, 3, 6, 2, 7};
3185: DMPlexGetCone(dm, f, &cone);
3186: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[(r+0)%3] - eStart);
3187: coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - eStart);
3188: DMPlexSetCone(rdm, newp, coneNew);
3189: #if 1
3190: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
3191: for (p = 0; p < 2; ++p) {
3192: 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);
3193: }
3194: #endif
3195: supportRef[0] = fStartNew + (f - fStart)*4 + (r+1)%3;
3196: supportRef[1] = fStartNew + (f - fStart)*4 + 3;
3197: for (s = 0; s < supportSize; ++s) {
3198: DMPlexGetConeSize(dm, support[s], &coneSize);
3199: DMPlexGetCone(dm, support[s], &cone);
3200: DMPlexGetConeOrientation(dm, support[s], &ornt);
3201: for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
3202: /* Here we want to determine whether edge newp contains a vertex which is part of the cross-tet edge */
3203: er = GetTriMidEdgeInverse_Static(ornt[c], r);
3204: if (er == eint[c]) {
3205: supportRef[2+intFaces++] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*8 + (c + 2)%4;
3206: } else {
3207: supportRef[2+intFaces++] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*8 + fint[(c*3 + er)*2 + 0];
3208: supportRef[2+intFaces++] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*8 + fint[(c*3 + er)*2 + 1];
3209: }
3210: }
3211: DMPlexSetSupport(rdm, newp, supportRef);
3212: #if 1
3213: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
3214: for (p = 0; p < intFaces; ++p) {
3215: 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);
3216: }
3217: #endif
3218: }
3219: }
3220: /* Interior edges have 2 vertices and 4 faces */
3221: for (c = cStart; c < cEnd; ++c) {
3222: const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
3223: const PetscInt *cone, *ornt, *fcone;
3224: PetscInt coneNew[2], supportNew[4], find;
3226: DMPlexGetCone(dm, c, &cone);
3227: DMPlexGetConeOrientation(dm, c, &ornt);
3228: DMPlexGetCone(dm, cone[0], &fcone);
3229: find = GetTriEdge_Static(ornt[0], 0);
3230: coneNew[0] = vStartNew + (vEnd - vStart) + (fcone[find] - eStart);
3231: DMPlexGetCone(dm, cone[2], &fcone);
3232: find = GetTriEdge_Static(ornt[2], 1);
3233: coneNew[1] = vStartNew + (vEnd - vStart) + (fcone[find] - eStart);
3234: DMPlexSetCone(rdm, newp, coneNew);
3235: #if 1
3236: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
3237: for (p = 0; p < 2; ++p) {
3238: 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);
3239: }
3240: #endif
3241: supportNew[0] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 4;
3242: supportNew[1] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 5;
3243: supportNew[2] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 6;
3244: supportNew[3] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 7;
3245: DMPlexSetSupport(rdm, newp, supportNew);
3246: #if 1
3247: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
3248: for (p = 0; p < 4; ++p) {
3249: 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);
3250: }
3251: #endif
3252: }
3253: /* Old vertices have identical supports */
3254: for (v = vStart; v < vEnd; ++v) {
3255: const PetscInt newp = vStartNew + (v - vStart);
3256: const PetscInt *support, *cone;
3257: PetscInt size, s;
3259: DMPlexGetSupportSize(dm, v, &size);
3260: DMPlexGetSupport(dm, v, &support);
3261: for (s = 0; s < size; ++s) {
3262: PetscInt r = 0;
3264: DMPlexGetCone(dm, support[s], &cone);
3265: if (cone[1] == v) r = 1;
3266: supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
3267: }
3268: DMPlexSetSupport(rdm, newp, supportRef);
3269: #if 1
3270: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
3271: for (p = 0; p < size; ++p) {
3272: 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);
3273: }
3274: #endif
3275: }
3276: /* Edge vertices have 2 + face*2 + 0/1 supports */
3277: for (e = eStart; e < eEnd; ++e) {
3278: const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
3279: const PetscInt *cone, *support;
3280: PetscInt *star = NULL, starSize, cellSize = 0, coneSize, size, s;
3282: DMPlexGetSupportSize(dm, e, &size);
3283: DMPlexGetSupport(dm, e, &support);
3284: supportRef[0] = eStartNew + (e - eStart)*2 + 0;
3285: supportRef[1] = eStartNew + (e - eStart)*2 + 1;
3286: for (s = 0; s < size; ++s) {
3287: PetscInt r = 0;
3289: DMPlexGetConeSize(dm, support[s], &coneSize);
3290: DMPlexGetCone(dm, support[s], &cone);
3291: for (r = 0; r < coneSize; ++r) {if (cone[r] == e) break;}
3292: supportRef[2+s*2+0] = eStartNew + (eEnd - eStart)*2 + (support[s] - fStart)*3 + (r+0)%3;
3293: supportRef[2+s*2+1] = eStartNew + (eEnd - eStart)*2 + (support[s] - fStart)*3 + (r+2)%3;
3294: }
3295: DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
3296: for (s = 0; s < starSize*2; s += 2) {
3297: const PetscInt *cone, *ornt;
3298: PetscInt e01, e23;
3300: if ((star[s] >= cStart) && (star[s] < cEnd)) {
3301: /* Check edge 0-1 */
3302: DMPlexGetCone(dm, star[s], &cone);
3303: DMPlexGetConeOrientation(dm, star[s], &ornt);
3304: DMPlexGetCone(dm, cone[0], &cone);
3305: e01 = cone[GetTriEdge_Static(ornt[0], 0)];
3306: /* Check edge 2-3 */
3307: DMPlexGetCone(dm, star[s], &cone);
3308: DMPlexGetConeOrientation(dm, star[s], &ornt);
3309: DMPlexGetCone(dm, cone[2], &cone);
3310: e23 = cone[GetTriEdge_Static(ornt[2], 1)];
3311: if ((e01 == e) || (e23 == e)) {supportRef[2+size*2+cellSize++] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (star[s] - cStart);}
3312: }
3313: }
3314: DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
3315: DMPlexSetSupport(rdm, newp, supportRef);
3316: #if 1
3317: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
3318: for (p = 0; p < 2+size*2+cellSize; ++p) {
3319: 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);
3320: }
3321: #endif
3322: }
3323: PetscFree(supportRef);
3324: DMPlexRestoreFaces_Internal(dm, 3, cStart, NULL, NULL, &faces);
3325: break;
3326: case REFINER_HYBRID_SIMPLEX_3D:
3327: DMPlexGetHybridBounds(rdm, &cMaxNew, &fMaxNew, &eMaxNew, NULL);
3328: /* Interior cells have 4 faces: Tet face order is prescribed in DMPlexGetFaces_Internal() */
3329: DMPlexGetRawFaces_Internal(dm, 3, 4, cellInd, NULL, NULL, &faces);
3330: for (c = cStart; c < cMax; ++c) {
3331: const PetscInt newp = cStartNew + (c - cStart)*8;
3332: const PetscInt *cone, *ornt;
3333: PetscInt coneNew[4], orntNew[4];
3335: DMPlexGetCone(dm, c, &cone);
3336: DMPlexGetConeOrientation(dm, c, &ornt);
3337: /* A tetrahedron: {0, a, c, d} */
3338: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 0); /* A */
3339: orntNew[0] = ornt[0];
3340: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 0); /* A */
3341: orntNew[1] = ornt[1];
3342: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 0); /* A */
3343: orntNew[2] = ornt[2];
3344: coneNew[3] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 0;
3345: orntNew[3] = 0;
3346: DMPlexSetCone(rdm, newp+0, coneNew);
3347: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
3348: #if 1
3349: 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);
3350: for (p = 0; p < 4; ++p) {
3351: 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);
3352: }
3353: #endif
3354: /* B tetrahedron: {a, 1, b, e} */
3355: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 1); /* B */
3356: orntNew[0] = ornt[0];
3357: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 2); /* C */
3358: orntNew[1] = ornt[1];
3359: coneNew[2] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 1;
3360: orntNew[2] = 0;
3361: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 1); /* B */
3362: orntNew[3] = ornt[3];
3363: DMPlexSetCone(rdm, newp+1, coneNew);
3364: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
3365: #if 1
3366: 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);
3367: for (p = 0; p < 4; ++p) {
3368: 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);
3369: }
3370: #endif
3371: /* C tetrahedron: {c, b, 2, f} */
3372: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 2); /* C */
3373: orntNew[0] = ornt[0];
3374: coneNew[1] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 2;
3375: orntNew[1] = 0;
3376: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 1); /* B */
3377: orntNew[2] = ornt[2];
3378: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 0); /* A */
3379: orntNew[3] = ornt[3];
3380: DMPlexSetCone(rdm, newp+2, coneNew);
3381: DMPlexSetConeOrientation(rdm, newp+2, orntNew);
3382: #if 1
3383: 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);
3384: for (p = 0; p < 4; ++p) {
3385: 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);
3386: }
3387: #endif
3388: /* D tetrahedron: {d, e, f, 3} */
3389: coneNew[0] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 3;
3390: orntNew[0] = 0;
3391: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 1); /* B */
3392: orntNew[1] = ornt[1];
3393: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 2); /* C */
3394: orntNew[2] = ornt[2];
3395: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 2); /* C */
3396: orntNew[3] = ornt[3];
3397: DMPlexSetCone(rdm, newp+3, coneNew);
3398: DMPlexSetConeOrientation(rdm, newp+3, orntNew);
3399: #if 1
3400: 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);
3401: for (p = 0; p < 4; ++p) {
3402: 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);
3403: }
3404: #endif
3405: /* A' tetrahedron: {d, a, c, f} */
3406: coneNew[0] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 0;
3407: orntNew[0] = -3;
3408: coneNew[1] = fStartNew + (cone[2] - fStart)*4 + 3;
3409: orntNew[1] = ornt[2] < 0 ? -(GetTriMidEdge_Static(ornt[2], 0)+1) : GetTriMidEdge_Static(ornt[2], 0);
3410: coneNew[2] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 5;
3411: orntNew[2] = 0;
3412: coneNew[3] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 4;
3413: orntNew[3] = 2;
3414: DMPlexSetCone(rdm, newp+4, coneNew);
3415: DMPlexSetConeOrientation(rdm, newp+4, orntNew);
3416: #if 1
3417: 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);
3418: for (p = 0; p < 4; ++p) {
3419: 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);
3420: }
3421: #endif
3422: /* B' tetrahedron: {e, b, a, f} */
3423: coneNew[0] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 1;
3424: orntNew[0] = -3;
3425: coneNew[1] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 6;
3426: orntNew[1] = 1;
3427: coneNew[2] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 7;
3428: orntNew[2] = 0;
3429: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + 3;
3430: orntNew[3] = ornt[3] < 0 ? -(GetTriMidEdge_Static(ornt[3], 0)+1) : GetTriMidEdge_Static(ornt[3], 0);
3431: DMPlexSetCone(rdm, newp+5, coneNew);
3432: DMPlexSetConeOrientation(rdm, newp+5, orntNew);
3433: #if 1
3434: 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);
3435: for (p = 0; p < 4; ++p) {
3436: 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);
3437: }
3438: #endif
3439: /* C' tetrahedron: {b, f, c, a} */
3440: coneNew[0] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 2;
3441: orntNew[0] = -3;
3442: coneNew[1] = fStartNew + (cone[0] - fStart)*4 + 3;
3443: orntNew[1] = ornt[0] < 0 ? -(GetTriMidEdge_Static(ornt[0], 2)+1) : GetTriMidEdge_Static(ornt[0], 2);
3444: coneNew[2] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 5;
3445: orntNew[2] = -3;
3446: coneNew[3] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 7;
3447: orntNew[3] = -2;
3448: DMPlexSetCone(rdm, newp+6, coneNew);
3449: DMPlexSetConeOrientation(rdm, newp+6, orntNew);
3450: #if 1
3451: 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);
3452: for (p = 0; p < 4; ++p) {
3453: 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);
3454: }
3455: #endif
3456: /* D' tetrahedron: {f, e, d, a} */
3457: coneNew[0] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 3;
3458: orntNew[0] = -3;
3459: coneNew[1] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 4;
3460: orntNew[1] = -3;
3461: coneNew[2] = fStartNew + (cone[1] - fStart)*4 + 3;
3462: orntNew[2] = ornt[1] < 0 ? -(GetTriMidEdge_Static(ornt[1], 0)+1) : GetTriMidEdge_Static(ornt[1], 0);
3463: coneNew[3] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 6;
3464: orntNew[3] = -3;
3465: DMPlexSetCone(rdm, newp+7, coneNew);
3466: DMPlexSetConeOrientation(rdm, newp+7, orntNew);
3467: #if 1
3468: 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);
3469: for (p = 0; p < 4; ++p) {
3470: 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);
3471: }
3472: #endif
3473: }
3474: /* Hybrid cells have 5 faces */
3475: for (c = cMax; c < cEnd; ++c) {
3476: const PetscInt newp = cStartNew + (cMax - cStart)*8 + (c - cMax)*4;
3477: const PetscInt *cone, *ornt, *fornt;
3478: PetscInt coneNew[5], orntNew[5], o, of, i;
3480: DMPlexGetCone(dm, c, &cone);
3481: DMPlexGetConeOrientation(dm, c, &ornt);
3482: DMPlexGetConeOrientation(dm, cone[0], &fornt);
3483: o = ornt[0] < 0 ? -1 : 1;
3484: for (r = 0; r < 3; ++r) {
3485: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], r);
3486: orntNew[0] = ornt[0];
3487: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], r);
3488: orntNew[1] = ornt[1];
3489: of = fornt[GetTriEdge_Static(ornt[0], r)] < 0 ? -1 : 1;
3490: i = GetTriEdgeInverse_Static(ornt[0], r) + 2;
3491: coneNew[i] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (cone[2+GetTriEdge_Static(ornt[0], r)] - fMax)*2 + (o*of < 0 ? 1 : 0);
3492: orntNew[i] = 0;
3493: i = GetTriEdgeInverse_Static(ornt[0], (r+1)%3) + 2;
3494: coneNew[i] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + GetTriSubface_Static(ornt[0], r);
3495: orntNew[i] = 0;
3496: of = fornt[GetTriEdge_Static(ornt[0], (r+2)%3)] < 0 ? -1 : 1;
3497: i = GetTriEdgeInverse_Static(ornt[0], (r+2)%3) + 2;
3498: 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);
3499: orntNew[i] = 0;
3500: DMPlexSetCone(rdm, newp+r, coneNew);
3501: DMPlexSetConeOrientation(rdm, newp+r, orntNew);
3502: #if 1
3503: 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);
3504: for (p = 0; p < 2; ++p) {
3505: 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);
3506: }
3507: for (p = 2; p < 5; ++p) {
3508: 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);
3509: }
3510: #endif
3511: }
3512: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + 3;
3513: orntNew[0] = 0;
3514: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + 3;
3515: orntNew[1] = 0;
3516: coneNew[2] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + 1;
3517: orntNew[2] = 0;
3518: coneNew[3] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + 2;
3519: orntNew[3] = 0;
3520: coneNew[4] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + 0;
3521: orntNew[4] = 0;
3522: DMPlexSetCone(rdm, newp+3, coneNew);
3523: DMPlexSetConeOrientation(rdm, newp+3, orntNew);
3524: #if 1
3525: 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);
3526: for (p = 0; p < 2; ++p) {
3527: 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);
3528: }
3529: for (p = 2; p < 5; ++p) {
3530: 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);
3531: }
3532: #endif
3533: }
3534: /* Split faces have 3 edges and the same cells as the parent */
3535: DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
3536: PetscMalloc1(2 + maxSupportSize*2, &supportRef);
3537: for (f = fStart; f < fMax; ++f) {
3538: const PetscInt newp = fStartNew + (f - fStart)*4;
3539: const PetscInt *cone, *ornt, *support;
3540: PetscInt coneNew[3], orntNew[3], coneSize, supportSize, s;
3542: DMPlexGetCone(dm, f, &cone);
3543: DMPlexGetConeOrientation(dm, f, &ornt);
3544: /* A triangle */
3545: coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1 : 0);
3546: orntNew[0] = ornt[0];
3547: coneNew[1] = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + 2;
3548: orntNew[1] = -2;
3549: coneNew[2] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 0 : 1);
3550: orntNew[2] = ornt[2];
3551: DMPlexSetCone(rdm, newp+0, coneNew);
3552: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
3553: #if 1
3554: 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);
3555: for (p = 0; p < 3; ++p) {
3556: 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);
3557: }
3558: #endif
3559: /* B triangle */
3560: coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 0 : 1);
3561: orntNew[0] = ornt[0];
3562: coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1 : 0);
3563: orntNew[1] = ornt[1];
3564: coneNew[2] = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + 0;
3565: orntNew[2] = -2;
3566: DMPlexSetCone(rdm, newp+1, coneNew);
3567: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
3568: #if 1
3569: 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);
3570: for (p = 0; p < 3; ++p) {
3571: 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);
3572: }
3573: #endif
3574: /* C triangle */
3575: coneNew[0] = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + 1;
3576: orntNew[0] = -2;
3577: coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 0 : 1);
3578: orntNew[1] = ornt[1];
3579: coneNew[2] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 1 : 0);
3580: orntNew[2] = ornt[2];
3581: DMPlexSetCone(rdm, newp+2, coneNew);
3582: DMPlexSetConeOrientation(rdm, newp+2, orntNew);
3583: #if 1
3584: 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);
3585: for (p = 0; p < 3; ++p) {
3586: 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);
3587: }
3588: #endif
3589: /* D triangle */
3590: coneNew[0] = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + 0;
3591: orntNew[0] = 0;
3592: coneNew[1] = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + 1;
3593: orntNew[1] = 0;
3594: coneNew[2] = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + 2;
3595: orntNew[2] = 0;
3596: DMPlexSetCone(rdm, newp+3, coneNew);
3597: DMPlexSetConeOrientation(rdm, newp+3, orntNew);
3598: #if 1
3599: 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);
3600: for (p = 0; p < 3; ++p) {
3601: 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);
3602: }
3603: #endif
3604: DMPlexGetSupportSize(dm, f, &supportSize);
3605: DMPlexGetSupport(dm, f, &support);
3606: for (r = 0; r < 4; ++r) {
3607: for (s = 0; s < supportSize; ++s) {
3608: PetscInt subf;
3609: DMPlexGetConeSize(dm, support[s], &coneSize);
3610: DMPlexGetCone(dm, support[s], &cone);
3611: DMPlexGetConeOrientation(dm, support[s], &ornt);
3612: for (c = 0; c < coneSize; ++c) {
3613: if (cone[c] == f) break;
3614: }
3615: subf = GetTriSubfaceInverse_Static(ornt[c], r);
3616: if (support[s] < cMax) {
3617: supportRef[s] = cStartNew + (support[s] - cStart)*8 + (r==3 ? (c+2)%4 + 4 : faces[c*3+subf]);
3618: } else {
3619: supportRef[s] = cStartNew + (cMax - cStart)*8 + (support[s] - cMax)*4 + (r==3 ? r : subf);
3620: }
3621: }
3622: DMPlexSetSupport(rdm, newp+r, supportRef);
3623: #if 1
3624: 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);
3625: for (p = 0; p < supportSize; ++p) {
3626: 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);
3627: }
3628: #endif
3629: }
3630: }
3631: /* Interior cell faces have 3 edges and 2 cells */
3632: for (c = cStart; c < cMax; ++c) {
3633: PetscInt newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*8;
3634: const PetscInt *cone, *ornt;
3635: PetscInt coneNew[3], orntNew[3];
3636: PetscInt supportNew[2];
3638: DMPlexGetCone(dm, c, &cone);
3639: DMPlexGetConeOrientation(dm, c, &ornt);
3640: /* Face A: {c, a, d} */
3641: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 2);
3642: orntNew[0] = ornt[0] < 0 ? -2 : 0;
3643: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 2);
3644: orntNew[1] = ornt[1] < 0 ? -2 : 0;
3645: coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 2);
3646: orntNew[2] = ornt[2] < 0 ? -2 : 0;
3647: DMPlexSetCone(rdm, newp, coneNew);
3648: DMPlexSetConeOrientation(rdm, newp, orntNew);
3649: #if 1
3650: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3651: for (p = 0; p < 3; ++p) {
3652: 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);
3653: }
3654: #endif
3655: supportNew[0] = (c - cStart)*8 + 0;
3656: supportNew[1] = (c - cStart)*8 + 0+4;
3657: DMPlexSetSupport(rdm, newp, supportNew);
3658: #if 1
3659: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3660: for (p = 0; p < 2; ++p) {
3661: 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);
3662: }
3663: #endif
3664: ++newp;
3665: /* Face B: {a, b, e} */
3666: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 0);
3667: orntNew[0] = ornt[0] < 0 ? -2 : 0;
3668: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 0);
3669: orntNew[1] = ornt[3] < 0 ? -2 : 0;
3670: coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 1);
3671: orntNew[2] = ornt[1] < 0 ? -2 : 0;
3672: DMPlexSetCone(rdm, newp, coneNew);
3673: DMPlexSetConeOrientation(rdm, newp, orntNew);
3674: #if 1
3675: 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);
3676: for (p = 0; p < 3; ++p) {
3677: 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);
3678: }
3679: #endif
3680: supportNew[0] = (c - cStart)*8 + 1;
3681: supportNew[1] = (c - cStart)*8 + 1+4;
3682: DMPlexSetSupport(rdm, newp, supportNew);
3683: #if 1
3684: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3685: for (p = 0; p < 2; ++p) {
3686: 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);
3687: }
3688: #endif
3689: ++newp;
3690: /* Face C: {c, f, b} */
3691: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 0);
3692: orntNew[0] = ornt[2] < 0 ? -2 : 0;
3693: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 2);
3694: orntNew[1] = ornt[3] < 0 ? -2 : 0;
3695: coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 1);
3696: orntNew[2] = ornt[0] < 0 ? -2 : 0;
3697: DMPlexSetCone(rdm, newp, coneNew);
3698: DMPlexSetConeOrientation(rdm, newp, orntNew);
3699: #if 1
3700: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3701: for (p = 0; p < 3; ++p) {
3702: 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);
3703: }
3704: #endif
3705: supportNew[0] = (c - cStart)*8 + 2;
3706: supportNew[1] = (c - cStart)*8 + 2+4;
3707: DMPlexSetSupport(rdm, newp, supportNew);
3708: #if 1
3709: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3710: for (p = 0; p < 2; ++p) {
3711: 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);
3712: }
3713: #endif
3714: ++newp;
3715: /* Face D: {d, e, f} */
3716: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 0);
3717: orntNew[0] = ornt[1] < 0 ? -2 : 0;
3718: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 1);
3719: orntNew[1] = ornt[3] < 0 ? -2 : 0;
3720: coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 1);
3721: orntNew[2] = ornt[2] < 0 ? -2 : 0;
3722: DMPlexSetCone(rdm, newp, coneNew);
3723: DMPlexSetConeOrientation(rdm, newp, orntNew);
3724: #if 1
3725: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3726: for (p = 0; p < 3; ++p) {
3727: 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);
3728: }
3729: #endif
3730: supportNew[0] = (c - cStart)*8 + 3;
3731: supportNew[1] = (c - cStart)*8 + 3+4;
3732: DMPlexSetSupport(rdm, newp, supportNew);
3733: #if 1
3734: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3735: for (p = 0; p < 2; ++p) {
3736: 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);
3737: }
3738: #endif
3739: ++newp;
3740: /* Face E: {d, f, a} */
3741: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 1);
3742: orntNew[0] = ornt[2] < 0 ? 0 : -2;
3743: coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
3744: orntNew[1] = -2;
3745: coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 2);
3746: orntNew[2] = ornt[1] < 0 ? -2 : 0;
3747: DMPlexSetCone(rdm, newp, coneNew);
3748: DMPlexSetConeOrientation(rdm, newp, orntNew);
3749: #if 1
3750: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3751: for (p = 0; p < 3; ++p) {
3752: 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);
3753: }
3754: #endif
3755: supportNew[0] = (c - cStart)*8 + 0+4;
3756: supportNew[1] = (c - cStart)*8 + 3+4;
3757: DMPlexSetSupport(rdm, newp, supportNew);
3758: #if 1
3759: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3760: for (p = 0; p < 2; ++p) {
3761: 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);
3762: }
3763: #endif
3764: ++newp;
3765: /* Face F: {c, a, f} */
3766: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 2);
3767: orntNew[0] = ornt[0] < 0 ? -2 : 0;
3768: coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
3769: orntNew[1] = 0;
3770: coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTriMidEdge_Static(ornt[2], 0);
3771: orntNew[2] = ornt[2] < 0 ? 0 : -2;
3772: DMPlexSetCone(rdm, newp, coneNew);
3773: DMPlexSetConeOrientation(rdm, newp, orntNew);
3774: #if 1
3775: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3776: for (p = 0; p < 3; ++p) {
3777: 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);
3778: }
3779: #endif
3780: supportNew[0] = (c - cStart)*8 + 0+4;
3781: supportNew[1] = (c - cStart)*8 + 2+4;
3782: DMPlexSetSupport(rdm, newp, supportNew);
3783: #if 1
3784: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3785: for (p = 0; p < 2; ++p) {
3786: 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);
3787: }
3788: #endif
3789: ++newp;
3790: /* Face G: {e, a, f} */
3791: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTriMidEdge_Static(ornt[1], 1);
3792: orntNew[0] = ornt[1] < 0 ? -2 : 0;
3793: coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
3794: orntNew[1] = 0;
3795: coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 1);
3796: orntNew[2] = ornt[3] < 0 ? 0 : -2;
3797: DMPlexSetCone(rdm, newp, coneNew);
3798: DMPlexSetConeOrientation(rdm, newp, orntNew);
3799: #if 1
3800: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3801: for (p = 0; p < 3; ++p) {
3802: 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);
3803: }
3804: #endif
3805: supportNew[0] = (c - cStart)*8 + 1+4;
3806: supportNew[1] = (c - cStart)*8 + 3+4;
3807: DMPlexSetSupport(rdm, newp, supportNew);
3808: #if 1
3809: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3810: for (p = 0; p < 2; ++p) {
3811: 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);
3812: }
3813: #endif
3814: ++newp;
3815: /* Face H: {a, b, f} */
3816: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTriMidEdge_Static(ornt[0], 0);
3817: orntNew[0] = ornt[0] < 0 ? -2 : 0;
3818: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTriMidEdge_Static(ornt[3], 2);
3819: orntNew[1] = ornt[3] < 0 ? 0 : -2;
3820: coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
3821: orntNew[2] = -2;
3822: DMPlexSetCone(rdm, newp, coneNew);
3823: DMPlexSetConeOrientation(rdm, newp, orntNew);
3824: #if 1
3825: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3826: for (p = 0; p < 3; ++p) {
3827: 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);
3828: }
3829: #endif
3830: supportNew[0] = (c - cStart)*8 + 1+4;
3831: supportNew[1] = (c - cStart)*8 + 2+4;
3832: DMPlexSetSupport(rdm, newp, supportNew);
3833: #if 1
3834: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3835: for (p = 0; p < 2; ++p) {
3836: 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);
3837: }
3838: #endif
3839: ++newp;
3840: }
3841: /* Hybrid split faces have 4 edges and same cells */
3842: for (f = fMax; f < fEnd; ++f) {
3843: const PetscInt *cone, *ornt, *support;
3844: PetscInt coneNew[4], orntNew[4];
3845: PetscInt supportNew[2], size, s, c;
3847: DMPlexGetCone(dm, f, &cone);
3848: DMPlexGetConeOrientation(dm, f, &ornt);
3849: DMPlexGetSupportSize(dm, f, &size);
3850: DMPlexGetSupport(dm, f, &support);
3851: for (r = 0; r < 2; ++r) {
3852: const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (f - fMax)*2 + r;
3854: coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1-r : r);
3855: orntNew[0] = ornt[0];
3856: coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1-r : r);
3857: orntNew[1] = ornt[1];
3858: coneNew[2+r] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (cone[2+r] - eMax);
3859: orntNew[2+r] = 0;
3860: coneNew[3-r] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (f - fMax);
3861: orntNew[3-r] = 0;
3862: DMPlexSetCone(rdm, newp, coneNew);
3863: DMPlexSetConeOrientation(rdm, newp, orntNew);
3864: #if 1
3865: if ((newp < fMaxNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", newp, fMaxNew, fEndNew);
3866: for (p = 0; p < 2; ++p) {
3867: 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);
3868: }
3869: for (p = 2; p < 4; ++p) {
3870: 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);
3871: }
3872: #endif
3873: for (s = 0; s < size; ++s) {
3874: const PetscInt *coneCell, *orntCell, *fornt;
3875: PetscInt o, of;
3877: DMPlexGetCone(dm, support[s], &coneCell);
3878: DMPlexGetConeOrientation(dm, support[s], &orntCell);
3879: o = orntCell[0] < 0 ? -1 : 1;
3880: for (c = 2; c < 5; ++c) if (coneCell[c] == f) break;
3881: if (c >= 5) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find face %d in cone of cell %d", f, support[s]);
3882: DMPlexGetConeOrientation(dm, coneCell[0], &fornt);
3883: of = fornt[c-2] < 0 ? -1 : 1;
3884: supportNew[s] = cStartNew + (cMax - cStart)*8 + (support[s] - cMax)*4 + (GetTriEdgeInverse_Static(orntCell[0], c-2) + (o*of < 0 ? 1-r : r))%3;
3885: }
3886: DMPlexSetSupport(rdm, newp, supportNew);
3887: #if 1
3888: if ((newp < fMaxNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", newp, fMaxNew, fEndNew);
3889: for (p = 0; p < size; ++p) {
3890: 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);
3891: }
3892: #endif
3893: }
3894: }
3895: /* Hybrid cell faces have 4 edges and 2 cells */
3896: for (c = cMax; c < cEnd; ++c) {
3897: PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3;
3898: const PetscInt *cone, *ornt;
3899: PetscInt coneNew[4], orntNew[4];
3900: PetscInt supportNew[2];
3902: DMPlexGetCone(dm, c, &cone);
3903: DMPlexGetConeOrientation(dm, c, &ornt);
3904: for (r = 0; r < 3; ++r) {
3905: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + (r+2)%3;
3906: orntNew[0] = 0;
3907: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + (r+2)%3;
3908: orntNew[1] = 0;
3909: coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (cone[2+(r+2)%3] - fMax);
3910: orntNew[2] = 0;
3911: coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (cone[2+r] - fMax);
3912: orntNew[3] = 0;
3913: DMPlexSetCone(rdm, newp+r, coneNew);
3914: DMPlexSetConeOrientation(rdm, newp+r, orntNew);
3915: #if 1
3916: 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);
3917: for (p = 0; p < 2; ++p) {
3918: 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);
3919: }
3920: for (p = 2; p < 4; ++p) {
3921: 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);
3922: }
3923: #endif
3924: supportNew[0] = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + GetTriSubface_Static(ornt[0], r);
3925: supportNew[1] = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + 3;
3926: DMPlexSetSupport(rdm, newp+r, supportNew);
3927: #if 1
3928: 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);
3929: for (p = 0; p < 2; ++p) {
3930: 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);
3931: }
3932: #endif
3933: }
3934: }
3935: /* Interior split edges have 2 vertices and the same faces as the parent */
3936: for (e = eStart; e < eMax; ++e) {
3937: const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);
3939: for (r = 0; r < 2; ++r) {
3940: const PetscInt newp = eStartNew + (e - eStart)*2 + r;
3941: const PetscInt *cone, *ornt, *support;
3942: PetscInt coneNew[2], coneSize, c, supportSize, s;
3944: DMPlexGetCone(dm, e, &cone);
3945: coneNew[0] = vStartNew + (cone[0] - vStart);
3946: coneNew[1] = vStartNew + (cone[1] - vStart);
3947: coneNew[(r+1)%2] = newv;
3948: DMPlexSetCone(rdm, newp, coneNew);
3949: #if 1
3950: if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
3951: for (p = 0; p < 2; ++p) {
3952: 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);
3953: }
3954: #endif
3955: DMPlexGetSupportSize(dm, e, &supportSize);
3956: DMPlexGetSupport(dm, e, &support);
3957: for (s = 0; s < supportSize; ++s) {
3958: DMPlexGetConeSize(dm, support[s], &coneSize);
3959: DMPlexGetCone(dm, support[s], &cone);
3960: DMPlexGetConeOrientation(dm, support[s], &ornt);
3961: for (c = 0; c < coneSize; ++c) if (cone[c] == e) break;
3962: if (support[s] < fMax) {
3963: supportRef[s] = fStartNew + (support[s] - fStart)*4 + (c + (ornt[c] < 0 ? 1-r : r))%3;
3964: } else {
3965: supportRef[s] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (support[s] - fMax)*2 + (ornt[c] < 0 ? 1-r : r);
3966: }
3967: }
3968: DMPlexSetSupport(rdm, newp, supportRef);
3969: #if 1
3970: if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
3971: for (p = 0; p < supportSize; ++p) {
3972: 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);
3973: }
3974: #endif
3975: }
3976: }
3977: /* Interior face edges have 2 vertices and 2+cells*(1/2) faces */
3978: for (f = fStart; f < fMax; ++f) {
3979: const PetscInt *cone, *ornt, *support;
3980: PetscInt coneSize, supportSize, s;
3982: DMPlexGetSupportSize(dm, f, &supportSize);
3983: DMPlexGetSupport(dm, f, &support);
3984: for (r = 0; r < 3; ++r) {
3985: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + r;
3986: PetscInt coneNew[2], intFaces = 0, er, eint[4] = {1, 0, 2, 0};
3987: PetscInt fint[24] = { 1, 7, -1, -1, 0, 5,
3988: -1, -1, 1, 6, 0, 4,
3989: 2, 5, 3, 4, -1, -1,
3990: -1, -1, 3, 6, 2, 7};
3992: DMPlexGetCone(dm, f, &cone);
3993: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[(r+0)%3] - eStart);
3994: coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - eStart);
3995: DMPlexSetCone(rdm, newp, coneNew);
3996: #if 1
3997: if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
3998: for (p = 0; p < 2; ++p) {
3999: 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);
4000: }
4001: #endif
4002: supportRef[0] = fStartNew + (f - fStart)*4 + (r+1)%3;
4003: supportRef[1] = fStartNew + (f - fStart)*4 + 3;
4004: for (s = 0; s < supportSize; ++s) {
4005: DMPlexGetConeSize(dm, support[s], &coneSize);
4006: DMPlexGetCone(dm, support[s], &cone);
4007: DMPlexGetConeOrientation(dm, support[s], &ornt);
4008: for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
4009: if (support[s] < cMax) {
4010: /* Here we want to determine whether edge newp contains a vertex which is part of the cross-tet edge */
4011: er = GetTriMidEdgeInverse_Static(ornt[c], r);
4012: if (er == eint[c]) {
4013: supportRef[2+intFaces++] = fStartNew + (fMax - fStart)*4 + (support[s] - cStart)*8 + (c + 2)%4;
4014: } else {
4015: supportRef[2+intFaces++] = fStartNew + (fMax - fStart)*4 + (support[s] - cStart)*8 + fint[(c*3 + er)*2 + 0];
4016: supportRef[2+intFaces++] = fStartNew + (fMax - fStart)*4 + (support[s] - cStart)*8 + fint[(c*3 + er)*2 + 1];
4017: }
4018: } else {
4019: supportRef[2+intFaces++] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (support[s] - cMax)*3 + (r + 1)%3;
4020: }
4021: }
4022: DMPlexSetSupport(rdm, newp, supportRef);
4023: #if 1
4024: if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
4025: for (p = 0; p < intFaces; ++p) {
4026: 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);
4027: }
4028: #endif
4029: }
4030: }
4031: /* Interior cell edges have 2 vertices and 4 faces */
4032: for (c = cStart; c < cMax; ++c) {
4033: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
4034: const PetscInt *cone, *ornt, *fcone;
4035: PetscInt coneNew[2], supportNew[4], find;
4037: DMPlexGetCone(dm, c, &cone);
4038: DMPlexGetConeOrientation(dm, c, &ornt);
4039: DMPlexGetCone(dm, cone[0], &fcone);
4040: find = GetTriEdge_Static(ornt[0], 0);
4041: coneNew[0] = vStartNew + (vEnd - vStart) + (fcone[find] - eStart);
4042: DMPlexGetCone(dm, cone[2], &fcone);
4043: find = GetTriEdge_Static(ornt[2], 1);
4044: coneNew[1] = vStartNew + (vEnd - vStart) + (fcone[find] - eStart);
4045: DMPlexSetCone(rdm, newp, coneNew);
4046: #if 1
4047: if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
4048: for (p = 0; p < 2; ++p) {
4049: 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);
4050: }
4051: #endif
4052: supportNew[0] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 4;
4053: supportNew[1] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 5;
4054: supportNew[2] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 6;
4055: supportNew[3] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 7;
4056: DMPlexSetSupport(rdm, newp, supportNew);
4057: #if 1
4058: if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
4059: for (p = 0; p < 4; ++p) {
4060: 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);
4061: }
4062: #endif
4063: }
4064: /* Hybrid edges have two vertices and the same faces */
4065: for (e = eMax; e < eEnd; ++e) {
4066: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (e - eMax);
4067: const PetscInt *cone, *support, *fcone;
4068: PetscInt coneNew[2], size, fsize, s;
4070: DMPlexGetCone(dm, e, &cone);
4071: DMPlexGetSupportSize(dm, e, &size);
4072: DMPlexGetSupport(dm, e, &support);
4073: coneNew[0] = vStartNew + (cone[0] - vStart);
4074: coneNew[1] = vStartNew + (cone[1] - vStart);
4075: DMPlexSetCone(rdm, newp, coneNew);
4076: #if 1
4077: if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
4078: for (p = 0; p < 2; ++p) {
4079: 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);
4080: }
4081: #endif
4082: for (s = 0; s < size; ++s) {
4083: DMPlexGetConeSize(dm, support[s], &fsize);
4084: DMPlexGetCone(dm, support[s], &fcone);
4085: for (c = 0; c < fsize; ++c) if (fcone[c] == e) break;
4086: if ((c < 2) || (c > 3)) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge %d not found in cone of face %d", e, support[s]);
4087: supportRef[s] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (support[s] - fMax)*2 + c-2;
4088: }
4089: DMPlexSetSupport(rdm, newp, supportRef);
4090: #if 1
4091: if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
4092: for (p = 0; p < size; ++p) {
4093: 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);
4094: }
4095: #endif
4096: }
4097: /* Hybrid face edges have 2 vertices and 2+2*cells faces */
4098: for (f = fMax; f < fEnd; ++f) {
4099: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (f - fMax);
4100: const PetscInt *cone, *support, *ccone, *cornt;
4101: PetscInt coneNew[2], size, csize, s;
4103: DMPlexGetCone(dm, f, &cone);
4104: DMPlexGetSupportSize(dm, f, &size);
4105: DMPlexGetSupport(dm, f, &support);
4106: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - eStart);
4107: coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - eStart);
4108: DMPlexSetCone(rdm, newp, coneNew);
4109: #if 1
4110: if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
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: supportRef[0] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (f - fMax)*2 + 0;
4116: supportRef[1] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (f - fMax)*2 + 1;
4117: for (s = 0; s < size; ++s) {
4118: DMPlexGetConeSize(dm, support[s], &csize);
4119: DMPlexGetCone(dm, support[s], &ccone);
4120: DMPlexGetConeOrientation(dm, support[s], &cornt);
4121: for (c = 0; c < csize; ++c) if (ccone[c] == f) break;
4122: 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]);
4123: supportRef[2+s*2+0] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (support[s] - cMax)*3 + c-2;
4124: supportRef[2+s*2+1] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (support[s] - cMax)*3 + (c-1)%3;
4125: }
4126: DMPlexSetSupport(rdm, newp, supportRef);
4127: #if 1
4128: if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
4129: for (p = 0; p < 2+size*2; ++p) {
4130: 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);
4131: }
4132: #endif
4133: }
4134: /* Interior vertices have identical supports */
4135: for (v = vStart; v < vEnd; ++v) {
4136: const PetscInt newp = vStartNew + (v - vStart);
4137: const PetscInt *support, *cone;
4138: PetscInt size, s;
4140: DMPlexGetSupportSize(dm, v, &size);
4141: DMPlexGetSupport(dm, v, &support);
4142: for (s = 0; s < size; ++s) {
4143: PetscInt r = 0;
4145: DMPlexGetCone(dm, support[s], &cone);
4146: if (cone[1] == v) r = 1;
4147: if (support[s] < eMax) supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
4148: else supportRef[s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (support[s] - eMax);
4149: }
4150: DMPlexSetSupport(rdm, newp, supportRef);
4151: #if 1
4152: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
4153: for (p = 0; p < size; ++p) {
4154: 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);
4155: }
4156: #endif
4157: }
4158: /* Interior edge vertices have 2 + interior face*2 + hybrid face + cells*0/1 supports */
4159: for (e = eStart; e < eMax; ++e) {
4160: const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
4161: const PetscInt *cone, *support;
4162: PetscInt *star = NULL, starSize, faceSize = 0, cellSize = 0, coneSize, size, s;
4164: DMPlexGetSupportSize(dm, e, &size);
4165: DMPlexGetSupport(dm, e, &support);
4166: supportRef[0] = eStartNew + (e - eStart)*2 + 0;
4167: supportRef[1] = eStartNew + (e - eStart)*2 + 1;
4168: for (s = 0; s < size; ++s) {
4169: PetscInt r = 0;
4171: if (support[s] < fMax) {
4172: DMPlexGetConeSize(dm, support[s], &coneSize);
4173: DMPlexGetCone(dm, support[s], &cone);
4174: for (r = 0; r < coneSize; ++r) {if (cone[r] == e) break;}
4175: supportRef[2+faceSize+0] = eStartNew + (eMax - eStart)*2 + (support[s] - fStart)*3 + (r+0)%3;
4176: supportRef[2+faceSize+1] = eStartNew + (eMax - eStart)*2 + (support[s] - fStart)*3 + (r+2)%3;
4177: faceSize += 2;
4178: } else {
4179: supportRef[2+faceSize+0] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (support[s] - fMax);
4180: ++faceSize;
4181: }
4182: }
4183: DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
4184: for (s = 0; s < starSize*2; s += 2) {
4185: const PetscInt *cone, *ornt;
4186: PetscInt e01, e23;
4188: if ((star[s] >= cStart) && (star[s] < cMax)) {
4189: /* Check edge 0-1 */
4190: DMPlexGetCone(dm, star[s], &cone);
4191: DMPlexGetConeOrientation(dm, star[s], &ornt);
4192: DMPlexGetCone(dm, cone[0], &cone);
4193: e01 = cone[GetTriEdge_Static(ornt[0], 0)];
4194: /* Check edge 2-3 */
4195: DMPlexGetCone(dm, star[s], &cone);
4196: DMPlexGetConeOrientation(dm, star[s], &ornt);
4197: DMPlexGetCone(dm, cone[2], &cone);
4198: e23 = cone[GetTriEdge_Static(ornt[2], 1)];
4199: if ((e01 == e) || (e23 == e)) {supportRef[2+faceSize+cellSize++] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (star[s] - cStart);}
4200: }
4201: }
4202: DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
4203: DMPlexSetSupport(rdm, newp, supportRef);
4204: #if 1
4205: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
4206: for (p = 0; p < 2+faceSize+cellSize; ++p) {
4207: 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);
4208: }
4209: #endif
4210: }
4211: PetscFree(supportRef);
4212: DMPlexRestoreFaces_Internal(dm, 3, cStart, NULL, NULL, &faces);
4213: break;
4214: case REFINER_SIMPLEX_TO_HEX_3D:
4215: DMPlexGetRawFaces_Internal(dm, 3, 4, cellInd, NULL, NULL, &faces);
4216: /* All cells have 6 faces */
4217: for (c = cStart; c < cEnd; ++c) {
4218: const PetscInt newp = cStartNew + (c - cStart)*4;
4219: const PetscInt *cone, *ornt;
4220: PetscInt coneNew[6];
4221: PetscInt orntNew[6];
4223: DMPlexGetCone(dm, c, &cone);
4224: DMPlexGetConeOrientation(dm, c, &ornt);
4225: /* A hex */
4226: coneNew[0] = fStartNew + (cone[0] - fStart)*3 + GetTriSubface_Static(ornt[0], 0); /* B */
4227: orntNew[0] = ornt[0] < 0 ? -1 : 1;
4228: coneNew[1] = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + 3; /* T */
4229: orntNew[1] = -4;
4230: coneNew[2] = fStartNew + (cone[2] - fStart)*3 + GetTriSubface_Static(ornt[2], 0); /* F */
4231: orntNew[2] = ornt[2] < 0 ? -1 : 1;
4232: coneNew[3] = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + 0; /* K */
4233: orntNew[3] = -1;
4234: coneNew[4] = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + 2; /* R */
4235: orntNew[4] = 0;
4236: coneNew[5] = fStartNew + (cone[1] - fStart)*3 + GetTriSubface_Static(ornt[1], 0); /* L */
4237: orntNew[5] = ornt[1] < 0 ? -1 : 1;
4238: DMPlexSetCone(rdm, newp+0, coneNew);
4239: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
4240: #if 1
4241: 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);
4242: for (p = 0; p < 6; ++p) {
4243: 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);
4244: }
4245: #endif
4246: /* B hex */
4247: coneNew[0] = fStartNew + (cone[0] - fStart)*3 + GetTriSubface_Static(ornt[0], 1); /* B */
4248: orntNew[0] = ornt[0] < 0 ? -2 : 0;
4249: coneNew[1] = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + 4; /* T */
4250: orntNew[1] = 0;
4251: coneNew[2] = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + 0; /* F */
4252: orntNew[2] = 0;
4253: coneNew[3] = fStartNew + (cone[3] - fStart)*3 + GetTriSubface_Static(ornt[3], 1); /* K */
4254: orntNew[3] = ornt[3] < 0 ? -2 : 0;
4255: coneNew[4] = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + 1; /* R */
4256: orntNew[4] = 0;
4257: coneNew[5] = fStartNew + (cone[1] - fStart)*3 + GetTriSubface_Static(ornt[1], 2); /* L */
4258: orntNew[5] = ornt[1] < 0 ? -4 : 2;
4259: DMPlexSetCone(rdm, newp+1, coneNew);
4260: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
4261: #if 1
4262: 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);
4263: for (p = 0; p < 6; ++p) {
4264: 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);
4265: }
4266: #endif
4267: /* C hex */
4268: coneNew[0] = fStartNew + (cone[0] - fStart)*3 + GetTriSubface_Static(ornt[0], 2); /* B */
4269: orntNew[0] = ornt[0] < 0 ? -4 : 2;
4270: coneNew[1] = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + 5; /* T */
4271: orntNew[1] = -4;
4272: coneNew[2] = fStartNew + (cone[2] - fStart)*3 + GetTriSubface_Static(ornt[2], 1); /* F */
4273: orntNew[2] = ornt[2] < 0 ? -2 : 0;
4274: coneNew[3] = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + 1; /* K */
4275: orntNew[3] = -1;
4276: coneNew[4] = fStartNew + (cone[3] - fStart)*3 + GetTriSubface_Static(ornt[3], 0); /* R */
4277: orntNew[4] = ornt[3] < 0 ? -1 : 1;
4278: coneNew[5] = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + 2; /* L */
4279: orntNew[5] = -4;
4280: DMPlexSetCone(rdm, newp+2, coneNew);
4281: DMPlexSetConeOrientation(rdm, newp+2, orntNew);
4282: #if 1
4283: 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);
4284: for (p = 0; p < 6; ++p) {
4285: 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);
4286: }
4287: #endif
4288: /* D hex */
4289: coneNew[0] = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + 3; /* B */
4290: orntNew[0] = 0;
4291: coneNew[1] = fStartNew + (cone[3] - fStart)*3 + GetTriSubface_Static(ornt[3], 2); /* T */
4292: orntNew[1] = ornt[3] < 0 ? -1 : 1;
4293: coneNew[2] = fStartNew + (cone[2] - fStart)*3 + GetTriSubface_Static(ornt[2], 2); /* F */
4294: orntNew[2] = ornt[2] < 0 ? -4 : 2;
4295: coneNew[3] = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + 4; /* K */
4296: orntNew[3] = -1;
4297: coneNew[4] = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + 5; /* R */
4298: orntNew[4] = 0;
4299: coneNew[5] = fStartNew + (cone[1] - fStart)*3 + GetTriSubface_Static(ornt[1], 1); /* L */
4300: orntNew[5] = ornt[1] < 0 ? -2 : 0;
4301: DMPlexSetCone(rdm, newp+3, coneNew);
4302: DMPlexSetConeOrientation(rdm, newp+3, orntNew);
4303: #if 1
4304: 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);
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: }
4310: /* Split faces have 4 edges and the same cells as the parent */
4311: DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
4312: PetscMalloc1(2 + maxSupportSize*2, &supportRef);
4313: for (f = fStart; f < fEnd; ++f) {
4314: const PetscInt newp = fStartNew + (f - fStart)*3;
4315: const PetscInt *cone, *ornt, *support;
4316: PetscInt coneNew[4], orntNew[4], coneSize, supportSize, s;
4318: DMPlexGetCone(dm, f, &cone);
4319: DMPlexGetConeOrientation(dm, f, &ornt);
4320: /* A quad */
4321: coneNew[0] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 0 : 1);
4322: orntNew[0] = ornt[2];
4323: coneNew[1] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1 : 0);
4324: orntNew[1] = ornt[0];
4325: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 0;
4326: orntNew[2] = 0;
4327: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 2;
4328: orntNew[3] = -2;
4329: DMPlexSetCone(rdm, newp+0, coneNew);
4330: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
4331: #if 1
4332: 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);
4333: for (p = 0; p < 4; ++p) {
4334: 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);
4335: }
4336: #endif
4337: /* B quad */
4338: coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 0 : 1);
4339: orntNew[0] = ornt[0];
4340: coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1 : 0);
4341: orntNew[1] = ornt[1];
4342: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 1;
4343: orntNew[2] = 0;
4344: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 0;
4345: orntNew[3] = -2;
4346: DMPlexSetCone(rdm, newp+1, coneNew);
4347: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
4348: #if 1
4349: 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);
4350: for (p = 0; p < 4; ++p) {
4351: 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);
4352: }
4353: #endif
4354: /* C quad */
4355: coneNew[0] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 0 : 1);
4356: orntNew[0] = ornt[1];
4357: coneNew[1] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 1 : 0);
4358: orntNew[1] = ornt[2];
4359: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 2;
4360: orntNew[2] = 0;
4361: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 1;
4362: orntNew[3] = -2;
4363: DMPlexSetCone(rdm, newp+2, coneNew);
4364: DMPlexSetConeOrientation(rdm, newp+2, orntNew);
4365: #if 1
4366: 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);
4367: for (p = 0; p < 4; ++p) {
4368: 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);
4369: }
4370: #endif
4371: DMPlexGetSupportSize(dm, f, &supportSize);
4372: DMPlexGetSupport(dm, f, &support);
4373: for (r = 0; r < 3; ++r) {
4374: for (s = 0; s < supportSize; ++s) {
4375: PetscInt subf;
4376: DMPlexGetConeSize(dm, support[s], &coneSize);
4377: DMPlexGetCone(dm, support[s], &cone);
4378: DMPlexGetConeOrientation(dm, support[s], &ornt);
4379: for (c = 0; c < coneSize; ++c) {
4380: if (cone[c] == f) break;
4381: }
4382: subf = GetTriSubfaceInverse_Static(ornt[c], r);
4383: supportRef[s] = cStartNew + (support[s] - cStart)*4 + faces[c*3+subf];
4384: }
4385: DMPlexSetSupport(rdm, newp+r, supportRef);
4386: #if 1
4387: 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);
4388: for (p = 0; p < supportSize; ++p) {
4389: 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);
4390: }
4391: #endif
4392: }
4393: }
4394: /* Interior faces have 4 edges and 2 cells */
4395: for (c = cStart; c < cEnd; ++c) {
4396: PetscInt newp = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6;
4397: const PetscInt *cone, *ornt;
4398: PetscInt coneNew[4], orntNew[4];
4399: PetscInt supportNew[2];
4401: DMPlexGetCone(dm, c, &cone);
4402: DMPlexGetConeOrientation(dm, c, &ornt);
4403: /* Face {a, g, m, h} */
4404: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTriInteriorEdge_Static(ornt[0],0);
4405: orntNew[0] = 0;
4406: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 0;
4407: orntNew[1] = 0;
4408: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 1;
4409: orntNew[2] = -2;
4410: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTriInteriorEdge_Static(ornt[1],2);
4411: orntNew[3] = -2;
4412: DMPlexSetCone(rdm, newp, coneNew);
4413: DMPlexSetConeOrientation(rdm, newp, orntNew);
4414: #if 1
4415: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
4416: for (p = 0; p < 4; ++p) {
4417: 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);
4418: }
4419: #endif
4420: supportNew[0] = (c - cStart)*4 + 0;
4421: supportNew[1] = (c - cStart)*4 + 1;
4422: DMPlexSetSupport(rdm, newp, supportNew);
4423: #if 1
4424: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
4425: for (p = 0; p < 2; ++p) {
4426: 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);
4427: }
4428: #endif
4429: ++newp;
4430: /* Face {g, b, l , m} */
4431: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTriInteriorEdge_Static(ornt[0],1);
4432: orntNew[0] = -2;
4433: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTriInteriorEdge_Static(ornt[3],0);
4434: orntNew[1] = 0;
4435: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 3;
4436: orntNew[2] = 0;
4437: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 0;
4438: orntNew[3] = -2;
4439: DMPlexSetCone(rdm, newp, coneNew);
4440: DMPlexSetConeOrientation(rdm, newp, orntNew);
4441: #if 1
4442: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
4443: for (p = 0; p < 4; ++p) {
4444: 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);
4445: }
4446: #endif
4447: supportNew[0] = (c - cStart)*4 + 1;
4448: supportNew[1] = (c - cStart)*4 + 2;
4449: DMPlexSetSupport(rdm, newp, supportNew);
4450: #if 1
4451: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
4452: for (p = 0; p < 2; ++p) {
4453: 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);
4454: }
4455: #endif
4456: ++newp;
4457: /* Face {c, g, m, i} */
4458: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTriInteriorEdge_Static(ornt[0],2);
4459: orntNew[0] = 0;
4460: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 0;
4461: orntNew[1] = 0;
4462: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 2;
4463: orntNew[2] = -2;
4464: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTriInteriorEdge_Static(ornt[2],0);
4465: orntNew[3] = -2;
4466: DMPlexSetCone(rdm, newp, coneNew);
4467: DMPlexSetConeOrientation(rdm, newp, orntNew);
4468: #if 1
4469: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
4470: for (p = 0; p < 4; ++p) {
4471: 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);
4472: }
4473: #endif
4474: supportNew[0] = (c - cStart)*4 + 0;
4475: supportNew[1] = (c - cStart)*4 + 2;
4476: DMPlexSetSupport(rdm, newp, supportNew);
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 < 2; ++p) {
4480: 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);
4481: }
4482: #endif
4483: ++newp;
4484: /* Face {d, h, m, i} */
4485: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTriInteriorEdge_Static(ornt[1],0);
4486: orntNew[0] = 0;
4487: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 1;
4488: orntNew[1] = 0;
4489: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 2;
4490: orntNew[2] = -2;
4491: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTriInteriorEdge_Static(ornt[2],2);
4492: orntNew[3] = -2;
4493: DMPlexSetCone(rdm, newp, coneNew);
4494: DMPlexSetConeOrientation(rdm, newp, orntNew);
4495: #if 1
4496: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
4497: for (p = 0; p < 4; ++p) {
4498: 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);
4499: }
4500: #endif
4501: supportNew[0] = (c - cStart)*4 + 0;
4502: supportNew[1] = (c - cStart)*4 + 3;
4503: DMPlexSetSupport(rdm, newp, supportNew);
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 < 2; ++p) {
4507: 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);
4508: }
4509: #endif
4510: ++newp;
4511: /* Face {h, m, l, e} */
4512: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 1;
4513: orntNew[0] = 0;
4514: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 3;
4515: orntNew[1] = -2;
4516: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTriInteriorEdge_Static(ornt[3],1);
4517: orntNew[2] = -2;
4518: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTriInteriorEdge_Static(ornt[1],1);
4519: orntNew[3] = 0;
4520: DMPlexSetCone(rdm, newp, coneNew);
4521: DMPlexSetConeOrientation(rdm, newp, orntNew);
4522: #if 1
4523: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
4524: for (p = 0; p < 4; ++p) {
4525: 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);
4526: }
4527: #endif
4528: supportNew[0] = (c - cStart)*4 + 1;
4529: supportNew[1] = (c - cStart)*4 + 3;
4530: DMPlexSetSupport(rdm, newp, supportNew);
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 < 2; ++p) {
4534: 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);
4535: }
4536: #endif
4537: ++newp;
4538: /* Face {i, m, l, f} */
4539: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 2;
4540: orntNew[0] = 0;
4541: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 3;
4542: orntNew[1] = -2;
4543: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTriInteriorEdge_Static(ornt[3],2);
4544: orntNew[2] = -2;
4545: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTriInteriorEdge_Static(ornt[2],1);
4546: orntNew[3] = 0;
4547: DMPlexSetCone(rdm, newp, coneNew);
4548: DMPlexSetConeOrientation(rdm, newp, orntNew);
4549: #if 1
4550: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
4551: for (p = 0; p < 4; ++p) {
4552: 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);
4553: }
4554: #endif
4555: supportNew[0] = (c - cStart)*4 + 2;
4556: supportNew[1] = (c - cStart)*4 + 3;
4557: DMPlexSetSupport(rdm, newp, supportNew);
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 < 2; ++p) {
4561: 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);
4562: }
4563: #endif
4564: ++newp;
4565: }
4566: /* Split Edges have 2 vertices and the same faces as the parent */
4567: for (e = eStart; e < eEnd; ++e) {
4568: const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);
4570: for (r = 0; r < 2; ++r) {
4571: const PetscInt newp = eStartNew + (e - eStart)*2 + r;
4572: const PetscInt *cone, *ornt, *support;
4573: PetscInt coneNew[2], coneSize, c, supportSize, s;
4575: DMPlexGetCone(dm, e, &cone);
4576: coneNew[0] = vStartNew + (cone[0] - vStart);
4577: coneNew[1] = vStartNew + (cone[1] - vStart);
4578: coneNew[(r+1)%2] = newv;
4579: DMPlexSetCone(rdm, newp, coneNew);
4580: #if 1
4581: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
4582: for (p = 0; p < 2; ++p) {
4583: 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);
4584: }
4585: #endif
4586: DMPlexGetSupportSize(dm, e, &supportSize);
4587: DMPlexGetSupport(dm, e, &support);
4588: for (s = 0; s < supportSize; ++s) {
4589: DMPlexGetConeSize(dm, support[s], &coneSize);
4590: DMPlexGetCone(dm, support[s], &cone);
4591: DMPlexGetConeOrientation(dm, support[s], &ornt);
4592: for (c = 0; c < coneSize; ++c) {
4593: if (cone[c] == e) break;
4594: }
4595: supportRef[s] = fStartNew + (support[s] - fStart)*3 + (c + (ornt[c] < 0 ? 1-r : r))%3;
4596: }
4597: DMPlexSetSupport(rdm, newp, supportRef);
4598: #if 1
4599: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
4600: for (p = 0; p < supportSize; ++p) {
4601: 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);
4602: }
4603: #endif
4604: }
4605: }
4606: /* Face edges have 2 vertices and 2 + cell faces supports */
4607: for (f = fStart; f < fEnd; ++f) {
4608: const PetscInt *cone, *ornt, *support;
4609: PetscInt coneSize, supportSize, s;
4611: DMPlexGetSupportSize(dm, f, &supportSize);
4612: DMPlexGetSupport(dm, f, &support);
4613: for (r = 0; r < 3; ++r) {
4614: const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + r;
4615: PetscInt coneNew[2];
4616: PetscInt fint[4][3] = { {0, 1, 2},
4617: {3, 4, 0},
4618: {2, 5, 3},
4619: {1, 4, 5} };
4621: DMPlexGetCone(dm, f, &cone);
4622: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - eStart);
4623: coneNew[1] = vStartNew + (vEnd - vStart) + (eEnd - eStart) + f - fStart;
4624: DMPlexSetCone(rdm, newp, coneNew);
4625: #if 1
4626: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
4627: for (p = 0; p < 2; ++p) {
4628: 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);
4629: }
4630: #endif
4631: supportRef[0] = fStartNew + (f - fStart)*3 + (r+0)%3;
4632: supportRef[1] = fStartNew + (f - fStart)*3 + (r+1)%3;
4633: for (s = 0; s < supportSize; ++s) {
4634: PetscInt er;
4635: DMPlexGetConeSize(dm, support[s], &coneSize);
4636: DMPlexGetCone(dm, support[s], &cone);
4637: DMPlexGetConeOrientation(dm, support[s], &ornt);
4638: for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
4639: er = GetTriInteriorEdgeInverse_Static(ornt[c], r);
4640: supportRef[2+s] = fStartNew + (fEnd - fStart)*3 + (support[s] - cStart)*6 + fint[c][er];
4641: }
4642: DMPlexSetSupport(rdm, newp, supportRef);
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 < supportSize + 2; ++p) {
4646: 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);
4647: }
4648: #endif
4649: }
4650: }
4651: /* Interior cell edges have 2 vertices and 3 faces */
4652: for (c = cStart; c < cEnd; ++c) {
4653: const PetscInt *cone;
4654: PetscInt fint[4][3] = { {0,1,2},
4655: {0,3,4},
4656: {2,3,5},
4657: {1,4,5} } ;
4659: DMPlexGetCone(dm, c, &cone);
4660: for (r = 0; r < 4; r++) {
4661: PetscInt coneNew[2], supportNew[3];
4662: const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + r;
4664: coneNew[0] = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (cone[r] - fStart);
4665: coneNew[1] = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd -fStart) + c - cStart;
4666: DMPlexSetCone(rdm, newp, coneNew);
4667: #if 1
4668: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
4669: for (p = 0; p < 2; ++p) {
4670: 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);
4671: }
4672: #endif
4673: supportNew[0] = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + fint[r][0];
4674: supportNew[1] = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + fint[r][1];
4675: supportNew[2] = fStartNew + (fEnd - fStart)*3 + (c - cStart)*6 + fint[r][2];
4676: DMPlexSetSupport(rdm, newp, supportNew);
4677: #if 1
4678: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
4679: for (p = 0; p < 3; ++p) {
4680: 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);
4681: }
4682: #endif
4683: }
4684: }
4685: /* Old vertices have identical supports */
4686: for (v = vStart; v < vEnd; ++v) {
4687: const PetscInt newp = vStartNew + (v - vStart);
4688: const PetscInt *support, *cone;
4689: PetscInt size, s;
4691: DMPlexGetSupportSize(dm, v, &size);
4692: DMPlexGetSupport(dm, v, &support);
4693: for (s = 0; s < size; ++s) {
4694: PetscInt r = 0;
4696: DMPlexGetCone(dm, support[s], &cone);
4697: if (cone[1] == v) r = 1;
4698: supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
4699: }
4700: DMPlexSetSupport(rdm, newp, supportRef);
4701: #if 1
4702: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
4703: for (p = 0; p < size; ++p) {
4704: 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);
4705: }
4706: #endif
4707: }
4708: /* Edge vertices have 2 + faces supports */
4709: for (e = eStart; e < eEnd; ++e) {
4710: const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
4711: const PetscInt *cone, *support;
4712: PetscInt size, s;
4714: DMPlexGetSupportSize(dm, e, &size);
4715: DMPlexGetSupport(dm, e, &support);
4716: supportRef[0] = eStartNew + (e - eStart)*2 + 0;
4717: supportRef[1] = eStartNew + (e - eStart)*2 + 1;
4718: for (s = 0; s < size; ++s) {
4719: PetscInt r = 0, coneSize;
4721: DMPlexGetConeSize(dm, support[s], &coneSize);
4722: DMPlexGetCone(dm, support[s], &cone);
4723: for (r = 0; r < coneSize; ++r) {if (cone[r] == e) break;}
4724: supportRef[2+s] = eStartNew + (eEnd - eStart)*2 + (support[s] - fStart)*3 + r;
4725: }
4726: DMPlexSetSupport(rdm, newp, supportRef);
4727: #if 1
4728: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
4729: for (p = 0; p < 2+size; ++p) {
4730: 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);
4731: }
4732: #endif
4733: }
4734: /* Face vertices have 3 + cells supports */
4735: for (f = fStart; f < fEnd; ++f) {
4736: const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (f - fStart);
4737: const PetscInt *cone, *support;
4738: PetscInt size, s;
4740: DMPlexGetSupportSize(dm, f, &size);
4741: DMPlexGetSupport(dm, f, &support);
4742: supportRef[0] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 0;
4743: supportRef[1] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 1;
4744: supportRef[2] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 2;
4745: for (s = 0; s < size; ++s) {
4746: PetscInt r = 0, coneSize;
4748: DMPlexGetConeSize(dm, support[s], &coneSize);
4749: DMPlexGetCone(dm, support[s], &cone);
4750: for (r = 0; r < coneSize; ++r) {if (cone[r] == f) break;}
4751: supportRef[3+s] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (support[s] - cStart)*4 + r;
4752: }
4753: DMPlexSetSupport(rdm, newp, supportRef);
4754: #if 1
4755: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
4756: for (p = 0; p < 3+size; ++p) {
4757: 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);
4758: }
4759: #endif
4760: }
4761: /* Interior cell vertices have 4 supports */
4762: for (c = cStart; c < cEnd; ++c) {
4763: const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + c - cStart;
4764: supportRef[0] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 0;
4765: supportRef[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 1;
4766: supportRef[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 2;
4767: supportRef[3] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart)*4 + 3;
4768: DMPlexSetSupport(rdm, newp, supportRef);
4769: #if 1
4770: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
4771: for (p = 0; p < 4; ++p) {
4772: 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);
4773: }
4774: #endif
4775: }
4776: PetscFree(supportRef);
4777: DMPlexRestoreFaces_Internal(dm, 3, cStart, NULL, NULL, &faces);
4778: break;
4779: case REFINER_HEX_3D:
4780: /*
4781: Bottom (viewed from top) Top
4782: 1---------2---------2 7---------2---------6
4783: | | | | | |
4784: | B 2 C | | H 2 G |
4785: | | | | | |
4786: 3----3----0----1----1 3----3----0----1----1
4787: | | | | | |
4788: | A 0 D | | E 0 F |
4789: | | | | | |
4790: 0---------0---------3 4---------0---------5
4791: */
4792: /* All cells have 6 faces: Bottom, Top, Front, Back, Right, Left */
4793: for (c = cStart; c < cEnd; ++c) {
4794: const PetscInt newp = (c - cStart)*8;
4795: const PetscInt *cone, *ornt;
4796: PetscInt coneNew[6], orntNew[6];
4798: DMPlexGetCone(dm, c, &cone);
4799: DMPlexGetConeOrientation(dm, c, &ornt);
4800: /* A hex */
4801: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 0);
4802: orntNew[0] = ornt[0];
4803: coneNew[1] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 8; /* AE */
4804: orntNew[1] = 0;
4805: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 0);
4806: orntNew[2] = ornt[2];
4807: coneNew[3] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 3; /* AB */
4808: orntNew[3] = 0;
4809: coneNew[4] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 0; /* AD */
4810: orntNew[4] = 0;
4811: coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 0);
4812: orntNew[5] = ornt[5];
4813: DMPlexSetCone(rdm, newp+0, coneNew);
4814: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
4815: #if 1
4816: 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);
4817: for (p = 0; p < 6; ++p) {
4818: 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);
4819: }
4820: #endif
4821: /* B hex */
4822: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 1);
4823: orntNew[0] = ornt[0];
4824: coneNew[1] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 11; /* BH */
4825: orntNew[1] = 0;
4826: coneNew[2] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 3; /* AB */
4827: orntNew[2] = -1;
4828: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 1);
4829: orntNew[3] = ornt[3];
4830: coneNew[4] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 2; /* BC */
4831: orntNew[4] = 0;
4832: coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 3);
4833: orntNew[5] = ornt[5];
4834: DMPlexSetCone(rdm, newp+1, coneNew);
4835: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
4836: #if 1
4837: 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);
4838: for (p = 0; p < 6; ++p) {
4839: 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);
4840: }
4841: #endif
4842: /* C hex */
4843: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 2);
4844: orntNew[0] = ornt[0];
4845: coneNew[1] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 10; /* CG */
4846: orntNew[1] = 0;
4847: coneNew[2] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 1; /* CD */
4848: orntNew[2] = -1;
4849: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 0);
4850: orntNew[3] = ornt[3];
4851: coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 1);
4852: orntNew[4] = ornt[4];
4853: coneNew[5] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 2; /* BC */
4854: orntNew[5] = -4;
4855: DMPlexSetCone(rdm, newp+2, coneNew);
4856: DMPlexSetConeOrientation(rdm, newp+2, orntNew);
4857: #if 1
4858: 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);
4859: for (p = 0; p < 6; ++p) {
4860: 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);
4861: }
4862: #endif
4863: /* D hex */
4864: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 3);
4865: orntNew[0] = ornt[0];
4866: coneNew[1] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 9; /* DF */
4867: orntNew[1] = 0;
4868: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 1);
4869: orntNew[2] = ornt[2];
4870: coneNew[3] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 1; /* CD */
4871: orntNew[3] = 0;
4872: coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 0);
4873: orntNew[4] = ornt[4];
4874: coneNew[5] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 0; /* AD */
4875: orntNew[5] = -4;
4876: DMPlexSetCone(rdm, newp+3, coneNew);
4877: DMPlexSetConeOrientation(rdm, newp+3, orntNew);
4878: #if 1
4879: 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);
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: /* E hex */
4885: coneNew[0] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 8; /* AE */
4886: orntNew[0] = -4;
4887: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 0);
4888: orntNew[1] = ornt[1];
4889: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 3);
4890: orntNew[2] = ornt[2];
4891: coneNew[3] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 7; /* EH */
4892: orntNew[3] = 0;
4893: coneNew[4] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 4; /* EF */
4894: orntNew[4] = -1;
4895: coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 1);
4896: orntNew[5] = ornt[5];
4897: DMPlexSetCone(rdm, newp+4, coneNew);
4898: DMPlexSetConeOrientation(rdm, newp+4, orntNew);
4899: #if 1
4900: 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);
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: /* F hex */
4906: coneNew[0] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 9; /* DF */
4907: orntNew[0] = -4;
4908: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 1);
4909: orntNew[1] = ornt[1];
4910: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 2);
4911: orntNew[2] = ornt[2];
4912: coneNew[3] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 5; /* FG */
4913: orntNew[3] = -1;
4914: coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 3);
4915: orntNew[4] = ornt[4];
4916: coneNew[5] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 4; /* EF */
4917: orntNew[5] = 1;
4918: DMPlexSetCone(rdm, newp+5, coneNew);
4919: DMPlexSetConeOrientation(rdm, newp+5, orntNew);
4920: #if 1
4921: 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);
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: /* G hex */
4927: coneNew[0] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 10; /* CG */
4928: orntNew[0] = -4;
4929: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 2);
4930: orntNew[1] = ornt[1];
4931: coneNew[2] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 5; /* FG */
4932: orntNew[2] = 0;
4933: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 3);
4934: orntNew[3] = ornt[3];
4935: coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 2);
4936: orntNew[4] = ornt[4];
4937: coneNew[5] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 6; /* GH */
4938: orntNew[5] = -3;
4939: DMPlexSetCone(rdm, newp+6, coneNew);
4940: DMPlexSetConeOrientation(rdm, newp+6, orntNew);
4941: #if 1
4942: 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);
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: /* H hex */
4948: coneNew[0] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 11; /* BH */
4949: orntNew[0] = -4;
4950: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 3);
4951: orntNew[1] = ornt[1];
4952: coneNew[2] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 7; /* EH */
4953: orntNew[2] = -1;
4954: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 2);
4955: orntNew[3] = ornt[3];
4956: coneNew[4] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 6; /* GH */
4957: orntNew[4] = 3;
4958: coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 2);
4959: orntNew[5] = ornt[5];
4960: DMPlexSetCone(rdm, newp+7, coneNew);
4961: DMPlexSetConeOrientation(rdm, newp+7, orntNew);
4962: #if 1
4963: 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);
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: }
4969: /* Split faces have 4 edges and the same cells as the parent */
4970: DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
4971: PetscMalloc1(4 + maxSupportSize*2, &supportRef);
4972: for (f = fStart; f < fEnd; ++f) {
4973: for (r = 0; r < 4; ++r) {
4974: /* TODO: This can come from GetFaces_Internal() */
4975: 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};
4976: const PetscInt newp = fStartNew + (f - fStart)*4 + r;
4977: const PetscInt *cone, *ornt, *support;
4978: PetscInt coneNew[4], orntNew[4], coneSize, c, supportSize, s;
4980: DMPlexGetCone(dm, f, &cone);
4981: DMPlexGetConeOrientation(dm, f, &ornt);
4982: coneNew[(r+3)%4] = eStartNew + (cone[(r+3)%4] - eStart)*2 + (ornt[(r+3)%4] < 0 ? 0 : 1);
4983: orntNew[(r+3)%4] = ornt[(r+3)%4];
4984: coneNew[(r+0)%4] = eStartNew + (cone[r] - eStart)*2 + (ornt[r] < 0 ? 1 : 0);
4985: orntNew[(r+0)%4] = ornt[r];
4986: coneNew[(r+1)%4] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + r;
4987: orntNew[(r+1)%4] = 0;
4988: coneNew[(r+2)%4] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + (r+3)%4;
4989: orntNew[(r+2)%4] = -2;
4990: DMPlexSetCone(rdm, newp, coneNew);
4991: DMPlexSetConeOrientation(rdm, newp, orntNew);
4992: #if 1
4993: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
4994: for (p = 0; p < 4; ++p) {
4995: 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);
4996: }
4997: #endif
4998: DMPlexGetSupportSize(dm, f, &supportSize);
4999: DMPlexGetSupport(dm, f, &support);
5000: for (s = 0; s < supportSize; ++s) {
5001: DMPlexGetConeSize(dm, support[s], &coneSize);
5002: DMPlexGetCone(dm, support[s], &cone);
5003: DMPlexGetConeOrientation(dm, support[s], &ornt);
5004: for (c = 0; c < coneSize; ++c) {
5005: if (cone[c] == f) break;
5006: }
5007: supportRef[s] = cStartNew + (support[s] - cStart)*8 + newCells[c*4+GetQuadSubfaceInverse_Static(ornt[c], r)];
5008: }
5009: DMPlexSetSupport(rdm, newp, supportRef);
5010: #if 1
5011: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
5012: for (p = 0; p < supportSize; ++p) {
5013: 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);
5014: }
5015: #endif
5016: }
5017: }
5018: /* Interior faces have 4 edges and 2 cells */
5019: for (c = cStart; c < cEnd; ++c) {
5020: 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};
5021: const PetscInt *cone, *ornt;
5022: PetscInt newp, coneNew[4], orntNew[4], supportNew[2];
5024: DMPlexGetCone(dm, c, &cone);
5025: DMPlexGetConeOrientation(dm, c, &ornt);
5026: /* A-D face */
5027: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 0;
5028: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 3);
5029: orntNew[0] = 0;
5030: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 0;
5031: orntNew[1] = 0;
5032: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 2;
5033: orntNew[2] = -2;
5034: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 0);
5035: orntNew[3] = -2;
5036: DMPlexSetCone(rdm, newp, coneNew);
5037: DMPlexSetConeOrientation(rdm, newp, orntNew);
5038: #if 1
5039: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
5040: for (p = 0; p < 4; ++p) {
5041: 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);
5042: }
5043: #endif
5044: /* C-D face */
5045: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 1;
5046: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 2);
5047: orntNew[0] = 0;
5048: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 0;
5049: orntNew[1] = 0;
5050: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 4;
5051: orntNew[2] = -2;
5052: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 0);
5053: orntNew[3] = -2;
5054: DMPlexSetCone(rdm, newp, coneNew);
5055: DMPlexSetConeOrientation(rdm, newp, orntNew);
5056: #if 1
5057: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
5058: for (p = 0; p < 4; ++p) {
5059: 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);
5060: }
5061: #endif
5062: /* B-C face */
5063: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 2;
5064: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 1);
5065: orntNew[0] = -2;
5066: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 0);
5067: orntNew[1] = 0;
5068: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 3;
5069: orntNew[2] = 0;
5070: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 0;
5071: orntNew[3] = -2;
5072: DMPlexSetCone(rdm, newp, coneNew);
5073: DMPlexSetConeOrientation(rdm, newp, orntNew);
5074: #if 1
5075: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
5076: for (p = 0; p < 4; ++p) {
5077: 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);
5078: }
5079: #endif
5080: /* A-B face */
5081: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 3;
5082: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 0);
5083: orntNew[0] = -2;
5084: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 3);
5085: orntNew[1] = 0;
5086: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 5;
5087: orntNew[2] = 0;
5088: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 0;
5089: orntNew[3] = -2;
5090: DMPlexSetCone(rdm, newp, coneNew);
5091: DMPlexSetConeOrientation(rdm, newp, orntNew);
5092: #if 1
5093: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
5094: for (p = 0; p < 4; ++p) {
5095: 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);
5096: }
5097: #endif
5098: /* E-F face */
5099: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 4;
5100: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 2;
5101: orntNew[0] = -2;
5102: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 2);
5103: orntNew[1] = -2;
5104: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 0);
5105: orntNew[2] = 0;
5106: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 1;
5107: orntNew[3] = 0;
5108: DMPlexSetCone(rdm, newp, coneNew);
5109: DMPlexSetConeOrientation(rdm, newp, orntNew);
5110: #if 1
5111: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
5112: for (p = 0; p < 4; ++p) {
5113: 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);
5114: }
5115: #endif
5116: /* F-G face */
5117: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 5;
5118: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 4;
5119: orntNew[0] = -2;
5120: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 2);
5121: orntNew[1] = -2;
5122: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 1);
5123: orntNew[2] = 0;
5124: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 1;
5125: orntNew[3] = 0;
5126: DMPlexSetCone(rdm, newp, coneNew);
5127: DMPlexSetConeOrientation(rdm, newp, orntNew);
5128: #if 1
5129: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
5130: for (p = 0; p < 4; ++p) {
5131: 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);
5132: }
5133: #endif
5134: /* G-H face */
5135: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 6;
5136: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 2);
5137: orntNew[0] = -2;
5138: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 2);
5139: orntNew[1] = 0;
5140: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 1;
5141: orntNew[2] = 0;
5142: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 3;
5143: orntNew[3] = -2;
5144: DMPlexSetCone(rdm, newp, coneNew);
5145: DMPlexSetConeOrientation(rdm, newp, orntNew);
5146: #if 1
5147: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
5148: for (p = 0; p < 4; ++p) {
5149: 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);
5150: }
5151: #endif
5152: /* E-H face */
5153: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 7;
5154: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 5;
5155: orntNew[0] = -2;
5156: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 1);
5157: orntNew[1] = -2;
5158: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 3);
5159: orntNew[2] = 0;
5160: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 1;
5161: orntNew[3] = 0;
5162: DMPlexSetCone(rdm, newp, coneNew);
5163: DMPlexSetConeOrientation(rdm, newp, orntNew);
5164: #if 1
5165: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
5166: for (p = 0; p < 4; ++p) {
5167: 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);
5168: }
5169: #endif
5170: /* A-E face */
5171: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 8;
5172: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 3);
5173: orntNew[0] = 0;
5174: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 2;
5175: orntNew[1] = 0;
5176: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 5;
5177: orntNew[2] = -2;
5178: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 0);
5179: orntNew[3] = -2;
5180: DMPlexSetCone(rdm, newp, coneNew);
5181: DMPlexSetConeOrientation(rdm, newp, orntNew);
5182: #if 1
5183: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
5184: for (p = 0; p < 4; ++p) {
5185: 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);
5186: }
5187: #endif
5188: /* D-F face */
5189: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 9;
5190: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 1);
5191: orntNew[0] = -2;
5192: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 3);
5193: orntNew[1] = 0;
5194: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 4;
5195: orntNew[2] = 0;
5196: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 2;
5197: orntNew[3] = -2;
5198: DMPlexSetCone(rdm, newp, coneNew);
5199: DMPlexSetConeOrientation(rdm, newp, orntNew);
5200: #if 1
5201: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
5202: for (p = 0; p < 4; ++p) {
5203: 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);
5204: }
5205: #endif
5206: /* C-G face */
5207: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 10;
5208: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 4;
5209: orntNew[0] = -2;
5210: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 1);
5211: orntNew[1] = -2;
5212: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 3);
5213: orntNew[2] = 0;
5214: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 3;
5215: orntNew[3] = 0;
5216: DMPlexSetCone(rdm, newp, coneNew);
5217: DMPlexSetConeOrientation(rdm, newp, orntNew);
5218: #if 1
5219: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
5220: for (p = 0; p < 4; ++p) {
5221: 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);
5222: }
5223: #endif
5224: /* B-H face */
5225: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 11;
5226: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 5;
5227: orntNew[0] = 0;
5228: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 3;
5229: orntNew[1] = -2;
5230: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 1);
5231: orntNew[2] = -2;
5232: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 2);
5233: orntNew[3] = 0;
5234: DMPlexSetCone(rdm, newp, coneNew);
5235: DMPlexSetConeOrientation(rdm, newp, orntNew);
5236: #if 1
5237: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
5238: for (p = 0; p < 4; ++p) {
5239: 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);
5240: }
5241: #endif
5242: for (r = 0; r < 12; ++r) {
5243: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + r;
5244: supportNew[0] = cStartNew + (c - cStart)*8 + newCells[r*2+0];
5245: supportNew[1] = cStartNew + (c - cStart)*8 + newCells[r*2+1];
5246: DMPlexSetSupport(rdm, newp, supportNew);
5247: #if 1
5248: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
5249: for (p = 0; p < 2; ++p) {
5250: 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);
5251: }
5252: #endif
5253: }
5254: }
5255: /* Split edges have 2 vertices and the same faces as the parent */
5256: DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
5257: for (e = eStart; e < eEnd; ++e) {
5258: const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);
5260: for (r = 0; r < 2; ++r) {
5261: const PetscInt newp = eStartNew + (e - eStart)*2 + r;
5262: const PetscInt *cone, *ornt, *support;
5263: PetscInt coneNew[2], coneSize, c, supportSize, s;
5265: DMPlexGetCone(dm, e, &cone);
5266: coneNew[0] = vStartNew + (cone[0] - vStart);
5267: coneNew[1] = vStartNew + (cone[1] - vStart);
5268: coneNew[(r+1)%2] = newv;
5269: DMPlexSetCone(rdm, newp, coneNew);
5270: #if 1
5271: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
5272: for (p = 0; p < 2; ++p) {
5273: 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);
5274: }
5275: #endif
5276: DMPlexGetSupportSize(dm, e, &supportSize);
5277: DMPlexGetSupport(dm, e, &support);
5278: for (s = 0; s < supportSize; ++s) {
5279: DMPlexGetConeSize(dm, support[s], &coneSize);
5280: DMPlexGetCone(dm, support[s], &cone);
5281: DMPlexGetConeOrientation(dm, support[s], &ornt);
5282: for (c = 0; c < coneSize; ++c) {
5283: if (cone[c] == e) break;
5284: }
5285: supportRef[s] = fStartNew + (support[s] - fStart)*4 + (ornt[c] < 0 ? (c+1-r)%4 : (c+r)%4);
5286: }
5287: DMPlexSetSupport(rdm, newp, supportRef);
5288: #if 1
5289: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
5290: for (p = 0; p < supportSize; ++p) {
5291: 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);
5292: }
5293: #endif
5294: }
5295: }
5296: /* Face edges have 2 vertices and 2+cells faces */
5297: for (f = fStart; f < fEnd; ++f) {
5298: 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};
5299: const PetscInt newv = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (f - fStart);
5300: const PetscInt *cone, *coneCell, *orntCell, *support;
5301: PetscInt coneNew[2], coneSize, c, supportSize, s;
5303: DMPlexGetCone(dm, f, &cone);
5304: for (r = 0; r < 4; ++r) {
5305: const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + r;
5307: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - eStart);
5308: coneNew[1] = newv;
5309: DMPlexSetCone(rdm, newp, coneNew);
5310: #if 1
5311: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
5312: for (p = 0; p < 2; ++p) {
5313: 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);
5314: }
5315: #endif
5316: DMPlexGetSupportSize(dm, f, &supportSize);
5317: DMPlexGetSupport(dm, f, &support);
5318: supportRef[0] = fStartNew + (f - fStart)*4 + r;
5319: supportRef[1] = fStartNew + (f - fStart)*4 + (r+1)%4;
5320: for (s = 0; s < supportSize; ++s) {
5321: DMPlexGetConeSize(dm, support[s], &coneSize);
5322: DMPlexGetCone(dm, support[s], &coneCell);
5323: DMPlexGetConeOrientation(dm, support[s], &orntCell);
5324: for (c = 0; c < coneSize; ++c) if (coneCell[c] == f) break;
5325: supportRef[2+s] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*12 + newFaces[c*4 + GetQuadEdgeInverse_Static(orntCell[c], r)];
5326: }
5327: DMPlexSetSupport(rdm, newp, supportRef);
5328: #if 1
5329: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
5330: for (p = 0; p < 2+supportSize; ++p) {
5331: 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);
5332: }
5333: #endif
5334: }
5335: }
5336: /* Cell edges have 2 vertices and 4 faces */
5337: for (c = cStart; c < cEnd; ++c) {
5338: 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};
5339: const PetscInt newv = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (c - cStart);
5340: const PetscInt *cone;
5341: PetscInt coneNew[2], supportNew[4];
5343: DMPlexGetCone(dm, c, &cone);
5344: for (r = 0; r < 6; ++r) {
5345: const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + r;
5347: coneNew[0] = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (cone[r] - fStart);
5348: coneNew[1] = newv;
5349: DMPlexSetCone(rdm, newp, coneNew);
5350: #if 1
5351: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
5352: for (p = 0; p < 2; ++p) {
5353: 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);
5354: }
5355: #endif
5356: for (f = 0; f < 4; ++f) supportNew[f] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + newFaces[r*4+f];
5357: DMPlexSetSupport(rdm, newp, supportNew);
5358: #if 1
5359: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
5360: for (p = 0; p < 4; ++p) {
5361: 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);
5362: }
5363: #endif
5364: }
5365: }
5366: /* Old vertices have identical supports */
5367: for (v = vStart; v < vEnd; ++v) {
5368: const PetscInt newp = vStartNew + (v - vStart);
5369: const PetscInt *support, *cone;
5370: PetscInt size, s;
5372: DMPlexGetSupportSize(dm, v, &size);
5373: DMPlexGetSupport(dm, v, &support);
5374: for (s = 0; s < size; ++s) {
5375: PetscInt r = 0;
5377: DMPlexGetCone(dm, support[s], &cone);
5378: if (cone[1] == v) r = 1;
5379: supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
5380: }
5381: DMPlexSetSupport(rdm, newp, supportRef);
5382: #if 1
5383: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
5384: for (p = 0; p < size; ++p) {
5385: 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);
5386: }
5387: #endif
5388: }
5389: /* Edge vertices have 2 + faces supports */
5390: for (e = eStart; e < eEnd; ++e) {
5391: const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
5392: const PetscInt *cone, *support;
5393: PetscInt size, s;
5395: DMPlexGetSupportSize(dm, e, &size);
5396: DMPlexGetSupport(dm, e, &support);
5397: supportRef[0] = eStartNew + (e - eStart)*2 + 0;
5398: supportRef[1] = eStartNew + (e - eStart)*2 + 1;
5399: for (s = 0; s < size; ++s) {
5400: PetscInt r;
5402: DMPlexGetCone(dm, support[s], &cone);
5403: for (r = 0; r < 4; ++r) if (cone[r] == e) break;
5404: supportRef[2+s] = eStartNew + (eEnd - eStart)*2 + (support[s] - fStart)*4 + r;
5405: }
5406: DMPlexSetSupport(rdm, newp, supportRef);
5407: #if 1
5408: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
5409: for (p = 0; p < 2+size; ++p) {
5410: 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);
5411: }
5412: #endif
5413: }
5414: /* Face vertices have 4 + cells supports */
5415: for (f = fStart; f < fEnd; ++f) {
5416: const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (f - fStart);
5417: const PetscInt *cone, *support;
5418: PetscInt size, s;
5420: DMPlexGetSupportSize(dm, f, &size);
5421: DMPlexGetSupport(dm, f, &support);
5422: for (r = 0; r < 4; ++r) supportRef[r] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + r;
5423: for (s = 0; s < size; ++s) {
5424: PetscInt r;
5426: DMPlexGetCone(dm, support[s], &cone);
5427: for (r = 0; r < 6; ++r) if (cone[r] == f) break;
5428: supportRef[4+s] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (support[s] - cStart)*6 + r;
5429: }
5430: DMPlexSetSupport(rdm, newp, supportRef);
5431: #if 1
5432: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
5433: for (p = 0; p < 4+size; ++p) {
5434: 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);
5435: }
5436: #endif
5437: }
5438: /* Cell vertices have 6 supports */
5439: for (c = cStart; c < cEnd; ++c) {
5440: const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (c - cStart);
5441: PetscInt supportNew[6];
5443: for (r = 0; r < 6; ++r) {
5444: supportNew[r] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + r;
5445: }
5446: DMPlexSetSupport(rdm, newp, supportNew);
5447: }
5448: PetscFree(supportRef);
5449: break;
5450: case REFINER_HYBRID_HEX_3D:
5451: DMPlexGetHybridBounds(rdm, &cMaxNew, &fMaxNew, &eMaxNew, NULL);
5452: /*
5453: Bottom (viewed from top) Top
5454: 1---------2---------2 7---------2---------6
5455: | | | | | |
5456: | B 2 C | | H 2 G |
5457: | | | | | |
5458: 3----3----0----1----1 3----3----0----1----1
5459: | | | | | |
5460: | A 0 D | | E 0 F |
5461: | | | | | |
5462: 0---------0---------3 4---------0---------5
5463: */
5464: /* Interior cells have 6 faces: Bottom, Top, Front, Back, Right, Left */
5465: for (c = cStart; c < cMax; ++c) {
5466: const PetscInt newp = (c - cStart)*8;
5467: const PetscInt *cone, *ornt;
5468: PetscInt coneNew[6], orntNew[6];
5470: DMPlexGetCone(dm, c, &cone);
5471: DMPlexGetConeOrientation(dm, c, &ornt);
5472: /* A hex */
5473: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 0);
5474: orntNew[0] = ornt[0];
5475: coneNew[1] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 8; /* AE */
5476: orntNew[1] = 0;
5477: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 0);
5478: orntNew[2] = ornt[2];
5479: coneNew[3] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 3; /* AB */
5480: orntNew[3] = 0;
5481: coneNew[4] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 0; /* AD */
5482: orntNew[4] = 0;
5483: coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 0);
5484: orntNew[5] = ornt[5];
5485: DMPlexSetCone(rdm, newp+0, coneNew);
5486: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
5487: #if 1
5488: 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);
5489: for (p = 0; p < 6; ++p) {
5490: 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);
5491: }
5492: #endif
5493: /* B hex */
5494: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 1);
5495: orntNew[0] = ornt[0];
5496: coneNew[1] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 11; /* BH */
5497: orntNew[1] = 0;
5498: coneNew[2] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 3; /* AB */
5499: orntNew[2] = -1;
5500: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 1);
5501: orntNew[3] = ornt[3];
5502: coneNew[4] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 2; /* BC */
5503: orntNew[4] = 0;
5504: coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 3);
5505: orntNew[5] = ornt[5];
5506: DMPlexSetCone(rdm, newp+1, coneNew);
5507: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
5508: #if 1
5509: 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);
5510: for (p = 0; p < 6; ++p) {
5511: 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);
5512: }
5513: #endif
5514: /* C hex */
5515: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 2);
5516: orntNew[0] = ornt[0];
5517: coneNew[1] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 10; /* CG */
5518: orntNew[1] = 0;
5519: coneNew[2] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 1; /* CD */
5520: orntNew[2] = -1;
5521: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 0);
5522: orntNew[3] = ornt[3];
5523: coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 1);
5524: orntNew[4] = ornt[4];
5525: coneNew[5] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 2; /* BC */
5526: orntNew[5] = -4;
5527: DMPlexSetCone(rdm, newp+2, coneNew);
5528: DMPlexSetConeOrientation(rdm, newp+2, orntNew);
5529: #if 1
5530: 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);
5531: for (p = 0; p < 6; ++p) {
5532: 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);
5533: }
5534: #endif
5535: /* D hex */
5536: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 3);
5537: orntNew[0] = ornt[0];
5538: coneNew[1] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 9; /* DF */
5539: orntNew[1] = 0;
5540: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 1);
5541: orntNew[2] = ornt[2];
5542: coneNew[3] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 1; /* CD */
5543: orntNew[3] = 0;
5544: coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 0);
5545: orntNew[4] = ornt[4];
5546: coneNew[5] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 0; /* AD */
5547: orntNew[5] = -4;
5548: DMPlexSetCone(rdm, newp+3, coneNew);
5549: DMPlexSetConeOrientation(rdm, newp+3, orntNew);
5550: #if 1
5551: 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);
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: /* E hex */
5557: coneNew[0] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 8; /* AE */
5558: orntNew[0] = -4;
5559: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 0);
5560: orntNew[1] = ornt[1];
5561: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 3);
5562: orntNew[2] = ornt[2];
5563: coneNew[3] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 7; /* EH */
5564: orntNew[3] = 0;
5565: coneNew[4] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 4; /* EF */
5566: orntNew[4] = -1;
5567: coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 1);
5568: orntNew[5] = ornt[5];
5569: DMPlexSetCone(rdm, newp+4, coneNew);
5570: DMPlexSetConeOrientation(rdm, newp+4, orntNew);
5571: #if 1
5572: 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);
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: /* F hex */
5578: coneNew[0] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 9; /* DF */
5579: orntNew[0] = -4;
5580: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 1);
5581: orntNew[1] = ornt[1];
5582: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 2);
5583: orntNew[2] = ornt[2];
5584: coneNew[3] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 5; /* FG */
5585: orntNew[3] = -1;
5586: coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 3);
5587: orntNew[4] = ornt[4];
5588: coneNew[5] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 4; /* EF */
5589: orntNew[5] = 1;
5590: DMPlexSetCone(rdm, newp+5, coneNew);
5591: DMPlexSetConeOrientation(rdm, newp+5, orntNew);
5592: #if 1
5593: 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);
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: /* G hex */
5599: coneNew[0] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 10; /* CG */
5600: orntNew[0] = -4;
5601: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 2);
5602: orntNew[1] = ornt[1];
5603: coneNew[2] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 5; /* FG */
5604: orntNew[2] = 0;
5605: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 3);
5606: orntNew[3] = ornt[3];
5607: coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 2);
5608: orntNew[4] = ornt[4];
5609: coneNew[5] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 6; /* GH */
5610: orntNew[5] = -3;
5611: DMPlexSetCone(rdm, newp+6, coneNew);
5612: DMPlexSetConeOrientation(rdm, newp+6, orntNew);
5613: #if 1
5614: 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);
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: /* H hex */
5620: coneNew[0] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 11; /* BH */
5621: orntNew[0] = -4;
5622: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 3);
5623: orntNew[1] = ornt[1];
5624: coneNew[2] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 7; /* EH */
5625: orntNew[2] = -1;
5626: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 2);
5627: orntNew[3] = ornt[3];
5628: coneNew[4] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 6; /* GH */
5629: orntNew[4] = 3;
5630: coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 2);
5631: orntNew[5] = ornt[5];
5632: DMPlexSetCone(rdm, newp+7, coneNew);
5633: DMPlexSetConeOrientation(rdm, newp+7, orntNew);
5634: #if 1
5635: 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);
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: }
5641: /* Hybrid cells have 6 faces: Front, Back, Sides */
5642: /*
5643: 3---------2---------2
5644: | | |
5645: | D 2 C |
5646: | | |
5647: 3----3----0----1----1
5648: | | |
5649: | A 0 B |
5650: | | |
5651: 0---------0---------1
5652: */
5653: for (c = cMax; c < cEnd; ++c) {
5654: const PetscInt newp = (cMax - cStart)*8 + (c - cMax)*4;
5655: const PetscInt *cone, *ornt, *fornt;
5656: PetscInt coneNew[6], orntNew[6], o, of, i;
5658: DMPlexGetCone(dm, c, &cone);
5659: DMPlexGetConeOrientation(dm, c, &ornt);
5660: DMPlexGetConeOrientation(dm, cone[0], &fornt);
5661: o = ornt[0] < 0 ? -1 : 1;
5662: for (r = 0; r < 4; ++r) {
5663: PetscInt subfA = GetQuadSubface_Static(ornt[0], r);
5664: PetscInt edgeA = GetQuadEdge_Static(ornt[0], r);
5665: PetscInt edgeB = GetQuadEdge_Static(ornt[0], (r+3)%4);
5666: 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]);
5667: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + subfA;
5668: orntNew[0] = ornt[0];
5669: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + subfA;
5670: orntNew[1] = ornt[0];
5671: of = fornt[edgeA] < 0 ? -1 : 1;
5672: i = GetQuadEdgeInverse_Static(ornt[0], r) + 2;
5673: coneNew[i] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (cone[2+edgeA] - fMax)*2 + (o*of < 0 ? 1 : 0);
5674: orntNew[i] = ornt[edgeA];
5675: i = GetQuadEdgeInverse_Static(ornt[0], (r+1)%4) + 2;
5676: coneNew[i] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + edgeA;
5677: orntNew[i] = 0;
5678: i = GetQuadEdgeInverse_Static(ornt[0], (r+2)%4) + 2;
5679: coneNew[i] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + edgeB;
5680: orntNew[i] = -2;
5681: of = fornt[edgeB] < 0 ? -1 : 1;
5682: i = GetQuadEdgeInverse_Static(ornt[0], (r+3)%4) + 2;
5683: coneNew[i] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (cone[2+edgeB] - fMax)*2 + (o*of < 0 ? 0 : 1);
5684: orntNew[i] = ornt[edgeB];
5685: DMPlexSetCone(rdm, newp+r, coneNew);
5686: DMPlexSetConeOrientation(rdm, newp+r, orntNew);
5687: #if 1
5688: 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);
5689: for (p = 0; p < 2; ++p) {
5690: 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);
5691: }
5692: for (p = 2; p < 6; ++p) {
5693: 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);
5694: }
5695: #endif
5696: }
5697: }
5698: /* Interior split faces have 4 edges and the same cells as the parent */
5699: DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
5700: PetscMalloc1(4 + maxSupportSize*2, &supportRef);
5701: for (f = fStart; f < fMax; ++f) {
5702: for (r = 0; r < 4; ++r) {
5703: /* TODO: This can come from GetFaces_Internal() */
5704: 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};
5705: const PetscInt newp = fStartNew + (f - fStart)*4 + r;
5706: const PetscInt *cone, *ornt, *support;
5707: PetscInt coneNew[4], orntNew[4], coneSize, c, supportSize, s;
5709: DMPlexGetCone(dm, f, &cone);
5710: DMPlexGetConeOrientation(dm, f, &ornt);
5711: coneNew[(r+3)%4] = eStartNew + (cone[(r+3)%4] - eStart)*2 + (ornt[(r+3)%4] < 0 ? 0 : 1);
5712: orntNew[(r+3)%4] = ornt[(r+3)%4];
5713: coneNew[(r+0)%4] = eStartNew + (cone[r] - eStart)*2 + (ornt[r] < 0 ? 1 : 0);
5714: orntNew[(r+0)%4] = ornt[r];
5715: coneNew[(r+1)%4] = eStartNew + (eMax - eStart)*2 + (f - fStart)*4 + r;
5716: orntNew[(r+1)%4] = 0;
5717: coneNew[(r+2)%4] = eStartNew + (eMax - eStart)*2 + (f - fStart)*4 + (r+3)%4;
5718: orntNew[(r+2)%4] = -2;
5719: DMPlexSetCone(rdm, newp, coneNew);
5720: DMPlexSetConeOrientation(rdm, newp, orntNew);
5721: #if 1
5722: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
5723: for (p = 0; p < 4; ++p) {
5724: 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);
5725: }
5726: #endif
5727: DMPlexGetSupportSize(dm, f, &supportSize);
5728: DMPlexGetSupport(dm, f, &support);
5729: for (s = 0; s < supportSize; ++s) {
5730: PetscInt subf;
5731: DMPlexGetConeSize(dm, support[s], &coneSize);
5732: DMPlexGetCone(dm, support[s], &cone);
5733: DMPlexGetConeOrientation(dm, support[s], &ornt);
5734: for (c = 0; c < coneSize; ++c) {
5735: if (cone[c] == f) break;
5736: }
5737: subf = GetQuadSubfaceInverse_Static(ornt[c], r);
5738: if (support[s] < cMax) {
5739: supportRef[s] = cStartNew + (support[s] - cStart)*8 + newCells[c*4+subf];
5740: } else {
5741: supportRef[s] = cStartNew + (cMax - cStart)*8 + (support[s] - cMax)*4 + subf;
5742: }
5743: }
5744: DMPlexSetSupport(rdm, newp, supportRef);
5745: #if 1
5746: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
5747: for (p = 0; p < supportSize; ++p) {
5748: 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);
5749: }
5750: #endif
5751: }
5752: }
5753: /* Interior cell faces have 4 edges and 2 cells */
5754: for (c = cStart; c < cMax; ++c) {
5755: 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};
5756: const PetscInt *cone, *ornt;
5757: PetscInt newp, coneNew[4], orntNew[4], supportNew[2];
5759: DMPlexGetCone(dm, c, &cone);
5760: DMPlexGetConeOrientation(dm, c, &ornt);
5761: /* A-D face */
5762: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 0;
5763: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 3);
5764: orntNew[0] = 0;
5765: coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 0;
5766: orntNew[1] = 0;
5767: coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 2;
5768: orntNew[2] = -2;
5769: coneNew[3] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 0);
5770: orntNew[3] = -2;
5771: DMPlexSetCone(rdm, newp, coneNew);
5772: DMPlexSetConeOrientation(rdm, newp, orntNew);
5773: #if 1
5774: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
5775: for (p = 0; p < 4; ++p) {
5776: 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);
5777: }
5778: #endif
5779: /* C-D face */
5780: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 1;
5781: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 2);
5782: orntNew[0] = 0;
5783: coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 0;
5784: orntNew[1] = 0;
5785: coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 4;
5786: orntNew[2] = -2;
5787: coneNew[3] = eStartNew + (eMax - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 0);
5788: orntNew[3] = -2;
5789: DMPlexSetCone(rdm, newp, coneNew);
5790: DMPlexSetConeOrientation(rdm, newp, orntNew);
5791: #if 1
5792: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
5793: for (p = 0; p < 4; ++p) {
5794: 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);
5795: }
5796: #endif
5797: /* B-C face */
5798: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 2;
5799: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 1);
5800: orntNew[0] = -2;
5801: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 0);
5802: orntNew[1] = 0;
5803: coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 3;
5804: orntNew[2] = 0;
5805: coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 0;
5806: orntNew[3] = -2;
5807: DMPlexSetCone(rdm, newp, coneNew);
5808: DMPlexSetConeOrientation(rdm, newp, orntNew);
5809: #if 1
5810: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
5811: for (p = 0; p < 4; ++p) {
5812: 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);
5813: }
5814: #endif
5815: /* A-B face */
5816: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 3;
5817: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 0);
5818: orntNew[0] = -2;
5819: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 3);
5820: orntNew[1] = 0;
5821: coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 5;
5822: orntNew[2] = 0;
5823: coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 0;
5824: orntNew[3] = -2;
5825: DMPlexSetCone(rdm, newp, coneNew);
5826: DMPlexSetConeOrientation(rdm, newp, orntNew);
5827: #if 1
5828: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
5829: for (p = 0; p < 4; ++p) {
5830: 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);
5831: }
5832: #endif
5833: /* E-F face */
5834: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 4;
5835: coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 2;
5836: orntNew[0] = -2;
5837: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 2);
5838: orntNew[1] = -2;
5839: coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 0);
5840: orntNew[2] = 0;
5841: coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 1;
5842: orntNew[3] = 0;
5843: DMPlexSetCone(rdm, newp, coneNew);
5844: DMPlexSetConeOrientation(rdm, newp, orntNew);
5845: #if 1
5846: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
5847: for (p = 0; p < 4; ++p) {
5848: 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);
5849: }
5850: #endif
5851: /* F-G face */
5852: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 5;
5853: coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 4;
5854: orntNew[0] = -2;
5855: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 2);
5856: orntNew[1] = -2;
5857: coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 1);
5858: orntNew[2] = 0;
5859: coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 1;
5860: orntNew[3] = 0;
5861: DMPlexSetCone(rdm, newp, coneNew);
5862: DMPlexSetConeOrientation(rdm, newp, orntNew);
5863: #if 1
5864: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
5865: for (p = 0; p < 4; ++p) {
5866: 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);
5867: }
5868: #endif
5869: /* G-H face */
5870: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 6;
5871: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 2);
5872: orntNew[0] = -2;
5873: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 2);
5874: orntNew[1] = 0;
5875: coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 1;
5876: orntNew[2] = 0;
5877: coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 3;
5878: orntNew[3] = -2;
5879: DMPlexSetCone(rdm, newp, coneNew);
5880: DMPlexSetConeOrientation(rdm, newp, orntNew);
5881: #if 1
5882: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
5883: for (p = 0; p < 4; ++p) {
5884: 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);
5885: }
5886: #endif
5887: /* E-H face */
5888: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 7;
5889: coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 5;
5890: orntNew[0] = -2;
5891: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 1);
5892: orntNew[1] = -2;
5893: coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 3);
5894: orntNew[2] = 0;
5895: coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 1;
5896: orntNew[3] = 0;
5897: DMPlexSetCone(rdm, newp, coneNew);
5898: DMPlexSetConeOrientation(rdm, newp, orntNew);
5899: #if 1
5900: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
5901: for (p = 0; p < 4; ++p) {
5902: 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);
5903: }
5904: #endif
5905: /* A-E face */
5906: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 8;
5907: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 3);
5908: orntNew[0] = 0;
5909: coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 2;
5910: orntNew[1] = 0;
5911: coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 5;
5912: orntNew[2] = -2;
5913: coneNew[3] = eStartNew + (eMax - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 0);
5914: orntNew[3] = -2;
5915: DMPlexSetCone(rdm, newp, coneNew);
5916: DMPlexSetConeOrientation(rdm, newp, orntNew);
5917: #if 1
5918: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
5919: for (p = 0; p < 4; ++p) {
5920: 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);
5921: }
5922: #endif
5923: /* D-F face */
5924: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 9;
5925: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 1);
5926: orntNew[0] = -2;
5927: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 3);
5928: orntNew[1] = 0;
5929: coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 4;
5930: orntNew[2] = 0;
5931: coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 2;
5932: orntNew[3] = -2;
5933: DMPlexSetCone(rdm, newp, coneNew);
5934: DMPlexSetConeOrientation(rdm, newp, orntNew);
5935: #if 1
5936: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
5937: for (p = 0; p < 4; ++p) {
5938: 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);
5939: }
5940: #endif
5941: /* C-G face */
5942: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 10;
5943: coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 4;
5944: orntNew[0] = -2;
5945: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 1);
5946: orntNew[1] = -2;
5947: coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 3);
5948: orntNew[2] = 0;
5949: coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 3;
5950: orntNew[3] = 0;
5951: DMPlexSetCone(rdm, newp, coneNew);
5952: DMPlexSetConeOrientation(rdm, newp, orntNew);
5953: #if 1
5954: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
5955: for (p = 0; p < 4; ++p) {
5956: 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);
5957: }
5958: #endif
5959: /* B-H face */
5960: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 11;
5961: coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 5;
5962: orntNew[0] = 0;
5963: coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 3;
5964: orntNew[1] = -2;
5965: coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 1);
5966: orntNew[2] = -2;
5967: coneNew[3] = eStartNew + (eMax - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 2);
5968: orntNew[3] = 0;
5969: DMPlexSetCone(rdm, newp, coneNew);
5970: DMPlexSetConeOrientation(rdm, newp, orntNew);
5971: #if 1
5972: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
5973: for (p = 0; p < 4; ++p) {
5974: 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);
5975: }
5976: #endif
5977: for (r = 0; r < 12; ++r) {
5978: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + r;
5979: supportNew[0] = cStartNew + (c - cStart)*8 + newCells[r*2+0];
5980: supportNew[1] = cStartNew + (c - cStart)*8 + newCells[r*2+1];
5981: DMPlexSetSupport(rdm, newp, supportNew);
5982: #if 1
5983: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
5984: for (p = 0; p < 2; ++p) {
5985: 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);
5986: }
5987: #endif
5988: }
5989: }
5990: /* Hybrid split faces have 4 edges and same cells */
5991: for (f = fMax; f < fEnd; ++f) {
5992: const PetscInt *cone, *ornt, *support;
5993: PetscInt coneNew[4], orntNew[4];
5994: PetscInt supportNew[2], size, s, c;
5996: DMPlexGetCone(dm, f, &cone);
5997: DMPlexGetConeOrientation(dm, f, &ornt);
5998: DMPlexGetSupportSize(dm, f, &size);
5999: DMPlexGetSupport(dm, f, &support);
6000: for (r = 0; r < 2; ++r) {
6001: const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (f - fMax)*2 + r;
6003: coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1-r : r);
6004: orntNew[0] = ornt[0];
6005: coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1-r : r);
6006: orntNew[1] = ornt[1];
6007: coneNew[2+r] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (cone[2+r] - eMax);
6008: orntNew[2+r] = 0;
6009: coneNew[3-r] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (f - fMax);
6010: orntNew[3-r] = 0;
6011: DMPlexSetCone(rdm, newp, coneNew);
6012: DMPlexSetConeOrientation(rdm, newp, orntNew);
6013: #if 1
6014: if ((newp < fMaxNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", newp, fMaxNew, fEndNew);
6015: for (p = 0; p < 2; ++p) {
6016: 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);
6017: }
6018: for (p = 2; p < 4; ++p) {
6019: 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);
6020: }
6021: #endif
6022: for (s = 0; s < size; ++s) {
6023: const PetscInt *coneCell, *orntCell, *fornt;
6024: PetscInt o, of;
6026: DMPlexGetCone(dm, support[s], &coneCell);
6027: DMPlexGetConeOrientation(dm, support[s], &orntCell);
6028: o = orntCell[0] < 0 ? -1 : 1;
6029: for (c = 2; c < 6; ++c) if (coneCell[c] == f) break;
6030: if (c >= 6) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find face %d in cone of cell %d", f, support[s]);
6031: DMPlexGetConeOrientation(dm, coneCell[0], &fornt);
6032: of = fornt[c-2] < 0 ? -1 : 1;
6033: supportNew[s] = cStartNew + (cMax - cStart)*8 + (support[s] - cMax)*4 + (GetQuadEdgeInverse_Static(orntCell[0], c-2) + (o*of < 0 ? 1-r : r))%4;
6034: }
6035: DMPlexSetSupport(rdm, newp, supportNew);
6036: #if 1
6037: if ((newp < fMaxNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", newp, fMaxNew, fEndNew);
6038: for (p = 0; p < size; ++p) {
6039: 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);
6040: }
6041: #endif
6042: }
6043: }
6044: /* Hybrid cell faces have 4 edges and 2 cells */
6045: for (c = cMax; c < cEnd; ++c) {
6046: PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4;
6047: const PetscInt *cone, *ornt;
6048: PetscInt coneNew[4], orntNew[4];
6049: PetscInt supportNew[2];
6051: DMPlexGetCone(dm, c, &cone);
6052: DMPlexGetConeOrientation(dm, c, &ornt);
6053: for (r = 0; r < 4; ++r) {
6054: #if 0
6055: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], r);
6056: orntNew[0] = 0;
6057: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], r);
6058: orntNew[1] = 0;
6059: coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (cone[2+GetQuadEdge_Static(ornt[0], r)] - fMax);
6060: orntNew[2] = 0;
6061: coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (fEnd - fMax) + (c - cMax);
6062: orntNew[3] = 0;
6063: #else
6064: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + r;
6065: orntNew[0] = 0;
6066: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + r;
6067: orntNew[1] = 0;
6068: coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (cone[2+r] - fMax);
6069: orntNew[2] = 0;
6070: coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (fEnd - fMax) + (c - cMax);
6071: orntNew[3] = 0;
6072: #endif
6073: DMPlexSetCone(rdm, newp+r, coneNew);
6074: DMPlexSetConeOrientation(rdm, newp+r, orntNew);
6075: #if 1
6076: 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);
6077: for (p = 0; p < 2; ++p) {
6078: 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);
6079: }
6080: for (p = 2; p < 4; ++p) {
6081: 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);
6082: }
6083: #endif
6084: supportNew[0] = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + GetQuadSubface_Static(ornt[0], r);
6085: supportNew[1] = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + GetQuadSubface_Static(ornt[0], (r+1)%4);
6086: DMPlexSetSupport(rdm, newp+r, supportNew);
6087: #if 1
6088: 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);
6089: for (p = 0; p < 2; ++p) {
6090: 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);
6091: }
6092: #endif
6093: }
6094: }
6095: /* Interior split edges have 2 vertices and the same faces as the parent */
6096: DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
6097: for (e = eStart; e < eMax; ++e) {
6098: const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);
6100: for (r = 0; r < 2; ++r) {
6101: const PetscInt newp = eStartNew + (e - eStart)*2 + r;
6102: const PetscInt *cone, *ornt, *support;
6103: PetscInt coneNew[2], coneSize, c, supportSize, s;
6105: DMPlexGetCone(dm, e, &cone);
6106: coneNew[0] = vStartNew + (cone[0] - vStart);
6107: coneNew[1] = vStartNew + (cone[1] - vStart);
6108: coneNew[(r+1)%2] = newv;
6109: DMPlexSetCone(rdm, newp, coneNew);
6110: #if 1
6111: if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
6112: for (p = 0; p < 2; ++p) {
6113: 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);
6114: }
6115: #endif
6116: DMPlexGetSupportSize(dm, e, &supportSize);
6117: DMPlexGetSupport(dm, e, &support);
6118: for (s = 0; s < supportSize; ++s) {
6119: DMPlexGetConeSize(dm, support[s], &coneSize);
6120: DMPlexGetCone(dm, support[s], &cone);
6121: DMPlexGetConeOrientation(dm, support[s], &ornt);
6122: for (c = 0; c < coneSize; ++c) {
6123: if (cone[c] == e) break;
6124: }
6125: if (support[s] < fMax) {
6126: supportRef[s] = fStartNew + (support[s] - fStart)*4 + (c + (ornt[c] < 0 ? 1-r : r))%4;
6127: } else {
6128: supportRef[s] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (support[s] - fMax)*2 + (ornt[c] < 0 ? 1-r : r);
6129: }
6130: }
6131: DMPlexSetSupport(rdm, newp, supportRef);
6132: #if 1
6133: if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
6134: for (p = 0; p < supportSize; ++p) {
6135: 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);
6136: }
6137: #endif
6138: }
6139: }
6140: /* Interior face edges have 2 vertices and 2+cells faces */
6141: for (f = fStart; f < fMax; ++f) {
6142: 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};
6143: const PetscInt newv = vStartNew + (vEnd - vStart) + (eMax - eStart) + (f - fStart);
6144: const PetscInt *cone, *coneCell, *orntCell, *support;
6145: PetscInt coneNew[2], coneSize, c, supportSize, s;
6147: DMPlexGetCone(dm, f, &cone);
6148: for (r = 0; r < 4; ++r) {
6149: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (f - fStart)*4 + r;
6151: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - eStart);
6152: coneNew[1] = newv;
6153: DMPlexSetCone(rdm, newp, coneNew);
6154: #if 1
6155: if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
6156: for (p = 0; p < 2; ++p) {
6157: 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);
6158: }
6159: #endif
6160: DMPlexGetSupportSize(dm, f, &supportSize);
6161: DMPlexGetSupport(dm, f, &support);
6162: supportRef[0] = fStartNew + (f - fStart)*4 + r;
6163: supportRef[1] = fStartNew + (f - fStart)*4 + (r+1)%4;
6164: for (s = 0; s < supportSize; ++s) {
6165: DMPlexGetConeSize(dm, support[s], &coneSize);
6166: DMPlexGetCone(dm, support[s], &coneCell);
6167: DMPlexGetConeOrientation(dm, support[s], &orntCell);
6168: for (c = 0; c < coneSize; ++c) if (coneCell[c] == f) break;
6169: if (support[s] < cMax) {
6170: supportRef[2+s] = fStartNew + (fMax - fStart)*4 + (support[s] - cStart)*12 + newFaces[c*4 + GetQuadEdgeInverse_Static(orntCell[c], r)];
6171: } else {
6172: supportRef[2+s] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (support[s] - cMax)*4 + r;
6173: }
6174: }
6175: DMPlexSetSupport(rdm, newp, supportRef);
6176: #if 1
6177: if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
6178: for (p = 0; p < 2+supportSize; ++p) {
6179: 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);
6180: }
6181: #endif
6182: }
6183: }
6184: /* Interior cell edges have 2 vertices and 4 faces */
6185: for (c = cStart; c < cMax; ++c) {
6186: 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};
6187: const PetscInt newv = vStartNew + (vEnd - vStart) + (eMax - eStart) + (fMax - fStart) + (c - cStart);
6188: const PetscInt *cone;
6189: PetscInt coneNew[2], supportNew[4];
6191: DMPlexGetCone(dm, c, &cone);
6192: for (r = 0; r < 6; ++r) {
6193: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + r;
6195: coneNew[0] = vStartNew + (vEnd - vStart) + (eMax - eStart) + (cone[r] - fStart);
6196: coneNew[1] = newv;
6197: DMPlexSetCone(rdm, newp, coneNew);
6198: #if 1
6199: if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
6200: for (p = 0; p < 2; ++p) {
6201: 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);
6202: }
6203: #endif
6204: for (f = 0; f < 4; ++f) supportNew[f] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + newFaces[r*4+f];
6205: DMPlexSetSupport(rdm, newp, supportNew);
6206: #if 1
6207: if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
6208: for (p = 0; p < 4; ++p) {
6209: 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);
6210: }
6211: #endif
6212: }
6213: }
6214: /* Hybrid edges have two vertices and the same faces */
6215: for (e = eMax; e < eEnd; ++e) {
6216: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (e - eMax);
6217: const PetscInt *cone, *support, *fcone;
6218: PetscInt coneNew[2], size, fsize, s;
6220: DMPlexGetCone(dm, e, &cone);
6221: DMPlexGetSupportSize(dm, e, &size);
6222: DMPlexGetSupport(dm, e, &support);
6223: coneNew[0] = vStartNew + (cone[0] - vStart);
6224: coneNew[1] = vStartNew + (cone[1] - vStart);
6225: DMPlexSetCone(rdm, newp, coneNew);
6226: #if 1
6227: if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
6228: for (p = 0; p < 2; ++p) {
6229: 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);
6230: }
6231: #endif
6232: for (s = 0; s < size; ++s) {
6233: DMPlexGetConeSize(dm, support[s], &fsize);
6234: DMPlexGetCone(dm, support[s], &fcone);
6235: for (c = 0; c < fsize; ++c) if (fcone[c] == e) break;
6236: if ((c < 2) || (c > 3)) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge %d not found in cone of face %d", e, support[s]);
6237: supportRef[s] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (support[s] - fMax)*2 + c-2;
6238: }
6239: DMPlexSetSupport(rdm, newp, supportRef);
6240: #if 1
6241: if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
6242: for (p = 0; p < size; ++p) {
6243: 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);
6244: }
6245: #endif
6246: }
6247: /* Hybrid face edges have 2 vertices and 2+cells faces */
6248: for (f = fMax; f < fEnd; ++f) {
6249: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (f - fMax);
6250: const PetscInt *cone, *support, *ccone, *cornt;
6251: PetscInt coneNew[2], size, csize, s;
6253: DMPlexGetCone(dm, f, &cone);
6254: DMPlexGetSupportSize(dm, f, &size);
6255: DMPlexGetSupport(dm, f, &support);
6256: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - eStart);
6257: coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - eStart);
6258: DMPlexSetCone(rdm, newp, coneNew);
6259: #if 1
6260: if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
6261: for (p = 0; p < 2; ++p) {
6262: 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);
6263: }
6264: #endif
6265: supportRef[0] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (f - fMax)*2 + 0;
6266: supportRef[1] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (f - fMax)*2 + 1;
6267: for (s = 0; s < size; ++s) {
6268: DMPlexGetConeSize(dm, support[s], &csize);
6269: DMPlexGetCone(dm, support[s], &ccone);
6270: DMPlexGetConeOrientation(dm, support[s], &cornt);
6271: for (c = 0; c < csize; ++c) if (ccone[c] == f) break;
6272: 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]);
6273: supportRef[2+s] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (support[s] - cMax)*4 + c-2;
6274: }
6275: DMPlexSetSupport(rdm, newp, supportRef);
6276: #if 1
6277: if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
6278: for (p = 0; p < 2+size; ++p) {
6279: 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);
6280: }
6281: #endif
6282: }
6283: /* Hybrid cell edges have 2 vertices and 4 faces */
6284: for (c = cMax; c < cEnd; ++c) {
6285: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (fEnd - fMax) + (c - cMax);
6286: const PetscInt *cone, *support;
6287: PetscInt coneNew[2], size;
6289: DMPlexGetCone(dm, c, &cone);
6290: DMPlexGetSupportSize(dm, c, &size);
6291: DMPlexGetSupport(dm, c, &support);
6292: coneNew[0] = vStartNew + (vEnd - vStart) + (eMax - eStart) + (cone[0] - fStart);
6293: coneNew[1] = vStartNew + (vEnd - vStart) + (eMax - eStart) + (cone[1] - fStart);
6294: DMPlexSetCone(rdm, newp, coneNew);
6295: #if 1
6296: if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
6297: for (p = 0; p < 2; ++p) {
6298: 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);
6299: }
6300: #endif
6301: supportRef[0] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + 0;
6302: supportRef[1] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + 1;
6303: supportRef[2] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + 2;
6304: supportRef[3] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + 3;
6305: DMPlexSetSupport(rdm, newp, supportRef);
6306: #if 1
6307: if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
6308: for (p = 0; p < 4; ++p) {
6309: 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);
6310: }
6311: #endif
6312: }
6313: /* Interior vertices have identical supports */
6314: for (v = vStart; v < vEnd; ++v) {
6315: const PetscInt newp = vStartNew + (v - vStart);
6316: const PetscInt *support, *cone;
6317: PetscInt size, s;
6319: DMPlexGetSupportSize(dm, v, &size);
6320: DMPlexGetSupport(dm, v, &support);
6321: for (s = 0; s < size; ++s) {
6322: PetscInt r = 0;
6324: DMPlexGetCone(dm, support[s], &cone);
6325: if (cone[1] == v) r = 1;
6326: if (support[s] < eMax) supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
6327: else supportRef[s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (support[s] - eMax);
6328: }
6329: DMPlexSetSupport(rdm, newp, supportRef);
6330: #if 1
6331: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
6332: for (p = 0; p < size; ++p) {
6333: 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);
6334: }
6335: #endif
6336: }
6337: /* Interior edge vertices have 2 + faces supports */
6338: for (e = eStart; e < eMax; ++e) {
6339: const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
6340: const PetscInt *cone, *support;
6341: PetscInt size, s;
6343: DMPlexGetSupportSize(dm, e, &size);
6344: DMPlexGetSupport(dm, e, &support);
6345: supportRef[0] = eStartNew + (e - eStart)*2 + 0;
6346: supportRef[1] = eStartNew + (e - eStart)*2 + 1;
6347: for (s = 0; s < size; ++s) {
6348: PetscInt r;
6350: DMPlexGetCone(dm, support[s], &cone);
6351: for (r = 0; r < 4; ++r) if (cone[r] == e) break;
6352: if (support[s] < fMax) {
6353: supportRef[2+s] = eStartNew + (eMax - eStart)*2 + (support[s] - fStart)*4 + r;
6354: } else {
6355: supportRef[2+s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (support[s] - fMax);
6356: }
6357: }
6358: DMPlexSetSupport(rdm, newp, supportRef);
6359: #if 1
6360: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
6361: for (p = 0; p < 2+size; ++p) {
6362: 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);
6363: }
6364: #endif
6365: }
6366: /* Interior face vertices have 4 + cells supports */
6367: for (f = fStart; f < fMax; ++f) {
6368: const PetscInt newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (f - fStart);
6369: const PetscInt *cone, *support;
6370: PetscInt size, s;
6372: DMPlexGetSupportSize(dm, f, &size);
6373: DMPlexGetSupport(dm, f, &support);
6374: for (r = 0; r < 4; ++r) supportRef[r] = eStartNew + (eMax - eStart)*2 + (f - fStart)*4 + r;
6375: for (s = 0; s < size; ++s) {
6376: PetscInt r;
6378: DMPlexGetCone(dm, support[s], &cone);
6379: for (r = 0; r < 6; ++r) if (cone[r] == f) break;
6380: if (support[s] < cMax) {
6381: supportRef[4+s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (support[s] - cStart)*6 + r;
6382: } else {
6383: supportRef[4+s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (fEnd - fMax) + (support[s] - cMax);
6384: }
6385: }
6386: DMPlexSetSupport(rdm, newp, supportRef);
6387: #if 1
6388: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
6389: for (p = 0; p < 4+size; ++p) {
6390: 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);
6391: }
6392: #endif
6393: }
6394: /* Cell vertices have 6 supports */
6395: for (c = cStart; c < cMax; ++c) {
6396: const PetscInt newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (fMax - fStart) + (c - cStart);
6397: PetscInt supportNew[6];
6399: for (r = 0; r < 6; ++r) {
6400: supportNew[r] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + r;
6401: }
6402: DMPlexSetSupport(rdm, newp, supportNew);
6403: }
6404: PetscFree(supportRef);
6405: break;
6406: default:
6407: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
6408: }
6409: return(0);
6410: }
6412: static PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
6413: {
6414: PetscSection coordSection, coordSectionNew;
6415: Vec coordinates, coordinatesNew;
6416: PetscScalar *coords, *coordsNew;
6417: const PetscInt numVertices = depthSize ? depthSize[0] : 0;
6418: PetscInt dim, spaceDim, depth, bs, coordSizeNew, cStart, cEnd, cMax;
6419: PetscInt c, vStart, vStartNew, vEnd, v, eStart, eEnd, eMax, e, fStart, fEnd, fMax, f;
6420: PetscInt cStartNew, cEndNew, vEndNew, *parentId = NULL;
6421: VecType vtype;
6422: PetscBool isperiodic, localize = PETSC_FALSE, needcoords = PETSC_FALSE;
6423: const PetscReal *maxCell, *L;
6424: const DMBoundaryType *bd;
6425: PetscErrorCode ierr;
6428: DMGetDimension(dm, &dim);
6429: DMPlexGetDepth(dm, &depth);
6430: DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
6431: DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);
6432: DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
6433: DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);
6434: DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, NULL);
6435: GetDepthStart_Private(depth, depthSize, &cStartNew, NULL, NULL, &vStartNew);
6436: GetDepthEnd_Private(depth, depthSize, &cEndNew, NULL, NULL, &vEndNew);
6437: DMGetCoordinateSection(dm, &coordSection);
6438: PetscSectionGetFieldComponents(coordSection, 0, &spaceDim);
6439: PetscSectionCreate(PetscObjectComm((PetscObject)dm), &coordSectionNew);
6440: PetscSectionSetNumFields(coordSectionNew, 1);
6441: PetscSectionSetFieldComponents(coordSectionNew, 0, spaceDim);
6442: DMGetPeriodicity(dm, &isperiodic, &maxCell, &L, &bd);
6443: DMSetPeriodicity(rdm, isperiodic, maxCell, L, bd);
6444: /* Determine if we need to localize coordinates when generating them */
6445: if (isperiodic && !maxCell) {
6446: DMGetCoordinatesLocalized(dm, &localize);
6447: if (!localize) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Cannot refine if coordinates have not been localized");
6448: }
6449: if (localize) {
6450: PetscInt p, r, newp, *pi;
6452: /* New coordinates will be already localized on the cell */
6453: PetscSectionSetChart(coordSectionNew, 0, vStartNew+numVertices);
6455: /* We need the parentId to properly localize coordinates */
6456: PetscMalloc1(cEndNew-cStartNew,&pi);
6457: switch (refiner) {
6458: case REFINER_NOOP:
6459: break;
6460: case REFINER_SIMPLEX_1D:
6461: for (p = cStart; p < cEnd; ++p) {
6462: for (r = 0; r < 2; ++r) {
6463: newp = (p - cStart)*2 + r;
6464: pi[newp] = p;
6465: }
6466: }
6467: break;
6468: case REFINER_SIMPLEX_2D:
6469: for (p = cStart; p < cEnd; ++p) {
6470: for (r = 0; r < 4; ++r) {
6471: newp = (p - cStart)*4 + r;
6472: pi[newp] = p;
6473: }
6474: }
6475: break;
6476: case REFINER_HEX_2D:
6477: for (p = cStart; p < cEnd; ++p) {
6478: for (r = 0; r < 4; ++r) {
6479: newp = (p - cStart)*4 + r;
6480: pi[newp] = p;
6481: }
6482: }
6483: break;
6484: case REFINER_SIMPLEX_TO_HEX_2D:
6485: for (p = cStart; p < cEnd; ++p) {
6486: for (r = 0; r < 3; ++r) {
6487: newp = (p - cStart)*3 + r;
6488: pi[newp] = p;
6489: }
6490: }
6491: break;
6492: case REFINER_HYBRID_SIMPLEX_2D:
6493: for (p = cStart; p < cMax; ++p) {
6494: for (r = 0; r < 4; ++r) {
6495: newp = (p - cStart)*4 + r;
6496: pi[newp] = p;
6497: }
6498: }
6499: for (p = cMax; p < cEnd; ++p) {
6500: for (r = 0; r < 2; ++r) {
6501: newp = (cMax - cStart)*4 + (p - cMax)*2 + r;
6502: pi[newp] = p;
6503: }
6504: }
6505: break;
6506: case REFINER_HYBRID_HEX_2D:
6507: for (p = cStart; p < cMax; ++p) {
6508: for (r = 0; r < 4; ++r) {
6509: newp = (p - cStart)*4 + r;
6510: pi[newp] = p;
6511: }
6512: }
6513: for (p = cMax; p < cEnd; ++p) {
6514: for (r = 0; r < 2; ++r) {
6515: newp = (cMax - cStart)*4 + (p - cMax)*2 + r;
6516: pi[newp] = p;
6517: }
6518: }
6519: break;
6520: case REFINER_SIMPLEX_3D:
6521: for (p = cStart; p < cEnd; ++p) {
6522: for (r = 0; r < 8; ++r) {
6523: newp = (p - cStart)*8 + r;
6524: pi[newp] = p;
6525: }
6526: }
6527: break;
6528: case REFINER_HYBRID_SIMPLEX_3D:
6529: for (p = cStart; p < cMax; ++p) {
6530: for (r = 0; r < 8; ++r) {
6531: newp = (p - cStart)*8 + r;
6532: pi[newp] = p;
6533: }
6534: }
6535: for (p = cMax; p < cEnd; ++p) {
6536: for (r = 0; r < 4; ++r) {
6537: newp = (cMax - cStart)*8 + (p - cMax)*4 + r;
6538: pi[newp] = p;
6539: }
6540: }
6541: break;
6542: case REFINER_SIMPLEX_TO_HEX_3D:
6543: for (p = cStart; p < cEnd; ++p) {
6544: for (r = 0; r < 4; ++r) {
6545: newp = (p - cStart)*4 + r;
6546: pi[newp] = p;
6547: }
6548: }
6549: break;
6550: case REFINER_HEX_3D:
6551: for (p = cStart; p < cEnd; ++p) {
6552: for (r = 0; r < 8; ++r) {
6553: newp = (p - cStart)*8 + r;
6554: pi[newp] = p;
6555: }
6556: }
6557: break;
6558: case REFINER_HYBRID_HEX_3D:
6559: for (p = cStart; p < cMax; ++p) {
6560: for (r = 0; r < 8; ++r) {
6561: newp = (p - cStart)*8 + r;
6562: pi[newp] = p;
6563: }
6564: }
6565: for (p = cMax; p < cEnd; ++p) {
6566: for (r = 0; r < 4; ++r) {
6567: newp = (cMax - cStart)*8 + (p - cMax)*4 + r;
6568: pi[newp] = p;
6569: }
6570: }
6571: break;
6572: default:
6573: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
6574: }
6575: parentId = pi;
6576: } else {
6577: PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+numVertices);
6578: }
6579: if (cMax < 0) cMax = cEnd;
6580: if (fMax < 0) fMax = fEnd;
6581: if (eMax < 0) eMax = eEnd;
6583: /* All vertices have the spaceDim coordinates */
6584: if (localize) {
6585: PetscInt c;
6587: for (c = cStartNew; c < cEndNew; ++c) {
6588: PetscInt *cone = NULL;
6589: PetscInt closureSize, coneSize = 0, p, pdof;
6591: PetscSectionGetDof(coordSection, parentId[c], &pdof);
6592: if (pdof) { /* localize on all cells that are refinement of a localized parent cell */
6593: DMPlexGetTransitiveClosure(rdm, c, PETSC_TRUE, &closureSize, &cone);
6594: for (p = 0; p < closureSize*2; p += 2) {
6595: const PetscInt point = cone[p];
6596: if ((point >= vStartNew) && (point < vEndNew)) coneSize++;
6597: }
6598: DMPlexRestoreTransitiveClosure(rdm, c, PETSC_TRUE, &closureSize, &cone);
6599: PetscSectionSetDof(coordSectionNew, c, coneSize*spaceDim);
6600: PetscSectionSetFieldDof(coordSectionNew, c, 0, coneSize*spaceDim);
6601: }
6602: }
6603: }
6604: for (v = vStartNew; v < vStartNew+numVertices; ++v) {
6605: PetscSectionSetDof(coordSectionNew, v, spaceDim);
6606: PetscSectionSetFieldDof(coordSectionNew, v, 0, spaceDim);
6607: }
6608: PetscSectionSetUp(coordSectionNew);
6609: DMSetCoordinateSection(rdm, PETSC_DETERMINE, coordSectionNew);
6610: DMGetCoordinatesLocal(dm, &coordinates);
6611: PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);
6612: VecCreate(PETSC_COMM_SELF, &coordinatesNew);
6613: PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");
6614: VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);
6615: VecGetBlockSize(coordinates, &bs);
6616: VecSetBlockSize(coordinatesNew, bs);
6617: VecGetType(coordinates, &vtype);
6618: VecSetType(coordinatesNew, vtype);
6619: VecGetArray(coordinates, &coords);
6620: VecGetArray(coordinatesNew, &coordsNew);
6622: switch (refiner) {
6623: case REFINER_NOOP: break;
6624: case REFINER_SIMPLEX_TO_HEX_3D:
6625: case REFINER_HEX_3D:
6626: case REFINER_HYBRID_HEX_3D:
6627: /* Face vertices have the average of corner coordinates */
6628: for (f = fStart; f < fMax; ++f) {
6629: const PetscInt newv = vStartNew + (vEnd - vStart) + (eMax - eStart) + (f - fStart);
6630: PetscInt *cone = NULL;
6631: PetscInt closureSize, coneSize = 0, off[8], offnew, p, d;
6633: DMPlexGetTransitiveClosure(dm, f, PETSC_TRUE, &closureSize, &cone);
6634: for (p = 0; p < closureSize*2; p += 2) {
6635: const PetscInt point = cone[p];
6636: if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point;
6637: }
6638: if (localize) {
6639: const PetscInt *support = NULL;
6640: PetscInt *rStar = NULL;
6641: PetscInt supportSize, rStarSize, coff, s, ccoff[8];
6642: PetscBool cellfound = PETSC_FALSE;
6644: DMPlexGetTransitiveClosure(rdm, newv, PETSC_FALSE, &rStarSize, &rStar);
6645: DMPlexGetSupportSize(dm,f,&supportSize);
6646: DMPlexGetSupport(dm,f,&support);
6647: /* Compute average of coordinates for each cell sharing the face */
6648: for (s = 0; s < supportSize; ++s) {
6649: PetscScalar coordsNewAux[3] = { 0.0, 0.0, 0.0 };
6650: PetscInt *cellCone = NULL;
6651: PetscInt cellClosureSize, cellConeSize = 0, cdof;
6652: const PetscInt cell = support[s];
6653: PetscBool copyoff = PETSC_FALSE;
6655: DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &cellClosureSize, &cellCone);
6656: for (p = 0; p < cellClosureSize*2; p += 2) {
6657: const PetscInt point = cellCone[p];
6658: if ((point >= vStart) && (point < vEnd)) cellCone[cellConeSize++] = point;
6659: }
6660: PetscSectionGetDof(coordSection, cell, &cdof);
6661: if (!cdof) { /* the parent cell does not have localized coordinates */
6662: cellfound = PETSC_TRUE;
6663: for (v = 0; v < coneSize; ++v) {
6664: PetscSectionGetOffset(coordSection, cone[v], &off[v]);
6665: for (d = 0; d < spaceDim; ++d) coordsNewAux[d] += coords[off[v]+d];
6666: }
6667: for (d = 0; d < spaceDim; ++d) coordsNewAux[d] /= coneSize;
6668: } else {
6669: PetscSectionGetOffset(coordSection, cell, &coff);
6670: for (p = 0; p < coneSize; ++p) {
6671: const PetscInt tv = cone[p];
6672: PetscInt cv, voff;
6673: PetscBool locv = PETSC_TRUE;
6675: for (cv = 0; cv < cellConeSize; ++cv) {
6676: if (cellCone[cv] == tv) {
6677: ccoff[p] = spaceDim*cv + coff;
6678: break;
6679: }
6680: }
6681: if (cv == cellConeSize) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unable to map vertex %D\n",tv);
6683: PetscSectionGetOffset(coordSection, cone[p], &voff);
6684: for (d = 0; d < spaceDim; ++d) {
6685: coordsNewAux[d] += coords[ccoff[p]+d];
6686: if (!cellfound && coords[voff+d] != coords[ccoff[p]+d]) locv = PETSC_FALSE;
6687: }
6688: if (locv && !cellfound) {
6689: cellfound = PETSC_TRUE;
6690: copyoff = PETSC_TRUE;
6691: }
6692: }
6693: for (d = 0; d < spaceDim; ++d) coordsNewAux[d] /= coneSize;
6695: /* Found a valid face for the "vertex" part of the Section (physical space)
6696: i.e., a face that has at least one corner in the physical space */
6697: if (copyoff) for (p = 0; p < coneSize; ++p) off[p] = ccoff[p];
6698: }
6700: /* Localize new coordinates on each refined cell */
6701: for (v = 0; v < rStarSize*2; v += 2) {
6702: if ((rStar[v] >= cStartNew) && (rStar[v] < cEndNew) && parentId[rStar[v]-cStartNew] == cell) {
6703: PetscInt *rcone = NULL, rclosureSize, lid, rcdof, rcoff;
6704: const PetscInt rcell = rStar[v];
6706: PetscSectionGetDof(coordSectionNew, rcell, &rcdof);
6707: if (!rcdof) continue;
6708: PetscSectionGetOffset(coordSectionNew, rcell, &rcoff);
6709: DMPlexGetTransitiveClosure(rdm, rcell, PETSC_TRUE, &rclosureSize, &rcone);
6710: for (p = 0, lid = 0; p < rclosureSize*2; p += 2) {
6711: if (rcone[p] == newv) {
6712: for (d = 0; d < spaceDim; d++) coordsNew[rcoff + lid*spaceDim + d] = coordsNewAux[d];
6713: break;
6714: }
6715: if (rcone[p] >= vStartNew && rcone[p] < vEndNew) lid++;
6716: }
6717: DMPlexRestoreTransitiveClosure(rdm, rcell, PETSC_TRUE, &rclosureSize, &rcone);
6718: if (p == closureSize*2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unable to map new vertex %D\n",newv);
6719: }
6720: }
6721: DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &cellClosureSize, &cellCone);
6722: }
6723: DMPlexRestoreTransitiveClosure(rdm, newv, PETSC_FALSE, &rStarSize, &rStar);
6724: if (!cellfound) {
6725: /* Could not find a valid face for the vertex part, we will get this vertex later (final reduction) */
6726: needcoords = PETSC_TRUE;
6727: coneSize = 0;
6728: }
6729: } else {
6730: for (v = 0; v < coneSize; ++v) {
6731: PetscSectionGetOffset(coordSection, cone[v], &off[v]);
6732: }
6733: }
6734: PetscSectionGetOffset(coordSectionNew, newv, &offnew);
6735: if (coneSize) {
6736: for (d = 0; d < spaceDim; ++d) coordsNew[offnew+d] = 0.0;
6737: for (v = 0; v < coneSize; ++v) {DMLocalizeAddCoordinate_Internal(dm, spaceDim, &coords[off[0]], &coords[off[v]], &coordsNew[offnew]);}
6738: for (d = 0; d < spaceDim; ++d) coordsNew[offnew+d] /= coneSize;
6739: } else {
6740: for (d = 0; d < spaceDim; ++d) coordsNew[offnew+d] = PETSC_MIN_REAL;
6741: }
6742: DMPlexRestoreTransitiveClosure(dm, f, PETSC_TRUE, &closureSize, &cone);
6743: }
6744: case REFINER_SIMPLEX_TO_HEX_2D:
6745: case REFINER_HEX_2D:
6746: case REFINER_HYBRID_HEX_2D:
6747: case REFINER_SIMPLEX_1D:
6748: /* Cell vertices have the average of corner coordinates */
6749: for (c = cStart; c < cMax; ++c) {
6750: const PetscInt newv = vStartNew + (vEnd - vStart) + (dim > 1 ? (eMax - eStart) : 0) + (c - cStart) + (dim > 2 ? (fMax - fStart) : 0);
6751: PetscInt *cone = NULL;
6752: PetscInt closureSize, coneSize = 0, off[8], offnew, p, d, cdof = 0;
6754: DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);
6755: for (p = 0; p < closureSize*2; p += 2) {
6756: const PetscInt point = cone[p];
6757: if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point;
6758: }
6759: if (localize) {
6760: PetscSectionGetDof(coordSection, c, &cdof);
6761: }
6762: if (cdof) {
6763: PetscInt coff;
6765: PetscSectionGetOffset(coordSection, c, &coff);
6766: for (v = 0; v < coneSize; ++v) off[v] = spaceDim*v + coff;
6767: } else {
6768: for (v = 0; v < coneSize; ++v) {
6769: PetscSectionGetOffset(coordSection, cone[v], &off[v]);
6770: }
6771: }
6772: PetscSectionGetOffset(coordSectionNew, newv, &offnew);
6773: for (d = 0; d < spaceDim; ++d) coordsNew[offnew+d] = 0.0;
6774: for (v = 0; v < coneSize; ++v) {DMLocalizeAddCoordinate_Internal(dm, spaceDim, &coords[off[0]], &coords[off[v]], &coordsNew[offnew]);}
6775: for (d = 0; d < spaceDim; ++d) coordsNew[offnew+d] /= coneSize;
6776: DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);
6778: /* Localize new coordinates on each refined cell */
6779: if (cdof) {
6780: PetscInt *rStar = NULL, rStarSize;
6782: DMPlexGetTransitiveClosure(rdm, newv, PETSC_FALSE, &rStarSize, &rStar);
6783: for (v = 0; v < rStarSize*2; v += 2) {
6784: if ((rStar[v] >= cStartNew) && (rStar[v] < cEndNew)) {
6785: PetscInt *cone = NULL, closureSize, lid, coff, rc, rcdof;
6787: rc = rStar[v];
6788: PetscSectionGetDof(coordSectionNew, rc, &rcdof);
6789: if (!rcdof) continue;
6790: PetscSectionGetOffset(coordSectionNew, rc, &coff);
6791: DMPlexGetTransitiveClosure(rdm, rc, PETSC_TRUE, &closureSize, &cone);
6792: for (p = 0, lid = 0; p < closureSize*2; p += 2) {
6793: if (cone[p] == newv) {
6794: for (d = 0; d < spaceDim; d++) coordsNew[coff + lid*spaceDim + d] = coordsNew[offnew + d];
6795: break;
6796: }
6797: if (cone[p] >= vStartNew && cone[p] < vEndNew) lid++;
6798: }
6799: if (p == closureSize*2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unable to map new vertex %D\n",newv);
6800: DMPlexRestoreTransitiveClosure(rdm, rc, PETSC_TRUE, &closureSize, &cone);
6801: }
6802: }
6803: DMPlexRestoreTransitiveClosure(rdm, newv, PETSC_FALSE, &rStarSize, &rStar);
6804: }
6805: }
6806: case REFINER_SIMPLEX_2D:
6807: case REFINER_HYBRID_SIMPLEX_2D:
6808: case REFINER_SIMPLEX_3D:
6809: case REFINER_HYBRID_SIMPLEX_3D:
6810: /* Edge vertices have the average of endpoint coordinates */
6811: for (e = eStart; e < eMax; ++e) {
6812: const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);
6813: const PetscInt *cone;
6814: PetscInt coneSize, offA, offB, offnew, d;
6816: DMPlexGetConeSize(dm, e, &coneSize);
6817: if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %d cone should have two vertices, not %d", e, coneSize);
6818: DMPlexGetCone(dm, e, &cone);
6819: if (localize) {
6820: PetscInt coff, toffA = -1, toffB = -1, voffA, voffB;
6821: PetscInt *eStar = NULL, eStarSize;
6822: PetscInt *rStar = NULL, rStarSize;
6823: PetscBool cellfound = PETSC_FALSE;
6825: offA = offB = -1;
6826: PetscSectionGetOffset(coordSection, cone[0], &voffA);
6827: PetscSectionGetOffset(coordSection, cone[1], &voffB);
6828: DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &eStarSize, &eStar);
6829: DMPlexGetTransitiveClosure(rdm, newv, PETSC_FALSE, &rStarSize, &rStar);
6830: for (v = 0; v < eStarSize*2; v += 2) {
6831: if ((eStar[v] >= cStart) && (eStar[v] < cEnd)) {
6832: PetscScalar coordsNewAux[3];
6833: PetscInt *cellCone = NULL;
6834: PetscInt cellClosureSize, s, cv, cdof;
6835: PetscBool locvA = PETSC_TRUE, locvB = PETSC_TRUE;
6836: const PetscInt cell = eStar[v];
6838: PetscSectionGetDof(coordSection, cell, &cdof);
6839: if (!cdof) {
6840: /* Found a valid edge for the "vertex" part of the Section */
6841: offA = voffA;
6842: offB = voffB;
6843: cellfound = PETSC_TRUE;
6844: } else {
6845: PetscSectionGetOffset(coordSection, cell, &coff);
6846: DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &cellClosureSize, &cellCone);
6847: for (s = 0, cv = 0; s < cellClosureSize*2; s += 2) {
6848: const PetscInt point = cellCone[s];
6849: if ((point >= vStart) && (point < vEnd)) {
6850: if (point == cone[0]) toffA = spaceDim*cv + coff;
6851: else if (point == cone[1]) toffB = spaceDim*cv + coff;
6852: cv++;
6853: }
6854: }
6855: DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &cellClosureSize, &cellCone);
6856: for (d = 0; d < spaceDim; ++d) {
6857: coordsNewAux[d] = 0.5*(coords[toffA+d] + coords[toffB+d]);
6858: if (coords[toffA+d] != coords[voffA+d]) locvA = PETSC_FALSE;
6859: if (coords[toffB+d] != coords[voffB+d]) locvB = PETSC_FALSE;
6860: }
6861: /* Found a valid edge for the "vertex" part of the Section */
6862: if (!cellfound && (locvA || locvB)) {
6863: cellfound = PETSC_TRUE;
6864: offA = toffA;
6865: offB = toffB;
6866: }
6867: }
6869: /* Localize new coordinates on each refined cell */
6870: for (s = 0; s < rStarSize*2; s += 2) {
6871: if ((rStar[s] >= cStartNew) && (rStar[s] < cEndNew) && parentId[rStar[s]-cStartNew] == cell) {
6872: PetscInt *rcone = NULL, rclosureSize, lid, p, rcdof;
6873: const PetscInt rcell = rStar[s];
6875: PetscSectionGetDof(coordSectionNew, rcell, &rcdof);
6876: if (!rcdof) continue;
6877: PetscSectionGetOffset(coordSectionNew, rcell, &coff);
6878: DMPlexGetTransitiveClosure(rdm, rcell, PETSC_TRUE, &rclosureSize, &rcone);
6879: for (p = 0, lid = 0; p < rclosureSize*2; p += 2) {
6880: if (rcone[p] == newv) {
6881: for (d = 0; d < spaceDim; d++) coordsNew[coff + lid*spaceDim + d] = coordsNewAux[d];
6882: break;
6883: }
6884: if (rcone[p] >= vStartNew && rcone[p] < vEndNew) lid++;
6885: }
6886: DMPlexRestoreTransitiveClosure(rdm, rcell, PETSC_TRUE, &rclosureSize, &rcone);
6887: if (p == rclosureSize*2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unable to map new vertex %D\n",newv);
6888: }
6889: }
6890: }
6891: }
6892: DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &eStarSize, &eStar);
6893: DMPlexRestoreTransitiveClosure(rdm, newv, PETSC_FALSE, &rStarSize, &rStar);
6894: if (!cellfound) {
6895: /* Could not find a valid edge for the vertex part, we will get this vertex later (final reduction) */
6896: needcoords = PETSC_TRUE;
6897: }
6898: } else {
6899: PetscSectionGetOffset(coordSection, cone[0], &offA);
6900: PetscSectionGetOffset(coordSection, cone[1], &offB);
6901: }
6902: PetscSectionGetOffset(coordSectionNew, newv, &offnew);
6903: if (offA != -1 && offB != -1) {
6904: DMLocalizeCoordinate_Internal(dm, spaceDim, &coords[offA], &coords[offB], &coordsNew[offnew]);
6905: for (d = 0; d < spaceDim; ++d) {
6906: coordsNew[offnew+d] = 0.5*(coords[offA+d] + coordsNew[offnew+d]);
6907: }
6908: } else {
6909: for (d = 0; d < spaceDim; ++d) coordsNew[offnew+d] = PETSC_MIN_REAL;
6910: }
6911: }
6912: /* Old vertices have the same coordinates */
6913: for (v = vStart; v < vEnd; ++v) {
6914: const PetscInt newv = vStartNew + (v - vStart);
6915: PetscInt off, offnew, d;
6917: PetscSectionGetOffset(coordSection, v, &off);
6918: PetscSectionGetOffset(coordSectionNew, newv, &offnew);
6919: for (d = 0; d < spaceDim; ++d) {
6920: coordsNew[offnew+d] = coords[off+d];
6921: }
6923: /* Localize new coordinates on each refined cell */
6924: if (localize) {
6925: PetscInt p;
6926: PetscInt *rStar = NULL, rStarSize;
6928: DMPlexGetTransitiveClosure(rdm, newv, PETSC_FALSE, &rStarSize, &rStar);
6929: for (p = 0; p < rStarSize*2; p += 2) {
6930: if ((rStar[p] >= cStartNew) && (rStar[p] < cEndNew)) {
6931: PetscScalar ocoords[3];
6932: PetscInt *cone = NULL, closureSize, lid, coff, s, oc, cdof;
6934: c = rStar[p];
6935: oc = parentId[c-cStartNew];
6936: PetscSectionGetDof(coordSectionNew, c, &cdof);
6937: if (!cdof) continue;
6938: PetscSectionGetDof(coordSection, oc, &cdof);
6939: if (!cdof) continue;
6940: PetscSectionGetOffset(coordSection, oc, &coff);
6941: DMPlexGetTransitiveClosure(dm, oc, PETSC_TRUE, &closureSize, &cone);
6942: for (s = 0, lid = 0; s < closureSize*2; s += 2) {
6943: if (cone[s] == v) {
6944: for (d = 0; d < spaceDim; d++) ocoords[d] = coords[coff + lid*spaceDim + d];
6945: break;
6946: }
6947: if (cone[s] >= vStart && cone[s] < vEnd) lid++;
6948: }
6949: if (s == closureSize*2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unable to map old vertex %D\n",v);
6950: DMPlexRestoreTransitiveClosure(dm, oc, PETSC_TRUE, &closureSize, &cone);
6952: PetscSectionGetOffset(coordSectionNew, c, &coff);
6953: DMPlexGetTransitiveClosure(rdm, c, PETSC_TRUE, &closureSize, &cone);
6954: for (s = 0, lid = 0; s < closureSize*2; s += 2) {
6955: if (cone[s] == newv) {
6956: for (d = 0; d < spaceDim; d++) coordsNew[coff + lid*spaceDim + d] = ocoords[d];
6957: break;
6958: }
6959: if (cone[s] >= vStartNew && cone[s] < vEndNew) lid++;
6960: }
6961: if (s == closureSize*2) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unable to map new vertex %D\n",newv);
6962: DMPlexRestoreTransitiveClosure(rdm, c, PETSC_TRUE, &closureSize, &cone);
6963: }
6964: }
6965: DMPlexRestoreTransitiveClosure(rdm, newv, PETSC_FALSE, &rStarSize, &rStar);
6966: }
6967: }
6968: break;
6969: default:
6970: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
6971: }
6972: VecRestoreArray(coordinates, &coords);
6973: VecRestoreArray(coordinatesNew, &coordsNew);
6974: DMSetCoordinatesLocal(rdm, coordinatesNew);
6976: /* Final reduction (if needed) if we are localizing */
6977: if (localize) {
6978: PetscBool gred;
6980: MPIU_Allreduce(&needcoords, &gred, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)rdm));
6981: if (gred) {
6982: DM cdm;
6983: Vec aux;
6984: PetscSF sf;
6985: const PetscScalar *lArray;
6986: PetscScalar *gArray;
6988: DMGetCoordinateDM(rdm, &cdm);
6989: DMCreateGlobalVector(cdm, &aux);
6990: DMGetDefaultSF(cdm, &sf);
6991: VecGetArrayRead(coordinatesNew, &lArray);
6992: VecSet(aux, PETSC_MIN_REAL);
6993: VecGetArray(aux, &gArray);
6994: PetscSFReduceBegin(sf, MPIU_SCALAR, lArray, gArray, MPIU_MAX);
6995: PetscSFReduceEnd(sf, MPIU_SCALAR, lArray, gArray, MPIU_MAX);
6996: VecRestoreArrayRead(coordinatesNew, &lArray);
6997: VecRestoreArray(aux, &gArray);
6998: DMGlobalToLocalBegin(cdm, aux, INSERT_VALUES, coordinatesNew);
6999: DMGlobalToLocalEnd(cdm, aux, INSERT_VALUES, coordinatesNew);
7000: VecDestroy(&aux);
7001: }
7002: }
7003: VecDestroy(&coordinatesNew);
7004: PetscSectionDestroy(&coordSectionNew);
7005: PetscFree(parentId);
7006: return(0);
7007: }
7009: /*@
7010: DMPlexCreateProcessSF - Create an SF which just has process connectivity
7012: Collective on DM
7014: Input Parameters:
7015: + dm - The DM
7016: - sfPoint - The PetscSF which encodes point connectivity
7018: Output Parameters:
7019: + processRanks - A list of process neighbors, or NULL
7020: - sfProcess - An SF encoding the process connectivity, or NULL
7022: Level: developer
7024: .seealso: PetscSFCreate(), DMPlexCreateTwoSidedProcessSF()
7025: @*/
7026: PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess)
7027: {
7028: PetscInt numRoots, numLeaves, l;
7029: const PetscInt *localPoints;
7030: const PetscSFNode *remotePoints;
7031: PetscInt *localPointsNew;
7032: PetscSFNode *remotePointsNew;
7033: PetscInt *ranks, *ranksNew;
7034: PetscMPIInt size;
7035: PetscErrorCode ierr;
7042: MPI_Comm_size(PetscObjectComm((PetscObject) dm), &size);
7043: PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);
7044: PetscMalloc1(numLeaves, &ranks);
7045: for (l = 0; l < numLeaves; ++l) {
7046: ranks[l] = remotePoints[l].rank;
7047: }
7048: PetscSortRemoveDupsInt(&numLeaves, ranks);
7049: PetscMalloc1(numLeaves, &ranksNew);
7050: PetscMalloc1(numLeaves, &localPointsNew);
7051: PetscMalloc1(numLeaves, &remotePointsNew);
7052: for (l = 0; l < numLeaves; ++l) {
7053: ranksNew[l] = ranks[l];
7054: localPointsNew[l] = l;
7055: remotePointsNew[l].index = 0;
7056: remotePointsNew[l].rank = ranksNew[l];
7057: }
7058: PetscFree(ranks);
7059: if (processRanks) {ISCreateGeneral(PetscObjectComm((PetscObject)dm), numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);}
7060: else {PetscFree(ranksNew);}
7061: if (sfProcess) {
7062: PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess);
7063: PetscObjectSetName((PetscObject) *sfProcess, "Process SF");
7064: PetscSFSetFromOptions(*sfProcess);
7065: PetscSFSetGraph(*sfProcess, size, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);
7066: }
7067: return(0);
7068: }
7070: static PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
7071: {
7072: PetscSF sf, sfNew, sfProcess;
7073: IS processRanks;
7074: MPI_Datatype depthType;
7075: PetscInt numRoots, numLeaves, numLeavesNew = 0, l, m;
7076: const PetscInt *localPoints, *neighbors;
7077: const PetscSFNode *remotePoints;
7078: PetscInt *localPointsNew;
7079: PetscSFNode *remotePointsNew;
7080: PetscInt *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew;
7081: PetscInt ldepth, depth, numNeighbors, pStartNew, pEndNew, cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax, r, n;
7082: PetscInt cStartNew = 0, vStartNew = 0, fStartNew = 0, eStartNew = 0;
7083: PetscErrorCode ierr;
7086: DMPlexGetChart(rdm, &pStartNew, &pEndNew);
7087: DMPlexGetDepth(dm, &ldepth);
7088: MPIU_Allreduce(&ldepth, &depth, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject) dm));
7089: if ((ldepth >= 0) && (depth != ldepth)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Inconsistent Plex depth %d != %d", ldepth, depth);
7090: DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
7091: DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);
7092: DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
7093: DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);
7094: DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);
7095: cMax = cMax < 0 ? cEnd : cMax;
7096: fMax = fMax < 0 ? fEnd : fMax;
7097: eMax = eMax < 0 ? eEnd : eMax;
7098: if (refiner) {GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);}
7099: DMGetPointSF(dm, &sf);
7100: DMGetPointSF(rdm, &sfNew);
7101: /* Calculate size of new SF */
7102: PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);
7103: if (numRoots < 0) return(0);
7104: for (l = 0; l < numLeaves; ++l) {
7105: const PetscInt p = localPoints[l];
7107: switch (refiner) {
7108: case REFINER_SIMPLEX_1D:
7109: if ((p >= vStart) && (p < vEnd)) {
7110: /* Interior vertices stay the same */
7111: ++numLeavesNew;
7112: } else if ((p >= cStart && p < cMax)) {
7113: /* Interior cells add new cells and interior vertices */
7114: numLeavesNew += 2 + 1;
7115: }
7116: break;
7117: case REFINER_SIMPLEX_2D:
7118: case REFINER_HYBRID_SIMPLEX_2D:
7119: if ((p >= vStart) && (p < vEnd)) {
7120: /* Interior vertices stay the same */
7121: ++numLeavesNew;
7122: } else if ((p >= fStart) && (p < fMax)) {
7123: /* Interior faces add new faces and vertex */
7124: numLeavesNew += 2 + 1;
7125: } else if ((p >= fMax) && (p < fEnd)) {
7126: /* Hybrid faces stay the same */
7127: ++numLeavesNew;
7128: } else if ((p >= cStart) && (p < cMax)) {
7129: /* Interior cells add new cells and interior faces */
7130: numLeavesNew += 4 + 3;
7131: } else if ((p >= cMax) && (p < cEnd)) {
7132: /* Hybrid cells add new cells and hybrid face */
7133: numLeavesNew += 2 + 1;
7134: }
7135: break;
7136: case REFINER_SIMPLEX_TO_HEX_2D:
7137: if ((p >= vStart) && (p < vEnd)) {
7138: /* Interior vertices stay the same */
7139: ++numLeavesNew;
7140: } else if ((p >= fStart) && (p < fEnd)) {
7141: /* Interior faces add new faces and vertex */
7142: numLeavesNew += 2 + 1;
7143: } else if ((p >= cStart) && (p < cEnd)) {
7144: /* Interior cells add new cells, interior faces, and vertex */
7145: numLeavesNew += 3 + 3 + 1;
7146: }
7147: break;
7148: case REFINER_HEX_2D:
7149: case REFINER_HYBRID_HEX_2D:
7150: if ((p >= vStart) && (p < vEnd)) {
7151: /* Interior vertices stay the same */
7152: ++numLeavesNew;
7153: } else if ((p >= fStart) && (p < fMax)) {
7154: /* Interior faces add new faces and vertex */
7155: numLeavesNew += 2 + 1;
7156: } else if ((p >= fMax) && (p < fEnd)) {
7157: /* Hybrid faces stay the same */
7158: ++numLeavesNew;
7159: } else if ((p >= cStart) && (p < cMax)) {
7160: /* Interior cells add new cells, interior faces, and vertex */
7161: numLeavesNew += 4 + 4 + 1;
7162: } else if ((p >= cMax) && (p < cEnd)) {
7163: /* Hybrid cells add new cells and hybrid face */
7164: numLeavesNew += 2 + 1;
7165: }
7166: break;
7167: case REFINER_SIMPLEX_3D:
7168: case REFINER_HYBRID_SIMPLEX_3D:
7169: if ((p >= vStart) && (p < vEnd)) {
7170: /* Interior vertices stay the same */
7171: ++numLeavesNew;
7172: } else if ((p >= eStart) && (p < eMax)) {
7173: /* Interior edges add new edges and vertex */
7174: numLeavesNew += 2 + 1;
7175: } else if ((p >= eMax) && (p < eEnd)) {
7176: /* Hybrid edges stay the same */
7177: ++numLeavesNew;
7178: } else if ((p >= fStart) && (p < fMax)) {
7179: /* Interior faces add new faces and edges */
7180: numLeavesNew += 4 + 3;
7181: } else if ((p >= fMax) && (p < fEnd)) {
7182: /* Hybrid faces add new faces and edges */
7183: numLeavesNew += 2 + 1;
7184: } else if ((p >= cStart) && (p < cMax)) {
7185: /* Interior cells add new cells, faces, and edges */
7186: numLeavesNew += 8 + 8 + 1;
7187: } else if ((p >= cMax) && (p < cEnd)) {
7188: /* Hybrid cells add new cells and faces */
7189: numLeavesNew += 4 + 3;
7190: }
7191: break;
7192: case REFINER_SIMPLEX_TO_HEX_3D:
7193: if ((p >= vStart) && (p < vEnd)) {
7194: /* Interior vertices stay the same */
7195: ++numLeavesNew;
7196: } else if ((p >= eStart) && (p < eEnd)) {
7197: /* Interior edges add new edges and vertex */
7198: numLeavesNew += 2 + 1;
7199: } else if ((p >= fStart) && (p < fEnd)) {
7200: /* Interior faces add new faces, edges and a vertex */
7201: numLeavesNew += 3 + 3 + 1;
7202: } else if ((p >= cStart) && (p < cEnd)) {
7203: /* Interior cells add new cells, faces, edges and a vertex */
7204: numLeavesNew += 4 + 6 + 4 + 1;
7205: }
7206: break;
7207: case REFINER_HEX_3D:
7208: case REFINER_HYBRID_HEX_3D:
7209: if ((p >= vStart) && (p < vEnd)) {
7210: /* Old vertices stay the same */
7211: ++numLeavesNew;
7212: } else if ((p >= eStart) && (p < eMax)) {
7213: /* Interior edges add new edges, and vertex */
7214: numLeavesNew += 2 + 1;
7215: } else if ((p >= eMax) && (p < eEnd)) {
7216: /* Hybrid edges stay the same */
7217: ++numLeavesNew;
7218: } else if ((p >= fStart) && (p < fMax)) {
7219: /* Interior faces add new faces, edges, and vertex */
7220: numLeavesNew += 4 + 4 + 1;
7221: } else if ((p >= fMax) && (p < fEnd)) {
7222: /* Hybrid faces add new faces and edges */
7223: numLeavesNew += 2 + 1;
7224: } else if ((p >= cStart) && (p < cMax)) {
7225: /* Interior cells add new cells, faces, edges, and vertex */
7226: numLeavesNew += 8 + 12 + 6 + 1;
7227: } else if ((p >= cStart) && (p < cEnd)) {
7228: /* Hybrid cells add new cells, faces, and edges */
7229: numLeavesNew += 4 + 4 + 1;
7230: }
7231: break;
7232: default:
7233: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
7234: }
7235: }
7236: /* Communicate depthSizes for each remote rank */
7237: DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);
7238: ISGetLocalSize(processRanks, &numNeighbors);
7239: PetscMalloc5((depth+1)*numNeighbors,&rdepthSize,numNeighbors,&rvStartNew,numNeighbors,&reStartNew,numNeighbors,&rfStartNew,numNeighbors,&rcStartNew);
7240: PetscMalloc7(depth+1,&depthSizeOld,(depth+1)*numNeighbors,&rdepthSizeOld,(depth+1)*numNeighbors,&rdepthMaxOld,numNeighbors,&rvStart,numNeighbors,&reStart,numNeighbors,&rfStart,numNeighbors,&rcStart);
7241: MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);
7242: MPI_Type_commit(&depthType);
7243: PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);
7244: PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);
7245: for (n = 0; n < numNeighbors; ++n) {
7246: GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);
7247: }
7248: depthSizeOld[depth] = cMax;
7249: depthSizeOld[0] = vMax;
7250: depthSizeOld[depth-1] = fMax;
7251: depthSizeOld[1] = eMax;
7253: PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);
7254: PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);
7256: depthSizeOld[depth] = cEnd - cStart;
7257: depthSizeOld[0] = vEnd - vStart;
7258: depthSizeOld[depth-1] = fEnd - fStart;
7259: depthSizeOld[1] = eEnd - eStart;
7261: PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);
7262: PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);
7263: for (n = 0; n < numNeighbors; ++n) {
7264: GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);
7265: rdepthMaxOld[n*(depth+1)+depth] = rdepthMaxOld[n*(depth+1)+depth] < 0 ? rdepthSizeOld[n*(depth+1)+depth] +rcStart[n]: rdepthMaxOld[n*(depth+1)+depth];
7266: 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];
7267: rdepthMaxOld[n*(depth+1)+1] = rdepthMaxOld[n*(depth+1)+1] < 0 ? rdepthSizeOld[n*(depth+1)+1] +reStart[n]: rdepthMaxOld[n*(depth+1)+1];
7268: }
7269: MPI_Type_free(&depthType);
7270: PetscSFDestroy(&sfProcess);
7271: /* Calculate new point SF */
7272: PetscMalloc1(numLeavesNew, &localPointsNew);
7273: PetscMalloc1(numLeavesNew, &remotePointsNew);
7274: ISGetIndices(processRanks, &neighbors);
7275: for (l = 0, m = 0; l < numLeaves; ++l) {
7276: PetscInt p = localPoints[l];
7277: PetscInt rp = remotePoints[l].index, n;
7278: PetscMPIInt rrank = remotePoints[l].rank;
7280: PetscFindInt(rrank, numNeighbors, neighbors, &n);
7281: if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank);
7282: switch (refiner) {
7283: case REFINER_SIMPLEX_1D:
7284: if ((p >= vStart) && (p < vEnd)) {
7285: /* Old vertices stay the same */
7286: localPointsNew[m] = vStartNew + (p - vStart);
7287: remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
7288: remotePointsNew[m].rank = rrank;
7289: ++m;
7290: } else if ((p >= cStart) && (p < cMax)) {
7291: /* Old interior cells add new cells and vertex */
7292: for (r = 0; r < 2; ++r, ++m) {
7293: localPointsNew[m] = cStartNew + (p - cStart)*2 + r;
7294: remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*2 + r;
7295: remotePointsNew[m].rank = rrank;
7296: }
7297: localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - cStart);
7298: remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rcStart[n]);
7299: remotePointsNew[m].rank = rrank;
7300: ++m;
7301: }
7302: break;
7303: case REFINER_SIMPLEX_2D:
7304: case REFINER_HYBRID_SIMPLEX_2D:
7305: if ((p >= vStart) && (p < vEnd)) {
7306: /* Old vertices stay the same */
7307: localPointsNew[m] = vStartNew + (p - vStart);
7308: remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
7309: remotePointsNew[m].rank = rrank;
7310: ++m;
7311: } else if ((p >= fStart) && (p < fMax)) {
7312: /* Old interior faces add new faces and vertex */
7313: for (r = 0; r < 2; ++r, ++m) {
7314: localPointsNew[m] = fStartNew + (p - fStart)*2 + r;
7315: remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
7316: remotePointsNew[m].rank = rrank;
7317: }
7318: localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart);
7319: remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
7320: remotePointsNew[m].rank = rrank;
7321: ++m;
7322: } else if ((p >= fMax) && (p < fEnd)) {
7323: /* Old hybrid faces stay the same */
7324: localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - fMax);
7325: remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]);
7326: remotePointsNew[m].rank = rrank;
7327: ++m;
7328: } else if ((p >= cStart) && (p < cMax)) {
7329: /* Old interior cells add new cells and interior faces */
7330: for (r = 0; r < 4; ++r, ++m) {
7331: localPointsNew[m] = cStartNew + (p - cStart)*4 + r;
7332: remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
7333: remotePointsNew[m].rank = rrank;
7334: }
7335: for (r = 0; r < 3; ++r, ++m) {
7336: localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - cStart)*3 + r;
7337: remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r;
7338: remotePointsNew[m].rank = rrank;
7339: }
7340: } else if ((p >= cMax) && (p < cEnd)) {
7341: /* Old hybrid cells add new cells and hybrid face */
7342: for (r = 0; r < 2; ++r, ++m) {
7343: localPointsNew[m] = cStartNew + (p - cStart)*4 + r;
7344: remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
7345: remotePointsNew[m].rank = rrank;
7346: }
7347: localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax);
7348: 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]);
7349: remotePointsNew[m].rank = rrank;
7350: ++m;
7351: }
7352: break;
7353: case REFINER_SIMPLEX_TO_HEX_2D:
7354: if ((p >= vStart) && (p < vEnd)) {
7355: /* Old vertices stay the same */
7356: localPointsNew[m] = vStartNew + (p - vStart);
7357: remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
7358: remotePointsNew[m].rank = rrank;
7359: ++m;
7360: } else if ((p >= fStart) && (p < fEnd)) {
7361: /* Old interior faces add new faces and vertex */
7362: for (r = 0; r < 2; ++r, ++m) {
7363: localPointsNew[m] = fStartNew + (p - fStart)*2 + r;
7364: remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
7365: remotePointsNew[m].rank = rrank;
7366: }
7367: localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart);
7368: remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
7369: remotePointsNew[m].rank = rrank;
7370: ++m;
7371: } else if ((p >= cStart) && (p < cEnd)) {
7372: /* Old interior cells add new cells, interior faces, and a vertex */
7373: for (r = 0; r < 3; ++r, ++m) {
7374: localPointsNew[m] = cStartNew + (p - cStart)*3 + r;
7375: remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*3 + r;
7376: remotePointsNew[m].rank = rrank;
7377: }
7378: for (r = 0; r < 3; ++r, ++m) {
7379: localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r;
7380: remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r;
7381: remotePointsNew[m].rank = rrank;
7382: }
7383: localPointsNew[m] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart);
7384: remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + rdepthSizeOld[n*(depth+1)+depth-1] + (rp - rcStart[n]);
7385: remotePointsNew[m].rank = rrank;
7386: ++m;
7387: }
7388: break;
7389: case REFINER_HEX_2D:
7390: case REFINER_HYBRID_HEX_2D:
7391: if ((p >= vStart) && (p < vEnd)) {
7392: /* Old vertices stay the same */
7393: localPointsNew[m] = vStartNew + (p - vStart);
7394: remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
7395: remotePointsNew[m].rank = rrank;
7396: ++m;
7397: } else if ((p >= fStart) && (p < fMax)) {
7398: /* Old interior faces add new faces and vertex */
7399: for (r = 0; r < 2; ++r, ++m) {
7400: localPointsNew[m] = fStartNew + (p - fStart)*2 + r;
7401: remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
7402: remotePointsNew[m].rank = rrank;
7403: }
7404: localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart);
7405: remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
7406: remotePointsNew[m].rank = rrank;
7407: ++m;
7408: } else if ((p >= fMax) && (p < fEnd)) {
7409: /* Old hybrid faces stay the same */
7410: localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - fMax);
7411: remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]);
7412: remotePointsNew[m].rank = rrank;
7413: ++m;
7414: } else if ((p >= cStart) && (p < cMax)) {
7415: /* Old interior cells add new cells, interior faces, and vertex */
7416: for (r = 0; r < 4; ++r, ++m) {
7417: localPointsNew[m] = cStartNew + (p - cStart)*4 + r;
7418: remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
7419: remotePointsNew[m].rank = rrank;
7420: }
7421: for (r = 0; r < 4; ++r, ++m) {
7422: localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - cStart)*4 + r;
7423: remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*4 + r;
7424: remotePointsNew[m].rank = rrank;
7425: }
7426: localPointsNew[m] = vStartNew + (vEnd - vStart) + (fMax - fStart) + (p - cStart);
7427: remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n]) + (rp - rcStart[n]);
7428: remotePointsNew[m].rank = rrank;
7429: ++m;
7430: } else if ((p >= cStart) && (p < cMax)) {
7431: /* Old hybrid cells add new cells and hybrid face */
7432: for (r = 0; r < 2; ++r, ++m) {
7433: localPointsNew[m] = cStartNew + (p - cStart)*4 + r;
7434: remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
7435: remotePointsNew[m].rank = rrank;
7436: }
7437: localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (p - cMax);
7438: 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]);
7439: remotePointsNew[m].rank = rrank;
7440: ++m;
7441: }
7442: break;
7443: case REFINER_SIMPLEX_3D:
7444: case REFINER_HYBRID_SIMPLEX_3D:
7445: if ((p >= vStart) && (p < vEnd)) {
7446: /* Interior vertices stay the same */
7447: localPointsNew[m] = vStartNew + (p - vStart);
7448: remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
7449: remotePointsNew[m].rank = rrank;
7450: ++m;
7451: } else if ((p >= eStart) && (p < eMax)) {
7452: /* Interior edges add new edges and vertex */
7453: for (r = 0; r < 2; ++r, ++m) {
7454: localPointsNew[m] = eStartNew + (p - eStart)*2 + r;
7455: remotePointsNew[m].index = reStartNew[n] + (rp - reStart[n])*2 + r;
7456: remotePointsNew[m].rank = rrank;
7457: }
7458: localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - eStart);
7459: remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - reStart[n]);
7460: remotePointsNew[m].rank = rrank;
7461: ++m;
7462: } else if ((p >= eMax) && (p < eEnd)) {
7463: /* Hybrid edges stay the same */
7464: localPointsNew[m] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (p - eMax);
7465: 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]);
7466: remotePointsNew[m].rank = rrank;
7467: ++m;
7468: } else if ((p >= fStart) && (p < fMax)) {
7469: /* Interior faces add new faces and edges */
7470: for (r = 0; r < 4; ++r, ++m) {
7471: localPointsNew[m] = fStartNew + (p - fStart)*4 + r;
7472: remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*4 + r;
7473: remotePointsNew[m].rank = rrank;
7474: }
7475: for (r = 0; r < 3; ++r, ++m) {
7476: localPointsNew[m] = eStartNew + (eMax - eStart)*2 + (p - fStart)*3 + r;
7477: remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rp - rfStart[n])*3 + r;
7478: remotePointsNew[m].rank = rrank;
7479: }
7480: } else if ((p >= fMax) && (p < fEnd)) {
7481: /* Hybrid faces add new faces and edges */
7482: for (r = 0; r < 2; ++r, ++m) {
7483: localPointsNew[m] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (p - fMax)*2 + r;
7484: 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;
7485: remotePointsNew[m].rank = rrank;
7486: }
7487: localPointsNew[m] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (p - fMax);
7488: 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]);
7489: remotePointsNew[m].rank = rrank;
7490: ++m;
7491: } else if ((p >= cStart) && (p < cMax)) {
7492: /* Interior cells add new cells, faces, and edges */
7493: for (r = 0; r < 8; ++r, ++m) {
7494: localPointsNew[m] = cStartNew + (p - cStart)*8 + r;
7495: remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*8 + r;
7496: remotePointsNew[m].rank = rrank;
7497: }
7498: for (r = 0; r < 8; ++r, ++m) {
7499: localPointsNew[m] = fStartNew + (fMax - fStart)*4 + (p - cStart)*8 + r;
7500: remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rp - rcStart[n])*8 + r;
7501: remotePointsNew[m].rank = rrank;
7502: }
7503: localPointsNew[m] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (p - cStart)*1 + 0;
7504: 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;
7505: remotePointsNew[m].rank = rrank;
7506: ++m;
7507: } else if ((p >= cMax) && (p < cEnd)) {
7508: /* Hybrid cells add new cells and faces */
7509: for (r = 0; r < 4; ++r, ++m) {
7510: localPointsNew[m] = cStartNew + (cMax - cStart)*8 + (p - cMax)*4 + r;
7511: remotePointsNew[m].index = rcStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*8 + (rp - rdepthMaxOld[n*(depth+1)+depth])*4 + r;
7512: remotePointsNew[m].rank = rrank;
7513: }
7514: for (r = 0; r < 3; ++r, ++m) {
7515: localPointsNew[m] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (p - cMax)*3 + r;
7516: 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;
7517: remotePointsNew[m].rank = rrank;
7518: }
7519: }
7520: break;
7521: case REFINER_SIMPLEX_TO_HEX_3D:
7522: if ((p >= vStart) && (p < vEnd)) {
7523: /* Interior vertices stay the same */
7524: localPointsNew[m] = vStartNew + (p - vStart);
7525: remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
7526: remotePointsNew[m].rank = rrank;
7527: ++m;
7528: } else if ((p >= eStart) && (p < eEnd)) {
7529: /* Interior edges add new edges and vertex */
7530: for (r = 0; r < 2; ++r, ++m) {
7531: localPointsNew[m] = eStartNew + (p - eStart)*2 + r;
7532: remotePointsNew[m].index = reStartNew[n] + (rp - reStart[n])*2 + r;
7533: remotePointsNew[m].rank = rrank;
7534: }
7535: localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - eStart);
7536: remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - reStart[n]);
7537: remotePointsNew[m].rank = rrank;
7538: ++m;
7539: } else if ((p >= fStart) && (p < fEnd)) {
7540: /* Interior faces add new faces, edges and a vertex */
7541: for (r = 0; r < 3; ++r, ++m) {
7542: localPointsNew[m] = fStartNew + (p - fStart)*3 + r;
7543: remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*3 + r;
7544: remotePointsNew[m].rank = rrank;
7545: }
7546: for (r = 0; r < 3; ++r, ++m) {
7547: localPointsNew[m] = eStartNew + (eEnd - eStart)*2 + (p - fStart)*3 + r;
7548: remotePointsNew[m].index = reStartNew[n] + (rdepthSizeOld[n*(depth+1)+1])*2 + (rp - rfStart[n])*3 + r;
7549: remotePointsNew[m].rank = rrank;
7550: }
7551: localPointsNew[m] = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (p - fStart);
7552: remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + rdepthSizeOld[n*(depth+1)+1] + (rp - rfStart[n]);
7553: remotePointsNew[m].rank = rrank;
7554: ++m;
7555: } else if ((p >= cStart) && (p < cEnd)) {
7556: /* Interior cells add new cells, faces, edges, and a vertex */
7557: for (r = 0; r < 4; ++r, ++m) {
7558: localPointsNew[m] = cStartNew + (p - cStart)*4 + r;
7559: remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
7560: remotePointsNew[m].rank = rrank;
7561: }
7562: for (r = 0; r < 6; ++r, ++m) {
7563: localPointsNew[m] = fStartNew + (fEnd - fStart)*3 + (p - cStart)*6 + r;
7564: remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*3 + (rp - rcStart[n])*6 + r;
7565: remotePointsNew[m].rank = rrank;
7566: }
7567: for (r = 0; r < 4; ++r, ++m) {
7568: localPointsNew[m] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (p - cStart)*4 + r;
7569: remotePointsNew[m].index = reStartNew[n] + rdepthSizeOld[n*(depth+1)+1]*2 + rdepthSizeOld[n*(depth+1)+depth-1]*3 + (rp - rcStart[n])*4 + r;
7570: remotePointsNew[m].rank = rrank;
7571: }
7572: localPointsNew[m] = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (p - cStart);
7573: remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + rdepthSizeOld[n*(depth+1)+1] + rdepthSizeOld[n*(depth+1)+depth-1] + (rp - rcStart[n]);
7574: remotePointsNew[m].rank = rrank;
7575: ++m;
7576: }
7577: break;
7578: case REFINER_HEX_3D:
7579: case REFINER_HYBRID_HEX_3D:
7580: if ((p >= vStart) && (p < vEnd)) {
7581: /* Interior vertices stay the same */
7582: localPointsNew[m] = vStartNew + (p - vStart);
7583: remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
7584: remotePointsNew[m].rank = rrank;
7585: ++m;
7586: } else if ((p >= eStart) && (p < eMax)) {
7587: /* Interior edges add new edges and vertex */
7588: for (r = 0; r < 2; ++r, ++m) {
7589: localPointsNew[m] = eStartNew + (p - eStart)*2 + r;
7590: remotePointsNew[m].index = reStartNew[n] + (rp - reStart[n])*2 + r;
7591: remotePointsNew[m].rank = rrank;
7592: }
7593: localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - eStart);
7594: remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - reStart[n]);
7595: remotePointsNew[m].rank = rrank;
7596: ++m;
7597: } else if ((p >= eMax) && (p < eEnd)) {
7598: /* Hybrid edges stay the same */
7599: localPointsNew[m] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (p - eMax);
7600: 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]);
7601: remotePointsNew[m].rank = rrank;
7602: ++m;
7603: } else if ((p >= fStart) && (p < fMax)) {
7604: /* Interior faces add new faces, edges, and vertex */
7605: for (r = 0; r < 4; ++r, ++m) {
7606: localPointsNew[m] = fStartNew + (p - fStart)*4 + r;
7607: remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*4 + r;
7608: remotePointsNew[m].rank = rrank;
7609: }
7610: for (r = 0; r < 4; ++r, ++m) {
7611: localPointsNew[m] = eStartNew + (eMax - eStart)*2 + (p - fStart)*4 + r;
7612: remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rp - rfStart[n])*4 + r;
7613: remotePointsNew[m].rank = rrank;
7614: }
7615: localPointsNew[m] = vStartNew + (vEnd - vStart) + (eMax - eStart) + (p - fStart);
7616: remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n]) + (rp - rfStart[n]);
7617: remotePointsNew[m].rank = rrank;
7618: ++m;
7619: } else if ((p >= fMax) && (p < fEnd)) {
7620: /* Hybrid faces add new faces and edges */
7621: for (r = 0; r < 2; ++r, ++m) {
7622: localPointsNew[m] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (p - fMax)*2 + r;
7623: 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;
7624: remotePointsNew[m].rank = rrank;
7625: }
7626: localPointsNew[m] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (p - fMax);
7627: 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]);
7628: remotePointsNew[m].rank = rrank;
7629: ++m;
7630: } else if ((p >= cStart) && (p < cMax)) {
7631: /* Interior cells add new cells, faces, edges, and vertex */
7632: for (r = 0; r < 8; ++r, ++m) {
7633: localPointsNew[m] = cStartNew + (p - cStart)*8 + r;
7634: remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*8 + r;
7635: remotePointsNew[m].rank = rrank;
7636: }
7637: for (r = 0; r < 12; ++r, ++m) {
7638: localPointsNew[m] = fStartNew + (fMax - fStart)*4 + (p - cStart)*12 + r;
7639: remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rp - rcStart[n])*12 + r;
7640: remotePointsNew[m].rank = rrank;
7641: }
7642: for (r = 0; r < 6; ++r, ++m) {
7643: localPointsNew[m] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (p - cStart)*6 + r;
7644: 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;
7645: remotePointsNew[m].rank = rrank;
7646: }
7647: for (r = 0; r < 1; ++r, ++m) {
7648: localPointsNew[m] = vStartNew + (eMax - eStart) + (fMax - fStart) + (p - cStart) + r;
7649: remotePointsNew[m].index = rvStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n]) + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n]) + (rp - rcStart[n]) + r;
7650: remotePointsNew[m].rank = rrank;
7651: }
7652: } else if ((p >= cMax) && (p < cEnd)) {
7653: /* Hybrid cells add new cells, faces, and edges */
7654: for (r = 0; r < 4; ++r, ++m) {
7655: localPointsNew[m] = cStartNew + (cMax - cStart)*8 + (p - cMax)*4 + r;
7656: remotePointsNew[m].index = rcStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*8 + (rp - rdepthMaxOld[n*(depth+1)+depth])*4 + r;
7657: remotePointsNew[m].rank = rrank;
7658: }
7659: for (r = 0; r < 4; ++r, ++m) {
7660: localPointsNew[m] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (p - cMax)*4 + r;
7661: 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;
7662: remotePointsNew[m].rank = rrank;
7663: }
7664: localPointsNew[m] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (fEnd - fMax) + (p - cMax);
7665: 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]);
7666: remotePointsNew[m].rank = rrank;
7667: ++m;
7668: }
7669: break;
7670: default:
7671: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
7672: }
7673: }
7674: if (m != numLeavesNew) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of leaf point %d should be %d", m, numLeavesNew);
7675: ISRestoreIndices(processRanks, &neighbors);
7676: ISDestroy(&processRanks);
7677: {
7678: PetscSFNode *rp, *rtmp;
7679: PetscInt *lp, *idx, *ltmp, i;
7681: /* SF needs sorted leaves to correct calculate Gather */
7682: PetscMalloc1(numLeavesNew,&idx);
7683: PetscMalloc1(numLeavesNew, &lp);
7684: PetscMalloc1(numLeavesNew, &rp);
7685: for (i = 0; i < numLeavesNew; ++i) {
7686: 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);
7687: idx[i] = i;
7688: }
7689: PetscSortIntWithPermutation(numLeavesNew, localPointsNew, idx);
7690: for (i = 0; i < numLeavesNew; ++i) {
7691: lp[i] = localPointsNew[idx[i]];
7692: rp[i] = remotePointsNew[idx[i]];
7693: }
7694: ltmp = localPointsNew;
7695: localPointsNew = lp;
7696: rtmp = remotePointsNew;
7697: remotePointsNew = rp;
7698: PetscFree(idx);
7699: PetscFree(ltmp);
7700: PetscFree(rtmp);
7701: }
7702: PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);
7703: PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);
7704: PetscFree7(depthSizeOld,rdepthSizeOld,rdepthMaxOld,rvStart,reStart,rfStart,rcStart);
7705: return(0);
7706: }
7708: static PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
7709: {
7710: PetscInt numLabels, l;
7711: PetscInt depth, newp, cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax, r;
7712: PetscInt cStartNew = 0, vStartNew = 0, fStartNew = 0, eStartNew = 0;
7716: DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
7717: DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);
7718: DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
7719: DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);
7720: DMPlexGetDepth(dm, &depth);
7721: if (refiner) {GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);}
7722: DMGetNumLabels(dm, &numLabels);
7723: DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);
7724: switch (refiner) {
7725: case REFINER_NOOP:
7726: case REFINER_SIMPLEX_1D:
7727: case REFINER_SIMPLEX_2D:
7728: case REFINER_SIMPLEX_TO_HEX_2D:
7729: case REFINER_HEX_2D:
7730: case REFINER_SIMPLEX_3D:
7731: case REFINER_HEX_3D:
7732: case REFINER_SIMPLEX_TO_HEX_3D:
7733: break;
7734: case REFINER_HYBRID_SIMPLEX_3D:
7735: case REFINER_HYBRID_HEX_3D:
7736: if (eMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No edge maximum specified in hybrid mesh");
7737: case REFINER_HYBRID_SIMPLEX_2D:
7738: case REFINER_HYBRID_HEX_2D:
7739: if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
7740: if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
7741: break;
7742: default:
7743: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
7744: }
7745: for (l = 0; l < numLabels; ++l) {
7746: DMLabel label, labelNew;
7747: const char *lname;
7748: PetscBool isDepth;
7749: IS valueIS;
7750: const PetscInt *values;
7751: PetscInt defVal;
7752: PetscInt numValues, val;
7754: DMGetLabelName(dm, l, &lname);
7755: PetscStrcmp(lname, "depth", &isDepth);
7756: if (isDepth) continue;
7757: DMCreateLabel(rdm, lname);
7758: DMGetLabel(dm, lname, &label);
7759: DMGetLabel(rdm, lname, &labelNew);
7760: DMLabelGetDefaultValue(label,&defVal);
7761: DMLabelSetDefaultValue(labelNew,defVal);
7762: DMLabelGetValueIS(label, &valueIS);
7763: ISGetLocalSize(valueIS, &numValues);
7764: ISGetIndices(valueIS, &values);
7765: for (val = 0; val < numValues; ++val) {
7766: IS pointIS;
7767: const PetscInt *points;
7768: PetscInt numPoints, n;
7770: DMLabelGetStratumIS(label, values[val], &pointIS);
7771: ISGetLocalSize(pointIS, &numPoints);
7772: ISGetIndices(pointIS, &points);
7773: /* Ensure refined label is created with same number of strata as
7774: * original (even if no entries here). */
7775: DMLabelAddStratum(labelNew, values[val]);
7776: for (n = 0; n < numPoints; ++n) {
7777: const PetscInt p = points[n];
7778: switch (refiner) {
7779: case REFINER_SIMPLEX_1D:
7780: if ((p >= vStart) && (p < vEnd)) {
7781: /* Old vertices stay the same */
7782: newp = vStartNew + (p - vStart);
7783: DMLabelSetValue(labelNew, newp, values[val]);
7784: } else if ((p >= cStart) && (p < cEnd)) {
7785: /* Old cells add new cells and vertex */
7786: newp = vStartNew + (vEnd - vStart) + (p - cStart);
7787: DMLabelSetValue(labelNew, newp, values[val]);
7788: for (r = 0; r < 2; ++r) {
7789: newp = cStartNew + (p - cStart)*2 + r;
7790: DMLabelSetValue(labelNew, newp, values[val]);
7791: }
7792: }
7793: break;
7794: case REFINER_SIMPLEX_2D:
7795: if ((p >= vStart) && (p < vEnd)) {
7796: /* Old vertices stay the same */
7797: newp = vStartNew + (p - vStart);
7798: DMLabelSetValue(labelNew, newp, values[val]);
7799: } else if ((p >= fStart) && (p < fEnd)) {
7800: /* Old faces add new faces and vertex */
7801: newp = vStartNew + (vEnd - vStart) + (p - fStart);
7802: DMLabelSetValue(labelNew, newp, values[val]);
7803: for (r = 0; r < 2; ++r) {
7804: newp = fStartNew + (p - fStart)*2 + r;
7805: DMLabelSetValue(labelNew, newp, values[val]);
7806: }
7807: } else if ((p >= cStart) && (p < cEnd)) {
7808: /* Old cells add new cells and interior faces */
7809: for (r = 0; r < 4; ++r) {
7810: newp = cStartNew + (p - cStart)*4 + r;
7811: DMLabelSetValue(labelNew, newp, values[val]);
7812: }
7813: for (r = 0; r < 3; ++r) {
7814: newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r;
7815: DMLabelSetValue(labelNew, newp, values[val]);
7816: }
7817: }
7818: break;
7819: case REFINER_SIMPLEX_TO_HEX_2D:
7820: if ((p >= vStart) && (p < vEnd)) {
7821: /* Old vertices stay the same */
7822: newp = vStartNew + (p - vStart);
7823: DMLabelSetValue(labelNew, newp, values[val]);
7824: } else if ((p >= fStart) && (p < fEnd)) {
7825: /* Old faces add new faces and vertex */
7826: newp = vStartNew + (vEnd - vStart) + (p - fStart);
7827: DMLabelSetValue(labelNew, newp, values[val]);
7828: for (r = 0; r < 2; ++r) {
7829: newp = fStartNew + (p - fStart)*2 + r;
7830: DMLabelSetValue(labelNew, newp, values[val]);
7831: }
7832: } else if ((p >= cStart) && (p < cEnd)) {
7833: /* Old cells add new cells, interior faces, and a vertex */
7834: for (r = 0; r < 3; ++r) {
7835: newp = cStartNew + (p - cStart)*3 + r;
7836: DMLabelSetValue(labelNew, newp, values[val]);
7837: }
7838: for (r = 0; r < 3; ++r) {
7839: newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r;
7840: DMLabelSetValue(labelNew, newp, values[val]);
7841: }
7842: newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + p;
7843: DMLabelSetValue(labelNew, newp, values[val]);
7844: }
7845: break;
7846: case REFINER_HEX_2D:
7847: if ((p >= vStart) && (p < vEnd)) {
7848: /* Old vertices stay the same */
7849: newp = vStartNew + (p - vStart);
7850: DMLabelSetValue(labelNew, newp, values[val]);
7851: } else if ((p >= fStart) && (p < fEnd)) {
7852: /* Old faces add new faces and vertex */
7853: newp = vStartNew + (vEnd - vStart) + (p - fStart);
7854: DMLabelSetValue(labelNew, newp, values[val]);
7855: for (r = 0; r < 2; ++r) {
7856: newp = fStartNew + (p - fStart)*2 + r;
7857: DMLabelSetValue(labelNew, newp, values[val]);
7858: }
7859: } else if ((p >= cStart) && (p < cEnd)) {
7860: /* Old cells add new cells and interior faces and vertex */
7861: for (r = 0; r < 4; ++r) {
7862: newp = cStartNew + (p - cStart)*4 + r;
7863: DMLabelSetValue(labelNew, newp, values[val]);
7864: }
7865: for (r = 0; r < 4; ++r) {
7866: newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r;
7867: DMLabelSetValue(labelNew, newp, values[val]);
7868: }
7869: newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart);
7870: DMLabelSetValue(labelNew, newp, values[val]);
7871: }
7872: break;
7873: case REFINER_HYBRID_SIMPLEX_2D:
7874: if ((p >= vStart) && (p < vEnd)) {
7875: /* Old vertices stay the same */
7876: newp = vStartNew + (p - vStart);
7877: DMLabelSetValue(labelNew, newp, values[val]);
7878: } else if ((p >= fStart) && (p < fMax)) {
7879: /* Old interior faces add new faces and vertex */
7880: newp = vStartNew + (vEnd - vStart) + (p - fStart);
7881: DMLabelSetValue(labelNew, newp, values[val]);
7882: for (r = 0; r < 2; ++r) {
7883: newp = fStartNew + (p - fStart)*2 + r;
7884: DMLabelSetValue(labelNew, newp, values[val]);
7885: }
7886: } else if ((p >= fMax) && (p < fEnd)) {
7887: /* Old hybrid faces stay the same */
7888: newp = fStartNew + (fMax - fStart)*2 + (p - fMax);
7889: DMLabelSetValue(labelNew, newp, values[val]);
7890: } else if ((p >= cStart) && (p < cMax)) {
7891: /* Old interior cells add new cells and interior faces */
7892: for (r = 0; r < 4; ++r) {
7893: newp = cStartNew + (p - cStart)*4 + r;
7894: DMLabelSetValue(labelNew, newp, values[val]);
7895: }
7896: for (r = 0; r < 3; ++r) {
7897: newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r;
7898: DMLabelSetValue(labelNew, newp, values[val]);
7899: }
7900: } else if ((p >= cMax) && (p < cEnd)) {
7901: /* Old hybrid cells add new cells and hybrid face */
7902: for (r = 0; r < 2; ++r) {
7903: newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r;
7904: DMLabelSetValue(labelNew, newp, values[val]);
7905: }
7906: newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax);
7907: DMLabelSetValue(labelNew, newp, values[val]);
7908: }
7909: break;
7910: case REFINER_HYBRID_HEX_2D:
7911: if ((p >= vStart) && (p < vEnd)) {
7912: /* Old vertices stay the same */
7913: newp = vStartNew + (p - vStart);
7914: DMLabelSetValue(labelNew, newp, values[val]);
7915: } else if ((p >= fStart) && (p < fMax)) {
7916: /* Old interior faces add new faces and vertex */
7917: newp = vStartNew + (vEnd - vStart) + (p - fStart);
7918: DMLabelSetValue(labelNew, newp, values[val]);
7919: for (r = 0; r < 2; ++r) {
7920: newp = fStartNew + (p - fStart)*2 + r;
7921: DMLabelSetValue(labelNew, newp, values[val]);
7922: }
7923: } else if ((p >= fMax) && (p < fEnd)) {
7924: /* Old hybrid faces stay the same */
7925: newp = fStartNew + (fMax - fStart)*2 + (p - fMax);
7926: DMLabelSetValue(labelNew, newp, values[val]);
7927: } else if ((p >= cStart) && (p < cMax)) {
7928: /* Old interior cells add new cells, interior faces, and vertex */
7929: for (r = 0; r < 4; ++r) {
7930: newp = cStartNew + (p - cStart)*4 + r;
7931: DMLabelSetValue(labelNew, newp, values[val]);
7932: }
7933: for (r = 0; r < 4; ++r) {
7934: newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r;
7935: DMLabelSetValue(labelNew, newp, values[val]);
7936: }
7937: newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart);
7938: DMLabelSetValue(labelNew, newp, values[val]);
7939: } else if ((p >= cMax) && (p < cEnd)) {
7940: /* Old hybrid cells add new cells and hybrid face */
7941: for (r = 0; r < 2; ++r) {
7942: newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r;
7943: DMLabelSetValue(labelNew, newp, values[val]);
7944: }
7945: newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (p - cMax);
7946: DMLabelSetValue(labelNew, newp, values[val]);
7947: }
7948: break;
7949: case REFINER_SIMPLEX_3D:
7950: if ((p >= vStart) && (p < vEnd)) {
7951: /* Old vertices stay the same */
7952: newp = vStartNew + (p - vStart);
7953: DMLabelSetValue(labelNew, newp, values[val]);
7954: } else if ((p >= eStart) && (p < eEnd)) {
7955: /* Old edges add new edges and vertex */
7956: for (r = 0; r < 2; ++r) {
7957: newp = eStartNew + (p - eStart)*2 + r;
7958: DMLabelSetValue(labelNew, newp, values[val]);
7959: }
7960: newp = vStartNew + (vEnd - vStart) + (p - eStart);
7961: DMLabelSetValue(labelNew, newp, values[val]);
7962: } else if ((p >= fStart) && (p < fEnd)) {
7963: /* Old faces add new faces and edges */
7964: for (r = 0; r < 4; ++r) {
7965: newp = fStartNew + (p - fStart)*4 + r;
7966: DMLabelSetValue(labelNew, newp, values[val]);
7967: }
7968: for (r = 0; r < 3; ++r) {
7969: newp = eStartNew + (eEnd - eStart)*2 + (p - fStart)*3 + r;
7970: DMLabelSetValue(labelNew, newp, values[val]);
7971: }
7972: } else if ((p >= cStart) && (p < cEnd)) {
7973: /* Old cells add new cells and interior faces and edges */
7974: for (r = 0; r < 8; ++r) {
7975: newp = cStartNew + (p - cStart)*8 + r;
7976: DMLabelSetValue(labelNew, newp, values[val]);
7977: }
7978: for (r = 0; r < 8; ++r) {
7979: newp = fStartNew + (fEnd - fStart)*4 + (p - cStart)*8 + r;
7980: DMLabelSetValue(labelNew, newp, values[val]);
7981: }
7982: for (r = 0; r < 1; ++r) {
7983: newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (p - cStart)*1 + r;
7984: DMLabelSetValue(labelNew, newp, values[val]);
7985: }
7986: }
7987: break;
7988: case REFINER_SIMPLEX_TO_HEX_3D:
7989: if ((p >= vStart) && (p < vEnd)) {
7990: /* Old vertices stay the same */
7991: newp = vStartNew + (p - vStart);
7992: DMLabelSetValue(labelNew, newp, values[val]);
7993: } else if ((p >= eStart) && (p < eEnd)) {
7994: /* Old edges add new edges and vertex */
7995: for (r = 0; r < 2; ++r) {
7996: newp = eStartNew + (p - eStart)*2 + r;
7997: DMLabelSetValue(labelNew, newp, values[val]);
7998: }
7999: newp = vStartNew + (vEnd - vStart) + (p - eStart);
8000: DMLabelSetValue(labelNew, newp, values[val]);
8001: } else if ((p >= fStart) && (p < fEnd)) {
8002: /* Old faces add new faces, edges and a vertex */
8003: for (r = 0; r < 3; ++r) {
8004: newp = fStartNew + (p - fStart)*3 + r;
8005: DMLabelSetValue(labelNew, newp, values[val]);
8006: }
8007: for (r = 0; r < 3; ++r) {
8008: newp = eStartNew + (eEnd - eStart)*2 + (p - fStart)*3 + r;
8009: DMLabelSetValue(labelNew, newp, values[val]);
8010: }
8011: } else if ((p >= cStart) && (p < cEnd)) {
8012: /* Old cells add new cells and interior faces and edges and a vertex */
8013: for (r = 0; r < 4; ++r) {
8014: newp = cStartNew + (p - cStart)*4 + r;
8015: DMLabelSetValue(labelNew, newp, values[val]);
8016: }
8017: for (r = 0; r < 6; ++r) {
8018: newp = fStartNew + (fEnd - fStart)*3 + (p - cStart)*6 + r;
8019: DMLabelSetValue(labelNew, newp, values[val]);
8020: }
8021: for (r = 0; r < 4; ++r) {
8022: newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (p - cStart)*4 + r;
8023: DMLabelSetValue(labelNew, newp, values[val]);
8024: }
8025: newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + p - cStart;
8026: DMLabelSetValue(labelNew, newp, values[val]);
8027: }
8028: break;
8029: case REFINER_HYBRID_SIMPLEX_3D:
8030: if ((p >= vStart) && (p < vEnd)) {
8031: /* Interior vertices stay the same */
8032: newp = vStartNew + (p - vStart);
8033: DMLabelSetValue(labelNew, newp, values[val]);
8034: } else if ((p >= eStart) && (p < eMax)) {
8035: /* Interior edges add new edges and vertex */
8036: for (r = 0; r < 2; ++r) {
8037: newp = eStartNew + (p - eStart)*2 + r;
8038: DMLabelSetValue(labelNew, newp, values[val]);
8039: }
8040: newp = vStartNew + (vEnd - vStart) + (p - eStart);
8041: DMLabelSetValue(labelNew, newp, values[val]);
8042: } else if ((p >= eMax) && (p < eEnd)) {
8043: /* Hybrid edges stay the same */
8044: newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (p - eMax);
8045: DMLabelSetValue(labelNew, newp, values[val]);
8046: } else if ((p >= fStart) && (p < fMax)) {
8047: /* Interior faces add new faces and edges */
8048: for (r = 0; r < 4; ++r) {
8049: newp = fStartNew + (p - fStart)*4 + r;
8050: DMLabelSetValue(labelNew, newp, values[val]);
8051: }
8052: for (r = 0; r < 3; ++r) {
8053: newp = eStartNew + (eMax - eStart)*2 + (p - fStart)*3 + r;
8054: DMLabelSetValue(labelNew, newp, values[val]);
8055: }
8056: } else if ((p >= fMax) && (p < fEnd)) {
8057: /* Hybrid faces add new faces and edges */
8058: for (r = 0; r < 2; ++r) {
8059: newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (p - fMax)*2 + r;
8060: DMLabelSetValue(labelNew, newp, values[val]);
8061: }
8062: newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (p - fMax);
8063: DMLabelSetValue(labelNew, newp, values[val]);
8064: } else if ((p >= cStart) && (p < cMax)) {
8065: /* Interior cells add new cells, faces, and edges */
8066: for (r = 0; r < 8; ++r) {
8067: newp = cStartNew + (p - cStart)*8 + r;
8068: DMLabelSetValue(labelNew, newp, values[val]);
8069: }
8070: for (r = 0; r < 8; ++r) {
8071: newp = fStartNew + (fMax - fStart)*4 + (p - cStart)*8 + r;
8072: DMLabelSetValue(labelNew, newp, values[val]);
8073: }
8074: newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (p - cStart);
8075: DMLabelSetValue(labelNew, newp, values[val]);
8076: } else if ((p >= cMax) && (p < cEnd)) {
8077: /* Hybrid cells add new cells and faces */
8078: for (r = 0; r < 4; ++r) {
8079: newp = cStartNew + (cMax - cStart)*8 + (p - cMax)*4 + r;
8080: DMLabelSetValue(labelNew, newp, values[val]);
8081: }
8082: for (r = 0; r < 3; ++r) {
8083: newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (p - cMax)*3 + r;
8084: DMLabelSetValue(labelNew, newp, values[val]);
8085: }
8086: }
8087: break;
8088: case REFINER_HEX_3D:
8089: if ((p >= vStart) && (p < vEnd)) {
8090: /* Old vertices stay the same */
8091: newp = vStartNew + (p - vStart);
8092: DMLabelSetValue(labelNew, newp, values[val]);
8093: } else if ((p >= eStart) && (p < eEnd)) {
8094: /* Old edges add new edges and vertex */
8095: for (r = 0; r < 2; ++r) {
8096: newp = eStartNew + (p - eStart)*2 + r;
8097: DMLabelSetValue(labelNew, newp, values[val]);
8098: }
8099: newp = vStartNew + (vEnd - vStart) + (p - eStart);
8100: DMLabelSetValue(labelNew, newp, values[val]);
8101: } else if ((p >= fStart) && (p < fEnd)) {
8102: /* Old faces add new faces, edges, and vertex */
8103: for (r = 0; r < 4; ++r) {
8104: newp = fStartNew + (p - fStart)*4 + r;
8105: DMLabelSetValue(labelNew, newp, values[val]);
8106: }
8107: for (r = 0; r < 4; ++r) {
8108: newp = eStartNew + (eEnd - eStart)*2 + (p - fStart)*4 + r;
8109: DMLabelSetValue(labelNew, newp, values[val]);
8110: }
8111: newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (p - fStart);
8112: DMLabelSetValue(labelNew, newp, values[val]);
8113: } else if ((p >= cStart) && (p < cEnd)) {
8114: /* Old cells add new cells, faces, edges, and vertex */
8115: for (r = 0; r < 8; ++r) {
8116: newp = cStartNew + (p - cStart)*8 + r;
8117: DMLabelSetValue(labelNew, newp, values[val]);
8118: }
8119: for (r = 0; r < 12; ++r) {
8120: newp = fStartNew + (fEnd - fStart)*4 + (p - cStart)*12 + r;
8121: DMLabelSetValue(labelNew, newp, values[val]);
8122: }
8123: for (r = 0; r < 6; ++r) {
8124: newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (p - cStart)*6 + r;
8125: DMLabelSetValue(labelNew, newp, values[val]);
8126: }
8127: newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (p - cStart);
8128: DMLabelSetValue(labelNew, newp, values[val]);
8129: }
8130: break;
8131: case REFINER_HYBRID_HEX_3D:
8132: if ((p >= vStart) && (p < vEnd)) {
8133: /* Interior vertices stay the same */
8134: newp = vStartNew + (p - vStart);
8135: DMLabelSetValue(labelNew, newp, values[val]);
8136: } else if ((p >= eStart) && (p < eMax)) {
8137: /* Interior edges add new edges and vertex */
8138: for (r = 0; r < 2; ++r) {
8139: newp = eStartNew + (p - eStart)*2 + r;
8140: DMLabelSetValue(labelNew, newp, values[val]);
8141: }
8142: newp = vStartNew + (vEnd - vStart) + (p - eStart);
8143: DMLabelSetValue(labelNew, newp, values[val]);
8144: } else if ((p >= eMax) && (p < eEnd)) {
8145: /* Hybrid edges stay the same */
8146: newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (p - eMax);
8147: DMLabelSetValue(labelNew, newp, values[val]);
8148: } else if ((p >= fStart) && (p < fMax)) {
8149: /* Interior faces add new faces, edges, and vertex */
8150: for (r = 0; r < 4; ++r) {
8151: newp = fStartNew + (p - fStart)*4 + r;
8152: DMLabelSetValue(labelNew, newp, values[val]);
8153: }
8154: for (r = 0; r < 4; ++r) {
8155: newp = eStartNew + (eMax - eStart)*2 + (p - fStart)*4 + r;
8156: DMLabelSetValue(labelNew, newp, values[val]);
8157: }
8158: newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (p - fStart);
8159: DMLabelSetValue(labelNew, newp, values[val]);
8160: } else if ((p >= fMax) && (p < fEnd)) {
8161: /* Hybrid faces add new faces and edges */
8162: for (r = 0; r < 2; ++r) {
8163: newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (p - fMax)*2 + r;
8164: DMLabelSetValue(labelNew, newp, values[val]);
8165: }
8166: newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (p - fMax);
8167: DMLabelSetValue(labelNew, newp, values[val]);
8168: } else if ((p >= cStart) && (p < cMax)) {
8169: /* Interior cells add new cells, faces, edges, and vertex */
8170: for (r = 0; r < 8; ++r) {
8171: newp = cStartNew + (p - cStart)*8 + r;
8172: DMLabelSetValue(labelNew, newp, values[val]);
8173: }
8174: for (r = 0; r < 12; ++r) {
8175: newp = fStartNew + (fMax - fStart)*4 + (p - cStart)*12 + r;
8176: DMLabelSetValue(labelNew, newp, values[val]);
8177: }
8178: for (r = 0; r < 6; ++r) {
8179: newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (p - cStart)*6 + r;
8180: DMLabelSetValue(labelNew, newp, values[val]);
8181: }
8182: newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (fMax - fStart) + (p - cStart);
8183: DMLabelSetValue(labelNew, newp, values[val]);
8184: } else if ((p >= cMax) && (p < cEnd)) {
8185: /* Hybrid cells add new cells, faces, and edges */
8186: for (r = 0; r < 4; ++r) {
8187: newp = cStartNew + (cMax - cStart)*8 + (p - cMax)*4 + r;
8188: DMLabelSetValue(labelNew, newp, values[val]);
8189: }
8190: for (r = 0; r < 4; ++r) {
8191: newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (p - cMax)*4 + r;
8192: DMLabelSetValue(labelNew, newp, values[val]);
8193: }
8194: newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (fEnd - fMax) + (p - cMax);
8195: DMLabelSetValue(labelNew, newp, values[val]);
8196: }
8197: break;
8198: default:
8199: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
8200: }
8201: }
8202: ISRestoreIndices(pointIS, &points);
8203: ISDestroy(&pointIS);
8204: }
8205: ISRestoreIndices(valueIS, &values);
8206: ISDestroy(&valueIS);
8207: if (0) {
8208: DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);
8209: }
8210: }
8211: return(0);
8212: }
8214: /* This will only work for interpolated meshes */
8215: PetscErrorCode DMPlexRefineUniform_Internal(DM dm, CellRefiner cellRefiner, DM *dmRefined)
8216: {
8217: DM rdm;
8218: PetscInt *depthSize;
8219: PetscInt dim, depth = 0, d, pStart = 0, pEnd = 0;
8223: DMCreate(PetscObjectComm((PetscObject)dm), &rdm);
8224: DMSetType(rdm, DMPLEX);
8225: DMGetDimension(dm, &dim);
8226: DMSetDimension(rdm, dim);
8227: /* Calculate number of new points of each depth */
8228: DMPlexGetDepth(dm, &depth);
8229: if (depth >= 0 && dim != depth) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Mesh must be interpolated for regular refinement");
8230: PetscMalloc1(depth+1, &depthSize);
8231: PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));
8232: CellRefinerGetSizes(cellRefiner, dm, depthSize);
8233: /* Step 1: Set chart */
8234: for (d = 0; d <= depth; ++d) pEnd += depthSize[d];
8235: DMPlexSetChart(rdm, pStart, pEnd);
8236: /* Step 2: Set cone/support sizes */
8237: CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);
8238: /* Step 3: Setup refined DM */
8239: DMSetUp(rdm);
8240: /* Step 4: Set cones and supports */
8241: CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);
8242: /* Step 5: Stratify */
8243: DMPlexStratify(rdm);
8244: /* Step 6: Create pointSF */
8245: CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);
8246: /* Step 7: Create labels */
8247: CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);
8248: /* Step 8: Set coordinates */
8249: CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);
8250: PetscFree(depthSize);
8252: *dmRefined = rdm;
8253: return(0);
8254: }
8256: /*@
8257: DMPlexCreateCoarsePointIS - Creates an IS covering the coarse DM chart with the fine points as data
8259: Input Parameter:
8260: . dm - The coarse DM
8262: Output Parameter:
8263: . fpointIS - The IS of all the fine points which exist in the original coarse mesh
8265: Level: developer
8267: .seealso: DMRefine(), DMPlexSetRefinementUniform(), DMPlexCreateSubpointIS()
8268: @*/
8269: PetscErrorCode DMPlexCreateCoarsePointIS(DM dm, IS *fpointIS)
8270: {
8271: CellRefiner cellRefiner;
8272: PetscInt *depthSize, *fpoints;
8273: PetscInt cStartNew = 0, vStartNew = 0, fStartNew = 0, eStartNew = 0;
8274: PetscInt depth, pStart, pEnd, p, vStart, vEnd, v;
8278: DMPlexGetDepth(dm, &depth);
8279: DMPlexGetChart(dm, &pStart, &pEnd);
8280: DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
8281: DMPlexGetCellRefiner_Internal(dm, &cellRefiner);
8282: PetscMalloc1(depth+1, &depthSize);
8283: CellRefinerGetSizes(cellRefiner, dm, depthSize);
8284: if (cellRefiner) {GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);}
8285: PetscMalloc1(pEnd-pStart,&fpoints);
8286: for (p = 0; p < pEnd-pStart; ++p) fpoints[p] = -1;
8287: switch (cellRefiner) {
8288: case REFINER_SIMPLEX_1D:
8289: case REFINER_SIMPLEX_2D:
8290: case REFINER_HYBRID_SIMPLEX_2D:
8291: case REFINER_HEX_2D:
8292: case REFINER_HYBRID_HEX_2D:
8293: case REFINER_SIMPLEX_3D:
8294: case REFINER_HYBRID_SIMPLEX_3D:
8295: case REFINER_HEX_3D:
8296: case REFINER_HYBRID_HEX_3D:
8297: for (v = vStart; v < vEnd; ++v) fpoints[v-pStart] = vStartNew + (v - vStart);
8298: break;
8299: default:
8300: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", cellRefiner);
8301: }
8302: ISCreateGeneral(PETSC_COMM_SELF, pEnd-pStart, fpoints, PETSC_OWN_POINTER, fpointIS);
8303: PetscFree(depthSize);
8304: return(0);
8305: }
8307: /*@
8308: DMPlexSetRefinementUniform - Set the flag for uniform refinement
8310: Input Parameters:
8311: + dm - The DM
8312: - refinementUniform - The flag for uniform refinement
8314: Level: developer
8316: .seealso: DMRefine(), DMPlexGetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
8317: @*/
8318: PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform)
8319: {
8320: DM_Plex *mesh = (DM_Plex*) dm->data;
8324: mesh->refinementUniform = refinementUniform;
8325: return(0);
8326: }
8328: /*@
8329: DMPlexGetRefinementUniform - Retrieve the flag for uniform refinement
8331: Input Parameter:
8332: . dm - The DM
8334: Output Parameter:
8335: . refinementUniform - The flag for uniform refinement
8337: Level: developer
8339: .seealso: DMRefine(), DMPlexSetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
8340: @*/
8341: PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform)
8342: {
8343: DM_Plex *mesh = (DM_Plex*) dm->data;
8348: *refinementUniform = mesh->refinementUniform;
8349: return(0);
8350: }
8352: /*@
8353: DMPlexSetRefinementLimit - Set the maximum cell volume for refinement
8355: Input Parameters:
8356: + dm - The DM
8357: - refinementLimit - The maximum cell volume in the refined mesh
8359: Level: developer
8361: .seealso: DMRefine(), DMPlexGetRefinementLimit(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform()
8362: @*/
8363: PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit)
8364: {
8365: DM_Plex *mesh = (DM_Plex*) dm->data;
8369: mesh->refinementLimit = refinementLimit;
8370: return(0);
8371: }
8373: /*@
8374: DMPlexGetRefinementLimit - Retrieve the maximum cell volume for refinement
8376: Input Parameter:
8377: . dm - The DM
8379: Output Parameter:
8380: . refinementLimit - The maximum cell volume in the refined mesh
8382: Level: developer
8384: .seealso: DMRefine(), DMPlexSetRefinementLimit(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform()
8385: @*/
8386: PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit)
8387: {
8388: DM_Plex *mesh = (DM_Plex*) dm->data;
8393: /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */
8394: *refinementLimit = mesh->refinementLimit;
8395: return(0);
8396: }
8398: /*@
8399: DMPlexSetRefinementFunction - Set the function giving the maximum cell volume for refinement
8401: Input Parameters:
8402: + dm - The DM
8403: - refinementFunc - Function giving the maximum cell volume in the refined mesh
8405: Note: The calling sequence is refinementFunc(coords, limit)
8406: $ coords - Coordinates of the current point, usually a cell centroid
8407: $ limit - The maximum cell volume for a cell containing this point
8409: Level: developer
8411: .seealso: DMRefine(), DMPlexGetRefinementFunction(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
8412: @*/
8413: PetscErrorCode DMPlexSetRefinementFunction(DM dm, PetscErrorCode (*refinementFunc)(const PetscReal [], PetscReal *))
8414: {
8415: DM_Plex *mesh = (DM_Plex*) dm->data;
8419: mesh->refinementFunc = refinementFunc;
8420: return(0);
8421: }
8423: /*@
8424: DMPlexGetRefinementFunction - Get the function giving the maximum cell volume for refinement
8426: Input Parameter:
8427: . dm - The DM
8429: Output Parameter:
8430: . refinementFunc - Function giving the maximum cell volume in the refined mesh
8432: Note: The calling sequence is refinementFunc(coords, limit)
8433: $ coords - Coordinates of the current point, usually a cell centroid
8434: $ limit - The maximum cell volume for a cell containing this point
8436: Level: developer
8438: .seealso: DMRefine(), DMPlexSetRefinementFunction(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
8439: @*/
8440: PetscErrorCode DMPlexGetRefinementFunction(DM dm, PetscErrorCode (**refinementFunc)(const PetscReal [], PetscReal *))
8441: {
8442: DM_Plex *mesh = (DM_Plex*) dm->data;
8447: *refinementFunc = mesh->refinementFunc;
8448: return(0);
8449: }
8451: PetscErrorCode DMPlexGetCellRefiner_Internal(DM dm, CellRefiner *cellRefiner)
8452: {
8453: PetscInt dim, cStart, cEnd, coneSize, cMax, fMax;
8457: DMGetDimension(dm, &dim);
8458: DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
8459: if (cEnd <= cStart) {*cellRefiner = REFINER_NOOP; return(0);}
8460: DMPlexGetConeSize(dm, cStart, &coneSize);
8461: DMPlexGetHybridBounds(dm, &cMax, &fMax, NULL, NULL);
8462: switch (dim) {
8463: case 1:
8464: switch (coneSize) {
8465: case 2:
8466: *cellRefiner = REFINER_SIMPLEX_1D;
8467: break;
8468: default:
8469: SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim);
8470: }
8471: break;
8472: case 2:
8473: switch (coneSize) {
8474: case 3:
8475: if (cMax >= 0) *cellRefiner = REFINER_HYBRID_SIMPLEX_2D;
8476: else *cellRefiner = REFINER_SIMPLEX_2D;
8477: break;
8478: case 4:
8479: if (cMax >= 0 && fMax >= 0) *cellRefiner = REFINER_HYBRID_HEX_2D;
8480: else *cellRefiner = REFINER_HEX_2D;
8481: break;
8482: default:
8483: SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim);
8484: }
8485: break;
8486: case 3:
8487: switch (coneSize) {
8488: case 4:
8489: if (cMax >= 0) *cellRefiner = REFINER_HYBRID_SIMPLEX_3D;
8490: else *cellRefiner = REFINER_SIMPLEX_3D;
8491: break;
8492: case 6:
8493: if (cMax >= 0) *cellRefiner = REFINER_HYBRID_HEX_3D;
8494: else *cellRefiner = REFINER_HEX_3D;
8495: break;
8496: default:
8497: SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim);
8498: }
8499: break;
8500: default:
8501: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim);
8502: }
8503: return(0);
8504: }
8506: PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined)
8507: {
8508: PetscBool isUniform;
8512: DMPlexGetRefinementUniform(dm, &isUniform);
8513: if (isUniform) {
8514: CellRefiner cellRefiner;
8515: PetscBool localized;
8517: DMGetCoordinatesLocalized(dm, &localized);
8518: DMPlexGetCellRefiner_Internal(dm, &cellRefiner);
8519: DMPlexRefineUniform_Internal(dm, cellRefiner, dmRefined);
8520: DMCopyBoundary(dm, *dmRefined);
8521: if (localized) {DMLocalizeCoordinates(*dmRefined);}
8522: } else {
8523: DMPlexRefine_Internal(dm, NULL, dmRefined);
8524: }
8525: return(0);
8526: }
8528: PetscErrorCode DMRefineHierarchy_Plex(DM dm, PetscInt nlevels, DM dmRefined[])
8529: {
8530: DM cdm = dm;
8531: PetscInt r;
8532: PetscBool isUniform, localized;
8536: DMPlexGetRefinementUniform(dm, &isUniform);
8537: DMGetCoordinatesLocalized(dm, &localized);
8538: if (isUniform) {
8539: for (r = 0; r < nlevels; ++r) {
8540: CellRefiner cellRefiner;
8542: DMPlexGetCellRefiner_Internal(cdm, &cellRefiner);
8543: DMPlexRefineUniform_Internal(cdm, cellRefiner, &dmRefined[r]);
8544: DMCopyBoundary(cdm, dmRefined[r]);
8545: if (localized) {DMLocalizeCoordinates(dmRefined[r]);}
8546: DMSetCoarseDM(dmRefined[r], cdm);
8547: DMPlexSetRegularRefinement(dmRefined[r], PETSC_TRUE);
8548: cdm = dmRefined[r];
8549: }
8550: } else {
8551: for (r = 0; r < nlevels; ++r) {
8552: DMRefine(cdm, PetscObjectComm((PetscObject) dm), &dmRefined[r]);
8553: DMCopyBoundary(cdm, dmRefined[r]);
8554: if (localized) {DMLocalizeCoordinates(dmRefined[r]);}
8555: DMSetCoarseDM(dmRefined[r], cdm);
8556: cdm = dmRefined[r];
8557: }
8558: }
8559: return(0);
8560: }