Actual source code: plexrefine.c
petsc-3.7.3 2016-08-01
1: #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/
2: #include <petscsf.h>
6: PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart)
7: {
9: if (cStart) *cStart = 0;
10: if (vStart) *vStart = depth < 0 ? 0 : depthSize[depth];
11: if (fStart) *fStart = depth < 0 ? 0 : depthSize[depth] + depthSize[0];
12: if (eStart) *eStart = depth < 0 ? 0 : depthSize[depth] + depthSize[0] + depthSize[depth-1];
13: return(0);
14: }
18: PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd)
19: {
21: if (cEnd) *cEnd = depth < 0 ? 0 : depthSize[depth];
22: if (vEnd) *vEnd = depth < 0 ? 0 : depthSize[depth] + depthSize[0];
23: if (fEnd) *fEnd = depth < 0 ? 0 : depthSize[depth] + depthSize[0] + depthSize[depth-1];
24: if (eEnd) *eEnd = depth < 0 ? 0 : depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1];
25: return(0);
26: }
30: /* Gets the affine map from the original cell to each subcell */
31: PetscErrorCode CellRefinerGetAffineTransforms_Internal(CellRefiner refiner, PetscInt *numSubcells, PetscReal *v0[], PetscReal *jac[], PetscReal *invjac[])
32: {
33: PetscReal *v = NULL, *j = NULL, *invj = NULL, detJ;
34: PetscInt dim, s;
38: switch (refiner) {
39: case REFINER_NOOP: break;
40: case REFINER_SIMPLEX_2D:
41: /*
42: 2
43: |\
44: | \
45: | \
46: | \
47: | C \
48: | \
49: | \
50: 2---1---1
51: |\ D / \
52: | 2 0 \
53: |A \ / B \
54: 0---0-------1
55: */
56: dim = 2;
57: if (numSubcells) *numSubcells = 4;
58: if (v0) {
59: PetscMalloc3(4*dim,&v,4*dim*dim,&j,4*dim*dim,&invj);
60: /* A */
61: v[0+0] = -1.0; v[0+1] = -1.0;
62: j[0+0] = 0.5; j[0+1] = 0.0;
63: j[0+2] = 0.0; j[0+3] = 0.5;
64: /* B */
65: v[2+0] = 0.0; v[2+1] = -1.0;
66: j[4+0] = 0.5; j[4+1] = 0.0;
67: j[4+2] = 0.0; j[4+3] = 0.5;
68: /* C */
69: v[4+0] = -1.0; v[4+1] = 0.0;
70: j[8+0] = 0.5; j[8+1] = 0.0;
71: j[8+2] = 0.0; j[8+3] = 0.5;
72: /* D */
73: v[6+0] = 0.0; v[6+1] = -1.0;
74: j[12+0] = 0.0; j[12+1] = -0.5;
75: j[12+2] = 0.5; j[12+3] = 0.5;
76: for (s = 0; s < 4; ++s) {
77: DMPlex_Det2D_Internal(&detJ, &j[s*dim*dim]);
78: DMPlex_Invert2D_Internal(&invj[s*dim*dim], &j[s*dim*dim], detJ);
79: }
80: }
81: break;
82: case REFINER_HEX_2D:
83: /*
84: 3---------2---------2
85: | | |
86: | D 2 C |
87: | | |
88: 3----3----0----1----1
89: | | |
90: | A 0 B |
91: | | |
92: 0---------0---------1
93: */
94: dim = 2;
95: if (numSubcells) *numSubcells = 4;
96: if (v0) {
97: PetscMalloc3(4*dim,&v,4*dim*dim,&j,4*dim*dim,&invj);
98: /* A */
99: v[0+0] = -1.0; v[0+1] = -1.0;
100: j[0+0] = 0.5; j[0+1] = 0.0;
101: j[0+2] = 0.0; j[0+3] = 0.5;
102: /* B */
103: v[2+0] = 0.0; v[2+1] = -1.0;
104: j[4+0] = 0.5; j[4+1] = 0.0;
105: j[4+2] = 0.0; j[4+3] = 0.5;
106: /* C */
107: v[4+0] = 0.0; v[4+1] = 0.0;
108: j[8+0] = 0.5; j[8+1] = 0.0;
109: j[8+2] = 0.0; j[8+3] = 0.5;
110: /* D */
111: v[6+0] = -1.0; v[6+1] = 0.0;
112: j[12+0] = 0.5; j[12+1] = 0.0;
113: j[12+2] = 0.0; j[12+3] = 0.5;
114: for (s = 0; s < 4; ++s) {
115: DMPlex_Det2D_Internal(&detJ, &j[s*dim*dim]);
116: DMPlex_Invert2D_Internal(&invj[s*dim*dim], &j[s*dim*dim], detJ);
117: }
118: }
119: break;
120: default:
121: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
122: }
123: if (v0) {*v0 = v; *jac = j; *invjac = invj;}
124: return(0);
125: }
129: PetscErrorCode CellRefinerRestoreAffineTransforms_Internal(CellRefiner refiner, PetscInt *numSubcells, PetscReal *v0[], PetscReal *jac[], PetscReal *invjac[])
130: {
134: PetscFree3(*v0,*jac,*invjac);
135: return(0);
136: }
140: /* Should this be here or in the DualSpace somehow? */
141: PetscErrorCode CellRefinerInCellTest_Internal(CellRefiner refiner, const PetscReal point[], PetscBool *inside)
142: {
143: PetscReal sum = 0.0;
144: PetscInt d;
147: *inside = PETSC_TRUE;
148: switch (refiner) {
149: case REFINER_NOOP: break;
150: case REFINER_SIMPLEX_2D:
151: for (d = 0; d < 2; ++d) {
152: if (point[d] < -1.0) {*inside = PETSC_FALSE; break;}
153: sum += point[d];
154: }
155: if (sum > 0.0) {*inside = PETSC_FALSE; break;}
156: break;
157: case REFINER_HEX_2D:
158: for (d = 0; d < 2; ++d) if ((point[d] < -1.0) || (point[d] > 1.0)) {*inside = PETSC_FALSE; break;}
159: break;
160: default:
161: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
162: }
163: return(0);
164: }
168: static PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[])
169: {
170: PetscInt cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax;
174: DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
175: DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);
176: DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
177: DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);
178: DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);
179: switch (refiner) {
180: case REFINER_NOOP:
181: break;
182: case REFINER_SIMPLEX_1D:
183: depthSize[0] = vEnd - vStart + cEnd - cStart; /* Add a vertex on every cell. */
184: depthSize[1] = 2*(cEnd - cStart); /* Split every cell in 2. */
185: break;
186: case REFINER_SIMPLEX_2D:
187: depthSize[0] = vEnd - vStart + fEnd - fStart; /* Add a vertex on every face */
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] = 4*(cEnd - cStart); /* Every cell split into 4 cells */
190: break;
191: case REFINER_HYBRID_SIMPLEX_2D:
192: if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
193: if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
194: depthSize[0] = vEnd - vStart + fMax - fStart; /* Add a vertex on every face, but not hybrid faces */
195: 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 */
196: depthSize[2] = 4*(cMax - cStart) + 2*(cEnd - cMax); /* Interior cells split into 4 cells, Hybrid cells split into 2 cells */
197: break;
198: case REFINER_HEX_2D:
199: depthSize[0] = vEnd - vStart + fEnd - fStart + cEnd - cStart; /* Add a vertex on every face and cell */
200: depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart); /* Every face is split into 2 faces and 4 faces are added for each cell */
201: depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */
202: break;
203: case REFINER_HYBRID_HEX_2D:
204: if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
205: if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
206: /* Quadrilateral */
207: depthSize[0] = vEnd - vStart + fMax - fStart + cMax - cStart; /* Add a vertex on every face and cell */
208: depthSize[1] = 2*(fMax - fStart) + 4*(cMax - cStart); /* Every face is split into 2 faces, and 4 faces are added for each cell */
209: depthSize[2] = 4*(cMax - cStart); /* Every cell split into 4 cells */
210: /* Segment Prisms */
211: depthSize[0] += 0; /* No hybrid vertices */
212: depthSize[1] += (fEnd - fMax) + (cEnd - cMax); /* Every hybrid face remains and 1 faces is added for each hybrid cell */
213: depthSize[2] += 2*(cEnd - cMax); /* Every hybrid cell split into 2 cells */
214: break;
215: case REFINER_SIMPLEX_3D:
216: depthSize[0] = vEnd - vStart + eEnd - eStart; /* Add a vertex on every edge */
217: 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 */
218: depthSize[2] = 4*(fEnd - fStart) + 8*(cEnd - cStart); /* Every face split into 4 faces and 8 faces are added for each cell */
219: depthSize[3] = 8*(cEnd - cStart); /* Every cell split into 8 cells */
220: break;
221: case REFINER_HYBRID_SIMPLEX_3D:
222: if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
223: if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
224: if (eMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No edge maximum specified in hybrid mesh");
225: /* Tetrahedra */
226: depthSize[0] = vEnd - vStart + eMax - eStart; /* Add a vertex on every interior edge */
227: 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 */
228: depthSize[2] = 4*(fMax - fStart) + 8*(cMax - cStart); /* Every interior face split into 4 faces, 8 faces added for each interior cell */
229: depthSize[3] = 8*(cMax - cStart); /* Every interior cell split into 8 cells */
230: /* Triangular Prisms */
231: depthSize[0] += 0; /* No hybrid vertices */
232: depthSize[1] += (eEnd - eMax) + (fEnd - fMax); /* Every hybrid edge remains, 1 edge for every hybrid face */
233: depthSize[2] += 2*(fEnd - fMax) + 3*(cEnd - cMax); /* Every hybrid face split into 2 faces and 3 faces are added for each hybrid cell */
234: depthSize[3] += 4*(cEnd - cMax); /* Every hybrid cell split into 4 cells */
235: break;
236: case REFINER_HEX_3D:
237: depthSize[0] = vEnd - vStart + eEnd - eStart + fEnd - fStart + cEnd - cStart; /* Add a vertex on every edge, face and cell */
238: 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 */
239: depthSize[2] = 4*(fEnd - fStart) + 12*(cEnd - cStart); /* Every face is split into 4 faces, and 12 faces are added for each cell */
240: depthSize[3] = 8*(cEnd - cStart); /* Every cell split into 8 cells */
241: break;
242: case REFINER_HYBRID_HEX_3D:
243: if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
244: if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
245: if (eMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No edge maximum specified in hybrid mesh");
246: /* Hexahedra */
247: depthSize[0] = vEnd - vStart + eMax - eStart + fMax - fStart + cMax - cStart; /* Add a vertex on every edge, face and cell */
248: 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 */
249: depthSize[2] = 4*(fMax - fStart) + 12*(cMax - cStart); /* Every face is split into 4 faces, and 12 faces are added for each cell */
250: depthSize[3] = 8*(cMax - cStart); /* Every cell split into 8 cells */
251: /* Quadrilateral Prisms */
252: depthSize[0] += 0; /* No hybrid vertices */
253: depthSize[1] += (eEnd - eMax) + (fEnd - fMax) + (cEnd - cMax); /* Every hybrid edge remains, 1 edge for every hybrid face and hybrid cell */
254: depthSize[2] += 2*(fEnd - fMax) + 4*(cEnd - cMax); /* Every hybrid face split into 2 faces and 4 faces are added for each hybrid cell */
255: depthSize[3] += 4*(cEnd - cMax); /* Every hybrid cell split into 4 cells */
256: break;
257: default:
258: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
259: }
260: return(0);
261: }
263: /* Return triangle edge for orientation o, if it is r for o == 0 */
264: PETSC_STATIC_INLINE PetscInt GetTriEdge_Static(PetscInt o, PetscInt r) {
265: return (o < 0 ? 2-(o+r) : o+r)%3;
266: }
267: PETSC_STATIC_INLINE PetscInt GetTriEdgeInverse_Static(PetscInt o, PetscInt s) {
268: return (o < 0 ? 2-(o+s) : 3+s-o)%3;
269: }
271: /* Return triangle subface for orientation o, if it is r for o == 0 */
272: PETSC_STATIC_INLINE PetscInt GetTriSubface_Static(PetscInt o, PetscInt r) {
273: return (o < 0 ? 3-(o+r) : o+r)%3;
274: }
275: PETSC_STATIC_INLINE PetscInt GetTriSubfaceInverse_Static(PetscInt o, PetscInt s) {
276: return (o < 0 ? 3-(o+s) : 3+s-o)%3;
277: }
279: /* I HAVE NO IDEA: Return ??? for orientation o, if it is r for o == 0 */
280: PETSC_STATIC_INLINE PetscInt GetTetSomething_Static(PetscInt o, PetscInt r) {
281: return (o < 0 ? 1-(o+r) : o+r)%3;
282: }
283: PETSC_STATIC_INLINE PetscInt GetTetSomethingInverse_Static(PetscInt o, PetscInt s) {
284: return (o < 0 ? 1-(o+s) : 3+s-o)%3;
285: }
288: /* Return quad edge for orientation o, if it is r for o == 0 */
289: PETSC_STATIC_INLINE PetscInt GetQuadEdge_Static(PetscInt o, PetscInt r) {
290: return (o < 0 ? 3-(o+r) : o+r)%4;
291: }
292: PETSC_STATIC_INLINE PetscInt GetQuadEdgeInverse_Static(PetscInt o, PetscInt s) {
293: return (o < 0 ? 3-(o+s) : 4+s-o)%4;
294: }
296: /* Return quad subface for orientation o, if it is r for o == 0 */
297: PETSC_STATIC_INLINE PetscInt GetQuadSubface_Static(PetscInt o, PetscInt r) {
298: return (o < 0 ? 4-(o+r) : o+r)%4;
299: }
300: PETSC_STATIC_INLINE PetscInt GetQuadSubfaceInverse_Static(PetscInt o, PetscInt s) {
301: return (o < 0 ? 4-(o+s) : 4+s-o)%4;
302: }
306: static PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
307: {
308: PetscInt depth, cStart, cStartNew, cEnd, cMax, c, vStart, vStartNew, vEnd, vMax, v, fStart, fStartNew, fEnd, fMax, f, eStart, eStartNew, eEnd, eMax, e, r;
312: if (!refiner) return(0);
313: DMPlexGetDepth(dm, &depth);
314: DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
315: DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);
316: DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
317: DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);
318: DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);
319: GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);
320: switch (refiner) {
321: case REFINER_SIMPLEX_1D:
322: /* All cells have 2 vertices */
323: for (c = cStart; c < cEnd; ++c) {
324: for (r = 0; r < 2; ++r) {
325: const PetscInt newp = cStartNew + (c - cStart)*2 + r;
327: DMPlexSetConeSize(rdm, newp, 2);
328: }
329: }
330: /* Old vertices have identical supports */
331: for (v = vStart; v < vEnd; ++v) {
332: const PetscInt newp = vStartNew + (v - vStart);
333: PetscInt size;
335: DMPlexGetSupportSize(dm, v, &size);
336: DMPlexSetSupportSize(rdm, newp, size);
337: }
338: /* Cell vertices have support 2 */
339: for (c = cStart; c < cEnd; ++c) {
340: const PetscInt newp = vStartNew + (vEnd - vStart) + (c - cStart);
342: DMPlexSetSupportSize(rdm, newp, 2);
343: }
344: break;
345: case REFINER_SIMPLEX_2D:
346: /* All cells have 3 faces */
347: for (c = cStart; c < cEnd; ++c) {
348: for (r = 0; r < 4; ++r) {
349: const PetscInt newp = (c - cStart)*4 + r;
351: DMPlexSetConeSize(rdm, newp, 3);
352: }
353: }
354: /* Split faces have 2 vertices and the same cells as the parent */
355: for (f = fStart; f < fEnd; ++f) {
356: for (r = 0; r < 2; ++r) {
357: const PetscInt newp = fStartNew + (f - fStart)*2 + r;
358: PetscInt size;
360: DMPlexSetConeSize(rdm, newp, 2);
361: DMPlexGetSupportSize(dm, f, &size);
362: DMPlexSetSupportSize(rdm, newp, size);
363: }
364: }
365: /* Interior faces have 2 vertices and 2 cells */
366: for (c = cStart; c < cEnd; ++c) {
367: for (r = 0; r < 3; ++r) {
368: const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r;
370: DMPlexSetConeSize(rdm, newp, 2);
371: DMPlexSetSupportSize(rdm, newp, 2);
372: }
373: }
374: /* Old vertices have identical supports */
375: for (v = vStart; v < vEnd; ++v) {
376: const PetscInt newp = vStartNew + (v - vStart);
377: PetscInt size;
379: DMPlexGetSupportSize(dm, v, &size);
380: DMPlexSetSupportSize(rdm, newp, size);
381: }
382: /* Face vertices have 2 + cells*2 supports */
383: for (f = fStart; f < fEnd; ++f) {
384: const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
385: PetscInt size;
387: DMPlexGetSupportSize(dm, f, &size);
388: DMPlexSetSupportSize(rdm, newp, 2 + size*2);
389: }
390: break;
391: case REFINER_HEX_2D:
392: /* All cells have 4 faces */
393: for (c = cStart; c < cEnd; ++c) {
394: for (r = 0; r < 4; ++r) {
395: const PetscInt newp = cStartNew + (c - cStart)*4 + r;
397: DMPlexSetConeSize(rdm, newp, 4);
398: }
399: }
400: /* Split faces have 2 vertices and the same cells as the parent */
401: for (f = fStart; f < fEnd; ++f) {
402: for (r = 0; r < 2; ++r) {
403: const PetscInt newp = fStartNew + (f - fStart)*2 + r;
404: PetscInt size;
406: DMPlexSetConeSize(rdm, newp, 2);
407: DMPlexGetSupportSize(dm, f, &size);
408: DMPlexSetSupportSize(rdm, newp, size);
409: }
410: }
411: /* Interior faces have 2 vertices and 2 cells */
412: for (c = cStart; c < cEnd; ++c) {
413: for (r = 0; r < 4; ++r) {
414: const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r;
416: DMPlexSetConeSize(rdm, newp, 2);
417: DMPlexSetSupportSize(rdm, newp, 2);
418: }
419: }
420: /* Old vertices have identical supports */
421: for (v = vStart; v < vEnd; ++v) {
422: const PetscInt newp = vStartNew + (v - vStart);
423: PetscInt size;
425: DMPlexGetSupportSize(dm, v, &size);
426: DMPlexSetSupportSize(rdm, newp, size);
427: }
428: /* Face vertices have 2 + cells supports */
429: for (f = fStart; f < fEnd; ++f) {
430: const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
431: PetscInt size;
433: DMPlexGetSupportSize(dm, f, &size);
434: DMPlexSetSupportSize(rdm, newp, 2 + size);
435: }
436: /* Cell vertices have 4 supports */
437: for (c = cStart; c < cEnd; ++c) {
438: const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart);
440: DMPlexSetSupportSize(rdm, newp, 4);
441: }
442: break;
443: case REFINER_HYBRID_SIMPLEX_2D:
444: if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
445: cMax = PetscMin(cEnd, cMax);
446: if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
447: fMax = PetscMin(fEnd, fMax);
448: DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);
449: /* Interior cells have 3 faces */
450: for (c = cStart; c < cMax; ++c) {
451: for (r = 0; r < 4; ++r) {
452: const PetscInt newp = cStartNew + (c - cStart)*4 + r;
454: DMPlexSetConeSize(rdm, newp, 3);
455: }
456: }
457: /* Hybrid cells have 4 faces */
458: for (c = cMax; c < cEnd; ++c) {
459: for (r = 0; r < 2; ++r) {
460: const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r;
462: DMPlexSetConeSize(rdm, newp, 4);
463: }
464: }
465: /* Interior split faces have 2 vertices and the same cells as the parent */
466: for (f = fStart; f < fMax; ++f) {
467: for (r = 0; r < 2; ++r) {
468: const PetscInt newp = fStartNew + (f - fStart)*2 + r;
469: PetscInt size;
471: DMPlexSetConeSize(rdm, newp, 2);
472: DMPlexGetSupportSize(dm, f, &size);
473: DMPlexSetSupportSize(rdm, newp, size);
474: }
475: }
476: /* Interior cell faces have 2 vertices and 2 cells */
477: for (c = cStart; c < cMax; ++c) {
478: for (r = 0; r < 3; ++r) {
479: const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r;
481: DMPlexSetConeSize(rdm, newp, 2);
482: DMPlexSetSupportSize(rdm, newp, 2);
483: }
484: }
485: /* Hybrid faces have 2 vertices and the same cells */
486: for (f = fMax; f < fEnd; ++f) {
487: const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax);
488: PetscInt size;
490: DMPlexSetConeSize(rdm, newp, 2);
491: DMPlexGetSupportSize(dm, f, &size);
492: DMPlexSetSupportSize(rdm, newp, size);
493: }
494: /* Hybrid cell faces have 2 vertices and 2 cells */
495: for (c = cMax; c < cEnd; ++c) {
496: const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax);
498: DMPlexSetConeSize(rdm, newp, 2);
499: DMPlexSetSupportSize(rdm, newp, 2);
500: }
501: /* Old vertices have identical supports */
502: for (v = vStart; v < vEnd; ++v) {
503: const PetscInt newp = vStartNew + (v - vStart);
504: PetscInt size;
506: DMPlexGetSupportSize(dm, v, &size);
507: DMPlexSetSupportSize(rdm, newp, size);
508: }
509: /* Face vertices have 2 + (2 interior, 1 hybrid) supports */
510: for (f = fStart; f < fMax; ++f) {
511: const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
512: const PetscInt *support;
513: PetscInt size, newSize = 2, s;
515: DMPlexGetSupportSize(dm, f, &size);
516: DMPlexGetSupport(dm, f, &support);
517: for (s = 0; s < size; ++s) {
518: if (support[s] >= cMax) newSize += 1;
519: else newSize += 2;
520: }
521: DMPlexSetSupportSize(rdm, newp, newSize);
522: }
523: break;
524: case REFINER_HYBRID_HEX_2D:
525: if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
526: cMax = PetscMin(cEnd, cMax);
527: if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
528: fMax = PetscMin(fEnd, fMax);
529: DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4, PETSC_DETERMINE, PETSC_DETERMINE);
530: /* Interior cells have 4 faces */
531: for (c = cStart; c < cMax; ++c) {
532: for (r = 0; r < 4; ++r) {
533: const PetscInt newp = cStartNew + (c - cStart)*4 + r;
535: DMPlexSetConeSize(rdm, newp, 4);
536: }
537: }
538: /* Hybrid cells have 4 faces */
539: for (c = cMax; c < cEnd; ++c) {
540: for (r = 0; r < 2; ++r) {
541: const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r;
543: DMPlexSetConeSize(rdm, newp, 4);
544: }
545: }
546: /* Interior split faces have 2 vertices and the same cells as the parent */
547: for (f = fStart; f < fMax; ++f) {
548: for (r = 0; r < 2; ++r) {
549: const PetscInt newp = fStartNew + (f - fStart)*2 + r;
550: PetscInt size;
552: DMPlexSetConeSize(rdm, newp, 2);
553: DMPlexGetSupportSize(dm, f, &size);
554: DMPlexSetSupportSize(rdm, newp, size);
555: }
556: }
557: /* Interior cell faces have 2 vertices and 2 cells */
558: for (c = cStart; c < cMax; ++c) {
559: for (r = 0; r < 4; ++r) {
560: const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + r;
562: DMPlexSetConeSize(rdm, newp, 2);
563: DMPlexSetSupportSize(rdm, newp, 2);
564: }
565: }
566: /* Hybrid faces have 2 vertices and the same cells */
567: for (f = fMax; f < fEnd; ++f) {
568: const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (f - fMax);
569: PetscInt size;
571: DMPlexSetConeSize(rdm, newp, 2);
572: DMPlexGetSupportSize(dm, f, &size);
573: DMPlexSetSupportSize(rdm, newp, size);
574: }
575: /* Hybrid cell faces have 2 vertices and 2 cells */
576: for (c = cMax; c < cEnd; ++c) {
577: const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (fEnd - fMax) + (c - cMax);
579: DMPlexSetConeSize(rdm, newp, 2);
580: DMPlexSetSupportSize(rdm, newp, 2);
581: }
582: /* Old vertices have identical supports */
583: for (v = vStart; v < vEnd; ++v) {
584: const PetscInt newp = vStartNew + (v - vStart);
585: PetscInt size;
587: DMPlexGetSupportSize(dm, v, &size);
588: DMPlexSetSupportSize(rdm, newp, size);
589: }
590: /* Face vertices have 2 + cells supports */
591: for (f = fStart; f < fMax; ++f) {
592: const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
593: PetscInt size;
595: DMPlexGetSupportSize(dm, f, &size);
596: DMPlexSetSupportSize(rdm, newp, 2 + size);
597: }
598: /* Cell vertices have 4 supports */
599: for (c = cStart; c < cMax; ++c) {
600: const PetscInt newp = vStartNew + (vEnd - vStart) + (fMax - fStart) + (c - cStart);
602: DMPlexSetSupportSize(rdm, newp, 4);
603: }
604: break;
605: case REFINER_SIMPLEX_3D:
606: /* All cells have 4 faces */
607: for (c = cStart; c < cEnd; ++c) {
608: for (r = 0; r < 8; ++r) {
609: const PetscInt newp = cStartNew + (c - cStart)*8 + r;
611: DMPlexSetConeSize(rdm, newp, 4);
612: }
613: }
614: /* Split faces have 3 edges and the same cells as the parent */
615: for (f = fStart; f < fEnd; ++f) {
616: for (r = 0; r < 4; ++r) {
617: const PetscInt newp = fStartNew + (f - fStart)*4 + r;
618: PetscInt size;
620: DMPlexSetConeSize(rdm, newp, 3);
621: DMPlexGetSupportSize(dm, f, &size);
622: DMPlexSetSupportSize(rdm, newp, size);
623: }
624: }
625: /* Interior cell faces have 3 edges and 2 cells */
626: for (c = cStart; c < cEnd; ++c) {
627: for (r = 0; r < 8; ++r) {
628: const PetscInt newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + r;
630: DMPlexSetConeSize(rdm, newp, 3);
631: DMPlexSetSupportSize(rdm, newp, 2);
632: }
633: }
634: /* Split edges have 2 vertices and the same faces */
635: for (e = eStart; e < eEnd; ++e) {
636: for (r = 0; r < 2; ++r) {
637: const PetscInt newp = eStartNew + (e - eStart)*2 + r;
638: PetscInt size;
640: DMPlexSetConeSize(rdm, newp, 2);
641: DMPlexGetSupportSize(dm, e, &size);
642: DMPlexSetSupportSize(rdm, newp, size);
643: }
644: }
645: /* Face edges have 2 vertices and 2+cells*(1/2) faces */
646: for (f = fStart; f < fEnd; ++f) {
647: for (r = 0; r < 3; ++r) {
648: const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + r;
649: const PetscInt *cone, *ornt, *support, eint[4] = {1, 0, 2, 0};
650: PetscInt coneSize, c, supportSize, s, er, intFaces = 0;
652: DMPlexSetConeSize(rdm, newp, 2);
653: DMPlexGetSupportSize(dm, f, &supportSize);
654: DMPlexGetSupport(dm, f, &support);
655: for (s = 0; s < supportSize; ++s) {
656: DMPlexGetConeSize(dm, support[s], &coneSize);
657: DMPlexGetCone(dm, support[s], &cone);
658: DMPlexGetConeOrientation(dm, support[s], &ornt);
659: for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
660: /* Here we want to determine whether edge newp contains a vertex which is part of the cross-tet edge */
661: er = GetTetSomethingInverse_Static(ornt[c], r);
662: if (er == eint[c]) {
663: intFaces += 1;
664: } else {
665: intFaces += 2;
666: }
667: }
668: DMPlexSetSupportSize(rdm, newp, 2+intFaces);
669: }
670: }
671: /* Interior cell edges have 2 vertices and 4 faces */
672: for (c = cStart; c < cEnd; ++c) {
673: const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
675: DMPlexSetConeSize(rdm, newp, 2);
676: DMPlexSetSupportSize(rdm, newp, 4);
677: }
678: /* Old vertices have identical supports */
679: for (v = vStart; v < vEnd; ++v) {
680: const PetscInt newp = vStartNew + (v - vStart);
681: PetscInt size;
683: DMPlexGetSupportSize(dm, v, &size);
684: DMPlexSetSupportSize(rdm, newp, size);
685: }
686: /* Edge vertices have 2 + faces*2 + cells*0/1 supports */
687: for (e = eStart; e < eEnd; ++e) {
688: const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
689: PetscInt size, *star = NULL, starSize, s, cellSize = 0;
691: DMPlexGetSupportSize(dm, e, &size);
692: DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
693: for (s = 0; s < starSize*2; s += 2) {
694: const PetscInt *cone, *ornt;
695: PetscInt e01, e23;
697: if ((star[s] >= cStart) && (star[s] < cEnd)) {
698: /* Check edge 0-1 */
699: DMPlexGetCone(dm, star[s], &cone);
700: DMPlexGetConeOrientation(dm, star[s], &ornt);
701: DMPlexGetCone(dm, cone[0], &cone);
702: e01 = cone[GetTriEdge_Static(ornt[0], 0)];
703: /* Check edge 2-3 */
704: DMPlexGetCone(dm, star[s], &cone);
705: DMPlexGetConeOrientation(dm, star[s], &ornt);
706: DMPlexGetCone(dm, cone[2], &cone);
707: e23 = cone[GetTriEdge_Static(ornt[2], 1)];
708: if ((e01 == e) || (e23 == e)) ++cellSize;
709: }
710: }
711: DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
712: DMPlexSetSupportSize(rdm, newp, 2 + size*2 + cellSize);
713: }
714: break;
715: case REFINER_HYBRID_SIMPLEX_3D:
716: DMPlexSetHybridBounds(rdm, cStartNew + 8*(cMax-cStart), fStartNew + 4*(fMax - fStart) + 8*(cMax - cStart),
717: eStartNew + 2*(eMax - eStart) + 3*(fMax - fStart) + (cMax - cStart), PETSC_DETERMINE);
718: /* Interior cells have 4 faces */
719: for (c = cStart; c < cMax; ++c) {
720: for (r = 0; r < 8; ++r) {
721: const PetscInt newp = cStartNew + (c - cStart)*8 + r;
723: DMPlexSetConeSize(rdm, newp, 4);
724: }
725: }
726: /* Hybrid cells have 5 faces */
727: for (c = cMax; c < cEnd; ++c) {
728: for (r = 0; r < 4; ++r) {
729: const PetscInt newp = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + r;
731: DMPlexSetConeSize(rdm, newp, 5);
732: }
733: }
734: /* Interior split faces have 3 edges and the same cells as the parent */
735: for (f = fStart; f < fMax; ++f) {
736: for (r = 0; r < 4; ++r) {
737: const PetscInt newp = fStartNew + (f - fStart)*4 + r;
738: PetscInt size;
740: DMPlexSetConeSize(rdm, newp, 3);
741: DMPlexGetSupportSize(dm, f, &size);
742: DMPlexSetSupportSize(rdm, newp, size);
743: }
744: }
745: /* Interior cell faces have 3 edges and 2 cells */
746: for (c = cStart; c < cMax; ++c) {
747: for (r = 0; r < 8; ++r) {
748: const PetscInt newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + r;
750: DMPlexSetConeSize(rdm, newp, 3);
751: DMPlexSetSupportSize(rdm, newp, 2);
752: }
753: }
754: /* Hybrid split faces have 4 edges and the same cells as the parent */
755: for (f = fMax; f < fEnd; ++f) {
756: for (r = 0; r < 2; ++r) {
757: const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (f - fMax)*2 + r;
758: PetscInt size;
760: DMPlexSetConeSize(rdm, newp, 4);
761: DMPlexGetSupportSize(dm, f, &size);
762: DMPlexSetSupportSize(rdm, newp, size);
763: }
764: }
765: /* Hybrid cells faces have 4 edges and 2 cells */
766: for (c = cMax; c < cEnd; ++c) {
767: for (r = 0; r < 3; ++r) {
768: const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + r;
770: DMPlexSetConeSize(rdm, newp, 4);
771: DMPlexSetSupportSize(rdm, newp, 2);
772: }
773: }
774: /* Interior split edges have 2 vertices and the same faces */
775: for (e = eStart; e < eMax; ++e) {
776: for (r = 0; r < 2; ++r) {
777: const PetscInt newp = eStartNew + (e - eStart)*2 + r;
778: PetscInt size;
780: DMPlexSetConeSize(rdm, newp, 2);
781: DMPlexGetSupportSize(dm, e, &size);
782: DMPlexSetSupportSize(rdm, newp, size);
783: }
784: }
785: /* Interior face edges have 2 vertices and 2+cells*(1/2) faces */
786: for (f = fStart; f < fMax; ++f) {
787: for (r = 0; r < 3; ++r) {
788: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + r;
789: const PetscInt *cone, *ornt, *support, eint[4] = {1, 0, 2, 0};
790: PetscInt coneSize, c, supportSize, s, er, intFaces = 0;
792: DMPlexSetConeSize(rdm, newp, 2);
793: DMPlexGetSupportSize(dm, f, &supportSize);
794: DMPlexGetSupport(dm, f, &support);
795: for (s = 0; s < supportSize; ++s) {
796: DMPlexGetConeSize(dm, support[s], &coneSize);
797: DMPlexGetCone(dm, support[s], &cone);
798: DMPlexGetConeOrientation(dm, support[s], &ornt);
799: for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
800: if (support[s] < cMax) {
801: /* Here we want to determine whether edge newp contains a vertex which is part of the cross-tet edge */
802: er = GetTetSomethingInverse_Static(ornt[c], r);
803: if (er == eint[c]) {
804: intFaces += 1;
805: } else {
806: intFaces += 2;
807: }
808: } else {
809: intFaces += 1;
810: }
811: }
812: DMPlexSetSupportSize(rdm, newp, 2+intFaces);
813: }
814: }
815: /* Interior cell edges have 2 vertices and 4 faces */
816: for (c = cStart; c < cMax; ++c) {
817: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
819: DMPlexSetConeSize(rdm, newp, 2);
820: DMPlexSetSupportSize(rdm, newp, 4);
821: }
822: /* Hybrid edges have 2 vertices and the same faces */
823: for (e = eMax; e < eEnd; ++e) {
824: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (e - eMax);
825: PetscInt size;
827: DMPlexSetConeSize(rdm, newp, 2);
828: DMPlexGetSupportSize(dm, e, &size);
829: DMPlexSetSupportSize(rdm, newp, size);
830: }
831: /* Hybrid face edges have 2 vertices and 2+2*cells faces */
832: for (f = fMax; f < fEnd; ++f) {
833: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (f - fMax);
834: PetscInt size;
836: DMPlexSetConeSize(rdm, newp, 2);
837: DMPlexGetSupportSize(dm, f, &size);
838: DMPlexSetSupportSize(rdm, newp, 2+2*size);
839: }
840: /* Interior vertices have identical supports */
841: for (v = vStart; v < vEnd; ++v) {
842: const PetscInt newp = vStartNew + (v - vStart);
843: PetscInt size;
845: DMPlexGetSupportSize(dm, v, &size);
846: DMPlexSetSupportSize(rdm, newp, size);
847: }
848: /* Interior edge vertices have 2 + interior face*2 + hybrid face + cells*0/1 supports */
849: for (e = eStart; e < eMax; ++e) {
850: const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
851: const PetscInt *support;
852: PetscInt size, *star = NULL, starSize, s, faceSize = 0, cellSize = 0;
854: DMPlexGetSupportSize(dm, e, &size);
855: DMPlexGetSupport(dm, e, &support);
856: for (s = 0; s < size; ++s) {
857: if (support[s] < fMax) faceSize += 2;
858: else faceSize += 1;
859: }
860: DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
861: for (s = 0; s < starSize*2; s += 2) {
862: const PetscInt *cone, *ornt;
863: PetscInt e01, e23;
865: if ((star[s] >= cStart) && (star[s] < cMax)) {
866: /* Check edge 0-1 */
867: DMPlexGetCone(dm, star[s], &cone);
868: DMPlexGetConeOrientation(dm, star[s], &ornt);
869: DMPlexGetCone(dm, cone[0], &cone);
870: e01 = cone[GetTriEdge_Static(ornt[0], 0)];
871: /* Check edge 2-3 */
872: DMPlexGetCone(dm, star[s], &cone);
873: DMPlexGetConeOrientation(dm, star[s], &ornt);
874: DMPlexGetCone(dm, cone[2], &cone);
875: e23 = cone[GetTriEdge_Static(ornt[2], 1)];
876: if ((e01 == e) || (e23 == e)) ++cellSize;
877: }
878: }
879: DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
880: DMPlexSetSupportSize(rdm, newp, 2 + faceSize + cellSize);
881: }
882: break;
883: case REFINER_HEX_3D:
884: /* All cells have 6 faces */
885: for (c = cStart; c < cEnd; ++c) {
886: for (r = 0; r < 8; ++r) {
887: const PetscInt newp = (c - cStart)*8 + r;
889: DMPlexSetConeSize(rdm, newp, 6);
890: }
891: }
892: /* Split faces have 4 edges and the same cells as the parent */
893: for (f = fStart; f < fEnd; ++f) {
894: for (r = 0; r < 4; ++r) {
895: const PetscInt newp = fStartNew + (f - fStart)*4 + r;
896: PetscInt size;
898: DMPlexSetConeSize(rdm, newp, 4);
899: DMPlexGetSupportSize(dm, f, &size);
900: DMPlexSetSupportSize(rdm, newp, size);
901: }
902: }
903: /* Interior faces have 4 edges and 2 cells */
904: for (c = cStart; c < cEnd; ++c) {
905: for (r = 0; r < 12; ++r) {
906: const PetscInt newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + r;
908: DMPlexSetConeSize(rdm, newp, 4);
909: DMPlexSetSupportSize(rdm, newp, 2);
910: }
911: }
912: /* Split edges have 2 vertices and the same faces as the parent */
913: for (e = eStart; e < eEnd; ++e) {
914: for (r = 0; r < 2; ++r) {
915: const PetscInt newp = eStartNew + (e - eStart)*2 + r;
916: PetscInt size;
918: DMPlexSetConeSize(rdm, newp, 2);
919: DMPlexGetSupportSize(dm, e, &size);
920: DMPlexSetSupportSize(rdm, newp, size);
921: }
922: }
923: /* Face edges have 2 vertices and 2+cells faces */
924: for (f = fStart; f < fEnd; ++f) {
925: for (r = 0; r < 4; ++r) {
926: const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + r;
927: PetscInt size;
929: DMPlexSetConeSize(rdm, newp, 2);
930: DMPlexGetSupportSize(dm, f, &size);
931: DMPlexSetSupportSize(rdm, newp, 2+size);
932: }
933: }
934: /* Cell edges have 2 vertices and 4 faces */
935: for (c = cStart; c < cEnd; ++c) {
936: for (r = 0; r < 6; ++r) {
937: const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + r;
939: DMPlexSetConeSize(rdm, newp, 2);
940: DMPlexSetSupportSize(rdm, newp, 4);
941: }
942: }
943: /* Old vertices have identical supports */
944: for (v = vStart; v < vEnd; ++v) {
945: const PetscInt newp = vStartNew + (v - vStart);
946: PetscInt size;
948: DMPlexGetSupportSize(dm, v, &size);
949: DMPlexSetSupportSize(rdm, newp, size);
950: }
951: /* Edge vertices have 2 + faces supports */
952: for (e = eStart; e < eEnd; ++e) {
953: const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
954: PetscInt size;
956: DMPlexGetSupportSize(dm, e, &size);
957: DMPlexSetSupportSize(rdm, newp, 2 + size);
958: }
959: /* Face vertices have 4 + cells supports */
960: for (f = fStart; f < fEnd; ++f) {
961: const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (f - fStart);
962: PetscInt size;
964: DMPlexGetSupportSize(dm, f, &size);
965: DMPlexSetSupportSize(rdm, newp, 4 + size);
966: }
967: /* Cell vertices have 6 supports */
968: for (c = cStart; c < cEnd; ++c) {
969: const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (c - cStart);
971: DMPlexSetSupportSize(rdm, newp, 6);
972: }
973: break;
974: case REFINER_HYBRID_HEX_3D:
975: DMPlexSetHybridBounds(rdm, cStartNew + 8*(cMax-cStart), fStartNew + 4*(fMax - fStart) + 12*(cMax - cStart),
976: eStartNew + 2*(eMax - eStart) + 4*(fMax - fStart) + 6*(cMax - cStart), PETSC_DETERMINE);
977: /* Interior cells have 6 faces */
978: for (c = cStart; c < cMax; ++c) {
979: for (r = 0; r < 8; ++r) {
980: const PetscInt newp = cStartNew + (c - cStart)*8 + r;
982: DMPlexSetConeSize(rdm, newp, 6);
983: }
984: }
985: /* Hybrid cells have 6 faces */
986: for (c = cMax; c < cEnd; ++c) {
987: for (r = 0; r < 4; ++r) {
988: const PetscInt newp = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + r;
990: DMPlexSetConeSize(rdm, newp, 6);
991: }
992: }
993: /* Interior split faces have 4 edges and the same cells as the parent */
994: for (f = fStart; f < fMax; ++f) {
995: for (r = 0; r < 4; ++r) {
996: const PetscInt newp = fStartNew + (f - fStart)*4 + r;
997: PetscInt size;
999: DMPlexSetConeSize(rdm, newp, 4);
1000: DMPlexGetSupportSize(dm, f, &size);
1001: DMPlexSetSupportSize(rdm, newp, size);
1002: }
1003: }
1004: /* Interior cell faces have 4 edges and 2 cells */
1005: for (c = cStart; c < cMax; ++c) {
1006: for (r = 0; r < 12; ++r) {
1007: const PetscInt newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + r;
1009: DMPlexSetConeSize(rdm, newp, 4);
1010: DMPlexSetSupportSize(rdm, newp, 2);
1011: }
1012: }
1013: /* Hybrid split faces have 4 edges and the same cells as the parent */
1014: for (f = fMax; f < fEnd; ++f) {
1015: for (r = 0; r < 2; ++r) {
1016: const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (f - fMax)*2 + r;
1017: PetscInt size;
1019: DMPlexSetConeSize(rdm, newp, 4);
1020: DMPlexGetSupportSize(dm, f, &size);
1021: DMPlexSetSupportSize(rdm, newp, size);
1022: }
1023: }
1024: /* Hybrid cells faces have 4 edges and 2 cells */
1025: for (c = cMax; c < cEnd; ++c) {
1026: for (r = 0; r < 4; ++r) {
1027: const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + r;
1029: DMPlexSetConeSize(rdm, newp, 4);
1030: DMPlexSetSupportSize(rdm, newp, 2);
1031: }
1032: }
1033: /* Interior split edges have 2 vertices and the same faces as the parent */
1034: for (e = eStart; e < eMax; ++e) {
1035: for (r = 0; r < 2; ++r) {
1036: const PetscInt newp = eStartNew + (e - eStart)*2 + r;
1037: PetscInt size;
1039: DMPlexSetConeSize(rdm, newp, 2);
1040: DMPlexGetSupportSize(dm, e, &size);
1041: DMPlexSetSupportSize(rdm, newp, size);
1042: }
1043: }
1044: /* Interior face edges have 2 vertices and 2+cells faces */
1045: for (f = fStart; f < fMax; ++f) {
1046: for (r = 0; r < 4; ++r) {
1047: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (f - fStart)*4 + r;
1048: PetscInt size;
1050: DMPlexSetConeSize(rdm, newp, 2);
1051: DMPlexGetSupportSize(dm, f, &size);
1052: DMPlexSetSupportSize(rdm, newp, 2+size);
1053: }
1054: }
1055: /* Interior cell edges have 2 vertices and 4 faces */
1056: for (c = cStart; c < cMax; ++c) {
1057: for (r = 0; r < 6; ++r) {
1058: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + r;
1060: DMPlexSetConeSize(rdm, newp, 2);
1061: DMPlexSetSupportSize(rdm, newp, 4);
1062: }
1063: }
1064: /* Hybrid edges have 2 vertices and the same faces */
1065: for (e = eMax; e < eEnd; ++e) {
1066: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (e - eMax);
1067: PetscInt size;
1069: DMPlexSetConeSize(rdm, newp, 2);
1070: DMPlexGetSupportSize(dm, e, &size);
1071: DMPlexSetSupportSize(rdm, newp, size);
1072: }
1073: /* Hybrid face edges have 2 vertices and 2+cells faces */
1074: for (f = fMax; f < fEnd; ++f) {
1075: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (f - fMax);
1076: PetscInt size;
1078: DMPlexSetConeSize(rdm, newp, 2);
1079: DMPlexGetSupportSize(dm, f, &size);
1080: DMPlexSetSupportSize(rdm, newp, 2+size);
1081: }
1082: /* Hybrid cell edges have 2 vertices and 4 faces */
1083: for (c = cMax; c < cEnd; ++c) {
1084: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (fEnd - fMax) + (c - cMax);
1086: DMPlexSetConeSize(rdm, newp, 2);
1087: DMPlexSetSupportSize(rdm, newp, 4);
1088: }
1089: /* Interior vertices have identical supports */
1090: for (v = vStart; v < vEnd; ++v) {
1091: const PetscInt newp = vStartNew + (v - vStart);
1092: PetscInt size;
1094: DMPlexGetSupportSize(dm, v, &size);
1095: DMPlexSetSupportSize(rdm, newp, size);
1096: }
1097: /* Interior edge vertices have 2 + faces supports */
1098: for (e = eStart; e < eMax; ++e) {
1099: const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
1100: PetscInt size;
1102: DMPlexGetSupportSize(dm, e, &size);
1103: DMPlexSetSupportSize(rdm, newp, 2 + size);
1104: }
1105: /* Interior face vertices have 4 + cells supports */
1106: for (f = fStart; f < fMax; ++f) {
1107: const PetscInt newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (f - fStart);
1108: PetscInt size;
1110: DMPlexGetSupportSize(dm, f, &size);
1111: DMPlexSetSupportSize(rdm, newp, 4 + size);
1112: }
1113: /* Interior cell vertices have 6 supports */
1114: for (c = cStart; c < cMax; ++c) {
1115: const PetscInt newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (fMax - fStart) + (c - cStart);
1117: DMPlexSetSupportSize(rdm, newp, 6);
1118: }
1119: break;
1120: default:
1121: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
1122: }
1123: return(0);
1124: }
1128: static PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
1129: {
1130: const PetscInt *faces, cellInd[4] = {0, 1, 2, 3};
1131: PetscInt cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax;
1132: PetscInt cStartNew, cEndNew, cMaxNew, vStartNew, vEndNew, fStartNew, fEndNew, fMaxNew, eStartNew, eEndNew, eMaxNew;
1133: PetscInt depth, maxSupportSize, *supportRef, c, f, e, v, r, p;
1134: PetscErrorCode ierr;
1137: if (!refiner) return(0);
1138: DMPlexGetDepth(dm, &depth);
1139: DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
1140: DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);
1141: DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
1142: DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);
1143: DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);
1144: GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);
1145: GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);
1146: switch (refiner) {
1147: case REFINER_SIMPLEX_1D:
1148: /* Max support size of refined mesh is 2 */
1149: PetscMalloc1(2, &supportRef);
1150: /* All cells have 2 vertices */
1151: for (c = cStart; c < cEnd; ++c) {
1152: const PetscInt newv = vStartNew + (vEnd - vStart) + (c - cStart);
1154: for (r = 0; r < 2; ++r) {
1155: const PetscInt newp = cStartNew + (c - cStart)*2 + r;
1156: const PetscInt *cone;
1157: PetscInt coneNew[2];
1159: DMPlexGetCone(dm, c, &cone);
1160: coneNew[0] = vStartNew + (cone[0] - vStart);
1161: coneNew[1] = vStartNew + (cone[1] - vStart);
1162: coneNew[(r+1)%2] = newv;
1163: DMPlexSetCone(rdm, newp, coneNew);
1164: #if 1
1165: if ((newp < cStartNew) || (newp >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp, cStartNew, cEndNew);
1166: for (p = 0; p < 2; ++p) {
1167: 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);
1168: }
1169: #endif
1170: }
1171: }
1172: /* Old vertices have identical supports */
1173: for (v = vStart; v < vEnd; ++v) {
1174: const PetscInt newp = vStartNew + (v - vStart);
1175: const PetscInt *support, *cone;
1176: PetscInt size, s;
1178: DMPlexGetSupportSize(dm, v, &size);
1179: DMPlexGetSupport(dm, v, &support);
1180: for (s = 0; s < size; ++s) {
1181: PetscInt r = 0;
1183: DMPlexGetCone(dm, support[s], &cone);
1184: if (cone[1] == v) r = 1;
1185: supportRef[s] = cStartNew + (support[s] - cStart)*2 + r;
1186: }
1187: DMPlexSetSupport(rdm, newp, supportRef);
1188: #if 1
1189: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
1190: for (p = 0; p < size; ++p) {
1191: 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);
1192: }
1193: #endif
1194: }
1195: /* Cell vertices have support of 2 cells */
1196: for (c = cStart; c < cEnd; ++c) {
1197: const PetscInt newp = vStartNew + (vEnd - vStart) + (c - cStart);
1199: supportRef[0] = cStartNew + (c - cStart)*2 + 0;
1200: supportRef[1] = cStartNew + (c - cStart)*2 + 1;
1201: DMPlexSetSupport(rdm, newp, supportRef);
1202: #if 1
1203: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
1204: for (p = 0; p < 2; ++p) {
1205: 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);
1206: }
1207: #endif
1208: }
1209: PetscFree(supportRef);
1210: break;
1211: case REFINER_SIMPLEX_2D:
1212: /*
1213: 2
1214: |\
1215: | \
1216: | \
1217: | \
1218: | C \
1219: | \
1220: | \
1221: 2---1---1
1222: |\ D / \
1223: | 2 0 \
1224: |A \ / B \
1225: 0---0-------1
1226: */
1227: /* All cells have 3 faces */
1228: for (c = cStart; c < cEnd; ++c) {
1229: const PetscInt newp = cStartNew + (c - cStart)*4;
1230: const PetscInt *cone, *ornt;
1231: PetscInt coneNew[3], orntNew[3];
1233: DMPlexGetCone(dm, c, &cone);
1234: DMPlexGetConeOrientation(dm, c, &ornt);
1235: /* A triangle */
1236: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
1237: orntNew[0] = ornt[0];
1238: coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2;
1239: orntNew[1] = -2;
1240: coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
1241: orntNew[2] = ornt[2];
1242: DMPlexSetCone(rdm, newp+0, coneNew);
1243: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
1244: #if 1
1245: 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);
1246: for (p = 0; p < 3; ++p) {
1247: 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);
1248: }
1249: #endif
1250: /* B triangle */
1251: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
1252: orntNew[0] = ornt[0];
1253: coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
1254: orntNew[1] = ornt[1];
1255: coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0;
1256: orntNew[2] = -2;
1257: DMPlexSetCone(rdm, newp+1, coneNew);
1258: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
1259: #if 1
1260: 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);
1261: for (p = 0; p < 3; ++p) {
1262: 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);
1263: }
1264: #endif
1265: /* C triangle */
1266: coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1;
1267: orntNew[0] = -2;
1268: coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
1269: orntNew[1] = ornt[1];
1270: coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
1271: orntNew[2] = ornt[2];
1272: DMPlexSetCone(rdm, newp+2, coneNew);
1273: DMPlexSetConeOrientation(rdm, newp+2, orntNew);
1274: #if 1
1275: 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);
1276: for (p = 0; p < 3; ++p) {
1277: 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);
1278: }
1279: #endif
1280: /* D triangle */
1281: coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0;
1282: orntNew[0] = 0;
1283: coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1;
1284: orntNew[1] = 0;
1285: coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2;
1286: orntNew[2] = 0;
1287: DMPlexSetCone(rdm, newp+3, coneNew);
1288: DMPlexSetConeOrientation(rdm, newp+3, orntNew);
1289: #if 1
1290: 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);
1291: for (p = 0; p < 3; ++p) {
1292: 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);
1293: }
1294: #endif
1295: }
1296: /* Split faces have 2 vertices and the same cells as the parent */
1297: DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
1298: PetscMalloc1(2 + maxSupportSize*2, &supportRef);
1299: for (f = fStart; f < fEnd; ++f) {
1300: const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
1302: for (r = 0; r < 2; ++r) {
1303: const PetscInt newp = fStartNew + (f - fStart)*2 + r;
1304: const PetscInt *cone, *ornt, *support;
1305: PetscInt coneNew[2], coneSize, c, supportSize, s;
1307: DMPlexGetCone(dm, f, &cone);
1308: coneNew[0] = vStartNew + (cone[0] - vStart);
1309: coneNew[1] = vStartNew + (cone[1] - vStart);
1310: coneNew[(r+1)%2] = newv;
1311: DMPlexSetCone(rdm, newp, coneNew);
1312: #if 1
1313: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1314: for (p = 0; p < 2; ++p) {
1315: 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);
1316: }
1317: #endif
1318: DMPlexGetSupportSize(dm, f, &supportSize);
1319: DMPlexGetSupport(dm, f, &support);
1320: for (s = 0; s < supportSize; ++s) {
1321: DMPlexGetConeSize(dm, support[s], &coneSize);
1322: DMPlexGetCone(dm, support[s], &cone);
1323: DMPlexGetConeOrientation(dm, support[s], &ornt);
1324: for (c = 0; c < coneSize; ++c) {
1325: if (cone[c] == f) break;
1326: }
1327: supportRef[s] = cStartNew + (support[s] - cStart)*4 + (ornt[c] < 0 ? (c+1-r)%3 : (c+r)%3);
1328: }
1329: DMPlexSetSupport(rdm, newp, supportRef);
1330: #if 1
1331: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1332: for (p = 0; p < supportSize; ++p) {
1333: 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);
1334: }
1335: #endif
1336: }
1337: }
1338: /* Interior faces have 2 vertices and 2 cells */
1339: for (c = cStart; c < cEnd; ++c) {
1340: const PetscInt *cone;
1342: DMPlexGetCone(dm, c, &cone);
1343: for (r = 0; r < 3; ++r) {
1344: const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r;
1345: PetscInt coneNew[2];
1346: PetscInt supportNew[2];
1348: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart);
1349: coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart);
1350: DMPlexSetCone(rdm, newp, coneNew);
1351: #if 1
1352: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1353: for (p = 0; p < 2; ++p) {
1354: 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);
1355: }
1356: #endif
1357: supportNew[0] = (c - cStart)*4 + (r+1)%3;
1358: supportNew[1] = (c - cStart)*4 + 3;
1359: DMPlexSetSupport(rdm, newp, supportNew);
1360: #if 1
1361: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1362: for (p = 0; p < 2; ++p) {
1363: 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);
1364: }
1365: #endif
1366: }
1367: }
1368: /* Old vertices have identical supports */
1369: for (v = vStart; v < vEnd; ++v) {
1370: const PetscInt newp = vStartNew + (v - vStart);
1371: const PetscInt *support, *cone;
1372: PetscInt size, s;
1374: DMPlexGetSupportSize(dm, v, &size);
1375: DMPlexGetSupport(dm, v, &support);
1376: for (s = 0; s < size; ++s) {
1377: PetscInt r = 0;
1379: DMPlexGetCone(dm, support[s], &cone);
1380: if (cone[1] == v) r = 1;
1381: supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
1382: }
1383: DMPlexSetSupport(rdm, newp, supportRef);
1384: #if 1
1385: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
1386: for (p = 0; p < size; ++p) {
1387: 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);
1388: }
1389: #endif
1390: }
1391: /* Face vertices have 2 + cells*2 supports */
1392: for (f = fStart; f < fEnd; ++f) {
1393: const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
1394: const PetscInt *cone, *support;
1395: PetscInt size, s;
1397: DMPlexGetSupportSize(dm, f, &size);
1398: DMPlexGetSupport(dm, f, &support);
1399: supportRef[0] = fStartNew + (f - fStart)*2 + 0;
1400: supportRef[1] = fStartNew + (f - fStart)*2 + 1;
1401: for (s = 0; s < size; ++s) {
1402: PetscInt r = 0;
1404: DMPlexGetCone(dm, support[s], &cone);
1405: if (cone[1] == f) r = 1;
1406: else if (cone[2] == f) r = 2;
1407: supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3;
1408: supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r;
1409: }
1410: DMPlexSetSupport(rdm, newp, supportRef);
1411: #if 1
1412: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
1413: for (p = 0; p < 2+size*2; ++p) {
1414: 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);
1415: }
1416: #endif
1417: }
1418: PetscFree(supportRef);
1419: break;
1420: case REFINER_HEX_2D:
1421: /*
1422: 3---------2---------2
1423: | | |
1424: | D 2 C |
1425: | | |
1426: 3----3----0----1----1
1427: | | |
1428: | A 0 B |
1429: | | |
1430: 0---------0---------1
1431: */
1432: /* All cells have 4 faces */
1433: for (c = cStart; c < cEnd; ++c) {
1434: const PetscInt newp = (c - cStart)*4;
1435: const PetscInt *cone, *ornt;
1436: PetscInt coneNew[4], orntNew[4];
1438: DMPlexGetCone(dm, c, &cone);
1439: DMPlexGetConeOrientation(dm, c, &ornt);
1440: /* A quad */
1441: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
1442: orntNew[0] = ornt[0];
1443: coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0;
1444: orntNew[1] = 0;
1445: coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3;
1446: orntNew[2] = -2;
1447: coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1);
1448: orntNew[3] = ornt[3];
1449: DMPlexSetCone(rdm, newp+0, coneNew);
1450: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
1451: #if 1
1452: 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);
1453: for (p = 0; p < 4; ++p) {
1454: 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);
1455: }
1456: #endif
1457: /* B quad */
1458: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
1459: orntNew[0] = ornt[0];
1460: coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
1461: orntNew[1] = ornt[1];
1462: coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1;
1463: orntNew[2] = 0;
1464: coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0;
1465: orntNew[3] = -2;
1466: DMPlexSetCone(rdm, newp+1, coneNew);
1467: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
1468: #if 1
1469: 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);
1470: for (p = 0; p < 4; ++p) {
1471: 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);
1472: }
1473: #endif
1474: /* C quad */
1475: coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1;
1476: orntNew[0] = -2;
1477: coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
1478: orntNew[1] = ornt[1];
1479: coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
1480: orntNew[2] = ornt[2];
1481: coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2;
1482: orntNew[3] = 0;
1483: DMPlexSetCone(rdm, newp+2, coneNew);
1484: DMPlexSetConeOrientation(rdm, newp+2, orntNew);
1485: #if 1
1486: 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);
1487: for (p = 0; p < 4; ++p) {
1488: 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);
1489: }
1490: #endif
1491: /* D quad */
1492: coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3;
1493: orntNew[0] = 0;
1494: coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2;
1495: orntNew[1] = -2;
1496: coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
1497: orntNew[2] = ornt[2];
1498: coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0);
1499: orntNew[3] = ornt[3];
1500: DMPlexSetCone(rdm, newp+3, coneNew);
1501: DMPlexSetConeOrientation(rdm, newp+3, orntNew);
1502: #if 1
1503: 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);
1504: for (p = 0; p < 4; ++p) {
1505: 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);
1506: }
1507: #endif
1508: }
1509: /* Split faces have 2 vertices and the same cells as the parent */
1510: DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
1511: PetscMalloc1(2 + maxSupportSize*2, &supportRef);
1512: for (f = fStart; f < fEnd; ++f) {
1513: const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
1515: for (r = 0; r < 2; ++r) {
1516: const PetscInt newp = fStartNew + (f - fStart)*2 + r;
1517: const PetscInt *cone, *ornt, *support;
1518: PetscInt coneNew[2], coneSize, c, supportSize, s;
1520: DMPlexGetCone(dm, f, &cone);
1521: coneNew[0] = vStartNew + (cone[0] - vStart);
1522: coneNew[1] = vStartNew + (cone[1] - vStart);
1523: coneNew[(r+1)%2] = newv;
1524: DMPlexSetCone(rdm, newp, coneNew);
1525: #if 1
1526: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1527: for (p = 0; p < 2; ++p) {
1528: 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);
1529: }
1530: #endif
1531: DMPlexGetSupportSize(dm, f, &supportSize);
1532: DMPlexGetSupport(dm, f, &support);
1533: for (s = 0; s < supportSize; ++s) {
1534: DMPlexGetConeSize(dm, support[s], &coneSize);
1535: DMPlexGetCone(dm, support[s], &cone);
1536: DMPlexGetConeOrientation(dm, support[s], &ornt);
1537: for (c = 0; c < coneSize; ++c) {
1538: if (cone[c] == f) break;
1539: }
1540: supportRef[s] = cStartNew + (support[s] - cStart)*4 + (ornt[c] < 0 ? (c+1-r)%4 : (c+r)%4);
1541: }
1542: DMPlexSetSupport(rdm, newp, supportRef);
1543: #if 1
1544: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1545: for (p = 0; p < supportSize; ++p) {
1546: 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);
1547: }
1548: #endif
1549: }
1550: }
1551: /* Interior faces have 2 vertices and 2 cells */
1552: for (c = cStart; c < cEnd; ++c) {
1553: const PetscInt *cone;
1554: PetscInt coneNew[2], supportNew[2];
1556: DMPlexGetCone(dm, c, &cone);
1557: for (r = 0; r < 4; ++r) {
1558: const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r;
1560: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart);
1561: coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart);
1562: DMPlexSetCone(rdm, newp, coneNew);
1563: #if 1
1564: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1565: for (p = 0; p < 2; ++p) {
1566: 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);
1567: }
1568: #endif
1569: supportNew[0] = (c - cStart)*4 + r;
1570: supportNew[1] = (c - cStart)*4 + (r+1)%4;
1571: DMPlexSetSupport(rdm, newp, supportNew);
1572: #if 1
1573: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1574: for (p = 0; p < 2; ++p) {
1575: 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);
1576: }
1577: #endif
1578: }
1579: }
1580: /* Old vertices have identical supports */
1581: for (v = vStart; v < vEnd; ++v) {
1582: const PetscInt newp = vStartNew + (v - vStart);
1583: const PetscInt *support, *cone;
1584: PetscInt size, s;
1586: DMPlexGetSupportSize(dm, v, &size);
1587: DMPlexGetSupport(dm, v, &support);
1588: for (s = 0; s < size; ++s) {
1589: PetscInt r = 0;
1591: DMPlexGetCone(dm, support[s], &cone);
1592: if (cone[1] == v) r = 1;
1593: supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
1594: }
1595: DMPlexSetSupport(rdm, newp, supportRef);
1596: #if 1
1597: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
1598: for (p = 0; p < size; ++p) {
1599: 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);
1600: }
1601: #endif
1602: }
1603: /* Face vertices have 2 + cells supports */
1604: for (f = fStart; f < fEnd; ++f) {
1605: const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
1606: const PetscInt *cone, *support;
1607: PetscInt size, s;
1609: DMPlexGetSupportSize(dm, f, &size);
1610: DMPlexGetSupport(dm, f, &support);
1611: supportRef[0] = fStartNew + (f - fStart)*2 + 0;
1612: supportRef[1] = fStartNew + (f - fStart)*2 + 1;
1613: for (s = 0; s < size; ++s) {
1614: PetscInt r = 0;
1616: DMPlexGetCone(dm, support[s], &cone);
1617: if (cone[1] == f) r = 1;
1618: else if (cone[2] == f) r = 2;
1619: else if (cone[3] == f) r = 3;
1620: supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r;
1621: }
1622: DMPlexSetSupport(rdm, newp, supportRef);
1623: #if 1
1624: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
1625: for (p = 0; p < 2+size; ++p) {
1626: 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);
1627: }
1628: #endif
1629: }
1630: /* Cell vertices have 4 supports */
1631: for (c = cStart; c < cEnd; ++c) {
1632: const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart);
1633: PetscInt supportNew[4];
1635: for (r = 0; r < 4; ++r) {
1636: supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r;
1637: }
1638: DMPlexSetSupport(rdm, newp, supportNew);
1639: }
1640: PetscFree(supportRef);
1641: break;
1642: case REFINER_HYBRID_SIMPLEX_2D:
1643: if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
1644: cMax = PetscMin(cEnd, cMax);
1645: if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
1646: fMax = PetscMin(fEnd, fMax);
1647: DMPlexGetHybridBounds(rdm, &cMaxNew, &fMaxNew, NULL, NULL);
1648: /* Interior cells have 3 faces */
1649: for (c = cStart; c < cMax; ++c) {
1650: const PetscInt newp = cStartNew + (c - cStart)*4;
1651: const PetscInt *cone, *ornt;
1652: PetscInt coneNew[3], orntNew[3];
1654: DMPlexGetCone(dm, c, &cone);
1655: DMPlexGetConeOrientation(dm, c, &ornt);
1656: /* A triangle */
1657: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
1658: orntNew[0] = ornt[0];
1659: coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2;
1660: orntNew[1] = -2;
1661: coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
1662: orntNew[2] = ornt[2];
1663: DMPlexSetCone(rdm, newp+0, coneNew);
1664: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
1665: #if 1
1666: 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);
1667: for (p = 0; p < 3; ++p) {
1668: 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);
1669: }
1670: #endif
1671: /* B triangle */
1672: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
1673: orntNew[0] = ornt[0];
1674: coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
1675: orntNew[1] = ornt[1];
1676: coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0;
1677: orntNew[2] = -2;
1678: DMPlexSetCone(rdm, newp+1, coneNew);
1679: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
1680: #if 1
1681: 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);
1682: for (p = 0; p < 3; ++p) {
1683: 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);
1684: }
1685: #endif
1686: /* C triangle */
1687: coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1;
1688: orntNew[0] = -2;
1689: coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
1690: orntNew[1] = ornt[1];
1691: coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
1692: orntNew[2] = ornt[2];
1693: DMPlexSetCone(rdm, newp+2, coneNew);
1694: DMPlexSetConeOrientation(rdm, newp+2, orntNew);
1695: #if 1
1696: 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);
1697: for (p = 0; p < 3; ++p) {
1698: 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);
1699: }
1700: #endif
1701: /* D triangle */
1702: coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 0;
1703: orntNew[0] = 0;
1704: coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 1;
1705: orntNew[1] = 0;
1706: coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + 2;
1707: orntNew[2] = 0;
1708: DMPlexSetCone(rdm, newp+3, coneNew);
1709: DMPlexSetConeOrientation(rdm, newp+3, orntNew);
1710: #if 1
1711: 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);
1712: for (p = 0; p < 3; ++p) {
1713: 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);
1714: }
1715: #endif
1716: }
1717: /*
1718: 2----3----3
1719: | |
1720: | B |
1721: | |
1722: 0----4--- 1
1723: | |
1724: | A |
1725: | |
1726: 0----2----1
1727: */
1728: /* Hybrid cells have 4 faces */
1729: for (c = cMax; c < cEnd; ++c) {
1730: const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2;
1731: const PetscInt *cone, *ornt;
1732: PetscInt coneNew[4], orntNew[4], r;
1734: DMPlexGetCone(dm, c, &cone);
1735: DMPlexGetConeOrientation(dm, c, &ornt);
1736: r = (ornt[0] < 0 ? 1 : 0);
1737: /* A quad */
1738: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + r;
1739: orntNew[0] = ornt[0];
1740: coneNew[1] = fStartNew + (cone[1] - fStart)*2 + r;
1741: orntNew[1] = ornt[1];
1742: coneNew[2+r] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[2+r] - fMax);
1743: orntNew[2+r] = 0;
1744: coneNew[3-r] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax);
1745: orntNew[3-r] = 0;
1746: DMPlexSetCone(rdm, newp+0, coneNew);
1747: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
1748: #if 1
1749: 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);
1750: for (p = 0; p < 4; ++p) {
1751: 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);
1752: }
1753: #endif
1754: /* B quad */
1755: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + 1-r;
1756: orntNew[0] = ornt[0];
1757: coneNew[1] = fStartNew + (cone[1] - fStart)*2 + 1-r;
1758: orntNew[1] = ornt[1];
1759: coneNew[2+r] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax);
1760: orntNew[2+r] = 0;
1761: coneNew[3-r] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (cone[3-r] - fMax);
1762: orntNew[3-r] = 0;
1763: DMPlexSetCone(rdm, newp+1, coneNew);
1764: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
1765: #if 1
1766: 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);
1767: for (p = 0; p < 4; ++p) {
1768: 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);
1769: }
1770: #endif
1771: }
1772: /* Interior split faces have 2 vertices and the same cells as the parent */
1773: DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
1774: PetscMalloc1(2 + maxSupportSize*2, &supportRef);
1775: for (f = fStart; f < fMax; ++f) {
1776: const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
1778: for (r = 0; r < 2; ++r) {
1779: const PetscInt newp = fStartNew + (f - fStart)*2 + r;
1780: const PetscInt *cone, *ornt, *support;
1781: PetscInt coneNew[2], coneSize, c, supportSize, s;
1783: DMPlexGetCone(dm, f, &cone);
1784: coneNew[0] = vStartNew + (cone[0] - vStart);
1785: coneNew[1] = vStartNew + (cone[1] - vStart);
1786: coneNew[(r+1)%2] = newv;
1787: DMPlexSetCone(rdm, newp, coneNew);
1788: #if 1
1789: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1790: for (p = 0; p < 2; ++p) {
1791: 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);
1792: }
1793: #endif
1794: DMPlexGetSupportSize(dm, f, &supportSize);
1795: DMPlexGetSupport(dm, f, &support);
1796: for (s = 0; s < supportSize; ++s) {
1797: DMPlexGetConeSize(dm, support[s], &coneSize);
1798: DMPlexGetCone(dm, support[s], &cone);
1799: DMPlexGetConeOrientation(dm, support[s], &ornt);
1800: for (c = 0; c < coneSize; ++c) if (cone[c] == f) break;
1801: if (support[s] >= cMax) {
1802: supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + (ornt[c] < 0 ? 1-r : r);
1803: } else {
1804: supportRef[s] = cStartNew + (support[s] - cStart)*4 + (ornt[c] < 0 ? (c+1-r)%3 : (c+r)%3);
1805: }
1806: }
1807: DMPlexSetSupport(rdm, newp, supportRef);
1808: #if 1
1809: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1810: for (p = 0; p < supportSize; ++p) {
1811: 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);
1812: }
1813: #endif
1814: }
1815: }
1816: /* Interior cell faces have 2 vertices and 2 cells */
1817: for (c = cStart; c < cMax; ++c) {
1818: const PetscInt *cone;
1820: DMPlexGetCone(dm, c, &cone);
1821: for (r = 0; r < 3; ++r) {
1822: const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r;
1823: PetscInt coneNew[2];
1824: PetscInt supportNew[2];
1826: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart);
1827: coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart);
1828: DMPlexSetCone(rdm, newp, coneNew);
1829: #if 1
1830: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1831: for (p = 0; p < 2; ++p) {
1832: 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);
1833: }
1834: #endif
1835: supportNew[0] = (c - cStart)*4 + (r+1)%3;
1836: supportNew[1] = (c - cStart)*4 + 3;
1837: DMPlexSetSupport(rdm, newp, supportNew);
1838: #if 1
1839: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1840: for (p = 0; p < 2; ++p) {
1841: 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);
1842: }
1843: #endif
1844: }
1845: }
1846: /* Interior hybrid faces have 2 vertices and the same cells */
1847: for (f = fMax; f < fEnd; ++f) {
1848: const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax);
1849: const PetscInt *cone, *ornt;
1850: const PetscInt *support;
1851: PetscInt coneNew[2];
1852: PetscInt supportNew[2];
1853: PetscInt size, s, r;
1855: DMPlexGetCone(dm, f, &cone);
1856: coneNew[0] = vStartNew + (cone[0] - vStart);
1857: coneNew[1] = vStartNew + (cone[1] - vStart);
1858: DMPlexSetCone(rdm, newp, coneNew);
1859: #if 1
1860: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1861: for (p = 0; p < 2; ++p) {
1862: 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);
1863: }
1864: #endif
1865: DMPlexGetSupportSize(dm, f, &size);
1866: DMPlexGetSupport(dm, f, &support);
1867: for (s = 0; s < size; ++s) {
1868: DMPlexGetCone(dm, support[s], &cone);
1869: DMPlexGetConeOrientation(dm, support[s], &ornt);
1870: for (r = 0; r < 2; ++r) {
1871: if (cone[r+2] == f) break;
1872: }
1873: supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + (ornt[0] < 0 ? 1-r : r);
1874: }
1875: DMPlexSetSupport(rdm, newp, supportNew);
1876: #if 1
1877: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1878: for (p = 0; p < size; ++p) {
1879: 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);
1880: }
1881: #endif
1882: }
1883: /* Cell hybrid faces have 2 vertices and 2 cells */
1884: for (c = cMax; c < cEnd; ++c) {
1885: const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax);
1886: const PetscInt *cone;
1887: PetscInt coneNew[2];
1888: PetscInt supportNew[2];
1890: DMPlexGetCone(dm, c, &cone);
1891: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart);
1892: coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart);
1893: DMPlexSetCone(rdm, newp, coneNew);
1894: #if 1
1895: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1896: for (p = 0; p < 2; ++p) {
1897: 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);
1898: }
1899: #endif
1900: supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0;
1901: supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1;
1902: DMPlexSetSupport(rdm, newp, supportNew);
1903: #if 1
1904: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
1905: for (p = 0; p < 2; ++p) {
1906: 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);
1907: }
1908: #endif
1909: }
1910: /* Old vertices have identical supports */
1911: for (v = vStart; v < vEnd; ++v) {
1912: const PetscInt newp = vStartNew + (v - vStart);
1913: const PetscInt *support, *cone;
1914: PetscInt size, s;
1916: DMPlexGetSupportSize(dm, v, &size);
1917: DMPlexGetSupport(dm, v, &support);
1918: for (s = 0; s < size; ++s) {
1919: if (support[s] >= fMax) {
1920: supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax);
1921: } else {
1922: PetscInt r = 0;
1924: DMPlexGetCone(dm, support[s], &cone);
1925: if (cone[1] == v) r = 1;
1926: supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
1927: }
1928: }
1929: DMPlexSetSupport(rdm, newp, supportRef);
1930: #if 1
1931: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
1932: for (p = 0; p < size; ++p) {
1933: 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);
1934: }
1935: #endif
1936: }
1937: /* Face vertices have 2 + (2 interior, 1 hybrid) supports */
1938: for (f = fStart; f < fMax; ++f) {
1939: const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
1940: const PetscInt *cone, *support;
1941: PetscInt size, newSize = 2, s;
1943: DMPlexGetSupportSize(dm, f, &size);
1944: DMPlexGetSupport(dm, f, &support);
1945: supportRef[0] = fStartNew + (f - fStart)*2 + 0;
1946: supportRef[1] = fStartNew + (f - fStart)*2 + 1;
1947: for (s = 0; s < size; ++s) {
1948: PetscInt r = 0;
1950: DMPlexGetCone(dm, support[s], &cone);
1951: if (support[s] >= cMax) {
1952: supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (support[s] - cMax);
1954: newSize += 1;
1955: } else {
1956: if (cone[1] == f) r = 1;
1957: else if (cone[2] == f) r = 2;
1958: supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3;
1959: supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r;
1961: newSize += 2;
1962: }
1963: }
1964: DMPlexSetSupport(rdm, newp, supportRef);
1965: #if 1
1966: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
1967: for (p = 0; p < newSize; ++p) {
1968: 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);
1969: }
1970: #endif
1971: }
1972: PetscFree(supportRef);
1973: break;
1974: case REFINER_HYBRID_HEX_2D:
1975: /* Hybrid Hex 2D */
1976: if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
1977: cMax = PetscMin(cEnd, cMax);
1978: if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
1979: fMax = PetscMin(fEnd, fMax);
1980: DMPlexGetHybridBounds(rdm, &cMaxNew, &fMaxNew, NULL, NULL);
1981: /* Interior cells have 4 faces */
1982: for (c = cStart; c < cMax; ++c) {
1983: const PetscInt newp = cStartNew + (c - cStart)*4;
1984: const PetscInt *cone, *ornt;
1985: PetscInt coneNew[4], orntNew[4];
1987: DMPlexGetCone(dm, c, &cone);
1988: DMPlexGetConeOrientation(dm, c, &ornt);
1989: /* A quad */
1990: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
1991: orntNew[0] = ornt[0];
1992: coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + 0;
1993: orntNew[1] = 0;
1994: coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + 3;
1995: orntNew[2] = -2;
1996: coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1);
1997: orntNew[3] = ornt[3];
1998: DMPlexSetCone(rdm, newp+0, coneNew);
1999: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
2000: #if 1
2001: 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);
2002: for (p = 0; p < 4; ++p) {
2003: 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);
2004: }
2005: #endif
2006: /* B quad */
2007: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
2008: orntNew[0] = ornt[0];
2009: coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
2010: orntNew[1] = ornt[1];
2011: coneNew[2] = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + 1;
2012: orntNew[2] = 0;
2013: coneNew[3] = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + 0;
2014: orntNew[3] = -2;
2015: DMPlexSetCone(rdm, newp+1, coneNew);
2016: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
2017: #if 1
2018: 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);
2019: for (p = 0; p < 4; ++p) {
2020: 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);
2021: }
2022: #endif
2023: /* C quad */
2024: coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + 1;
2025: orntNew[0] = -2;
2026: coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
2027: orntNew[1] = ornt[1];
2028: coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
2029: orntNew[2] = ornt[2];
2030: coneNew[3] = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + 2;
2031: orntNew[3] = 0;
2032: DMPlexSetCone(rdm, newp+2, coneNew);
2033: DMPlexSetConeOrientation(rdm, newp+2, orntNew);
2034: #if 1
2035: 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);
2036: for (p = 0; p < 4; ++p) {
2037: 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);
2038: }
2039: #endif
2040: /* D quad */
2041: coneNew[0] = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + 3;
2042: orntNew[0] = 0;
2043: coneNew[1] = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + 2;
2044: orntNew[1] = -2;
2045: coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
2046: orntNew[2] = ornt[2];
2047: coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0);
2048: orntNew[3] = ornt[3];
2049: DMPlexSetCone(rdm, newp+3, coneNew);
2050: DMPlexSetConeOrientation(rdm, newp+3, orntNew);
2051: #if 1
2052: 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);
2053: for (p = 0; p < 4; ++p) {
2054: 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);
2055: }
2056: #endif
2057: }
2058: /*
2059: 2----3----3
2060: | |
2061: | B |
2062: | |
2063: 0----4--- 1
2064: | |
2065: | A |
2066: | |
2067: 0----2----1
2068: */
2069: /* Hybrid cells have 4 faces */
2070: for (c = cMax; c < cEnd; ++c) {
2071: const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2;
2072: const PetscInt *cone, *ornt;
2073: PetscInt coneNew[4], orntNew[4];
2075: DMPlexGetCone(dm, c, &cone);
2076: DMPlexGetConeOrientation(dm, c, &ornt);
2077: /* A quad */
2078: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
2079: orntNew[0] = ornt[0];
2080: coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
2081: orntNew[1] = ornt[1];
2082: coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (cone[2] - fMax);
2083: orntNew[2] = 0;
2084: coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (fEnd - fMax) + (c - cMax);
2085: orntNew[3] = 0;
2086: DMPlexSetCone(rdm, newp+0, coneNew);
2087: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
2088: #if 1
2089: 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);
2090: for (p = 0; p < 4; ++p) {
2091: 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);
2092: }
2093: #endif
2094: /* B quad */
2095: coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
2096: orntNew[0] = ornt[0];
2097: coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
2098: orntNew[1] = ornt[1];
2099: coneNew[2] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (fEnd - fMax) + (c - cMax);
2100: orntNew[2] = 0;
2101: coneNew[3] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (cone[3] - fMax);
2102: orntNew[3] = 0;
2103: DMPlexSetCone(rdm, newp+1, coneNew);
2104: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
2105: #if 1
2106: 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);
2107: for (p = 0; p < 4; ++p) {
2108: 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);
2109: }
2110: #endif
2111: }
2112: /* Interior split faces have 2 vertices and the same cells as the parent */
2113: DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
2114: PetscMalloc1(2 + maxSupportSize*2, &supportRef);
2115: for (f = fStart; f < fMax; ++f) {
2116: const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
2118: for (r = 0; r < 2; ++r) {
2119: const PetscInt newp = fStartNew + (f - fStart)*2 + r;
2120: const PetscInt *cone, *ornt, *support;
2121: PetscInt coneNew[2], coneSize, c, supportSize, s;
2123: DMPlexGetCone(dm, f, &cone);
2124: coneNew[0] = vStartNew + (cone[0] - vStart);
2125: coneNew[1] = vStartNew + (cone[1] - vStart);
2126: coneNew[(r+1)%2] = newv;
2127: DMPlexSetCone(rdm, newp, coneNew);
2128: #if 1
2129: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2130: for (p = 0; p < 2; ++p) {
2131: 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);
2132: }
2133: #endif
2134: DMPlexGetSupportSize(dm, f, &supportSize);
2135: DMPlexGetSupport(dm, f, &support);
2136: for (s = 0; s < supportSize; ++s) {
2137: if (support[s] >= cMax) {
2138: supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r;
2139: } else {
2140: DMPlexGetConeSize(dm, support[s], &coneSize);
2141: DMPlexGetCone(dm, support[s], &cone);
2142: DMPlexGetConeOrientation(dm, support[s], &ornt);
2143: for (c = 0; c < coneSize; ++c) {
2144: if (cone[c] == f) break;
2145: }
2146: supportRef[s] = cStartNew + (support[s] - cStart)*4 + (ornt[c] < 0 ? (c+1-r)%4 : (c+r)%4);
2147: }
2148: }
2149: DMPlexSetSupport(rdm, newp, supportRef);
2150: #if 1
2151: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2152: for (p = 0; p < supportSize; ++p) {
2153: 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);
2154: }
2155: #endif
2156: }
2157: }
2158: /* Interior cell faces have 2 vertices and 2 cells */
2159: for (c = cStart; c < cMax; ++c) {
2160: const PetscInt *cone;
2162: DMPlexGetCone(dm, c, &cone);
2163: for (r = 0; r < 4; ++r) {
2164: const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + r;
2165: PetscInt coneNew[2], supportNew[2];
2167: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart);
2168: coneNew[1] = vStartNew + (vEnd - vStart) + (fMax - fStart) + (c - cStart);
2169: DMPlexSetCone(rdm, newp, coneNew);
2170: #if 1
2171: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2172: for (p = 0; p < 2; ++p) {
2173: 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);
2174: }
2175: #endif
2176: supportNew[0] = (c - cStart)*4 + r;
2177: supportNew[1] = (c - cStart)*4 + (r+1)%4;
2178: DMPlexSetSupport(rdm, newp, supportNew);
2179: #if 1
2180: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2181: for (p = 0; p < 2; ++p) {
2182: 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);
2183: }
2184: #endif
2185: }
2186: }
2187: /* Hybrid faces have 2 vertices and the same cells */
2188: for (f = fMax; f < fEnd; ++f) {
2189: const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (f - fMax);
2190: const PetscInt *cone, *support;
2191: PetscInt coneNew[2], supportNew[2];
2192: PetscInt size, s, r;
2194: DMPlexGetCone(dm, f, &cone);
2195: coneNew[0] = vStartNew + (cone[0] - vStart);
2196: coneNew[1] = vStartNew + (cone[1] - vStart);
2197: DMPlexSetCone(rdm, newp, coneNew);
2198: #if 1
2199: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2200: for (p = 0; p < 2; ++p) {
2201: 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);
2202: }
2203: #endif
2204: DMPlexGetSupportSize(dm, f, &size);
2205: DMPlexGetSupport(dm, f, &support);
2206: for (s = 0; s < size; ++s) {
2207: DMPlexGetCone(dm, support[s], &cone);
2208: for (r = 0; r < 2; ++r) {
2209: if (cone[r+2] == f) break;
2210: }
2211: supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r;
2212: }
2213: DMPlexSetSupport(rdm, newp, supportNew);
2214: #if 1
2215: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2216: for (p = 0; p < size; ++p) {
2217: 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);
2218: }
2219: #endif
2220: }
2221: /* Cell hybrid faces have 2 vertices and 2 cells */
2222: for (c = cMax; c < cEnd; ++c) {
2223: const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (fEnd - fMax) + (c - cMax);
2224: const PetscInt *cone;
2225: PetscInt coneNew[2], supportNew[2];
2227: DMPlexGetCone(dm, c, &cone);
2228: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart);
2229: coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart);
2230: DMPlexSetCone(rdm, newp, coneNew);
2231: #if 1
2232: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2233: for (p = 0; p < 2; ++p) {
2234: 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);
2235: }
2236: #endif
2237: supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0;
2238: supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1;
2239: DMPlexSetSupport(rdm, newp, supportNew);
2240: #if 1
2241: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2242: for (p = 0; p < 2; ++p) {
2243: 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);
2244: }
2245: #endif
2246: }
2247: /* Old vertices have identical supports */
2248: for (v = vStart; v < vEnd; ++v) {
2249: const PetscInt newp = vStartNew + (v - vStart);
2250: const PetscInt *support, *cone;
2251: PetscInt size, s;
2253: DMPlexGetSupportSize(dm, v, &size);
2254: DMPlexGetSupport(dm, v, &support);
2255: for (s = 0; s < size; ++s) {
2256: if (support[s] >= fMax) {
2257: supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (support[s] - fMax);
2258: } else {
2259: PetscInt r = 0;
2261: DMPlexGetCone(dm, support[s], &cone);
2262: if (cone[1] == v) r = 1;
2263: supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
2264: }
2265: }
2266: DMPlexSetSupport(rdm, newp, supportRef);
2267: #if 1
2268: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
2269: for (p = 0; p < size; ++p) {
2270: 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);
2271: }
2272: #endif
2273: }
2274: /* Face vertices have 2 + cells supports */
2275: for (f = fStart; f < fMax; ++f) {
2276: const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
2277: const PetscInt *cone, *support;
2278: PetscInt size, s;
2280: DMPlexGetSupportSize(dm, f, &size);
2281: DMPlexGetSupport(dm, f, &support);
2282: supportRef[0] = fStartNew + (f - fStart)*2 + 0;
2283: supportRef[1] = fStartNew + (f - fStart)*2 + 1;
2284: for (s = 0; s < size; ++s) {
2285: PetscInt r = 0;
2287: DMPlexGetCone(dm, support[s], &cone);
2288: if (support[s] >= cMax) {
2289: supportRef[2+s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (fEnd - fMax) + (support[s] - cMax);
2290: } else {
2291: if (cone[1] == f) r = 1;
2292: else if (cone[2] == f) r = 2;
2293: else if (cone[3] == f) r = 3;
2294: supportRef[2+s] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*4 + r;
2295: }
2296: }
2297: DMPlexSetSupport(rdm, newp, supportRef);
2298: #if 1
2299: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
2300: for (p = 0; p < 2+size; ++p) {
2301: 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);
2302: }
2303: #endif
2304: }
2305: /* Cell vertices have 4 supports */
2306: for (c = cStart; c < cMax; ++c) {
2307: const PetscInt newp = vStartNew + (vEnd - vStart) + (fMax - fStart) + (c - cStart);
2308: PetscInt supportNew[4];
2310: for (r = 0; r < 4; ++r) {
2311: supportNew[r] = fStartNew + (fMax - fStart)*2 + (c - cStart)*4 + r;
2312: }
2313: DMPlexSetSupport(rdm, newp, supportNew);
2314: }
2315: PetscFree(supportRef);
2316: break;
2317: case REFINER_SIMPLEX_3D:
2318: /* All cells have 4 faces: Tet face order is prescribed in DMPlexGetFaces_Internal() */
2319: DMPlexGetRawFaces_Internal(dm, 3, 4, cellInd, NULL, NULL, &faces);
2320: for (c = cStart; c < cEnd; ++c) {
2321: const PetscInt newp = cStartNew + (c - cStart)*8;
2322: const PetscInt *cone, *ornt;
2323: PetscInt coneNew[4], orntNew[4];
2325: DMPlexGetCone(dm, c, &cone);
2326: DMPlexGetConeOrientation(dm, c, &ornt);
2327: /* A tetrahedron: {0, a, c, d} */
2328: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 0); /* A */
2329: orntNew[0] = ornt[0];
2330: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 0); /* A */
2331: orntNew[1] = ornt[1];
2332: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 0); /* A */
2333: orntNew[2] = ornt[2];
2334: coneNew[3] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 0;
2335: orntNew[3] = 0;
2336: DMPlexSetCone(rdm, newp+0, coneNew);
2337: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
2338: #if 1
2339: 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);
2340: for (p = 0; p < 4; ++p) {
2341: 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);
2342: }
2343: #endif
2344: /* B tetrahedron: {a, 1, b, e} */
2345: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 1); /* B */
2346: orntNew[0] = ornt[0];
2347: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 2); /* C */
2348: orntNew[1] = ornt[1];
2349: coneNew[2] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 1;
2350: orntNew[2] = 0;
2351: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 1); /* B */
2352: orntNew[3] = ornt[3];
2353: DMPlexSetCone(rdm, newp+1, coneNew);
2354: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
2355: #if 1
2356: 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);
2357: for (p = 0; p < 4; ++p) {
2358: 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);
2359: }
2360: #endif
2361: /* C tetrahedron: {c, b, 2, f} */
2362: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 2); /* C */
2363: orntNew[0] = ornt[0];
2364: coneNew[1] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 2;
2365: orntNew[1] = 0;
2366: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 1); /* B */
2367: orntNew[2] = ornt[2];
2368: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 0); /* A */
2369: orntNew[3] = ornt[3];
2370: DMPlexSetCone(rdm, newp+2, coneNew);
2371: DMPlexSetConeOrientation(rdm, newp+2, orntNew);
2372: #if 1
2373: 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);
2374: for (p = 0; p < 4; ++p) {
2375: 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);
2376: }
2377: #endif
2378: /* D tetrahedron: {d, e, f, 3} */
2379: coneNew[0] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 3;
2380: orntNew[0] = 0;
2381: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 1); /* B */
2382: orntNew[1] = ornt[1];
2383: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 2); /* C */
2384: orntNew[2] = ornt[2];
2385: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 2); /* C */
2386: orntNew[3] = ornt[3];
2387: DMPlexSetCone(rdm, newp+3, coneNew);
2388: DMPlexSetConeOrientation(rdm, newp+3, orntNew);
2389: #if 1
2390: 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);
2391: for (p = 0; p < 4; ++p) {
2392: 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);
2393: }
2394: #endif
2395: /* A' tetrahedron: {c, d, a, f} */
2396: coneNew[0] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 0;
2397: orntNew[0] = -3;
2398: coneNew[1] = fStartNew + (cone[2] - fStart)*4 + 3;
2399: orntNew[1] = ornt[2] < 0 ? -(GetTetSomething_Static(ornt[2], 0)+1) : GetTetSomething_Static(ornt[2], 0);
2400: coneNew[2] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 5;
2401: orntNew[2] = 0;
2402: coneNew[3] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 4;
2403: orntNew[3] = 2;
2404: DMPlexSetCone(rdm, newp+4, coneNew);
2405: DMPlexSetConeOrientation(rdm, newp+4, orntNew);
2406: #if 1
2407: 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);
2408: for (p = 0; p < 4; ++p) {
2409: 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);
2410: }
2411: #endif
2412: /* B' tetrahedron: {e, b, a, f} */
2413: coneNew[0] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 1;
2414: orntNew[0] = -2;
2415: coneNew[1] = fStartNew + (cone[3] - fStart)*4 + 3;
2416: orntNew[1] = ornt[3] < 0 ? -(GetTetSomething_Static(ornt[3], 1)+1) : GetTetSomething_Static(ornt[3], 1);
2417: coneNew[2] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 6;
2418: orntNew[2] = 0;
2419: coneNew[3] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 7;
2420: orntNew[3] = 0;
2421: DMPlexSetCone(rdm, newp+5, coneNew);
2422: DMPlexSetConeOrientation(rdm, newp+5, orntNew);
2423: #if 1
2424: 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);
2425: for (p = 0; p < 4; ++p) {
2426: 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);
2427: }
2428: #endif
2429: /* C' tetrahedron: {f, a, c, b} */
2430: coneNew[0] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 5;
2431: orntNew[0] = -2;
2432: coneNew[1] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 7;
2433: orntNew[1] = -2;
2434: coneNew[2] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 2;
2435: orntNew[2] = -1;
2436: coneNew[3] = fStartNew + (cone[0] - fStart)*4 + 3;
2437: orntNew[3] = ornt[0] < 0 ? -(GetTetSomething_Static(ornt[0], 2)+1) : GetTetSomething_Static(ornt[0], 2);
2438: DMPlexSetCone(rdm, newp+6, coneNew);
2439: DMPlexSetConeOrientation(rdm, newp+6, orntNew);
2440: #if 1
2441: 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);
2442: for (p = 0; p < 4; ++p) {
2443: 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);
2444: }
2445: #endif
2446: /* D' tetrahedron: {f, a, e, d} */
2447: coneNew[0] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 6;
2448: orntNew[0] = -2;
2449: coneNew[1] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 4;
2450: orntNew[1] = -1;
2451: coneNew[2] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 3;
2452: orntNew[2] = -2;
2453: coneNew[3] = fStartNew + (cone[1] - fStart)*4 + 3;
2454: orntNew[3] = ornt[1] < 0 ? -(GetTetSomething_Static(ornt[1], 1)+1) : GetTetSomething_Static(ornt[1], 1);
2455: DMPlexSetCone(rdm, newp+7, coneNew);
2456: DMPlexSetConeOrientation(rdm, newp+7, orntNew);
2457: #if 1
2458: 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);
2459: for (p = 0; p < 4; ++p) {
2460: 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);
2461: }
2462: #endif
2463: }
2464: /* Split faces have 3 edges and the same cells as the parent */
2465: DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
2466: PetscMalloc1(2 + maxSupportSize*2, &supportRef);
2467: for (f = fStart; f < fEnd; ++f) {
2468: const PetscInt newp = fStartNew + (f - fStart)*4;
2469: const PetscInt *cone, *ornt, *support;
2470: PetscInt coneNew[3], orntNew[3], coneSize, supportSize, s;
2472: DMPlexGetCone(dm, f, &cone);
2473: DMPlexGetConeOrientation(dm, f, &ornt);
2474: /* A triangle */
2475: coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1 : 0);
2476: orntNew[0] = ornt[0];
2477: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 2;
2478: orntNew[1] = -2;
2479: coneNew[2] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 0 : 1);
2480: orntNew[2] = ornt[2];
2481: DMPlexSetCone(rdm, newp+0, coneNew);
2482: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
2483: #if 1
2484: 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);
2485: for (p = 0; p < 3; ++p) {
2486: 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);
2487: }
2488: #endif
2489: /* B triangle */
2490: coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 0 : 1);
2491: orntNew[0] = ornt[0];
2492: coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1 : 0);
2493: orntNew[1] = ornt[1];
2494: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 0;
2495: orntNew[2] = -2;
2496: DMPlexSetCone(rdm, newp+1, coneNew);
2497: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
2498: #if 1
2499: 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);
2500: for (p = 0; p < 3; ++p) {
2501: 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);
2502: }
2503: #endif
2504: /* C triangle */
2505: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 1;
2506: orntNew[0] = -2;
2507: coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 0 : 1);
2508: orntNew[1] = ornt[1];
2509: coneNew[2] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 1 : 0);
2510: orntNew[2] = ornt[2];
2511: DMPlexSetCone(rdm, newp+2, coneNew);
2512: DMPlexSetConeOrientation(rdm, newp+2, orntNew);
2513: #if 1
2514: 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);
2515: for (p = 0; p < 3; ++p) {
2516: 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);
2517: }
2518: #endif
2519: /* D triangle */
2520: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 0;
2521: orntNew[0] = 0;
2522: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 1;
2523: orntNew[1] = 0;
2524: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + 2;
2525: orntNew[2] = 0;
2526: DMPlexSetCone(rdm, newp+3, coneNew);
2527: DMPlexSetConeOrientation(rdm, newp+3, orntNew);
2528: #if 1
2529: 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);
2530: for (p = 0; p < 3; ++p) {
2531: 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);
2532: }
2533: #endif
2534: DMPlexGetSupportSize(dm, f, &supportSize);
2535: DMPlexGetSupport(dm, f, &support);
2536: for (r = 0; r < 4; ++r) {
2537: for (s = 0; s < supportSize; ++s) {
2538: PetscInt subf;
2539: DMPlexGetConeSize(dm, support[s], &coneSize);
2540: DMPlexGetCone(dm, support[s], &cone);
2541: DMPlexGetConeOrientation(dm, support[s], &ornt);
2542: for (c = 0; c < coneSize; ++c) {
2543: if (cone[c] == f) break;
2544: }
2545: subf = GetTriSubfaceInverse_Static(ornt[c], r);
2546: supportRef[s] = cStartNew + (support[s] - cStart)*8 + (r==3 ? (c+2)%4 + 4 : faces[c*3+subf]);
2547: }
2548: DMPlexSetSupport(rdm, newp+r, supportRef);
2549: #if 1
2550: 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);
2551: for (p = 0; p < supportSize; ++p) {
2552: 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);
2553: }
2554: #endif
2555: }
2556: }
2557: /* Interior faces have 3 edges and 2 cells */
2558: for (c = cStart; c < cEnd; ++c) {
2559: PetscInt newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8;
2560: const PetscInt *cone, *ornt;
2561: PetscInt coneNew[3], orntNew[3];
2562: PetscInt supportNew[2];
2564: DMPlexGetCone(dm, c, &cone);
2565: DMPlexGetConeOrientation(dm, c, &ornt);
2566: /* Face A: {c, a, d} */
2567: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTetSomething_Static(ornt[0], 2);
2568: orntNew[0] = ornt[0] < 0 ? -2 : 0;
2569: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTetSomething_Static(ornt[1], 2);
2570: orntNew[1] = ornt[1] < 0 ? -2 : 0;
2571: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTetSomething_Static(ornt[2], 2);
2572: orntNew[2] = ornt[2] < 0 ? -2 : 0;
2573: DMPlexSetCone(rdm, newp, coneNew);
2574: DMPlexSetConeOrientation(rdm, newp, orntNew);
2575: #if 1
2576: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2577: for (p = 0; p < 3; ++p) {
2578: 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);
2579: }
2580: #endif
2581: supportNew[0] = (c - cStart)*8 + 0;
2582: supportNew[1] = (c - cStart)*8 + 0+4;
2583: DMPlexSetSupport(rdm, newp, supportNew);
2584: #if 1
2585: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2586: for (p = 0; p < 2; ++p) {
2587: 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);
2588: }
2589: #endif
2590: ++newp;
2591: /* Face B: {a, b, e} */
2592: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTetSomething_Static(ornt[0], 0);
2593: orntNew[0] = ornt[0] < 0 ? -2 : 0;
2594: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTetSomething_Static(ornt[3], 0);
2595: orntNew[1] = ornt[3] < 0 ? -2 : 0;
2596: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTetSomething_Static(ornt[1], 1);
2597: orntNew[2] = ornt[1] < 0 ? -2 : 0;
2598: DMPlexSetCone(rdm, newp, coneNew);
2599: DMPlexSetConeOrientation(rdm, newp, orntNew);
2600: #if 1
2601: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2602: for (p = 0; p < 3; ++p) {
2603: 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);
2604: }
2605: #endif
2606: supportNew[0] = (c - cStart)*8 + 1;
2607: supportNew[1] = (c - cStart)*8 + 1+4;
2608: DMPlexSetSupport(rdm, newp, supportNew);
2609: #if 1
2610: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2611: for (p = 0; p < 2; ++p) {
2612: 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);
2613: }
2614: #endif
2615: ++newp;
2616: /* Face C: {c, f, b} */
2617: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTetSomething_Static(ornt[2], 0);
2618: orntNew[0] = ornt[2] < 0 ? -2 : 0;
2619: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTetSomething_Static(ornt[3], 2);
2620: orntNew[1] = ornt[3] < 0 ? -2 : 0;
2621: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTetSomething_Static(ornt[0], 1);
2622: orntNew[2] = ornt[0] < 0 ? -2 : 0;
2623: DMPlexSetCone(rdm, newp, coneNew);
2624: DMPlexSetConeOrientation(rdm, newp, orntNew);
2625: #if 1
2626: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2627: for (p = 0; p < 3; ++p) {
2628: 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);
2629: }
2630: #endif
2631: supportNew[0] = (c - cStart)*8 + 2;
2632: supportNew[1] = (c - cStart)*8 + 2+4;
2633: DMPlexSetSupport(rdm, newp, supportNew);
2634: #if 1
2635: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2636: for (p = 0; p < 2; ++p) {
2637: 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);
2638: }
2639: #endif
2640: ++newp;
2641: /* Face D: {d, e, f} */
2642: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTetSomething_Static(ornt[1], 0);
2643: orntNew[0] = ornt[1] < 0 ? -2 : 0;
2644: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTetSomething_Static(ornt[3], 1);
2645: orntNew[1] = ornt[3] < 0 ? -2 : 0;
2646: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTetSomething_Static(ornt[2], 1);
2647: orntNew[2] = ornt[2] < 0 ? -2 : 0;
2648: DMPlexSetCone(rdm, newp, coneNew);
2649: DMPlexSetConeOrientation(rdm, newp, orntNew);
2650: #if 1
2651: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2652: for (p = 0; p < 3; ++p) {
2653: 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);
2654: }
2655: #endif
2656: supportNew[0] = (c - cStart)*8 + 3;
2657: supportNew[1] = (c - cStart)*8 + 3+4;
2658: DMPlexSetSupport(rdm, newp, supportNew);
2659: #if 1
2660: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2661: for (p = 0; p < 2; ++p) {
2662: 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);
2663: }
2664: #endif
2665: ++newp;
2666: /* Face E: {d, f, a} */
2667: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTetSomething_Static(ornt[2], 1);
2668: orntNew[0] = ornt[2] < 0 ? 0 : -2;
2669: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
2670: orntNew[1] = -2;
2671: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTetSomething_Static(ornt[1], 2);
2672: orntNew[2] = ornt[1] < 0 ? -2 : 0;
2673: DMPlexSetCone(rdm, newp, coneNew);
2674: DMPlexSetConeOrientation(rdm, newp, orntNew);
2675: #if 1
2676: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2677: for (p = 0; p < 3; ++p) {
2678: 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);
2679: }
2680: #endif
2681: supportNew[0] = (c - cStart)*8 + 0+4;
2682: supportNew[1] = (c - cStart)*8 + 3+4;
2683: DMPlexSetSupport(rdm, newp, supportNew);
2684: #if 1
2685: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2686: for (p = 0; p < 2; ++p) {
2687: 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);
2688: }
2689: #endif
2690: ++newp;
2691: /* Face F: {c, a, f} */
2692: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTetSomething_Static(ornt[0], 2);
2693: orntNew[0] = ornt[0] < 0 ? -2 : 0;
2694: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
2695: orntNew[1] = 0;
2696: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + GetTetSomething_Static(ornt[2], 0);
2697: orntNew[2] = ornt[2] < 0 ? 0 : -2;
2698: DMPlexSetCone(rdm, newp, coneNew);
2699: DMPlexSetConeOrientation(rdm, newp, orntNew);
2700: #if 1
2701: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2702: for (p = 0; p < 3; ++p) {
2703: 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);
2704: }
2705: #endif
2706: supportNew[0] = (c - cStart)*8 + 0+4;
2707: supportNew[1] = (c - cStart)*8 + 2+4;
2708: DMPlexSetSupport(rdm, newp, supportNew);
2709: #if 1
2710: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2711: for (p = 0; p < 2; ++p) {
2712: 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);
2713: }
2714: #endif
2715: ++newp;
2716: /* Face G: {e, a, f} */
2717: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + GetTetSomething_Static(ornt[1], 1);
2718: orntNew[0] = ornt[1] < 0 ? -2 : 0;
2719: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
2720: orntNew[1] = 0;
2721: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTetSomething_Static(ornt[3], 1);
2722: orntNew[2] = ornt[3] < 0 ? 0 : -2;
2723: DMPlexSetCone(rdm, newp, coneNew);
2724: DMPlexSetConeOrientation(rdm, newp, orntNew);
2725: #if 1
2726: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2727: for (p = 0; p < 3; ++p) {
2728: 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);
2729: }
2730: #endif
2731: supportNew[0] = (c - cStart)*8 + 1+4;
2732: supportNew[1] = (c - cStart)*8 + 3+4;
2733: DMPlexSetSupport(rdm, newp, supportNew);
2734: #if 1
2735: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2736: for (p = 0; p < 2; ++p) {
2737: 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);
2738: }
2739: #endif
2740: ++newp;
2741: /* Face H: {a, b, f} */
2742: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + GetTetSomething_Static(ornt[0], 0);
2743: orntNew[0] = ornt[0] < 0 ? -2 : 0;
2744: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + GetTetSomething_Static(ornt[3], 2);
2745: orntNew[1] = ornt[3] < 0 ? 0 : -2;
2746: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
2747: orntNew[2] = -2;
2748: DMPlexSetCone(rdm, newp, coneNew);
2749: DMPlexSetConeOrientation(rdm, newp, orntNew);
2750: #if 1
2751: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2752: for (p = 0; p < 3; ++p) {
2753: 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);
2754: }
2755: #endif
2756: supportNew[0] = (c - cStart)*8 + 1+4;
2757: supportNew[1] = (c - cStart)*8 + 2+4;
2758: DMPlexSetSupport(rdm, newp, supportNew);
2759: #if 1
2760: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
2761: for (p = 0; p < 2; ++p) {
2762: 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);
2763: }
2764: #endif
2765: ++newp;
2766: }
2767: /* Split Edges have 2 vertices and the same faces as the parent */
2768: for (e = eStart; e < eEnd; ++e) {
2769: const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);
2771: for (r = 0; r < 2; ++r) {
2772: const PetscInt newp = eStartNew + (e - eStart)*2 + r;
2773: const PetscInt *cone, *ornt, *support;
2774: PetscInt coneNew[2], coneSize, c, supportSize, s;
2776: DMPlexGetCone(dm, e, &cone);
2777: coneNew[0] = vStartNew + (cone[0] - vStart);
2778: coneNew[1] = vStartNew + (cone[1] - vStart);
2779: coneNew[(r+1)%2] = newv;
2780: DMPlexSetCone(rdm, newp, coneNew);
2781: #if 1
2782: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
2783: for (p = 0; p < 2; ++p) {
2784: 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);
2785: }
2786: #endif
2787: DMPlexGetSupportSize(dm, e, &supportSize);
2788: DMPlexGetSupport(dm, e, &support);
2789: for (s = 0; s < supportSize; ++s) {
2790: DMPlexGetConeSize(dm, support[s], &coneSize);
2791: DMPlexGetCone(dm, support[s], &cone);
2792: DMPlexGetConeOrientation(dm, support[s], &ornt);
2793: for (c = 0; c < coneSize; ++c) {
2794: if (cone[c] == e) break;
2795: }
2796: supportRef[s] = fStartNew + (support[s] - fStart)*4 + (c + (ornt[c] < 0 ? 1-r : r))%3;
2797: }
2798: DMPlexSetSupport(rdm, newp, supportRef);
2799: #if 1
2800: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
2801: for (p = 0; p < supportSize; ++p) {
2802: 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);
2803: }
2804: #endif
2805: }
2806: }
2807: /* Face edges have 2 vertices and 2+cells*(1/2) faces */
2808: for (f = fStart; f < fEnd; ++f) {
2809: const PetscInt *cone, *ornt, *support;
2810: PetscInt coneSize, supportSize, s;
2812: DMPlexGetSupportSize(dm, f, &supportSize);
2813: DMPlexGetSupport(dm, f, &support);
2814: for (r = 0; r < 3; ++r) {
2815: const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + r;
2816: PetscInt coneNew[2], intFaces = 0, er, eint[4] = {1, 0, 2, 0};
2817: PetscInt fint[24] = { 1, 7, -1, -1, 0, 5,
2818: -1, -1, 1, 6, 0, 4,
2819: 2, 5, 3, 4, -1, -1,
2820: -1, -1, 3, 6, 2, 7};
2822: DMPlexGetCone(dm, f, &cone);
2823: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[(r+0)%3] - eStart);
2824: coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - eStart);
2825: DMPlexSetCone(rdm, newp, coneNew);
2826: #if 1
2827: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
2828: for (p = 0; p < 2; ++p) {
2829: 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);
2830: }
2831: #endif
2832: supportRef[0] = fStartNew + (f - fStart)*4 + (r+1)%3;
2833: supportRef[1] = fStartNew + (f - fStart)*4 + 3;
2834: for (s = 0; s < supportSize; ++s) {
2835: DMPlexGetConeSize(dm, support[s], &coneSize);
2836: DMPlexGetCone(dm, support[s], &cone);
2837: DMPlexGetConeOrientation(dm, support[s], &ornt);
2838: for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
2839: /* Here we want to determine whether edge newp contains a vertex which is part of the cross-tet edge */
2840: er = GetTetSomethingInverse_Static(ornt[c], r);
2841: if (er == eint[c]) {
2842: supportRef[2+intFaces++] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*8 + (c + 2)%4;
2843: } else {
2844: supportRef[2+intFaces++] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*8 + fint[(c*3 + er)*2 + 0];
2845: supportRef[2+intFaces++] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*8 + fint[(c*3 + er)*2 + 1];
2846: }
2847: }
2848: DMPlexSetSupport(rdm, newp, supportRef);
2849: #if 1
2850: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
2851: for (p = 0; p < intFaces; ++p) {
2852: 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);
2853: }
2854: #endif
2855: }
2856: }
2857: /* Interior edges have 2 vertices and 4 faces */
2858: for (c = cStart; c < cEnd; ++c) {
2859: const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
2860: const PetscInt *cone, *ornt, *fcone;
2861: PetscInt coneNew[2], supportNew[4], find;
2863: DMPlexGetCone(dm, c, &cone);
2864: DMPlexGetConeOrientation(dm, c, &ornt);
2865: DMPlexGetCone(dm, cone[0], &fcone);
2866: find = GetTriEdge_Static(ornt[0], 0);
2867: coneNew[0] = vStartNew + (vEnd - vStart) + (fcone[find] - eStart);
2868: DMPlexGetCone(dm, cone[2], &fcone);
2869: find = GetTriEdge_Static(ornt[2], 1);
2870: coneNew[1] = vStartNew + (vEnd - vStart) + (fcone[find] - eStart);
2871: DMPlexSetCone(rdm, newp, coneNew);
2872: #if 1
2873: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
2874: for (p = 0; p < 2; ++p) {
2875: 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);
2876: }
2877: #endif
2878: supportNew[0] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 4;
2879: supportNew[1] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 5;
2880: supportNew[2] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 6;
2881: supportNew[3] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 7;
2882: DMPlexSetSupport(rdm, newp, supportNew);
2883: #if 1
2884: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
2885: for (p = 0; p < 4; ++p) {
2886: 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);
2887: }
2888: #endif
2889: }
2890: /* Old vertices have identical supports */
2891: for (v = vStart; v < vEnd; ++v) {
2892: const PetscInt newp = vStartNew + (v - vStart);
2893: const PetscInt *support, *cone;
2894: PetscInt size, s;
2896: DMPlexGetSupportSize(dm, v, &size);
2897: DMPlexGetSupport(dm, v, &support);
2898: for (s = 0; s < size; ++s) {
2899: PetscInt r = 0;
2901: DMPlexGetCone(dm, support[s], &cone);
2902: if (cone[1] == v) r = 1;
2903: supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
2904: }
2905: DMPlexSetSupport(rdm, newp, supportRef);
2906: #if 1
2907: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
2908: for (p = 0; p < size; ++p) {
2909: 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);
2910: }
2911: #endif
2912: }
2913: /* Edge vertices have 2 + face*2 + 0/1 supports */
2914: for (e = eStart; e < eEnd; ++e) {
2915: const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
2916: const PetscInt *cone, *support;
2917: PetscInt *star = NULL, starSize, cellSize = 0, coneSize, size, s;
2919: DMPlexGetSupportSize(dm, e, &size);
2920: DMPlexGetSupport(dm, e, &support);
2921: supportRef[0] = eStartNew + (e - eStart)*2 + 0;
2922: supportRef[1] = eStartNew + (e - eStart)*2 + 1;
2923: for (s = 0; s < size; ++s) {
2924: PetscInt r = 0;
2926: DMPlexGetConeSize(dm, support[s], &coneSize);
2927: DMPlexGetCone(dm, support[s], &cone);
2928: for (r = 0; r < coneSize; ++r) {if (cone[r] == e) break;}
2929: supportRef[2+s*2+0] = eStartNew + (eEnd - eStart)*2 + (support[s] - fStart)*3 + (r+0)%3;
2930: supportRef[2+s*2+1] = eStartNew + (eEnd - eStart)*2 + (support[s] - fStart)*3 + (r+2)%3;
2931: }
2932: DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
2933: for (s = 0; s < starSize*2; s += 2) {
2934: const PetscInt *cone, *ornt;
2935: PetscInt e01, e23;
2937: if ((star[s] >= cStart) && (star[s] < cEnd)) {
2938: /* Check edge 0-1 */
2939: DMPlexGetCone(dm, star[s], &cone);
2940: DMPlexGetConeOrientation(dm, star[s], &ornt);
2941: DMPlexGetCone(dm, cone[0], &cone);
2942: e01 = cone[GetTriEdge_Static(ornt[0], 0)];
2943: /* Check edge 2-3 */
2944: DMPlexGetCone(dm, star[s], &cone);
2945: DMPlexGetConeOrientation(dm, star[s], &ornt);
2946: DMPlexGetCone(dm, cone[2], &cone);
2947: e23 = cone[GetTriEdge_Static(ornt[2], 1)];
2948: if ((e01 == e) || (e23 == e)) {supportRef[2+size*2+cellSize++] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (star[s] - cStart);}
2949: }
2950: }
2951: DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
2952: DMPlexSetSupport(rdm, newp, supportRef);
2953: #if 1
2954: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
2955: for (p = 0; p < 2+size*2+cellSize; ++p) {
2956: 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);
2957: }
2958: #endif
2959: }
2960: PetscFree(supportRef);
2961: DMPlexRestoreFaces_Internal(dm, 3, cStart, NULL, NULL, &faces);
2962: break;
2963: case REFINER_HYBRID_SIMPLEX_3D:
2964: DMPlexGetHybridBounds(rdm, &cMaxNew, &fMaxNew, &eMaxNew, NULL);
2965: /* Interior cells have 4 faces: Tet face order is prescribed in DMPlexGetFaces_Internal() */
2966: DMPlexGetRawFaces_Internal(dm, 3, 4, cellInd, NULL, NULL, &faces);
2967: for (c = cStart; c < cMax; ++c) {
2968: const PetscInt newp = cStartNew + (c - cStart)*8;
2969: const PetscInt *cone, *ornt;
2970: PetscInt coneNew[4], orntNew[4];
2972: DMPlexGetCone(dm, c, &cone);
2973: DMPlexGetConeOrientation(dm, c, &ornt);
2974: /* A tetrahedron: {0, a, c, d} */
2975: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 0); /* A */
2976: orntNew[0] = ornt[0];
2977: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 0); /* A */
2978: orntNew[1] = ornt[1];
2979: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 0); /* A */
2980: orntNew[2] = ornt[2];
2981: coneNew[3] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 0;
2982: orntNew[3] = 0;
2983: DMPlexSetCone(rdm, newp+0, coneNew);
2984: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
2985: #if 1
2986: 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);
2987: for (p = 0; p < 4; ++p) {
2988: 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);
2989: }
2990: #endif
2991: /* B tetrahedron: {a, 1, b, e} */
2992: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 1); /* B */
2993: orntNew[0] = ornt[0];
2994: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 2); /* C */
2995: orntNew[1] = ornt[1];
2996: coneNew[2] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 1;
2997: orntNew[2] = 0;
2998: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 1); /* B */
2999: orntNew[3] = ornt[3];
3000: DMPlexSetCone(rdm, newp+1, coneNew);
3001: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
3002: #if 1
3003: 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);
3004: for (p = 0; p < 4; ++p) {
3005: 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);
3006: }
3007: #endif
3008: /* C tetrahedron: {c, b, 2, f} */
3009: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], 2); /* C */
3010: orntNew[0] = ornt[0];
3011: coneNew[1] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 2;
3012: orntNew[1] = 0;
3013: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 1); /* B */
3014: orntNew[2] = ornt[2];
3015: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 0); /* A */
3016: orntNew[3] = ornt[3];
3017: DMPlexSetCone(rdm, newp+2, coneNew);
3018: DMPlexSetConeOrientation(rdm, newp+2, orntNew);
3019: #if 1
3020: 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);
3021: for (p = 0; p < 4; ++p) {
3022: 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);
3023: }
3024: #endif
3025: /* D tetrahedron: {d, e, f, 3} */
3026: coneNew[0] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 3;
3027: orntNew[0] = 0;
3028: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], 1); /* B */
3029: orntNew[1] = ornt[1];
3030: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetTriSubface_Static(ornt[2], 2); /* C */
3031: orntNew[2] = ornt[2];
3032: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetTriSubface_Static(ornt[3], 2); /* C */
3033: orntNew[3] = ornt[3];
3034: DMPlexSetCone(rdm, newp+3, coneNew);
3035: DMPlexSetConeOrientation(rdm, newp+3, orntNew);
3036: #if 1
3037: 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);
3038: for (p = 0; p < 4; ++p) {
3039: 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);
3040: }
3041: #endif
3042: /* A' tetrahedron: {d, a, c, f} */
3043: coneNew[0] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 0;
3044: orntNew[0] = -3;
3045: coneNew[1] = fStartNew + (cone[2] - fStart)*4 + 3;
3046: orntNew[1] = ornt[2] < 0 ? -(GetTetSomething_Static(ornt[2], 0)+1) : GetTetSomething_Static(ornt[2], 0);
3047: coneNew[2] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 5;
3048: orntNew[2] = 0;
3049: coneNew[3] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 4;
3050: orntNew[3] = 2;
3051: DMPlexSetCone(rdm, newp+4, coneNew);
3052: DMPlexSetConeOrientation(rdm, newp+4, orntNew);
3053: #if 1
3054: 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);
3055: for (p = 0; p < 4; ++p) {
3056: 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);
3057: }
3058: #endif
3059: /* B' tetrahedron: {e, b, a, f} */
3060: coneNew[0] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 1;
3061: orntNew[0] = -3;
3062: coneNew[1] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 6;
3063: orntNew[1] = 1;
3064: coneNew[2] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 7;
3065: orntNew[2] = 0;
3066: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + 3;
3067: orntNew[3] = ornt[3] < 0 ? -(GetTetSomething_Static(ornt[3], 0)+1) : GetTetSomething_Static(ornt[3], 0);
3068: DMPlexSetCone(rdm, newp+5, coneNew);
3069: DMPlexSetConeOrientation(rdm, newp+5, orntNew);
3070: #if 1
3071: 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);
3072: for (p = 0; p < 4; ++p) {
3073: 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);
3074: }
3075: #endif
3076: /* C' tetrahedron: {b, f, c, a} */
3077: coneNew[0] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 2;
3078: orntNew[0] = -3;
3079: coneNew[1] = fStartNew + (cone[0] - fStart)*4 + 3;
3080: orntNew[1] = ornt[0] < 0 ? -(GetTetSomething_Static(ornt[0], 2)+1) : GetTetSomething_Static(ornt[0], 2);
3081: coneNew[2] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 5;
3082: orntNew[2] = -3;
3083: coneNew[3] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 7;
3084: orntNew[3] = -2;
3085: DMPlexSetCone(rdm, newp+6, coneNew);
3086: DMPlexSetConeOrientation(rdm, newp+6, orntNew);
3087: #if 1
3088: 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);
3089: for (p = 0; p < 4; ++p) {
3090: 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);
3091: }
3092: #endif
3093: /* D' tetrahedron: {f, e, d, a} */
3094: coneNew[0] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 3;
3095: orntNew[0] = -3;
3096: coneNew[1] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 4;
3097: orntNew[1] = -3;
3098: coneNew[2] = fStartNew + (cone[1] - fStart)*4 + 3;
3099: orntNew[2] = ornt[1] < 0 ? -(GetTetSomething_Static(ornt[1], 0)+1) : GetTetSomething_Static(ornt[1], 0);
3100: coneNew[3] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 6;
3101: orntNew[3] = -3;
3102: DMPlexSetCone(rdm, newp+7, coneNew);
3103: DMPlexSetConeOrientation(rdm, newp+7, orntNew);
3104: #if 1
3105: 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);
3106: for (p = 0; p < 4; ++p) {
3107: 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);
3108: }
3109: #endif
3110: }
3111: /* Hybrid cells have 5 faces */
3112: for (c = cMax; c < cEnd; ++c) {
3113: const PetscInt newp = cStartNew + (cMax - cStart)*8 + (c - cMax)*4;
3114: const PetscInt *cone, *ornt, *fornt;
3115: PetscInt coneNew[5], orntNew[5], o, of, i;
3117: DMPlexGetCone(dm, c, &cone);
3118: DMPlexGetConeOrientation(dm, c, &ornt);
3119: DMPlexGetConeOrientation(dm, cone[0], &fornt);
3120: o = ornt[0] < 0 ? -1 : 1;
3121: for (r = 0; r < 3; ++r) {
3122: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetTriSubface_Static(ornt[0], r);
3123: orntNew[0] = ornt[0];
3124: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetTriSubface_Static(ornt[1], r);
3125: orntNew[1] = ornt[1];
3126: of = fornt[GetTriEdge_Static(ornt[0], r)] < 0 ? -1 : 1;
3127: i = GetTriEdgeInverse_Static(ornt[0], r) + 2;
3128: coneNew[i] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (cone[2+GetTriEdge_Static(ornt[0], r)] - fMax)*2 + (o*of < 0 ? 1 : 0);
3129: orntNew[i] = 0;
3130: i = GetTriEdgeInverse_Static(ornt[0], (r+1)%3) + 2;
3131: coneNew[i] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + GetTriSubface_Static(ornt[0], r);
3132: orntNew[i] = 0;
3133: of = fornt[GetTriEdge_Static(ornt[0], (r+2)%3)] < 0 ? -1 : 1;
3134: i = GetTriEdgeInverse_Static(ornt[0], (r+2)%3) + 2;
3135: 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);
3136: orntNew[i] = 0;
3137: DMPlexSetCone(rdm, newp+r, coneNew);
3138: DMPlexSetConeOrientation(rdm, newp+r, orntNew);
3139: #if 1
3140: 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);
3141: for (p = 0; p < 2; ++p) {
3142: 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);
3143: }
3144: for (p = 2; p < 5; ++p) {
3145: 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);
3146: }
3147: #endif
3148: }
3149: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + 3;
3150: orntNew[0] = 0;
3151: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + 3;
3152: orntNew[1] = 0;
3153: coneNew[2] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + 1;
3154: orntNew[2] = 0;
3155: coneNew[3] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + 2;
3156: orntNew[3] = 0;
3157: coneNew[4] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3 + 0;
3158: orntNew[4] = 0;
3159: DMPlexSetCone(rdm, newp+3, coneNew);
3160: DMPlexSetConeOrientation(rdm, newp+3, orntNew);
3161: #if 1
3162: 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);
3163: for (p = 0; p < 2; ++p) {
3164: 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);
3165: }
3166: for (p = 2; p < 5; ++p) {
3167: 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);
3168: }
3169: #endif
3170: }
3171: /* Split faces have 3 edges and the same cells as the parent */
3172: DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
3173: PetscMalloc1(2 + maxSupportSize*2, &supportRef);
3174: for (f = fStart; f < fMax; ++f) {
3175: const PetscInt newp = fStartNew + (f - fStart)*4;
3176: const PetscInt *cone, *ornt, *support;
3177: PetscInt coneNew[3], orntNew[3], coneSize, supportSize, s;
3179: DMPlexGetCone(dm, f, &cone);
3180: DMPlexGetConeOrientation(dm, f, &ornt);
3181: /* A triangle */
3182: coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1 : 0);
3183: orntNew[0] = ornt[0];
3184: coneNew[1] = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + 2;
3185: orntNew[1] = -2;
3186: coneNew[2] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 0 : 1);
3187: orntNew[2] = ornt[2];
3188: DMPlexSetCone(rdm, newp+0, coneNew);
3189: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
3190: #if 1
3191: 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);
3192: for (p = 0; p < 3; ++p) {
3193: 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);
3194: }
3195: #endif
3196: /* B triangle */
3197: coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 0 : 1);
3198: orntNew[0] = ornt[0];
3199: coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1 : 0);
3200: orntNew[1] = ornt[1];
3201: coneNew[2] = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + 0;
3202: orntNew[2] = -2;
3203: DMPlexSetCone(rdm, newp+1, coneNew);
3204: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
3205: #if 1
3206: 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);
3207: for (p = 0; p < 3; ++p) {
3208: 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);
3209: }
3210: #endif
3211: /* C triangle */
3212: coneNew[0] = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + 1;
3213: orntNew[0] = -2;
3214: coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 0 : 1);
3215: orntNew[1] = ornt[1];
3216: coneNew[2] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 1 : 0);
3217: orntNew[2] = ornt[2];
3218: DMPlexSetCone(rdm, newp+2, coneNew);
3219: DMPlexSetConeOrientation(rdm, newp+2, orntNew);
3220: #if 1
3221: 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);
3222: for (p = 0; p < 3; ++p) {
3223: 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);
3224: }
3225: #endif
3226: /* D triangle */
3227: coneNew[0] = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + 0;
3228: orntNew[0] = 0;
3229: coneNew[1] = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + 1;
3230: orntNew[1] = 0;
3231: coneNew[2] = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + 2;
3232: orntNew[2] = 0;
3233: DMPlexSetCone(rdm, newp+3, coneNew);
3234: DMPlexSetConeOrientation(rdm, newp+3, orntNew);
3235: #if 1
3236: 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);
3237: for (p = 0; p < 3; ++p) {
3238: 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);
3239: }
3240: #endif
3241: DMPlexGetSupportSize(dm, f, &supportSize);
3242: DMPlexGetSupport(dm, f, &support);
3243: for (r = 0; r < 4; ++r) {
3244: for (s = 0; s < supportSize; ++s) {
3245: PetscInt subf;
3246: DMPlexGetConeSize(dm, support[s], &coneSize);
3247: DMPlexGetCone(dm, support[s], &cone);
3248: DMPlexGetConeOrientation(dm, support[s], &ornt);
3249: for (c = 0; c < coneSize; ++c) {
3250: if (cone[c] == f) break;
3251: }
3252: subf = GetTriSubfaceInverse_Static(ornt[c], r);
3253: if (support[s] < cMax) {
3254: supportRef[s] = cStartNew + (support[s] - cStart)*8 + (r==3 ? (c+2)%4 + 4 : faces[c*3+subf]);
3255: } else {
3256: supportRef[s] = cStartNew + (cMax - cStart)*8 + (support[s] - cMax)*4 + (r==3 ? r : subf);
3257: }
3258: }
3259: DMPlexSetSupport(rdm, newp+r, supportRef);
3260: #if 1
3261: 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);
3262: for (p = 0; p < supportSize; ++p) {
3263: 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);
3264: }
3265: #endif
3266: }
3267: }
3268: /* Interior cell faces have 3 edges and 2 cells */
3269: for (c = cStart; c < cMax; ++c) {
3270: PetscInt newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*8;
3271: const PetscInt *cone, *ornt;
3272: PetscInt coneNew[3], orntNew[3];
3273: PetscInt supportNew[2];
3275: DMPlexGetCone(dm, c, &cone);
3276: DMPlexGetConeOrientation(dm, c, &ornt);
3277: /* Face A: {c, a, d} */
3278: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTetSomething_Static(ornt[0], 2);
3279: orntNew[0] = ornt[0] < 0 ? -2 : 0;
3280: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTetSomething_Static(ornt[1], 2);
3281: orntNew[1] = ornt[1] < 0 ? -2 : 0;
3282: coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTetSomething_Static(ornt[2], 2);
3283: orntNew[2] = ornt[2] < 0 ? -2 : 0;
3284: DMPlexSetCone(rdm, newp, coneNew);
3285: DMPlexSetConeOrientation(rdm, newp, orntNew);
3286: #if 1
3287: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3288: for (p = 0; p < 3; ++p) {
3289: 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);
3290: }
3291: #endif
3292: supportNew[0] = (c - cStart)*8 + 0;
3293: supportNew[1] = (c - cStart)*8 + 0+4;
3294: DMPlexSetSupport(rdm, newp, supportNew);
3295: #if 1
3296: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3297: for (p = 0; p < 2; ++p) {
3298: 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);
3299: }
3300: #endif
3301: ++newp;
3302: /* Face B: {a, b, e} */
3303: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTetSomething_Static(ornt[0], 0);
3304: orntNew[0] = ornt[0] < 0 ? -2 : 0;
3305: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTetSomething_Static(ornt[3], 0);
3306: orntNew[1] = ornt[3] < 0 ? -2 : 0;
3307: coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTetSomething_Static(ornt[1], 1);
3308: orntNew[2] = ornt[1] < 0 ? -2 : 0;
3309: DMPlexSetCone(rdm, newp, coneNew);
3310: DMPlexSetConeOrientation(rdm, newp, orntNew);
3311: #if 1
3312: 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);
3313: for (p = 0; p < 3; ++p) {
3314: 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);
3315: }
3316: #endif
3317: supportNew[0] = (c - cStart)*8 + 1;
3318: supportNew[1] = (c - cStart)*8 + 1+4;
3319: DMPlexSetSupport(rdm, newp, supportNew);
3320: #if 1
3321: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3322: for (p = 0; p < 2; ++p) {
3323: 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);
3324: }
3325: #endif
3326: ++newp;
3327: /* Face C: {c, f, b} */
3328: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTetSomething_Static(ornt[2], 0);
3329: orntNew[0] = ornt[2] < 0 ? -2 : 0;
3330: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTetSomething_Static(ornt[3], 2);
3331: orntNew[1] = ornt[3] < 0 ? -2 : 0;
3332: coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTetSomething_Static(ornt[0], 1);
3333: orntNew[2] = ornt[0] < 0 ? -2 : 0;
3334: DMPlexSetCone(rdm, newp, coneNew);
3335: DMPlexSetConeOrientation(rdm, newp, orntNew);
3336: #if 1
3337: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3338: for (p = 0; p < 3; ++p) {
3339: 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);
3340: }
3341: #endif
3342: supportNew[0] = (c - cStart)*8 + 2;
3343: supportNew[1] = (c - cStart)*8 + 2+4;
3344: DMPlexSetSupport(rdm, newp, supportNew);
3345: #if 1
3346: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3347: for (p = 0; p < 2; ++p) {
3348: 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);
3349: }
3350: #endif
3351: ++newp;
3352: /* Face D: {d, e, f} */
3353: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTetSomething_Static(ornt[1], 0);
3354: orntNew[0] = ornt[1] < 0 ? -2 : 0;
3355: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTetSomething_Static(ornt[3], 1);
3356: orntNew[1] = ornt[3] < 0 ? -2 : 0;
3357: coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTetSomething_Static(ornt[2], 1);
3358: orntNew[2] = ornt[2] < 0 ? -2 : 0;
3359: DMPlexSetCone(rdm, newp, coneNew);
3360: DMPlexSetConeOrientation(rdm, newp, orntNew);
3361: #if 1
3362: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3363: for (p = 0; p < 3; ++p) {
3364: 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);
3365: }
3366: #endif
3367: supportNew[0] = (c - cStart)*8 + 3;
3368: supportNew[1] = (c - cStart)*8 + 3+4;
3369: DMPlexSetSupport(rdm, newp, supportNew);
3370: #if 1
3371: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3372: for (p = 0; p < 2; ++p) {
3373: 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);
3374: }
3375: #endif
3376: ++newp;
3377: /* Face E: {d, f, a} */
3378: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTetSomething_Static(ornt[2], 1);
3379: orntNew[0] = ornt[2] < 0 ? 0 : -2;
3380: coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
3381: orntNew[1] = -2;
3382: coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTetSomething_Static(ornt[1], 2);
3383: orntNew[2] = ornt[1] < 0 ? -2 : 0;
3384: DMPlexSetCone(rdm, newp, coneNew);
3385: DMPlexSetConeOrientation(rdm, newp, orntNew);
3386: #if 1
3387: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3388: for (p = 0; p < 3; ++p) {
3389: 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);
3390: }
3391: #endif
3392: supportNew[0] = (c - cStart)*8 + 0+4;
3393: supportNew[1] = (c - cStart)*8 + 3+4;
3394: DMPlexSetSupport(rdm, newp, supportNew);
3395: #if 1
3396: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3397: for (p = 0; p < 2; ++p) {
3398: 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);
3399: }
3400: #endif
3401: ++newp;
3402: /* Face F: {c, a, f} */
3403: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTetSomething_Static(ornt[0], 2);
3404: orntNew[0] = ornt[0] < 0 ? -2 : 0;
3405: coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
3406: orntNew[1] = 0;
3407: coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*3 + GetTetSomething_Static(ornt[2], 0);
3408: orntNew[2] = ornt[2] < 0 ? 0 : -2;
3409: DMPlexSetCone(rdm, newp, coneNew);
3410: DMPlexSetConeOrientation(rdm, newp, orntNew);
3411: #if 1
3412: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3413: for (p = 0; p < 3; ++p) {
3414: 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);
3415: }
3416: #endif
3417: supportNew[0] = (c - cStart)*8 + 0+4;
3418: supportNew[1] = (c - cStart)*8 + 2+4;
3419: DMPlexSetSupport(rdm, newp, supportNew);
3420: #if 1
3421: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3422: for (p = 0; p < 2; ++p) {
3423: 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);
3424: }
3425: #endif
3426: ++newp;
3427: /* Face G: {e, a, f} */
3428: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + GetTetSomething_Static(ornt[1], 1);
3429: orntNew[0] = ornt[1] < 0 ? -2 : 0;
3430: coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
3431: orntNew[1] = 0;
3432: coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTetSomething_Static(ornt[3], 1);
3433: orntNew[2] = ornt[3] < 0 ? 0 : -2;
3434: DMPlexSetCone(rdm, newp, coneNew);
3435: DMPlexSetConeOrientation(rdm, newp, orntNew);
3436: #if 1
3437: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3438: for (p = 0; p < 3; ++p) {
3439: 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);
3440: }
3441: #endif
3442: supportNew[0] = (c - cStart)*8 + 1+4;
3443: supportNew[1] = (c - cStart)*8 + 3+4;
3444: DMPlexSetSupport(rdm, newp, supportNew);
3445: #if 1
3446: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3447: for (p = 0; p < 2; ++p) {
3448: 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);
3449: }
3450: #endif
3451: ++newp;
3452: /* Face H: {a, b, f} */
3453: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + GetTetSomething_Static(ornt[0], 0);
3454: orntNew[0] = ornt[0] < 0 ? -2 : 0;
3455: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*3 + GetTetSomething_Static(ornt[3], 2);
3456: orntNew[1] = ornt[3] < 0 ? 0 : -2;
3457: coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
3458: orntNew[2] = -2;
3459: DMPlexSetCone(rdm, newp, coneNew);
3460: DMPlexSetConeOrientation(rdm, newp, orntNew);
3461: #if 1
3462: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3463: for (p = 0; p < 3; ++p) {
3464: 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);
3465: }
3466: #endif
3467: supportNew[0] = (c - cStart)*8 + 1+4;
3468: supportNew[1] = (c - cStart)*8 + 2+4;
3469: DMPlexSetSupport(rdm, newp, supportNew);
3470: #if 1
3471: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
3472: for (p = 0; p < 2; ++p) {
3473: 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);
3474: }
3475: #endif
3476: ++newp;
3477: }
3478: /* Hybrid split faces have 4 edges and same cells */
3479: for (f = fMax; f < fEnd; ++f) {
3480: const PetscInt *cone, *ornt, *support;
3481: PetscInt coneNew[4], orntNew[4];
3482: PetscInt supportNew[2], size, s, c;
3484: DMPlexGetCone(dm, f, &cone);
3485: DMPlexGetConeOrientation(dm, f, &ornt);
3486: DMPlexGetSupportSize(dm, f, &size);
3487: DMPlexGetSupport(dm, f, &support);
3488: for (r = 0; r < 2; ++r) {
3489: const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (f - fMax)*2 + r;
3491: coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1-r : r);
3492: orntNew[0] = ornt[0];
3493: coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1-r : r);
3494: orntNew[1] = ornt[1];
3495: coneNew[2+r] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (cone[2+r] - eMax);
3496: orntNew[2+r] = 0;
3497: coneNew[3-r] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (f - fMax);
3498: orntNew[3-r] = 0;
3499: DMPlexSetCone(rdm, newp, coneNew);
3500: DMPlexSetConeOrientation(rdm, newp, orntNew);
3501: #if 1
3502: if ((newp < fMaxNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", newp, fMaxNew, fEndNew);
3503: for (p = 0; p < 2; ++p) {
3504: 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);
3505: }
3506: for (p = 2; p < 4; ++p) {
3507: 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);
3508: }
3509: #endif
3510: for (s = 0; s < size; ++s) {
3511: const PetscInt *coneCell, *orntCell, *fornt;
3512: PetscInt o, of;
3514: DMPlexGetCone(dm, support[s], &coneCell);
3515: DMPlexGetConeOrientation(dm, support[s], &orntCell);
3516: o = orntCell[0] < 0 ? -1 : 1;
3517: for (c = 2; c < 5; ++c) if (coneCell[c] == f) break;
3518: if (c >= 5) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find face %d in cone of cell %d", f, support[s]);
3519: DMPlexGetConeOrientation(dm, coneCell[0], &fornt);
3520: of = fornt[c-2] < 0 ? -1 : 1;
3521: supportNew[s] = cStartNew + (cMax - cStart)*8 + (support[s] - cMax)*4 + (GetTriEdgeInverse_Static(orntCell[0], c-2) + (o*of < 0 ? 1-r : r))%3;
3522: }
3523: DMPlexSetSupport(rdm, newp, supportNew);
3524: #if 1
3525: if ((newp < fMaxNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", newp, fMaxNew, fEndNew);
3526: for (p = 0; p < size; ++p) {
3527: 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);
3528: }
3529: #endif
3530: }
3531: }
3532: /* Hybrid cell faces have 4 edges and 2 cells */
3533: for (c = cMax; c < cEnd; ++c) {
3534: PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (c - cMax)*3;
3535: const PetscInt *cone, *ornt;
3536: PetscInt coneNew[4], orntNew[4];
3537: PetscInt supportNew[2];
3539: DMPlexGetCone(dm, c, &cone);
3540: DMPlexGetConeOrientation(dm, c, &ornt);
3541: for (r = 0; r < 3; ++r) {
3542: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*3 + (r+2)%3;
3543: orntNew[0] = 0;
3544: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*3 + (r+2)%3;
3545: orntNew[1] = 0;
3546: coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (cone[2+(r+2)%3] - fMax);
3547: orntNew[2] = 0;
3548: coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (cone[2+r] - fMax);
3549: orntNew[3] = 0;
3550: DMPlexSetCone(rdm, newp+r, coneNew);
3551: DMPlexSetConeOrientation(rdm, newp+r, orntNew);
3552: #if 1
3553: 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);
3554: for (p = 0; p < 2; ++p) {
3555: 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);
3556: }
3557: for (p = 2; p < 4; ++p) {
3558: 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);
3559: }
3560: #endif
3561: supportNew[0] = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + GetTriSubface_Static(ornt[0], r);
3562: supportNew[1] = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + 3;
3563: DMPlexSetSupport(rdm, newp+r, supportNew);
3564: #if 1
3565: 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);
3566: for (p = 0; p < 2; ++p) {
3567: 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);
3568: }
3569: #endif
3570: }
3571: }
3572: /* Interior split edges have 2 vertices and the same faces as the parent */
3573: for (e = eStart; e < eMax; ++e) {
3574: const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);
3576: for (r = 0; r < 2; ++r) {
3577: const PetscInt newp = eStartNew + (e - eStart)*2 + r;
3578: const PetscInt *cone, *ornt, *support;
3579: PetscInt coneNew[2], coneSize, c, supportSize, s;
3581: DMPlexGetCone(dm, e, &cone);
3582: coneNew[0] = vStartNew + (cone[0] - vStart);
3583: coneNew[1] = vStartNew + (cone[1] - vStart);
3584: coneNew[(r+1)%2] = newv;
3585: DMPlexSetCone(rdm, newp, coneNew);
3586: #if 1
3587: if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
3588: for (p = 0; p < 2; ++p) {
3589: 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);
3590: }
3591: #endif
3592: DMPlexGetSupportSize(dm, e, &supportSize);
3593: DMPlexGetSupport(dm, e, &support);
3594: for (s = 0; s < supportSize; ++s) {
3595: DMPlexGetConeSize(dm, support[s], &coneSize);
3596: DMPlexGetCone(dm, support[s], &cone);
3597: DMPlexGetConeOrientation(dm, support[s], &ornt);
3598: for (c = 0; c < coneSize; ++c) if (cone[c] == e) break;
3599: if (support[s] < fMax) {
3600: supportRef[s] = fStartNew + (support[s] - fStart)*4 + (c + (ornt[c] < 0 ? 1-r : r))%3;
3601: } else {
3602: supportRef[s] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (support[s] - fMax)*2 + (ornt[c] < 0 ? 1-r : r);
3603: }
3604: }
3605: DMPlexSetSupport(rdm, newp, supportRef);
3606: #if 1
3607: if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
3608: for (p = 0; p < supportSize; ++p) {
3609: 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);
3610: }
3611: #endif
3612: }
3613: }
3614: /* Interior face edges have 2 vertices and 2+cells*(1/2) faces */
3615: for (f = fStart; f < fMax; ++f) {
3616: const PetscInt *cone, *ornt, *support;
3617: PetscInt coneSize, supportSize, s;
3619: DMPlexGetSupportSize(dm, f, &supportSize);
3620: DMPlexGetSupport(dm, f, &support);
3621: for (r = 0; r < 3; ++r) {
3622: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (f - fStart)*3 + r;
3623: PetscInt coneNew[2], intFaces = 0, er, eint[4] = {1, 0, 2, 0};
3624: PetscInt fint[24] = { 1, 7, -1, -1, 0, 5,
3625: -1, -1, 1, 6, 0, 4,
3626: 2, 5, 3, 4, -1, -1,
3627: -1, -1, 3, 6, 2, 7};
3629: DMPlexGetCone(dm, f, &cone);
3630: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[(r+0)%3] - eStart);
3631: coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - eStart);
3632: DMPlexSetCone(rdm, newp, coneNew);
3633: #if 1
3634: if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
3635: for (p = 0; p < 2; ++p) {
3636: 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);
3637: }
3638: #endif
3639: supportRef[0] = fStartNew + (f - fStart)*4 + (r+1)%3;
3640: supportRef[1] = fStartNew + (f - fStart)*4 + 3;
3641: for (s = 0; s < supportSize; ++s) {
3642: DMPlexGetConeSize(dm, support[s], &coneSize);
3643: DMPlexGetCone(dm, support[s], &cone);
3644: DMPlexGetConeOrientation(dm, support[s], &ornt);
3645: for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
3646: if (support[s] < cMax) {
3647: /* Here we want to determine whether edge newp contains a vertex which is part of the cross-tet edge */
3648: er = GetTetSomethingInverse_Static(ornt[c], r);
3649: if (er == eint[c]) {
3650: supportRef[2+intFaces++] = fStartNew + (fMax - fStart)*4 + (support[s] - cStart)*8 + (c + 2)%4;
3651: } else {
3652: supportRef[2+intFaces++] = fStartNew + (fMax - fStart)*4 + (support[s] - cStart)*8 + fint[(c*3 + er)*2 + 0];
3653: supportRef[2+intFaces++] = fStartNew + (fMax - fStart)*4 + (support[s] - cStart)*8 + fint[(c*3 + er)*2 + 1];
3654: }
3655: } else {
3656: supportRef[2+intFaces++] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (support[s] - cMax)*3 + (r + 1)%3;
3657: }
3658: }
3659: DMPlexSetSupport(rdm, newp, supportRef);
3660: #if 1
3661: if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
3662: for (p = 0; p < intFaces; ++p) {
3663: 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);
3664: }
3665: #endif
3666: }
3667: }
3668: /* Interior cell edges have 2 vertices and 4 faces */
3669: for (c = cStart; c < cMax; ++c) {
3670: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (c - cStart);
3671: const PetscInt *cone, *ornt, *fcone;
3672: PetscInt coneNew[2], supportNew[4], find;
3674: DMPlexGetCone(dm, c, &cone);
3675: DMPlexGetConeOrientation(dm, c, &ornt);
3676: DMPlexGetCone(dm, cone[0], &fcone);
3677: find = GetTriEdge_Static(ornt[0], 0);
3678: coneNew[0] = vStartNew + (vEnd - vStart) + (fcone[find] - eStart);
3679: DMPlexGetCone(dm, cone[2], &fcone);
3680: find = GetTriEdge_Static(ornt[2], 1);
3681: coneNew[1] = vStartNew + (vEnd - vStart) + (fcone[find] - eStart);
3682: DMPlexSetCone(rdm, newp, coneNew);
3683: #if 1
3684: if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
3685: for (p = 0; p < 2; ++p) {
3686: 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);
3687: }
3688: #endif
3689: supportNew[0] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 4;
3690: supportNew[1] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 5;
3691: supportNew[2] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 6;
3692: supportNew[3] = fStartNew + (fMax - fStart)*4 + (c - cStart)*8 + 7;
3693: DMPlexSetSupport(rdm, newp, supportNew);
3694: #if 1
3695: if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
3696: for (p = 0; p < 4; ++p) {
3697: 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);
3698: }
3699: #endif
3700: }
3701: /* Hybrid edges have two vertices and the same faces */
3702: for (e = eMax; e < eEnd; ++e) {
3703: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (e - eMax);
3704: const PetscInt *cone, *support, *fcone;
3705: PetscInt coneNew[2], size, fsize, s;
3707: DMPlexGetCone(dm, e, &cone);
3708: DMPlexGetSupportSize(dm, e, &size);
3709: DMPlexGetSupport(dm, e, &support);
3710: coneNew[0] = vStartNew + (cone[0] - vStart);
3711: coneNew[1] = vStartNew + (cone[1] - vStart);
3712: DMPlexSetCone(rdm, newp, coneNew);
3713: #if 1
3714: if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
3715: for (p = 0; p < 2; ++p) {
3716: 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);
3717: }
3718: #endif
3719: for (s = 0; s < size; ++s) {
3720: DMPlexGetConeSize(dm, support[s], &fsize);
3721: DMPlexGetCone(dm, support[s], &fcone);
3722: for (c = 0; c < fsize; ++c) if (fcone[c] == e) break;
3723: if ((c < 2) || (c > 3)) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge %d not found in cone of face %d", e, support[s]);
3724: supportRef[s] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (support[s] - fMax)*2 + c-2;
3725: }
3726: DMPlexSetSupport(rdm, newp, supportRef);
3727: #if 1
3728: if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
3729: for (p = 0; p < size; ++p) {
3730: 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);
3731: }
3732: #endif
3733: }
3734: /* Hybrid face edges have 2 vertices and 2+2*cells faces */
3735: for (f = fMax; f < fEnd; ++f) {
3736: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (f - fMax);
3737: const PetscInt *cone, *support, *ccone, *cornt;
3738: PetscInt coneNew[2], size, csize, s;
3740: DMPlexGetCone(dm, f, &cone);
3741: DMPlexGetSupportSize(dm, f, &size);
3742: DMPlexGetSupport(dm, f, &support);
3743: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - eStart);
3744: coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - eStart);
3745: DMPlexSetCone(rdm, newp, coneNew);
3746: #if 1
3747: if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
3748: for (p = 0; p < 2; ++p) {
3749: 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);
3750: }
3751: #endif
3752: supportRef[0] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (f - fMax)*2 + 0;
3753: supportRef[1] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (f - fMax)*2 + 1;
3754: for (s = 0; s < size; ++s) {
3755: DMPlexGetConeSize(dm, support[s], &csize);
3756: DMPlexGetCone(dm, support[s], &ccone);
3757: DMPlexGetConeOrientation(dm, support[s], &cornt);
3758: for (c = 0; c < csize; ++c) if (ccone[c] == f) break;
3759: 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]);
3760: supportRef[2+s*2+0] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (support[s] - cMax)*3 + c-2;
3761: supportRef[2+s*2+1] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (support[s] - cMax)*3 + (c-1)%3;
3762: }
3763: DMPlexSetSupport(rdm, newp, supportRef);
3764: #if 1
3765: if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
3766: for (p = 0; p < 2+size*2; ++p) {
3767: 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);
3768: }
3769: #endif
3770: }
3771: /* Interior vertices have identical supports */
3772: for (v = vStart; v < vEnd; ++v) {
3773: const PetscInt newp = vStartNew + (v - vStart);
3774: const PetscInt *support, *cone;
3775: PetscInt size, s;
3777: DMPlexGetSupportSize(dm, v, &size);
3778: DMPlexGetSupport(dm, v, &support);
3779: for (s = 0; s < size; ++s) {
3780: PetscInt r = 0;
3782: DMPlexGetCone(dm, support[s], &cone);
3783: if (cone[1] == v) r = 1;
3784: if (support[s] < eMax) supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
3785: else supportRef[s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (support[s] - eMax);
3786: }
3787: DMPlexSetSupport(rdm, newp, supportRef);
3788: #if 1
3789: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
3790: for (p = 0; p < size; ++p) {
3791: 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);
3792: }
3793: #endif
3794: }
3795: /* Interior edge vertices have 2 + interior face*2 + hybrid face + cells*0/1 supports */
3796: for (e = eStart; e < eMax; ++e) {
3797: const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
3798: const PetscInt *cone, *support;
3799: PetscInt *star = NULL, starSize, faceSize = 0, cellSize = 0, coneSize, size, s;
3801: DMPlexGetSupportSize(dm, e, &size);
3802: DMPlexGetSupport(dm, e, &support);
3803: supportRef[0] = eStartNew + (e - eStart)*2 + 0;
3804: supportRef[1] = eStartNew + (e - eStart)*2 + 1;
3805: for (s = 0; s < size; ++s) {
3806: PetscInt r = 0;
3808: if (support[s] < fMax) {
3809: DMPlexGetConeSize(dm, support[s], &coneSize);
3810: DMPlexGetCone(dm, support[s], &cone);
3811: for (r = 0; r < coneSize; ++r) {if (cone[r] == e) break;}
3812: supportRef[2+faceSize+0] = eStartNew + (eMax - eStart)*2 + (support[s] - fStart)*3 + (r+0)%3;
3813: supportRef[2+faceSize+1] = eStartNew + (eMax - eStart)*2 + (support[s] - fStart)*3 + (r+2)%3;
3814: faceSize += 2;
3815: } else {
3816: supportRef[2+faceSize+0] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (support[s] - fMax);
3817: ++faceSize;
3818: }
3819: }
3820: DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
3821: for (s = 0; s < starSize*2; s += 2) {
3822: const PetscInt *cone, *ornt;
3823: PetscInt e01, e23;
3825: if ((star[s] >= cStart) && (star[s] < cMax)) {
3826: /* Check edge 0-1 */
3827: DMPlexGetCone(dm, star[s], &cone);
3828: DMPlexGetConeOrientation(dm, star[s], &ornt);
3829: DMPlexGetCone(dm, cone[0], &cone);
3830: e01 = cone[GetTriEdge_Static(ornt[0], 0)];
3831: /* Check edge 2-3 */
3832: DMPlexGetCone(dm, star[s], &cone);
3833: DMPlexGetConeOrientation(dm, star[s], &ornt);
3834: DMPlexGetCone(dm, cone[2], &cone);
3835: e23 = cone[GetTriEdge_Static(ornt[2], 1)];
3836: if ((e01 == e) || (e23 == e)) {supportRef[2+faceSize+cellSize++] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (star[s] - cStart);}
3837: }
3838: }
3839: DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);
3840: DMPlexSetSupport(rdm, newp, supportRef);
3841: #if 1
3842: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
3843: for (p = 0; p < 2+faceSize+cellSize; ++p) {
3844: 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);
3845: }
3846: #endif
3847: }
3848: PetscFree(supportRef);
3849: DMPlexRestoreFaces_Internal(dm, 3, cStart, NULL, NULL, &faces);
3850: break;
3851: case REFINER_HEX_3D:
3852: /*
3853: Bottom (viewed from top) Top
3854: 1---------2---------2 7---------2---------6
3855: | | | | | |
3856: | B 2 C | | H 2 G |
3857: | | | | | |
3858: 3----3----0----1----1 3----3----0----1----1
3859: | | | | | |
3860: | A 0 D | | E 0 F |
3861: | | | | | |
3862: 0---------0---------3 4---------0---------5
3863: */
3864: /* All cells have 6 faces: Bottom, Top, Front, Back, Right, Left */
3865: for (c = cStart; c < cEnd; ++c) {
3866: const PetscInt newp = (c - cStart)*8;
3867: const PetscInt *cone, *ornt;
3868: PetscInt coneNew[6], orntNew[6];
3870: DMPlexGetCone(dm, c, &cone);
3871: DMPlexGetConeOrientation(dm, c, &ornt);
3872: /* A hex */
3873: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 0);
3874: orntNew[0] = ornt[0];
3875: coneNew[1] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 8; /* AE */
3876: orntNew[1] = 0;
3877: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 0);
3878: orntNew[2] = ornt[2];
3879: coneNew[3] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 3; /* AB */
3880: orntNew[3] = 0;
3881: coneNew[4] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 0; /* AD */
3882: orntNew[4] = 0;
3883: coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 0);
3884: orntNew[5] = ornt[5];
3885: DMPlexSetCone(rdm, newp+0, coneNew);
3886: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
3887: #if 1
3888: 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);
3889: for (p = 0; p < 6; ++p) {
3890: 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);
3891: }
3892: #endif
3893: /* B hex */
3894: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 1);
3895: orntNew[0] = ornt[0];
3896: coneNew[1] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 11; /* BH */
3897: orntNew[1] = 0;
3898: coneNew[2] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 3; /* AB */
3899: orntNew[2] = -1;
3900: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 1);
3901: orntNew[3] = ornt[3];
3902: coneNew[4] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 2; /* BC */
3903: orntNew[4] = 0;
3904: coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 3);
3905: orntNew[5] = ornt[5];
3906: DMPlexSetCone(rdm, newp+1, coneNew);
3907: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
3908: #if 1
3909: 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);
3910: for (p = 0; p < 6; ++p) {
3911: 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);
3912: }
3913: #endif
3914: /* C hex */
3915: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 2);
3916: orntNew[0] = ornt[0];
3917: coneNew[1] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 10; /* CG */
3918: orntNew[1] = 0;
3919: coneNew[2] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 1; /* CD */
3920: orntNew[2] = -1;
3921: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 0);
3922: orntNew[3] = ornt[3];
3923: coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 1);
3924: orntNew[4] = ornt[4];
3925: coneNew[5] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 2; /* BC */
3926: orntNew[5] = -4;
3927: DMPlexSetCone(rdm, newp+2, coneNew);
3928: DMPlexSetConeOrientation(rdm, newp+2, orntNew);
3929: #if 1
3930: 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);
3931: for (p = 0; p < 6; ++p) {
3932: 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);
3933: }
3934: #endif
3935: /* D hex */
3936: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 3);
3937: orntNew[0] = ornt[0];
3938: coneNew[1] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 9; /* DF */
3939: orntNew[1] = 0;
3940: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 1);
3941: orntNew[2] = ornt[2];
3942: coneNew[3] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 1; /* CD */
3943: orntNew[3] = 0;
3944: coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 0);
3945: orntNew[4] = ornt[4];
3946: coneNew[5] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 0; /* AD */
3947: orntNew[5] = -4;
3948: DMPlexSetCone(rdm, newp+3, coneNew);
3949: DMPlexSetConeOrientation(rdm, newp+3, orntNew);
3950: #if 1
3951: 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);
3952: for (p = 0; p < 6; ++p) {
3953: 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);
3954: }
3955: #endif
3956: /* E hex */
3957: coneNew[0] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 8; /* AE */
3958: orntNew[0] = -4;
3959: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 0);
3960: orntNew[1] = ornt[1];
3961: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 3);
3962: orntNew[2] = ornt[2];
3963: coneNew[3] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 7; /* EH */
3964: orntNew[3] = 0;
3965: coneNew[4] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 4; /* EF */
3966: orntNew[4] = -1;
3967: coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 1);
3968: orntNew[5] = ornt[5];
3969: DMPlexSetCone(rdm, newp+4, coneNew);
3970: DMPlexSetConeOrientation(rdm, newp+4, orntNew);
3971: #if 1
3972: 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);
3973: for (p = 0; p < 6; ++p) {
3974: 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);
3975: }
3976: #endif
3977: /* F hex */
3978: coneNew[0] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 9; /* DF */
3979: orntNew[0] = -4;
3980: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 1);
3981: orntNew[1] = ornt[1];
3982: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 2);
3983: orntNew[2] = ornt[2];
3984: coneNew[3] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 5; /* FG */
3985: orntNew[3] = -1;
3986: coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 3);
3987: orntNew[4] = ornt[4];
3988: coneNew[5] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 4; /* EF */
3989: orntNew[5] = 1;
3990: DMPlexSetCone(rdm, newp+5, coneNew);
3991: DMPlexSetConeOrientation(rdm, newp+5, orntNew);
3992: #if 1
3993: 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);
3994: for (p = 0; p < 6; ++p) {
3995: 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);
3996: }
3997: #endif
3998: /* G hex */
3999: coneNew[0] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 10; /* CG */
4000: orntNew[0] = -4;
4001: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 2);
4002: orntNew[1] = ornt[1];
4003: coneNew[2] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 5; /* FG */
4004: orntNew[2] = 0;
4005: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 3);
4006: orntNew[3] = ornt[3];
4007: coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 2);
4008: orntNew[4] = ornt[4];
4009: coneNew[5] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 6; /* GH */
4010: orntNew[5] = -3;
4011: DMPlexSetCone(rdm, newp+6, coneNew);
4012: DMPlexSetConeOrientation(rdm, newp+6, orntNew);
4013: #if 1
4014: 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);
4015: for (p = 0; p < 6; ++p) {
4016: 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);
4017: }
4018: #endif
4019: /* H hex */
4020: coneNew[0] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 11; /* BH */
4021: orntNew[0] = -4;
4022: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 3);
4023: orntNew[1] = ornt[1];
4024: coneNew[2] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 7; /* EH */
4025: orntNew[2] = -1;
4026: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 2);
4027: orntNew[3] = ornt[3];
4028: coneNew[4] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 6; /* GH */
4029: orntNew[4] = 3;
4030: coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 2);
4031: orntNew[5] = ornt[5];
4032: DMPlexSetCone(rdm, newp+7, coneNew);
4033: DMPlexSetConeOrientation(rdm, newp+7, orntNew);
4034: #if 1
4035: 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);
4036: for (p = 0; p < 6; ++p) {
4037: 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);
4038: }
4039: #endif
4040: }
4041: /* Split faces have 4 edges and the same cells as the parent */
4042: DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
4043: PetscMalloc1(4 + maxSupportSize*2, &supportRef);
4044: for (f = fStart; f < fEnd; ++f) {
4045: for (r = 0; r < 4; ++r) {
4046: /* TODO: This can come from GetFaces_Internal() */
4047: 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};
4048: const PetscInt newp = fStartNew + (f - fStart)*4 + r;
4049: const PetscInt *cone, *ornt, *support;
4050: PetscInt coneNew[4], orntNew[4], coneSize, c, supportSize, s;
4052: DMPlexGetCone(dm, f, &cone);
4053: DMPlexGetConeOrientation(dm, f, &ornt);
4054: coneNew[(r+3)%4] = eStartNew + (cone[(r+3)%4] - eStart)*2 + (ornt[(r+3)%4] < 0 ? 0 : 1);
4055: orntNew[(r+3)%4] = ornt[(r+3)%4];
4056: coneNew[(r+0)%4] = eStartNew + (cone[r] - eStart)*2 + (ornt[r] < 0 ? 1 : 0);
4057: orntNew[(r+0)%4] = ornt[r];
4058: coneNew[(r+1)%4] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + r;
4059: orntNew[(r+1)%4] = 0;
4060: coneNew[(r+2)%4] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + (r+3)%4;
4061: orntNew[(r+2)%4] = -2;
4062: DMPlexSetCone(rdm, newp, coneNew);
4063: DMPlexSetConeOrientation(rdm, newp, orntNew);
4064: #if 1
4065: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
4066: for (p = 0; p < 4; ++p) {
4067: 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);
4068: }
4069: #endif
4070: DMPlexGetSupportSize(dm, f, &supportSize);
4071: DMPlexGetSupport(dm, f, &support);
4072: for (s = 0; s < supportSize; ++s) {
4073: DMPlexGetConeSize(dm, support[s], &coneSize);
4074: DMPlexGetCone(dm, support[s], &cone);
4075: DMPlexGetConeOrientation(dm, support[s], &ornt);
4076: for (c = 0; c < coneSize; ++c) {
4077: if (cone[c] == f) break;
4078: }
4079: supportRef[s] = cStartNew + (support[s] - cStart)*8 + newCells[c*4+GetQuadSubfaceInverse_Static(ornt[c], r)];
4080: }
4081: DMPlexSetSupport(rdm, newp, supportRef);
4082: #if 1
4083: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
4084: for (p = 0; p < supportSize; ++p) {
4085: 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);
4086: }
4087: #endif
4088: }
4089: }
4090: /* Interior faces have 4 edges and 2 cells */
4091: for (c = cStart; c < cEnd; ++c) {
4092: 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};
4093: const PetscInt *cone, *ornt;
4094: PetscInt newp, coneNew[4], orntNew[4], supportNew[2];
4096: DMPlexGetCone(dm, c, &cone);
4097: DMPlexGetConeOrientation(dm, c, &ornt);
4098: /* A-D face */
4099: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 0;
4100: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 3);
4101: orntNew[0] = 0;
4102: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 0;
4103: orntNew[1] = 0;
4104: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 2;
4105: orntNew[2] = -2;
4106: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 0);
4107: orntNew[3] = -2;
4108: DMPlexSetCone(rdm, newp, coneNew);
4109: DMPlexSetConeOrientation(rdm, newp, orntNew);
4110: #if 1
4111: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
4112: for (p = 0; p < 4; ++p) {
4113: 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);
4114: }
4115: #endif
4116: /* C-D face */
4117: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 1;
4118: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 2);
4119: orntNew[0] = 0;
4120: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 0;
4121: orntNew[1] = 0;
4122: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 4;
4123: orntNew[2] = -2;
4124: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 0);
4125: orntNew[3] = -2;
4126: DMPlexSetCone(rdm, newp, coneNew);
4127: DMPlexSetConeOrientation(rdm, newp, orntNew);
4128: #if 1
4129: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
4130: for (p = 0; p < 4; ++p) {
4131: 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);
4132: }
4133: #endif
4134: /* B-C face */
4135: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 2;
4136: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 1);
4137: orntNew[0] = -2;
4138: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 0);
4139: orntNew[1] = 0;
4140: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 3;
4141: orntNew[2] = 0;
4142: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 0;
4143: orntNew[3] = -2;
4144: DMPlexSetCone(rdm, newp, coneNew);
4145: DMPlexSetConeOrientation(rdm, newp, orntNew);
4146: #if 1
4147: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
4148: for (p = 0; p < 4; ++p) {
4149: 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);
4150: }
4151: #endif
4152: /* A-B face */
4153: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 3;
4154: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 0);
4155: orntNew[0] = -2;
4156: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 3);
4157: orntNew[1] = 0;
4158: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 5;
4159: orntNew[2] = 0;
4160: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 0;
4161: orntNew[3] = -2;
4162: DMPlexSetCone(rdm, newp, coneNew);
4163: DMPlexSetConeOrientation(rdm, newp, orntNew);
4164: #if 1
4165: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
4166: for (p = 0; p < 4; ++p) {
4167: 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);
4168: }
4169: #endif
4170: /* E-F face */
4171: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 4;
4172: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 2;
4173: orntNew[0] = -2;
4174: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 2);
4175: orntNew[1] = -2;
4176: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 0);
4177: orntNew[2] = 0;
4178: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 1;
4179: orntNew[3] = 0;
4180: DMPlexSetCone(rdm, newp, coneNew);
4181: DMPlexSetConeOrientation(rdm, newp, orntNew);
4182: #if 1
4183: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
4184: for (p = 0; p < 4; ++p) {
4185: 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);
4186: }
4187: #endif
4188: /* F-G face */
4189: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 5;
4190: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 4;
4191: orntNew[0] = -2;
4192: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 2);
4193: orntNew[1] = -2;
4194: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 1);
4195: orntNew[2] = 0;
4196: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 1;
4197: orntNew[3] = 0;
4198: DMPlexSetCone(rdm, newp, coneNew);
4199: DMPlexSetConeOrientation(rdm, newp, orntNew);
4200: #if 1
4201: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
4202: for (p = 0; p < 4; ++p) {
4203: 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);
4204: }
4205: #endif
4206: /* G-H face */
4207: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 6;
4208: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 2);
4209: orntNew[0] = -2;
4210: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 2);
4211: orntNew[1] = 0;
4212: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 1;
4213: orntNew[2] = 0;
4214: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 3;
4215: orntNew[3] = -2;
4216: DMPlexSetCone(rdm, newp, coneNew);
4217: DMPlexSetConeOrientation(rdm, newp, orntNew);
4218: #if 1
4219: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
4220: for (p = 0; p < 4; ++p) {
4221: 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);
4222: }
4223: #endif
4224: /* E-H face */
4225: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 7;
4226: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 5;
4227: orntNew[0] = -2;
4228: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 1);
4229: orntNew[1] = -2;
4230: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 3);
4231: orntNew[2] = 0;
4232: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 1;
4233: orntNew[3] = 0;
4234: DMPlexSetCone(rdm, newp, coneNew);
4235: DMPlexSetConeOrientation(rdm, newp, orntNew);
4236: #if 1
4237: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
4238: for (p = 0; p < 4; ++p) {
4239: 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);
4240: }
4241: #endif
4242: /* A-E face */
4243: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 8;
4244: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 3);
4245: orntNew[0] = 0;
4246: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 2;
4247: orntNew[1] = 0;
4248: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 5;
4249: orntNew[2] = -2;
4250: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 0);
4251: orntNew[3] = -2;
4252: DMPlexSetCone(rdm, newp, coneNew);
4253: DMPlexSetConeOrientation(rdm, newp, orntNew);
4254: #if 1
4255: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
4256: for (p = 0; p < 4; ++p) {
4257: 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);
4258: }
4259: #endif
4260: /* D-F face */
4261: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 9;
4262: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 1);
4263: orntNew[0] = -2;
4264: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 3);
4265: orntNew[1] = 0;
4266: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 4;
4267: orntNew[2] = 0;
4268: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 2;
4269: orntNew[3] = -2;
4270: DMPlexSetCone(rdm, newp, coneNew);
4271: DMPlexSetConeOrientation(rdm, newp, orntNew);
4272: #if 1
4273: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
4274: for (p = 0; p < 4; ++p) {
4275: 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);
4276: }
4277: #endif
4278: /* C-G face */
4279: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 10;
4280: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 4;
4281: orntNew[0] = -2;
4282: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 1);
4283: orntNew[1] = -2;
4284: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 3);
4285: orntNew[2] = 0;
4286: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 3;
4287: orntNew[3] = 0;
4288: DMPlexSetCone(rdm, newp, coneNew);
4289: DMPlexSetConeOrientation(rdm, newp, orntNew);
4290: #if 1
4291: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
4292: for (p = 0; p < 4; ++p) {
4293: 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);
4294: }
4295: #endif
4296: /* B-H face */
4297: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + 11;
4298: coneNew[0] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 5;
4299: orntNew[0] = 0;
4300: coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + 3;
4301: orntNew[1] = -2;
4302: coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 1);
4303: orntNew[2] = -2;
4304: coneNew[3] = eStartNew + (eEnd - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 2);
4305: orntNew[3] = 0;
4306: DMPlexSetCone(rdm, newp, coneNew);
4307: DMPlexSetConeOrientation(rdm, newp, orntNew);
4308: #if 1
4309: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
4310: for (p = 0; p < 4; ++p) {
4311: 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);
4312: }
4313: #endif
4314: for (r = 0; r < 12; ++r) {
4315: newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + r;
4316: supportNew[0] = cStartNew + (c - cStart)*8 + newCells[r*2+0];
4317: supportNew[1] = cStartNew + (c - cStart)*8 + newCells[r*2+1];
4318: DMPlexSetSupport(rdm, newp, supportNew);
4319: #if 1
4320: if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
4321: for (p = 0; p < 2; ++p) {
4322: 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);
4323: }
4324: #endif
4325: }
4326: }
4327: /* Split edges have 2 vertices and the same faces as the parent */
4328: DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
4329: for (e = eStart; e < eEnd; ++e) {
4330: const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);
4332: for (r = 0; r < 2; ++r) {
4333: const PetscInt newp = eStartNew + (e - eStart)*2 + r;
4334: const PetscInt *cone, *ornt, *support;
4335: PetscInt coneNew[2], coneSize, c, supportSize, s;
4337: DMPlexGetCone(dm, e, &cone);
4338: coneNew[0] = vStartNew + (cone[0] - vStart);
4339: coneNew[1] = vStartNew + (cone[1] - vStart);
4340: coneNew[(r+1)%2] = newv;
4341: DMPlexSetCone(rdm, newp, coneNew);
4342: #if 1
4343: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
4344: for (p = 0; p < 2; ++p) {
4345: 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);
4346: }
4347: #endif
4348: DMPlexGetSupportSize(dm, e, &supportSize);
4349: DMPlexGetSupport(dm, e, &support);
4350: for (s = 0; s < supportSize; ++s) {
4351: DMPlexGetConeSize(dm, support[s], &coneSize);
4352: DMPlexGetCone(dm, support[s], &cone);
4353: DMPlexGetConeOrientation(dm, support[s], &ornt);
4354: for (c = 0; c < coneSize; ++c) {
4355: if (cone[c] == e) break;
4356: }
4357: supportRef[s] = fStartNew + (support[s] - fStart)*4 + (ornt[c] < 0 ? (c+1-r)%4 : (c+r)%4);
4358: }
4359: DMPlexSetSupport(rdm, newp, supportRef);
4360: #if 1
4361: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
4362: for (p = 0; p < supportSize; ++p) {
4363: 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);
4364: }
4365: #endif
4366: }
4367: }
4368: /* Face edges have 2 vertices and 2+cells faces */
4369: for (f = fStart; f < fEnd; ++f) {
4370: 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};
4371: const PetscInt newv = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (f - fStart);
4372: const PetscInt *cone, *coneCell, *orntCell, *support;
4373: PetscInt coneNew[2], coneSize, c, supportSize, s;
4375: DMPlexGetCone(dm, f, &cone);
4376: for (r = 0; r < 4; ++r) {
4377: const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + r;
4379: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - eStart);
4380: coneNew[1] = newv;
4381: DMPlexSetCone(rdm, newp, coneNew);
4382: #if 1
4383: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
4384: for (p = 0; p < 2; ++p) {
4385: 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);
4386: }
4387: #endif
4388: DMPlexGetSupportSize(dm, f, &supportSize);
4389: DMPlexGetSupport(dm, f, &support);
4390: supportRef[0] = fStartNew + (f - fStart)*4 + r;
4391: supportRef[1] = fStartNew + (f - fStart)*4 + (r+1)%4;
4392: for (s = 0; s < supportSize; ++s) {
4393: DMPlexGetConeSize(dm, support[s], &coneSize);
4394: DMPlexGetCone(dm, support[s], &coneCell);
4395: DMPlexGetConeOrientation(dm, support[s], &orntCell);
4396: for (c = 0; c < coneSize; ++c) if (coneCell[c] == f) break;
4397: supportRef[2+s] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*12 + newFaces[c*4 + GetQuadEdgeInverse_Static(orntCell[c], r)];
4398: }
4399: DMPlexSetSupport(rdm, newp, supportRef);
4400: #if 1
4401: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
4402: for (p = 0; p < 2+supportSize; ++p) {
4403: 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);
4404: }
4405: #endif
4406: }
4407: }
4408: /* Cell edges have 2 vertices and 4 faces */
4409: for (c = cStart; c < cEnd; ++c) {
4410: 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};
4411: const PetscInt newv = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (c - cStart);
4412: const PetscInt *cone;
4413: PetscInt coneNew[2], supportNew[4];
4415: DMPlexGetCone(dm, c, &cone);
4416: for (r = 0; r < 6; ++r) {
4417: const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + r;
4419: coneNew[0] = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (cone[r] - fStart);
4420: coneNew[1] = newv;
4421: DMPlexSetCone(rdm, newp, coneNew);
4422: #if 1
4423: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
4424: for (p = 0; p < 2; ++p) {
4425: 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);
4426: }
4427: #endif
4428: for (f = 0; f < 4; ++f) supportNew[f] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*12 + newFaces[r*4+f];
4429: DMPlexSetSupport(rdm, newp, supportNew);
4430: #if 1
4431: if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
4432: for (p = 0; p < 4; ++p) {
4433: 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);
4434: }
4435: #endif
4436: }
4437: }
4438: /* Old vertices have identical supports */
4439: for (v = vStart; v < vEnd; ++v) {
4440: const PetscInt newp = vStartNew + (v - vStart);
4441: const PetscInt *support, *cone;
4442: PetscInt size, s;
4444: DMPlexGetSupportSize(dm, v, &size);
4445: DMPlexGetSupport(dm, v, &support);
4446: for (s = 0; s < size; ++s) {
4447: PetscInt r = 0;
4449: DMPlexGetCone(dm, support[s], &cone);
4450: if (cone[1] == v) r = 1;
4451: supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
4452: }
4453: DMPlexSetSupport(rdm, newp, supportRef);
4454: #if 1
4455: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
4456: for (p = 0; p < size; ++p) {
4457: 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);
4458: }
4459: #endif
4460: }
4461: /* Edge vertices have 2 + faces supports */
4462: for (e = eStart; e < eEnd; ++e) {
4463: const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
4464: const PetscInt *cone, *support;
4465: PetscInt size, s;
4467: DMPlexGetSupportSize(dm, e, &size);
4468: DMPlexGetSupport(dm, e, &support);
4469: supportRef[0] = eStartNew + (e - eStart)*2 + 0;
4470: supportRef[1] = eStartNew + (e - eStart)*2 + 1;
4471: for (s = 0; s < size; ++s) {
4472: PetscInt r;
4474: DMPlexGetCone(dm, support[s], &cone);
4475: for (r = 0; r < 4; ++r) if (cone[r] == e) break;
4476: supportRef[2+s] = eStartNew + (eEnd - eStart)*2 + (support[s] - fStart)*4 + r;
4477: }
4478: DMPlexSetSupport(rdm, newp, supportRef);
4479: #if 1
4480: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
4481: for (p = 0; p < 2+size; ++p) {
4482: 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);
4483: }
4484: #endif
4485: }
4486: /* Face vertices have 4 + cells supports */
4487: for (f = fStart; f < fEnd; ++f) {
4488: const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (f - fStart);
4489: const PetscInt *cone, *support;
4490: PetscInt size, s;
4492: DMPlexGetSupportSize(dm, f, &size);
4493: DMPlexGetSupport(dm, f, &support);
4494: for (r = 0; r < 4; ++r) supportRef[r] = eStartNew + (eEnd - eStart)*2 + (f - fStart)*4 + r;
4495: for (s = 0; s < size; ++s) {
4496: PetscInt r;
4498: DMPlexGetCone(dm, support[s], &cone);
4499: for (r = 0; r < 6; ++r) if (cone[r] == f) break;
4500: supportRef[4+s] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (support[s] - cStart)*6 + r;
4501: }
4502: DMPlexSetSupport(rdm, newp, supportRef);
4503: #if 1
4504: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
4505: for (p = 0; p < 4+size; ++p) {
4506: 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);
4507: }
4508: #endif
4509: }
4510: /* Cell vertices have 6 supports */
4511: for (c = cStart; c < cEnd; ++c) {
4512: const PetscInt newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (c - cStart);
4513: PetscInt supportNew[6];
4515: for (r = 0; r < 6; ++r) {
4516: supportNew[r] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (c - cStart)*6 + r;
4517: }
4518: DMPlexSetSupport(rdm, newp, supportNew);
4519: }
4520: PetscFree(supportRef);
4521: break;
4522: case REFINER_HYBRID_HEX_3D:
4523: DMPlexGetHybridBounds(rdm, &cMaxNew, &fMaxNew, &eMaxNew, NULL);
4524: /*
4525: Bottom (viewed from top) Top
4526: 1---------2---------2 7---------2---------6
4527: | | | | | |
4528: | B 2 C | | H 2 G |
4529: | | | | | |
4530: 3----3----0----1----1 3----3----0----1----1
4531: | | | | | |
4532: | A 0 D | | E 0 F |
4533: | | | | | |
4534: 0---------0---------3 4---------0---------5
4535: */
4536: /* Interior cells have 6 faces: Bottom, Top, Front, Back, Right, Left */
4537: for (c = cStart; c < cMax; ++c) {
4538: const PetscInt newp = (c - cStart)*8;
4539: const PetscInt *cone, *ornt;
4540: PetscInt coneNew[6], orntNew[6];
4542: DMPlexGetCone(dm, c, &cone);
4543: DMPlexGetConeOrientation(dm, c, &ornt);
4544: /* A hex */
4545: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 0);
4546: orntNew[0] = ornt[0];
4547: coneNew[1] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 8; /* AE */
4548: orntNew[1] = 0;
4549: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 0);
4550: orntNew[2] = ornt[2];
4551: coneNew[3] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 3; /* AB */
4552: orntNew[3] = 0;
4553: coneNew[4] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 0; /* AD */
4554: orntNew[4] = 0;
4555: coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 0);
4556: orntNew[5] = ornt[5];
4557: DMPlexSetCone(rdm, newp+0, coneNew);
4558: DMPlexSetConeOrientation(rdm, newp+0, orntNew);
4559: #if 1
4560: 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);
4561: for (p = 0; p < 6; ++p) {
4562: 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);
4563: }
4564: #endif
4565: /* B hex */
4566: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 1);
4567: orntNew[0] = ornt[0];
4568: coneNew[1] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 11; /* BH */
4569: orntNew[1] = 0;
4570: coneNew[2] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 3; /* AB */
4571: orntNew[2] = -1;
4572: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 1);
4573: orntNew[3] = ornt[3];
4574: coneNew[4] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 2; /* BC */
4575: orntNew[4] = 0;
4576: coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 3);
4577: orntNew[5] = ornt[5];
4578: DMPlexSetCone(rdm, newp+1, coneNew);
4579: DMPlexSetConeOrientation(rdm, newp+1, orntNew);
4580: #if 1
4581: 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);
4582: for (p = 0; p < 6; ++p) {
4583: 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);
4584: }
4585: #endif
4586: /* C hex */
4587: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 2);
4588: orntNew[0] = ornt[0];
4589: coneNew[1] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 10; /* CG */
4590: orntNew[1] = 0;
4591: coneNew[2] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 1; /* CD */
4592: orntNew[2] = -1;
4593: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 0);
4594: orntNew[3] = ornt[3];
4595: coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 1);
4596: orntNew[4] = ornt[4];
4597: coneNew[5] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 2; /* BC */
4598: orntNew[5] = -4;
4599: DMPlexSetCone(rdm, newp+2, coneNew);
4600: DMPlexSetConeOrientation(rdm, newp+2, orntNew);
4601: #if 1
4602: 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);
4603: for (p = 0; p < 6; ++p) {
4604: 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);
4605: }
4606: #endif
4607: /* D hex */
4608: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], 3);
4609: orntNew[0] = ornt[0];
4610: coneNew[1] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 9; /* DF */
4611: orntNew[1] = 0;
4612: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 1);
4613: orntNew[2] = ornt[2];
4614: coneNew[3] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 1; /* CD */
4615: orntNew[3] = 0;
4616: coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 0);
4617: orntNew[4] = ornt[4];
4618: coneNew[5] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 0; /* AD */
4619: orntNew[5] = -4;
4620: DMPlexSetCone(rdm, newp+3, coneNew);
4621: DMPlexSetConeOrientation(rdm, newp+3, orntNew);
4622: #if 1
4623: 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);
4624: for (p = 0; p < 6; ++p) {
4625: 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);
4626: }
4627: #endif
4628: /* E hex */
4629: coneNew[0] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 8; /* AE */
4630: orntNew[0] = -4;
4631: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 0);
4632: orntNew[1] = ornt[1];
4633: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 3);
4634: orntNew[2] = ornt[2];
4635: coneNew[3] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 7; /* EH */
4636: orntNew[3] = 0;
4637: coneNew[4] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 4; /* EF */
4638: orntNew[4] = -1;
4639: coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 1);
4640: orntNew[5] = ornt[5];
4641: DMPlexSetCone(rdm, newp+4, coneNew);
4642: DMPlexSetConeOrientation(rdm, newp+4, orntNew);
4643: #if 1
4644: 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);
4645: for (p = 0; p < 6; ++p) {
4646: 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);
4647: }
4648: #endif
4649: /* F hex */
4650: coneNew[0] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 9; /* DF */
4651: orntNew[0] = -4;
4652: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 1);
4653: orntNew[1] = ornt[1];
4654: coneNew[2] = fStartNew + (cone[2] - fStart)*4 + GetQuadSubface_Static(ornt[2], 2);
4655: orntNew[2] = ornt[2];
4656: coneNew[3] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 5; /* FG */
4657: orntNew[3] = -1;
4658: coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 3);
4659: orntNew[4] = ornt[4];
4660: coneNew[5] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 4; /* EF */
4661: orntNew[5] = 1;
4662: DMPlexSetCone(rdm, newp+5, coneNew);
4663: DMPlexSetConeOrientation(rdm, newp+5, orntNew);
4664: #if 1
4665: 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);
4666: for (p = 0; p < 6; ++p) {
4667: 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);
4668: }
4669: #endif
4670: /* G hex */
4671: coneNew[0] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 10; /* CG */
4672: orntNew[0] = -4;
4673: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 2);
4674: orntNew[1] = ornt[1];
4675: coneNew[2] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 5; /* FG */
4676: orntNew[2] = 0;
4677: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 3);
4678: orntNew[3] = ornt[3];
4679: coneNew[4] = fStartNew + (cone[4] - fStart)*4 + GetQuadSubface_Static(ornt[4], 2);
4680: orntNew[4] = ornt[4];
4681: coneNew[5] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 6; /* GH */
4682: orntNew[5] = -3;
4683: DMPlexSetCone(rdm, newp+6, coneNew);
4684: DMPlexSetConeOrientation(rdm, newp+6, orntNew);
4685: #if 1
4686: 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);
4687: for (p = 0; p < 6; ++p) {
4688: 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);
4689: }
4690: #endif
4691: /* H hex */
4692: coneNew[0] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 11; /* BH */
4693: orntNew[0] = -4;
4694: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], 3);
4695: orntNew[1] = ornt[1];
4696: coneNew[2] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 7; /* EH */
4697: orntNew[2] = -1;
4698: coneNew[3] = fStartNew + (cone[3] - fStart)*4 + GetQuadSubface_Static(ornt[3], 2);
4699: orntNew[3] = ornt[3];
4700: coneNew[4] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 6; /* GH */
4701: orntNew[4] = 3;
4702: coneNew[5] = fStartNew + (cone[5] - fStart)*4 + GetQuadSubface_Static(ornt[5], 2);
4703: orntNew[5] = ornt[5];
4704: DMPlexSetCone(rdm, newp+7, coneNew);
4705: DMPlexSetConeOrientation(rdm, newp+7, orntNew);
4706: #if 1
4707: 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);
4708: for (p = 0; p < 6; ++p) {
4709: 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);
4710: }
4711: #endif
4712: }
4713: /* Hybrid cells have 6 faces: Front, Back, Sides */
4714: /*
4715: 3---------2---------2
4716: | | |
4717: | D 2 C |
4718: | | |
4719: 3----3----0----1----1
4720: | | |
4721: | A 0 B |
4722: | | |
4723: 0---------0---------1
4724: */
4725: for (c = cMax; c < cEnd; ++c) {
4726: const PetscInt newp = (cMax - cStart)*8 + (c - cMax)*4;
4727: const PetscInt *cone, *ornt, *fornt;
4728: PetscInt coneNew[6], orntNew[6], o, of, i;
4730: DMPlexGetCone(dm, c, &cone);
4731: DMPlexGetConeOrientation(dm, c, &ornt);
4732: DMPlexGetConeOrientation(dm, cone[0], &fornt);
4733: o = ornt[0] < 0 ? -1 : 1;
4734: for (r = 0; r < 4; ++r) {
4735: PetscInt subfA = GetQuadSubface_Static(ornt[0], r);
4736: PetscInt edgeA = GetQuadEdge_Static(ornt[0], r);
4737: PetscInt edgeB = GetQuadEdge_Static(ornt[0], (r+3)%4);
4738: 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]);
4739: coneNew[0] = fStartNew + (cone[0] - fStart)*4 + subfA;
4740: orntNew[0] = ornt[0];
4741: coneNew[1] = fStartNew + (cone[1] - fStart)*4 + subfA;
4742: orntNew[1] = ornt[0];
4743: of = fornt[edgeA] < 0 ? -1 : 1;
4744: i = GetQuadEdgeInverse_Static(ornt[0], r) + 2;
4745: coneNew[i] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (cone[2+edgeA] - fMax)*2 + (o*of < 0 ? 1 : 0);
4746: orntNew[i] = ornt[edgeA];
4747: i = GetQuadEdgeInverse_Static(ornt[0], (r+1)%4) + 2;
4748: coneNew[i] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + edgeA;
4749: orntNew[i] = 0;
4750: i = GetQuadEdgeInverse_Static(ornt[0], (r+2)%4) + 2;
4751: coneNew[i] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + edgeB;
4752: orntNew[i] = -2;
4753: of = fornt[edgeB] < 0 ? -1 : 1;
4754: i = GetQuadEdgeInverse_Static(ornt[0], (r+3)%4) + 2;
4755: coneNew[i] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (cone[2+edgeB] - fMax)*2 + (o*of < 0 ? 0 : 1);
4756: orntNew[i] = ornt[edgeB];
4757: DMPlexSetCone(rdm, newp+r, coneNew);
4758: DMPlexSetConeOrientation(rdm, newp+r, orntNew);
4759: #if 1
4760: 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);
4761: for (p = 0; p < 2; ++p) {
4762: 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);
4763: }
4764: for (p = 2; p < 6; ++p) {
4765: 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);
4766: }
4767: #endif
4768: }
4769: }
4770: /* Interior split faces have 4 edges and the same cells as the parent */
4771: DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
4772: PetscMalloc1(4 + maxSupportSize*2, &supportRef);
4773: for (f = fStart; f < fMax; ++f) {
4774: for (r = 0; r < 4; ++r) {
4775: /* TODO: This can come from GetFaces_Internal() */
4776: 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};
4777: const PetscInt newp = fStartNew + (f - fStart)*4 + r;
4778: const PetscInt *cone, *ornt, *support;
4779: PetscInt coneNew[4], orntNew[4], coneSize, c, supportSize, s;
4781: DMPlexGetCone(dm, f, &cone);
4782: DMPlexGetConeOrientation(dm, f, &ornt);
4783: coneNew[(r+3)%4] = eStartNew + (cone[(r+3)%4] - eStart)*2 + (ornt[(r+3)%4] < 0 ? 0 : 1);
4784: orntNew[(r+3)%4] = ornt[(r+3)%4];
4785: coneNew[(r+0)%4] = eStartNew + (cone[r] - eStart)*2 + (ornt[r] < 0 ? 1 : 0);
4786: orntNew[(r+0)%4] = ornt[r];
4787: coneNew[(r+1)%4] = eStartNew + (eMax - eStart)*2 + (f - fStart)*4 + r;
4788: orntNew[(r+1)%4] = 0;
4789: coneNew[(r+2)%4] = eStartNew + (eMax - eStart)*2 + (f - fStart)*4 + (r+3)%4;
4790: orntNew[(r+2)%4] = -2;
4791: DMPlexSetCone(rdm, newp, coneNew);
4792: DMPlexSetConeOrientation(rdm, newp, orntNew);
4793: #if 1
4794: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4795: for (p = 0; p < 4; ++p) {
4796: 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);
4797: }
4798: #endif
4799: DMPlexGetSupportSize(dm, f, &supportSize);
4800: DMPlexGetSupport(dm, f, &support);
4801: for (s = 0; s < supportSize; ++s) {
4802: PetscInt subf;
4803: DMPlexGetConeSize(dm, support[s], &coneSize);
4804: DMPlexGetCone(dm, support[s], &cone);
4805: DMPlexGetConeOrientation(dm, support[s], &ornt);
4806: for (c = 0; c < coneSize; ++c) {
4807: if (cone[c] == f) break;
4808: }
4809: subf = GetQuadSubfaceInverse_Static(ornt[c], r);
4810: if (support[s] < cMax) {
4811: supportRef[s] = cStartNew + (support[s] - cStart)*8 + newCells[c*4+subf];
4812: } else {
4813: supportRef[s] = cStartNew + (cMax - cStart)*8 + (support[s] - cMax)*4 + subf;
4814: }
4815: }
4816: DMPlexSetSupport(rdm, newp, supportRef);
4817: #if 1
4818: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4819: for (p = 0; p < supportSize; ++p) {
4820: 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);
4821: }
4822: #endif
4823: }
4824: }
4825: /* Interior cell faces have 4 edges and 2 cells */
4826: for (c = cStart; c < cMax; ++c) {
4827: 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};
4828: const PetscInt *cone, *ornt;
4829: PetscInt newp, coneNew[4], orntNew[4], supportNew[2];
4831: DMPlexGetCone(dm, c, &cone);
4832: DMPlexGetConeOrientation(dm, c, &ornt);
4833: /* A-D face */
4834: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 0;
4835: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 3);
4836: orntNew[0] = 0;
4837: coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 0;
4838: orntNew[1] = 0;
4839: coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 2;
4840: orntNew[2] = -2;
4841: coneNew[3] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 0);
4842: orntNew[3] = -2;
4843: DMPlexSetCone(rdm, newp, coneNew);
4844: DMPlexSetConeOrientation(rdm, newp, orntNew);
4845: #if 1
4846: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4847: for (p = 0; p < 4; ++p) {
4848: 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);
4849: }
4850: #endif
4851: /* C-D face */
4852: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 1;
4853: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 2);
4854: orntNew[0] = 0;
4855: coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 0;
4856: orntNew[1] = 0;
4857: coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 4;
4858: orntNew[2] = -2;
4859: coneNew[3] = eStartNew + (eMax - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 0);
4860: orntNew[3] = -2;
4861: DMPlexSetCone(rdm, newp, coneNew);
4862: DMPlexSetConeOrientation(rdm, newp, orntNew);
4863: #if 1
4864: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4865: for (p = 0; p < 4; ++p) {
4866: 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);
4867: }
4868: #endif
4869: /* B-C face */
4870: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 2;
4871: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 1);
4872: orntNew[0] = -2;
4873: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 0);
4874: orntNew[1] = 0;
4875: coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 3;
4876: orntNew[2] = 0;
4877: coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 0;
4878: orntNew[3] = -2;
4879: DMPlexSetCone(rdm, newp, coneNew);
4880: DMPlexSetConeOrientation(rdm, newp, orntNew);
4881: #if 1
4882: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4883: for (p = 0; p < 4; ++p) {
4884: 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);
4885: }
4886: #endif
4887: /* A-B face */
4888: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 3;
4889: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + GetQuadEdge_Static(ornt[0], 0);
4890: orntNew[0] = -2;
4891: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 3);
4892: orntNew[1] = 0;
4893: coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 5;
4894: orntNew[2] = 0;
4895: coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 0;
4896: orntNew[3] = -2;
4897: DMPlexSetCone(rdm, newp, coneNew);
4898: DMPlexSetConeOrientation(rdm, newp, orntNew);
4899: #if 1
4900: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4901: for (p = 0; p < 4; ++p) {
4902: 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);
4903: }
4904: #endif
4905: /* E-F face */
4906: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 4;
4907: coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 2;
4908: orntNew[0] = -2;
4909: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 2);
4910: orntNew[1] = -2;
4911: coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 0);
4912: orntNew[2] = 0;
4913: coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 1;
4914: orntNew[3] = 0;
4915: DMPlexSetCone(rdm, newp, coneNew);
4916: DMPlexSetConeOrientation(rdm, newp, orntNew);
4917: #if 1
4918: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4919: for (p = 0; p < 4; ++p) {
4920: 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);
4921: }
4922: #endif
4923: /* F-G face */
4924: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 5;
4925: coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 4;
4926: orntNew[0] = -2;
4927: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 2);
4928: orntNew[1] = -2;
4929: coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 1);
4930: orntNew[2] = 0;
4931: coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 1;
4932: orntNew[3] = 0;
4933: DMPlexSetCone(rdm, newp, coneNew);
4934: DMPlexSetConeOrientation(rdm, newp, orntNew);
4935: #if 1
4936: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4937: for (p = 0; p < 4; ++p) {
4938: 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);
4939: }
4940: #endif
4941: /* G-H face */
4942: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 6;
4943: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 2);
4944: orntNew[0] = -2;
4945: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 2);
4946: orntNew[1] = 0;
4947: coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 1;
4948: orntNew[2] = 0;
4949: coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 3;
4950: orntNew[3] = -2;
4951: DMPlexSetCone(rdm, newp, coneNew);
4952: DMPlexSetConeOrientation(rdm, newp, orntNew);
4953: #if 1
4954: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4955: for (p = 0; p < 4; ++p) {
4956: 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);
4957: }
4958: #endif
4959: /* E-H face */
4960: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 7;
4961: coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 5;
4962: orntNew[0] = -2;
4963: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 1);
4964: orntNew[1] = -2;
4965: coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + GetQuadEdge_Static(ornt[1], 3);
4966: orntNew[2] = 0;
4967: coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 1;
4968: orntNew[3] = 0;
4969: DMPlexSetCone(rdm, newp, coneNew);
4970: DMPlexSetConeOrientation(rdm, newp, orntNew);
4971: #if 1
4972: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4973: for (p = 0; p < 4; ++p) {
4974: 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);
4975: }
4976: #endif
4977: /* A-E face */
4978: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 8;
4979: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 3);
4980: orntNew[0] = 0;
4981: coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 2;
4982: orntNew[1] = 0;
4983: coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 5;
4984: orntNew[2] = -2;
4985: coneNew[3] = eStartNew + (eMax - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 0);
4986: orntNew[3] = -2;
4987: DMPlexSetCone(rdm, newp, coneNew);
4988: DMPlexSetConeOrientation(rdm, newp, orntNew);
4989: #if 1
4990: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
4991: for (p = 0; p < 4; ++p) {
4992: 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);
4993: }
4994: #endif
4995: /* D-F face */
4996: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 9;
4997: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[2] - fStart)*4 + GetQuadEdge_Static(ornt[2], 1);
4998: orntNew[0] = -2;
4999: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 3);
5000: orntNew[1] = 0;
5001: coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 4;
5002: orntNew[2] = 0;
5003: coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 2;
5004: orntNew[3] = -2;
5005: DMPlexSetCone(rdm, newp, coneNew);
5006: DMPlexSetConeOrientation(rdm, newp, orntNew);
5007: #if 1
5008: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
5009: for (p = 0; p < 4; ++p) {
5010: 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);
5011: }
5012: #endif
5013: /* C-G face */
5014: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 10;
5015: coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 4;
5016: orntNew[0] = -2;
5017: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[4] - fStart)*4 + GetQuadEdge_Static(ornt[4], 1);
5018: orntNew[1] = -2;
5019: coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 3);
5020: orntNew[2] = 0;
5021: coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 3;
5022: orntNew[3] = 0;
5023: DMPlexSetCone(rdm, newp, coneNew);
5024: DMPlexSetConeOrientation(rdm, newp, orntNew);
5025: #if 1
5026: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
5027: for (p = 0; p < 4; ++p) {
5028: 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);
5029: }
5030: #endif
5031: /* B-H face */
5032: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + 11;
5033: coneNew[0] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 5;
5034: orntNew[0] = 0;
5035: coneNew[1] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + 3;
5036: orntNew[1] = -2;
5037: coneNew[2] = eStartNew + (eMax - eStart)*2 + (cone[3] - fStart)*4 + GetQuadEdge_Static(ornt[3], 1);
5038: orntNew[2] = -2;
5039: coneNew[3] = eStartNew + (eMax - eStart)*2 + (cone[5] - fStart)*4 + GetQuadEdge_Static(ornt[5], 2);
5040: orntNew[3] = 0;
5041: DMPlexSetCone(rdm, newp, coneNew);
5042: DMPlexSetConeOrientation(rdm, newp, orntNew);
5043: #if 1
5044: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
5045: for (p = 0; p < 4; ++p) {
5046: 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);
5047: }
5048: #endif
5049: for (r = 0; r < 12; ++r) {
5050: newp = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + r;
5051: supportNew[0] = cStartNew + (c - cStart)*8 + newCells[r*2+0];
5052: supportNew[1] = cStartNew + (c - cStart)*8 + newCells[r*2+1];
5053: DMPlexSetSupport(rdm, newp, supportNew);
5054: #if 1
5055: if ((newp < fStartNew) || (newp >= fMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fMaxNew);
5056: for (p = 0; p < 2; ++p) {
5057: 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);
5058: }
5059: #endif
5060: }
5061: }
5062: /* Hybrid split faces have 4 edges and same cells */
5063: for (f = fMax; f < fEnd; ++f) {
5064: const PetscInt *cone, *ornt, *support;
5065: PetscInt coneNew[4], orntNew[4];
5066: PetscInt supportNew[2], size, s, c;
5068: DMPlexGetCone(dm, f, &cone);
5069: DMPlexGetConeOrientation(dm, f, &ornt);
5070: DMPlexGetSupportSize(dm, f, &size);
5071: DMPlexGetSupport(dm, f, &support);
5072: for (r = 0; r < 2; ++r) {
5073: const PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (f - fMax)*2 + r;
5075: coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1-r : r);
5076: orntNew[0] = ornt[0];
5077: coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1-r : r);
5078: orntNew[1] = ornt[1];
5079: coneNew[2+r] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (cone[2+r] - eMax);
5080: orntNew[2+r] = 0;
5081: coneNew[3-r] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (f - fMax);
5082: orntNew[3-r] = 0;
5083: DMPlexSetCone(rdm, newp, coneNew);
5084: DMPlexSetConeOrientation(rdm, newp, orntNew);
5085: #if 1
5086: if ((newp < fMaxNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", newp, fMaxNew, fEndNew);
5087: for (p = 0; p < 2; ++p) {
5088: 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);
5089: }
5090: for (p = 2; p < 4; ++p) {
5091: 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);
5092: }
5093: #endif
5094: for (s = 0; s < size; ++s) {
5095: const PetscInt *coneCell, *orntCell, *fornt;
5096: PetscInt o, of;
5098: DMPlexGetCone(dm, support[s], &coneCell);
5099: DMPlexGetConeOrientation(dm, support[s], &orntCell);
5100: o = orntCell[0] < 0 ? -1 : 1;
5101: for (c = 2; c < 6; ++c) if (coneCell[c] == f) break;
5102: if (c >= 6) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find face %d in cone of cell %d", f, support[s]);
5103: DMPlexGetConeOrientation(dm, coneCell[0], &fornt);
5104: of = fornt[c-2] < 0 ? -1 : 1;
5105: supportNew[s] = cStartNew + (cMax - cStart)*8 + (support[s] - cMax)*4 + (GetQuadEdgeInverse_Static(orntCell[0], c-2) + (o*of < 0 ? 1-r : r))%4;
5106: }
5107: DMPlexSetSupport(rdm, newp, supportNew);
5108: #if 1
5109: if ((newp < fMaxNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid face [%d, %d)", newp, fMaxNew, fEndNew);
5110: for (p = 0; p < size; ++p) {
5111: 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);
5112: }
5113: #endif
5114: }
5115: }
5116: /* Hybrid cell faces have 4 edges and 2 cells */
5117: for (c = cMax; c < cEnd; ++c) {
5118: PetscInt newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4;
5119: const PetscInt *cone, *ornt;
5120: PetscInt coneNew[4], orntNew[4];
5121: PetscInt supportNew[2];
5123: DMPlexGetCone(dm, c, &cone);
5124: DMPlexGetConeOrientation(dm, c, &ornt);
5125: for (r = 0; r < 4; ++r) {
5126: #if 0
5127: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + GetQuadSubface_Static(ornt[0], r);
5128: orntNew[0] = 0;
5129: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + GetQuadSubface_Static(ornt[1], r);
5130: orntNew[1] = 0;
5131: coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (cone[2+GetQuadEdge_Static(ornt[0], r)] - fMax);
5132: orntNew[2] = 0;
5133: coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (fEnd - fMax) + (c - cMax);
5134: orntNew[3] = 0;
5135: #else
5136: coneNew[0] = eStartNew + (eMax - eStart)*2 + (cone[0] - fStart)*4 + r;
5137: orntNew[0] = 0;
5138: coneNew[1] = eStartNew + (eMax - eStart)*2 + (cone[1] - fStart)*4 + r;
5139: orntNew[1] = 0;
5140: coneNew[2] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (cone[2+r] - fMax);
5141: orntNew[2] = 0;
5142: coneNew[3] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (fEnd - fMax) + (c - cMax);
5143: orntNew[3] = 0;
5144: #endif
5145: DMPlexSetCone(rdm, newp+r, coneNew);
5146: DMPlexSetConeOrientation(rdm, newp+r, orntNew);
5147: #if 1
5148: 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);
5149: for (p = 0; p < 2; ++p) {
5150: 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);
5151: }
5152: for (p = 2; p < 4; ++p) {
5153: 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);
5154: }
5155: #endif
5156: supportNew[0] = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + GetQuadSubface_Static(ornt[0], r);
5157: supportNew[1] = cStartNew + (cMax - cStart)*8 + (c - cMax)*4 + GetQuadSubface_Static(ornt[0], (r+1)%4);
5158: DMPlexSetSupport(rdm, newp+r, supportNew);
5159: #if 1
5160: 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);
5161: for (p = 0; p < 2; ++p) {
5162: 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);
5163: }
5164: #endif
5165: }
5166: }
5167: /* Interior split edges have 2 vertices and the same faces as the parent */
5168: DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);
5169: for (e = eStart; e < eMax; ++e) {
5170: const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);
5172: for (r = 0; r < 2; ++r) {
5173: const PetscInt newp = eStartNew + (e - eStart)*2 + r;
5174: const PetscInt *cone, *ornt, *support;
5175: PetscInt coneNew[2], coneSize, c, supportSize, s;
5177: DMPlexGetCone(dm, e, &cone);
5178: coneNew[0] = vStartNew + (cone[0] - vStart);
5179: coneNew[1] = vStartNew + (cone[1] - vStart);
5180: coneNew[(r+1)%2] = newv;
5181: DMPlexSetCone(rdm, newp, coneNew);
5182: #if 1
5183: if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
5184: for (p = 0; p < 2; ++p) {
5185: 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);
5186: }
5187: #endif
5188: DMPlexGetSupportSize(dm, e, &supportSize);
5189: DMPlexGetSupport(dm, e, &support);
5190: for (s = 0; s < supportSize; ++s) {
5191: DMPlexGetConeSize(dm, support[s], &coneSize);
5192: DMPlexGetCone(dm, support[s], &cone);
5193: DMPlexGetConeOrientation(dm, support[s], &ornt);
5194: for (c = 0; c < coneSize; ++c) {
5195: if (cone[c] == e) break;
5196: }
5197: if (support[s] < fMax) {
5198: supportRef[s] = fStartNew + (support[s] - fStart)*4 + (c + (ornt[c] < 0 ? 1-r : r))%4;
5199: } else {
5200: supportRef[s] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (support[s] - fMax)*2 + (ornt[c] < 0 ? 1-r : r);
5201: }
5202: }
5203: DMPlexSetSupport(rdm, newp, supportRef);
5204: #if 1
5205: if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
5206: for (p = 0; p < supportSize; ++p) {
5207: 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);
5208: }
5209: #endif
5210: }
5211: }
5212: /* Interior face edges have 2 vertices and 2+cells faces */
5213: for (f = fStart; f < fMax; ++f) {
5214: 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};
5215: const PetscInt newv = vStartNew + (vEnd - vStart) + (eMax - eStart) + (f - fStart);
5216: const PetscInt *cone, *coneCell, *orntCell, *support;
5217: PetscInt coneNew[2], coneSize, c, supportSize, s;
5219: DMPlexGetCone(dm, f, &cone);
5220: for (r = 0; r < 4; ++r) {
5221: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (f - fStart)*4 + r;
5223: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - eStart);
5224: coneNew[1] = newv;
5225: DMPlexSetCone(rdm, newp, coneNew);
5226: #if 1
5227: if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
5228: for (p = 0; p < 2; ++p) {
5229: 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);
5230: }
5231: #endif
5232: DMPlexGetSupportSize(dm, f, &supportSize);
5233: DMPlexGetSupport(dm, f, &support);
5234: supportRef[0] = fStartNew + (f - fStart)*4 + r;
5235: supportRef[1] = fStartNew + (f - fStart)*4 + (r+1)%4;
5236: for (s = 0; s < supportSize; ++s) {
5237: DMPlexGetConeSize(dm, support[s], &coneSize);
5238: DMPlexGetCone(dm, support[s], &coneCell);
5239: DMPlexGetConeOrientation(dm, support[s], &orntCell);
5240: for (c = 0; c < coneSize; ++c) if (coneCell[c] == f) break;
5241: if (support[s] < cMax) {
5242: supportRef[2+s] = fStartNew + (fMax - fStart)*4 + (support[s] - cStart)*12 + newFaces[c*4 + GetQuadEdgeInverse_Static(orntCell[c], r)];
5243: } else {
5244: supportRef[2+s] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (support[s] - cMax)*4 + r;
5245: }
5246: }
5247: DMPlexSetSupport(rdm, newp, supportRef);
5248: #if 1
5249: if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
5250: for (p = 0; p < 2+supportSize; ++p) {
5251: 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);
5252: }
5253: #endif
5254: }
5255: }
5256: /* Interior cell edges have 2 vertices and 4 faces */
5257: for (c = cStart; c < cMax; ++c) {
5258: 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};
5259: const PetscInt newv = vStartNew + (vEnd - vStart) + (eMax - eStart) + (fMax - fStart) + (c - cStart);
5260: const PetscInt *cone;
5261: PetscInt coneNew[2], supportNew[4];
5263: DMPlexGetCone(dm, c, &cone);
5264: for (r = 0; r < 6; ++r) {
5265: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + r;
5267: coneNew[0] = vStartNew + (vEnd - vStart) + (eMax - eStart) + (cone[r] - fStart);
5268: coneNew[1] = newv;
5269: DMPlexSetCone(rdm, newp, coneNew);
5270: #if 1
5271: if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
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: for (f = 0; f < 4; ++f) supportNew[f] = fStartNew + (fMax - fStart)*4 + (c - cStart)*12 + newFaces[r*4+f];
5277: DMPlexSetSupport(rdm, newp, supportNew);
5278: #if 1
5279: if ((newp < eStartNew) || (newp >= eMaxNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eMaxNew);
5280: for (p = 0; p < 4; ++p) {
5281: 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);
5282: }
5283: #endif
5284: }
5285: }
5286: /* Hybrid edges have two vertices and the same faces */
5287: for (e = eMax; e < eEnd; ++e) {
5288: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (e - eMax);
5289: const PetscInt *cone, *support, *fcone;
5290: PetscInt coneNew[2], size, fsize, s;
5292: DMPlexGetCone(dm, e, &cone);
5293: DMPlexGetSupportSize(dm, e, &size);
5294: DMPlexGetSupport(dm, e, &support);
5295: coneNew[0] = vStartNew + (cone[0] - vStart);
5296: coneNew[1] = vStartNew + (cone[1] - vStart);
5297: DMPlexSetCone(rdm, newp, coneNew);
5298: #if 1
5299: if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
5300: for (p = 0; p < 2; ++p) {
5301: 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);
5302: }
5303: #endif
5304: for (s = 0; s < size; ++s) {
5305: DMPlexGetConeSize(dm, support[s], &fsize);
5306: DMPlexGetCone(dm, support[s], &fcone);
5307: for (c = 0; c < fsize; ++c) if (fcone[c] == e) break;
5308: if ((c < 2) || (c > 3)) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge %d not found in cone of face %d", e, support[s]);
5309: supportRef[s] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (support[s] - fMax)*2 + c-2;
5310: }
5311: DMPlexSetSupport(rdm, newp, supportRef);
5312: #if 1
5313: if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
5314: for (p = 0; p < size; ++p) {
5315: 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);
5316: }
5317: #endif
5318: }
5319: /* Hybrid face edges have 2 vertices and 2+cells faces */
5320: for (f = fMax; f < fEnd; ++f) {
5321: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (f - fMax);
5322: const PetscInt *cone, *support, *ccone, *cornt;
5323: PetscInt coneNew[2], size, csize, s;
5325: DMPlexGetCone(dm, f, &cone);
5326: DMPlexGetSupportSize(dm, f, &size);
5327: DMPlexGetSupport(dm, f, &support);
5328: coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - eStart);
5329: coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - eStart);
5330: DMPlexSetCone(rdm, newp, coneNew);
5331: #if 1
5332: if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
5333: for (p = 0; p < 2; ++p) {
5334: 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);
5335: }
5336: #endif
5337: supportRef[0] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (f - fMax)*2 + 0;
5338: supportRef[1] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (f - fMax)*2 + 1;
5339: for (s = 0; s < size; ++s) {
5340: DMPlexGetConeSize(dm, support[s], &csize);
5341: DMPlexGetCone(dm, support[s], &ccone);
5342: DMPlexGetConeOrientation(dm, support[s], &cornt);
5343: for (c = 0; c < csize; ++c) if (ccone[c] == f) break;
5344: 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]);
5345: supportRef[2+s] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (support[s] - cMax)*4 + c-2;
5346: }
5347: DMPlexSetSupport(rdm, newp, supportRef);
5348: #if 1
5349: if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
5350: for (p = 0; p < 2+size; ++p) {
5351: 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);
5352: }
5353: #endif
5354: }
5355: /* Hybrid cell edges have 2 vertices and 4 faces */
5356: for (c = cMax; c < cEnd; ++c) {
5357: const PetscInt newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (fEnd - fMax) + (c - cMax);
5358: const PetscInt *cone, *support;
5359: PetscInt coneNew[2], size;
5361: DMPlexGetCone(dm, c, &cone);
5362: DMPlexGetSupportSize(dm, c, &size);
5363: DMPlexGetSupport(dm, c, &support);
5364: coneNew[0] = vStartNew + (vEnd - vStart) + (eMax - eStart) + (cone[0] - fStart);
5365: coneNew[1] = vStartNew + (vEnd - vStart) + (eMax - eStart) + (cone[1] - fStart);
5366: DMPlexSetCone(rdm, newp, coneNew);
5367: #if 1
5368: if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
5369: for (p = 0; p < 2; ++p) {
5370: 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);
5371: }
5372: #endif
5373: supportRef[0] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + 0;
5374: supportRef[1] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + 1;
5375: supportRef[2] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + 2;
5376: supportRef[3] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (c - cMax)*4 + 3;
5377: DMPlexSetSupport(rdm, newp, supportRef);
5378: #if 1
5379: if ((newp < eMaxNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a hybrid edge [%d, %d)", newp, eMaxNew, eEndNew);
5380: for (p = 0; p < 4; ++p) {
5381: 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);
5382: }
5383: #endif
5384: }
5385: /* Interior vertices have identical supports */
5386: for (v = vStart; v < vEnd; ++v) {
5387: const PetscInt newp = vStartNew + (v - vStart);
5388: const PetscInt *support, *cone;
5389: PetscInt size, s;
5391: DMPlexGetSupportSize(dm, v, &size);
5392: DMPlexGetSupport(dm, v, &support);
5393: for (s = 0; s < size; ++s) {
5394: PetscInt r = 0;
5396: DMPlexGetCone(dm, support[s], &cone);
5397: if (cone[1] == v) r = 1;
5398: if (support[s] < eMax) supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
5399: else supportRef[s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (support[s] - eMax);
5400: }
5401: DMPlexSetSupport(rdm, newp, supportRef);
5402: #if 1
5403: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
5404: for (p = 0; p < size; ++p) {
5405: 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);
5406: }
5407: #endif
5408: }
5409: /* Interior edge vertices have 2 + faces supports */
5410: for (e = eStart; e < eMax; ++e) {
5411: const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
5412: const PetscInt *cone, *support;
5413: PetscInt size, s;
5415: DMPlexGetSupportSize(dm, e, &size);
5416: DMPlexGetSupport(dm, e, &support);
5417: supportRef[0] = eStartNew + (e - eStart)*2 + 0;
5418: supportRef[1] = eStartNew + (e - eStart)*2 + 1;
5419: for (s = 0; s < size; ++s) {
5420: PetscInt r;
5422: DMPlexGetCone(dm, support[s], &cone);
5423: for (r = 0; r < 4; ++r) if (cone[r] == e) break;
5424: if (support[s] < fMax) {
5425: supportRef[2+s] = eStartNew + (eMax - eStart)*2 + (support[s] - fStart)*4 + r;
5426: } else {
5427: supportRef[2+s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (support[s] - fMax);
5428: }
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 < 2+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: /* Interior face vertices have 4 + cells supports */
5439: for (f = fStart; f < fMax; ++f) {
5440: const PetscInt newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (f - fStart);
5441: const PetscInt *cone, *support;
5442: PetscInt size, s;
5444: DMPlexGetSupportSize(dm, f, &size);
5445: DMPlexGetSupport(dm, f, &support);
5446: for (r = 0; r < 4; ++r) supportRef[r] = eStartNew + (eMax - eStart)*2 + (f - fStart)*4 + r;
5447: for (s = 0; s < size; ++s) {
5448: PetscInt r;
5450: DMPlexGetCone(dm, support[s], &cone);
5451: for (r = 0; r < 6; ++r) if (cone[r] == f) break;
5452: if (support[s] < cMax) {
5453: supportRef[4+s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (support[s] - cStart)*6 + r;
5454: } else {
5455: supportRef[4+s] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (fEnd - fMax) + (support[s] - cMax);
5456: }
5457: }
5458: DMPlexSetSupport(rdm, newp, supportRef);
5459: #if 1
5460: if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
5461: for (p = 0; p < 4+size; ++p) {
5462: 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);
5463: }
5464: #endif
5465: }
5466: /* Cell vertices have 6 supports */
5467: for (c = cStart; c < cMax; ++c) {
5468: const PetscInt newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (fMax - fStart) + (c - cStart);
5469: PetscInt supportNew[6];
5471: for (r = 0; r < 6; ++r) {
5472: supportNew[r] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (c - cStart)*6 + r;
5473: }
5474: DMPlexSetSupport(rdm, newp, supportNew);
5475: }
5476: PetscFree(supportRef);
5477: break;
5478: default:
5479: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
5480: }
5481: return(0);
5482: }
5486: static PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
5487: {
5488: PetscSection coordSection, coordSectionNew;
5489: Vec coordinates, coordinatesNew;
5490: PetscScalar *coords, *coordsNew;
5491: const PetscInt numVertices = depthSize ? depthSize[0] : 0;
5492: PetscInt dim, spaceDim, depth, bs, coordSizeNew, cStart, cEnd, cMax, c, vStart, vStartNew, vEnd, v, eStart, eEnd, eMax, e, fStart, fEnd, fMax, f;
5496: DMGetDimension(dm, &dim);
5497: DMPlexGetDepth(dm, &depth);
5498: DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
5499: DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);
5500: DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
5501: DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);
5502: DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, NULL);
5503: if (refiner) {GetDepthStart_Private(depth, depthSize, NULL, NULL, NULL, &vStartNew);}
5504: GetDepthStart_Private(depth, depthSize, NULL, NULL, NULL, &vStartNew);
5505: DMGetCoordinateSection(dm, &coordSection);
5506: PetscSectionGetFieldComponents(coordSection, 0, &spaceDim);
5507: PetscSectionCreate(PetscObjectComm((PetscObject)dm), &coordSectionNew);
5508: PetscSectionSetNumFields(coordSectionNew, 1);
5509: PetscSectionSetFieldComponents(coordSectionNew, 0, spaceDim);
5510: PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+numVertices);
5511: if (cMax < 0) cMax = cEnd;
5512: if (fMax < 0) fMax = fEnd;
5513: if (eMax < 0) eMax = eEnd;
5514: /* All vertices have the spaceDim coordinates */
5515: for (v = vStartNew; v < vStartNew+numVertices; ++v) {
5516: PetscSectionSetDof(coordSectionNew, v, spaceDim);
5517: PetscSectionSetFieldDof(coordSectionNew, v, 0, spaceDim);
5518: }
5519: PetscSectionSetUp(coordSectionNew);
5520: DMSetCoordinateSection(rdm, PETSC_DETERMINE, coordSectionNew);
5521: DMGetCoordinatesLocal(dm, &coordinates);
5522: PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);
5523: VecCreate(PetscObjectComm((PetscObject)dm), &coordinatesNew);
5524: PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");
5525: VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);
5526: VecGetBlockSize(coordinates, &bs);
5527: VecSetBlockSize(coordinatesNew, bs);
5528: VecSetFromOptions(coordinatesNew);
5529: VecGetArray(coordinates, &coords);
5530: VecGetArray(coordinatesNew, &coordsNew);
5531: switch (refiner) {
5532: case REFINER_NOOP: break;
5533: case REFINER_HEX_3D:
5534: case REFINER_HYBRID_HEX_3D:
5535: /* Face vertices have the average of corner coordinates */
5536: for (f = fStart; f < fMax; ++f) {
5537: const PetscInt newv = vStartNew + (vEnd - vStart) + (eMax - eStart) + (f - fStart);
5538: PetscInt *cone = NULL;
5539: PetscInt closureSize, coneSize = 0, off[8], offnew, p, d;
5541: DMPlexGetTransitiveClosure(dm, f, PETSC_TRUE, &closureSize, &cone);
5542: for (p = 0; p < closureSize*2; p += 2) {
5543: const PetscInt point = cone[p];
5544: if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point;
5545: }
5546: for (v = 0; v < coneSize; ++v) {
5547: PetscSectionGetOffset(coordSection, cone[v], &off[v]);
5548: }
5549: PetscSectionGetOffset(coordSectionNew, newv, &offnew);
5550: for (d = 0; d < spaceDim; ++d) coordsNew[offnew+d] = 0.0;
5551: for (v = 0; v < coneSize; ++v) {DMLocalizeAddCoordinate_Internal(dm, spaceDim, &coords[off[0]], &coords[off[v]], &coordsNew[offnew]);}
5552: for (d = 0; d < spaceDim; ++d) coordsNew[offnew+d] /= coneSize;
5553: DMPlexRestoreTransitiveClosure(dm, f, PETSC_TRUE, &closureSize, &cone);
5554: }
5555: case REFINER_HEX_2D:
5556: case REFINER_HYBRID_HEX_2D:
5557: case REFINER_SIMPLEX_1D:
5558: /* Cell vertices have the average of corner coordinates */
5559: for (c = cStart; c < cMax; ++c) {
5560: const PetscInt newv = vStartNew + (vEnd - vStart) + (dim > 1 ? (eMax - eStart) : 0) + (c - cStart) + (dim > 2 ? (fMax - fStart) : 0);
5561: PetscInt *cone = NULL;
5562: PetscInt closureSize, coneSize = 0, off[8], offnew, p, d;
5564: DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);
5565: for (p = 0; p < closureSize*2; p += 2) {
5566: const PetscInt point = cone[p];
5567: if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point;
5568: }
5569: for (v = 0; v < coneSize; ++v) {
5570: PetscSectionGetOffset(coordSection, cone[v], &off[v]);
5571: }
5572: PetscSectionGetOffset(coordSectionNew, newv, &offnew);
5573: for (d = 0; d < spaceDim; ++d) coordsNew[offnew+d] = 0.0;
5574: for (v = 0; v < coneSize; ++v) {DMLocalizeAddCoordinate_Internal(dm, spaceDim, &coords[off[0]], &coords[off[v]], &coordsNew[offnew]);}
5575: for (d = 0; d < spaceDim; ++d) coordsNew[offnew+d] /= coneSize;
5576: DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);
5577: }
5578: case REFINER_SIMPLEX_2D:
5579: case REFINER_HYBRID_SIMPLEX_2D:
5580: case REFINER_SIMPLEX_3D:
5581: case REFINER_HYBRID_SIMPLEX_3D:
5582: /* Edge vertices have the average of endpoint coordinates */
5583: for (e = eStart; e < eMax; ++e) {
5584: const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);
5585: const PetscInt *cone;
5586: PetscInt coneSize, offA, offB, offnew, d;
5588: DMPlexGetConeSize(dm, e, &coneSize);
5589: if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %d cone should have two vertices, not %d", e, coneSize);
5590: DMPlexGetCone(dm, e, &cone);
5591: PetscSectionGetOffset(coordSection, cone[0], &offA);
5592: PetscSectionGetOffset(coordSection, cone[1], &offB);
5593: PetscSectionGetOffset(coordSectionNew, newv, &offnew);
5594: DMLocalizeCoordinate_Internal(dm, spaceDim, &coords[offA], &coords[offB], &coordsNew[offnew]);
5595: for (d = 0; d < spaceDim; ++d) {
5596: coordsNew[offnew+d] = 0.5*(coords[offA+d] + coordsNew[offnew+d]);
5597: }
5598: }
5599: /* Old vertices have the same coordinates */
5600: for (v = vStart; v < vEnd; ++v) {
5601: const PetscInt newv = vStartNew + (v - vStart);
5602: PetscInt off, offnew, d;
5604: PetscSectionGetOffset(coordSection, v, &off);
5605: PetscSectionGetOffset(coordSectionNew, newv, &offnew);
5606: for (d = 0; d < spaceDim; ++d) {
5607: coordsNew[offnew+d] = coords[off+d];
5608: }
5609: }
5610: break;
5611: default:
5612: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
5613: }
5614: VecRestoreArray(coordinates, &coords);
5615: VecRestoreArray(coordinatesNew, &coordsNew);
5616: DMSetCoordinatesLocal(rdm, coordinatesNew);
5617: VecDestroy(&coordinatesNew);
5618: PetscSectionDestroy(&coordSectionNew);
5619: if (dm->maxCell) {
5620: const PetscReal *maxCell, *L;
5621: const DMBoundaryType *bd;
5622: DMGetPeriodicity(dm, &maxCell, &L, &bd);
5623: DMSetPeriodicity(rdm, maxCell, L, bd);
5624: }
5625: return(0);
5626: }
5630: /*@
5631: DMPlexCreateProcessSF - Create an SF which just has process connectivity
5633: Collective on DM
5635: Input Parameters:
5636: + dm - The DM
5637: - sfPoint - The PetscSF which encodes point connectivity
5639: Output Parameters:
5640: + processRanks - A list of process neighbors, or NULL
5641: - sfProcess - An SF encoding the process connectivity, or NULL
5643: Level: developer
5645: .seealso: PetscSFCreate(), DMPlexCreateTwoSidedProcessSF()
5646: @*/
5647: PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess)
5648: {
5649: PetscInt numRoots, numLeaves, l;
5650: const PetscInt *localPoints;
5651: const PetscSFNode *remotePoints;
5652: PetscInt *localPointsNew;
5653: PetscSFNode *remotePointsNew;
5654: PetscInt *ranks, *ranksNew;
5655: PetscMPIInt numProcs;
5656: PetscErrorCode ierr;
5663: MPI_Comm_size(PetscObjectComm((PetscObject) dm), &numProcs);
5664: PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);
5665: PetscMalloc1(numLeaves, &ranks);
5666: for (l = 0; l < numLeaves; ++l) {
5667: ranks[l] = remotePoints[l].rank;
5668: }
5669: PetscSortRemoveDupsInt(&numLeaves, ranks);
5670: PetscMalloc1(numLeaves, &ranksNew);
5671: PetscMalloc1(numLeaves, &localPointsNew);
5672: PetscMalloc1(numLeaves, &remotePointsNew);
5673: for (l = 0; l < numLeaves; ++l) {
5674: ranksNew[l] = ranks[l];
5675: localPointsNew[l] = l;
5676: remotePointsNew[l].index = 0;
5677: remotePointsNew[l].rank = ranksNew[l];
5678: }
5679: PetscFree(ranks);
5680: if (processRanks) {ISCreateGeneral(PetscObjectComm((PetscObject)dm), numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);}
5681: else {PetscFree(ranksNew);}
5682: if (sfProcess) {
5683: PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess);
5684: PetscObjectSetName((PetscObject) *sfProcess, "Process SF");
5685: PetscSFSetFromOptions(*sfProcess);
5686: PetscSFSetGraph(*sfProcess, numProcs, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);
5687: }
5688: return(0);
5689: }
5693: static PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
5694: {
5695: PetscSF sf, sfNew, sfProcess;
5696: IS processRanks;
5697: MPI_Datatype depthType;
5698: PetscInt numRoots, numLeaves, numLeavesNew = 0, l, m;
5699: const PetscInt *localPoints, *neighbors;
5700: const PetscSFNode *remotePoints;
5701: PetscInt *localPointsNew;
5702: PetscSFNode *remotePointsNew;
5703: PetscInt *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew;
5704: PetscInt ldepth, depth, numNeighbors, pStartNew, pEndNew, cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax, r, n;
5705: PetscInt cStartNew = 0, vStartNew = 0, fStartNew = 0, eStartNew = 0;
5706: PetscErrorCode ierr;
5709: DMPlexGetChart(rdm, &pStartNew, &pEndNew);
5710: DMPlexGetDepth(dm, &ldepth);
5711: MPIU_Allreduce(&ldepth, &depth, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject) dm));
5712: if ((ldepth >= 0) && (depth != ldepth)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Inconsistent Plex depth %d != %d", ldepth, depth);
5713: DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
5714: DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);
5715: DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
5716: DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);
5717: DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);
5718: cMax = cMax < 0 ? cEnd : cMax;
5719: fMax = fMax < 0 ? fEnd : fMax;
5720: eMax = eMax < 0 ? eEnd : eMax;
5721: if (refiner) {GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);}
5722: DMGetPointSF(dm, &sf);
5723: DMGetPointSF(rdm, &sfNew);
5724: /* Calculate size of new SF */
5725: PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);
5726: if (numRoots < 0) return(0);
5727: for (l = 0; l < numLeaves; ++l) {
5728: const PetscInt p = localPoints[l];
5730: switch (refiner) {
5731: case REFINER_SIMPLEX_1D:
5732: if ((p >= vStart) && (p < vEnd)) {
5733: /* Interior vertices stay the same */
5734: ++numLeavesNew;
5735: } else if ((p >= cStart && p < cMax)) {
5736: /* Interior cells add new cells and interior vertices */
5737: numLeavesNew += 2 + 1;
5738: }
5739: break;
5740: case REFINER_SIMPLEX_2D:
5741: case REFINER_HYBRID_SIMPLEX_2D:
5742: if ((p >= vStart) && (p < vEnd)) {
5743: /* Interior vertices stay the same */
5744: ++numLeavesNew;
5745: } else if ((p >= fStart) && (p < fMax)) {
5746: /* Interior faces add new faces and vertex */
5747: numLeavesNew += 2 + 1;
5748: } else if ((p >= fMax) && (p < fEnd)) {
5749: /* Hybrid faces stay the same */
5750: ++numLeavesNew;
5751: } else if ((p >= cStart) && (p < cMax)) {
5752: /* Interior cells add new cells and interior faces */
5753: numLeavesNew += 4 + 3;
5754: } else if ((p >= cMax) && (p < cEnd)) {
5755: /* Hybrid cells add new cells and hybrid face */
5756: numLeavesNew += 2 + 1;
5757: }
5758: break;
5759: case REFINER_HEX_2D:
5760: case REFINER_HYBRID_HEX_2D:
5761: if ((p >= vStart) && (p < vEnd)) {
5762: /* Interior vertices stay the same */
5763: ++numLeavesNew;
5764: } else if ((p >= fStart) && (p < fMax)) {
5765: /* Interior faces add new faces and vertex */
5766: numLeavesNew += 2 + 1;
5767: } else if ((p >= fMax) && (p < fEnd)) {
5768: /* Hybrid faces stay the same */
5769: ++numLeavesNew;
5770: } else if ((p >= cStart) && (p < cMax)) {
5771: /* Interior cells add new cells, interior faces, and vertex */
5772: numLeavesNew += 4 + 4 + 1;
5773: } else if ((p >= cMax) && (p < cEnd)) {
5774: /* Hybrid cells add new cells and hybrid face */
5775: numLeavesNew += 2 + 1;
5776: }
5777: break;
5778: case REFINER_SIMPLEX_3D:
5779: case REFINER_HYBRID_SIMPLEX_3D:
5780: if ((p >= vStart) && (p < vEnd)) {
5781: /* Interior vertices stay the same */
5782: ++numLeavesNew;
5783: } else if ((p >= eStart) && (p < eMax)) {
5784: /* Interior edges add new edges and vertex */
5785: numLeavesNew += 2 + 1;
5786: } else if ((p >= eMax) && (p < eEnd)) {
5787: /* Hybrid edges stay the same */
5788: ++numLeavesNew;
5789: } else if ((p >= fStart) && (p < fMax)) {
5790: /* Interior faces add new faces and edges */
5791: numLeavesNew += 4 + 3;
5792: } else if ((p >= fMax) && (p < fEnd)) {
5793: /* Hybrid faces add new faces and edges */
5794: numLeavesNew += 2 + 1;
5795: } else if ((p >= cStart) && (p < cMax)) {
5796: /* Interior cells add new cells, faces, and edges */
5797: numLeavesNew += 8 + 8 + 1;
5798: } else if ((p >= cMax) && (p < cEnd)) {
5799: /* Hybrid cells add new cells and faces */
5800: numLeavesNew += 4 + 3;
5801: }
5802: break;
5803: case REFINER_HEX_3D:
5804: case REFINER_HYBRID_HEX_3D:
5805: if ((p >= vStart) && (p < vEnd)) {
5806: /* Old vertices stay the same */
5807: ++numLeavesNew;
5808: } else if ((p >= eStart) && (p < eMax)) {
5809: /* Interior edges add new edges, and vertex */
5810: numLeavesNew += 2 + 1;
5811: } else if ((p >= eMax) && (p < eEnd)) {
5812: /* Hybrid edges stay the same */
5813: ++numLeavesNew;
5814: } else if ((p >= fStart) && (p < fMax)) {
5815: /* Interior faces add new faces, edges, and vertex */
5816: numLeavesNew += 4 + 4 + 1;
5817: } else if ((p >= fMax) && (p < fEnd)) {
5818: /* Hybrid faces add new faces and edges */
5819: numLeavesNew += 2 + 1;
5820: } else if ((p >= cStart) && (p < cMax)) {
5821: /* Interior cells add new cells, faces, edges, and vertex */
5822: numLeavesNew += 8 + 12 + 6 + 1;
5823: } else if ((p >= cStart) && (p < cEnd)) {
5824: /* Hybrid cells add new cells, faces, and edges */
5825: numLeavesNew += 4 + 4 + 1;
5826: }
5827: break;
5828: default:
5829: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
5830: }
5831: }
5832: /* Communicate depthSizes for each remote rank */
5833: DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);
5834: ISGetLocalSize(processRanks, &numNeighbors);
5835: PetscMalloc5((depth+1)*numNeighbors,&rdepthSize,numNeighbors,&rvStartNew,numNeighbors,&reStartNew,numNeighbors,&rfStartNew,numNeighbors,&rcStartNew);
5836: PetscMalloc7(depth+1,&depthSizeOld,(depth+1)*numNeighbors,&rdepthSizeOld,(depth+1)*numNeighbors,&rdepthMaxOld,numNeighbors,&rvStart,numNeighbors,&reStart,numNeighbors,&rfStart,numNeighbors,&rcStart);
5837: MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);
5838: MPI_Type_commit(&depthType);
5839: PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);
5840: PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);
5841: for (n = 0; n < numNeighbors; ++n) {
5842: GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);
5843: }
5844: depthSizeOld[depth] = cMax;
5845: depthSizeOld[0] = vMax;
5846: depthSizeOld[depth-1] = fMax;
5847: depthSizeOld[1] = eMax;
5849: PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);
5850: PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);
5852: depthSizeOld[depth] = cEnd - cStart;
5853: depthSizeOld[0] = vEnd - vStart;
5854: depthSizeOld[depth-1] = fEnd - fStart;
5855: depthSizeOld[1] = eEnd - eStart;
5857: PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);
5858: PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);
5859: for (n = 0; n < numNeighbors; ++n) {
5860: GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);
5861: rdepthMaxOld[n*(depth+1)+depth] = rdepthMaxOld[n*(depth+1)+depth] < 0 ? rdepthSizeOld[n*(depth+1)+depth] +rcStart[n]: rdepthMaxOld[n*(depth+1)+depth];
5862: 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];
5863: rdepthMaxOld[n*(depth+1)+1] = rdepthMaxOld[n*(depth+1)+1] < 0 ? rdepthSizeOld[n*(depth+1)+1] +reStart[n]: rdepthMaxOld[n*(depth+1)+1];
5864: }
5865: MPI_Type_free(&depthType);
5866: PetscSFDestroy(&sfProcess);
5867: /* Calculate new point SF */
5868: PetscMalloc1(numLeavesNew, &localPointsNew);
5869: PetscMalloc1(numLeavesNew, &remotePointsNew);
5870: ISGetIndices(processRanks, &neighbors);
5871: for (l = 0, m = 0; l < numLeaves; ++l) {
5872: PetscInt p = localPoints[l];
5873: PetscInt rp = remotePoints[l].index, n;
5874: PetscMPIInt rrank = remotePoints[l].rank;
5876: PetscFindInt(rrank, numNeighbors, neighbors, &n);
5877: if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank);
5878: switch (refiner) {
5879: case REFINER_SIMPLEX_1D:
5880: if ((p >= vStart) && (p < vEnd)) {
5881: /* Old vertices stay the same */
5882: localPointsNew[m] = vStartNew + (p - vStart);
5883: remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
5884: remotePointsNew[m].rank = rrank;
5885: ++m;
5886: } else if ((p >= cStart) && (p < cMax)) {
5887: /* Old interior cells add new cells and vertex */
5888: for (r = 0; r < 2; ++r, ++m) {
5889: localPointsNew[m] = cStartNew + (p - cStart)*2 + r;
5890: remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*2 + r;
5891: remotePointsNew[m].rank = rrank;
5892: }
5893: localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - cStart);
5894: remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rcStart[n]);
5895: remotePointsNew[m].rank = rrank;
5896: ++m;
5897: }
5898: break;
5899: case REFINER_SIMPLEX_2D:
5900: case REFINER_HYBRID_SIMPLEX_2D:
5901: if ((p >= vStart) && (p < vEnd)) {
5902: /* Old vertices stay the same */
5903: localPointsNew[m] = vStartNew + (p - vStart);
5904: remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
5905: remotePointsNew[m].rank = rrank;
5906: ++m;
5907: } else if ((p >= fStart) && (p < fMax)) {
5908: /* Old interior faces add new faces and vertex */
5909: for (r = 0; r < 2; ++r, ++m) {
5910: localPointsNew[m] = fStartNew + (p - fStart)*2 + r;
5911: remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
5912: remotePointsNew[m].rank = rrank;
5913: }
5914: localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart);
5915: remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
5916: remotePointsNew[m].rank = rrank;
5917: ++m;
5918: } else if ((p >= fMax) && (p < fEnd)) {
5919: /* Old hybrid faces stay the same */
5920: localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - fMax);
5921: remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]);
5922: remotePointsNew[m].rank = rrank;
5923: ++m;
5924: } else if ((p >= cStart) && (p < cMax)) {
5925: /* Old interior cells add new cells and interior faces */
5926: for (r = 0; r < 4; ++r, ++m) {
5927: localPointsNew[m] = cStartNew + (p - cStart)*4 + r;
5928: remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
5929: remotePointsNew[m].rank = rrank;
5930: }
5931: for (r = 0; r < 3; ++r, ++m) {
5932: localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - cStart)*3 + r;
5933: remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r;
5934: remotePointsNew[m].rank = rrank;
5935: }
5936: } else if ((p >= cMax) && (p < cEnd)) {
5937: /* Old hybrid cells add new cells and hybrid face */
5938: for (r = 0; r < 2; ++r, ++m) {
5939: localPointsNew[m] = cStartNew + (p - cStart)*4 + r;
5940: remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
5941: remotePointsNew[m].rank = rrank;
5942: }
5943: localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax);
5944: 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]);
5945: remotePointsNew[m].rank = rrank;
5946: ++m;
5947: }
5948: break;
5949: case REFINER_HEX_2D:
5950: case REFINER_HYBRID_HEX_2D:
5951: if ((p >= vStart) && (p < vEnd)) {
5952: /* Old vertices stay the same */
5953: localPointsNew[m] = vStartNew + (p - vStart);
5954: remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
5955: remotePointsNew[m].rank = rrank;
5956: ++m;
5957: } else if ((p >= fStart) && (p < fMax)) {
5958: /* Old interior faces add new faces and vertex */
5959: for (r = 0; r < 2; ++r, ++m) {
5960: localPointsNew[m] = fStartNew + (p - fStart)*2 + r;
5961: remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
5962: remotePointsNew[m].rank = rrank;
5963: }
5964: localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart);
5965: remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
5966: remotePointsNew[m].rank = rrank;
5967: ++m;
5968: } else if ((p >= fMax) && (p < fEnd)) {
5969: /* Old hybrid faces stay the same */
5970: localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - fMax);
5971: remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]);
5972: remotePointsNew[m].rank = rrank;
5973: ++m;
5974: } else if ((p >= cStart) && (p < cMax)) {
5975: /* Old interior cells add new cells, interior faces, and vertex */
5976: for (r = 0; r < 4; ++r, ++m) {
5977: localPointsNew[m] = cStartNew + (p - cStart)*4 + r;
5978: remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
5979: remotePointsNew[m].rank = rrank;
5980: }
5981: for (r = 0; r < 4; ++r, ++m) {
5982: localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - cStart)*4 + r;
5983: remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*4 + r;
5984: remotePointsNew[m].rank = rrank;
5985: }
5986: localPointsNew[m] = vStartNew + (vEnd - vStart) + (fMax - fStart) + (p - cStart);
5987: remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n]) + (rp - rcStart[n]);
5988: remotePointsNew[m].rank = rrank;
5989: ++m;
5990: } else if ((p >= cStart) && (p < cMax)) {
5991: /* Old hybrid cells add new cells and hybrid face */
5992: for (r = 0; r < 2; ++r, ++m) {
5993: localPointsNew[m] = cStartNew + (p - cStart)*4 + r;
5994: remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
5995: remotePointsNew[m].rank = rrank;
5996: }
5997: localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (p - cMax);
5998: 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]);
5999: remotePointsNew[m].rank = rrank;
6000: ++m;
6001: }
6002: break;
6003: case REFINER_SIMPLEX_3D:
6004: case REFINER_HYBRID_SIMPLEX_3D:
6005: if ((p >= vStart) && (p < vEnd)) {
6006: /* Interior vertices stay the same */
6007: localPointsNew[m] = vStartNew + (p - vStart);
6008: remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
6009: remotePointsNew[m].rank = rrank;
6010: ++m;
6011: } else if ((p >= eStart) && (p < eMax)) {
6012: /* Interior edges add new edges and vertex */
6013: for (r = 0; r < 2; ++r, ++m) {
6014: localPointsNew[m] = eStartNew + (p - eStart)*2 + r;
6015: remotePointsNew[m].index = reStartNew[n] + (rp - reStart[n])*2 + r;
6016: remotePointsNew[m].rank = rrank;
6017: }
6018: localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - eStart);
6019: remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - reStart[n]);
6020: remotePointsNew[m].rank = rrank;
6021: ++m;
6022: } else if ((p >= eMax) && (p < eEnd)) {
6023: /* Hybrid edges stay the same */
6024: localPointsNew[m] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (p - eMax);
6025: 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]);
6026: remotePointsNew[m].rank = rrank;
6027: ++m;
6028: } else if ((p >= fStart) && (p < fMax)) {
6029: /* Interior faces add new faces and edges */
6030: for (r = 0; r < 4; ++r, ++m) {
6031: localPointsNew[m] = fStartNew + (p - fStart)*4 + r;
6032: remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*4 + r;
6033: remotePointsNew[m].rank = rrank;
6034: }
6035: for (r = 0; r < 3; ++r, ++m) {
6036: localPointsNew[m] = eStartNew + (eMax - eStart)*2 + (p - fStart)*3 + r;
6037: remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rp - rfStart[n])*3 + r;
6038: remotePointsNew[m].rank = rrank;
6039: }
6040: } else if ((p >= fMax) && (p < fEnd)) {
6041: /* Hybrid faces add new faces and edges */
6042: for (r = 0; r < 2; ++r, ++m) {
6043: localPointsNew[m] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (p - fMax)*2 + r;
6044: 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;
6045: remotePointsNew[m].rank = rrank;
6046: }
6047: localPointsNew[m] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (p - fMax);
6048: 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]);
6049: remotePointsNew[m].rank = rrank;
6050: ++m;
6051: } else if ((p >= cStart) && (p < cMax)) {
6052: /* Interior cells add new cells, faces, and edges */
6053: for (r = 0; r < 8; ++r, ++m) {
6054: localPointsNew[m] = cStartNew + (p - cStart)*8 + r;
6055: remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*8 + r;
6056: remotePointsNew[m].rank = rrank;
6057: }
6058: for (r = 0; r < 8; ++r, ++m) {
6059: localPointsNew[m] = fStartNew + (fMax - fStart)*4 + (p - cStart)*8 + r;
6060: remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rp - rcStart[n])*8 + r;
6061: remotePointsNew[m].rank = rrank;
6062: }
6063: localPointsNew[m] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (p - cStart)*1 + 0;
6064: 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;
6065: remotePointsNew[m].rank = rrank;
6066: ++m;
6067: } else if ((p >= cMax) && (p < cEnd)) {
6068: /* Hybrid cells add new cells and faces */
6069: for (r = 0; r < 4; ++r, ++m) {
6070: localPointsNew[m] = cStartNew + (cMax - cStart)*8 + (p - cMax)*4 + r;
6071: remotePointsNew[m].index = rcStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*8 + (rp - rdepthMaxOld[n*(depth+1)+depth])*4 + r;
6072: remotePointsNew[m].rank = rrank;
6073: }
6074: for (r = 0; r < 3; ++r, ++m) {
6075: localPointsNew[m] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (p - cMax)*3 + r;
6076: 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;
6077: remotePointsNew[m].rank = rrank;
6078: }
6079: }
6080: break;
6081: case REFINER_HEX_3D:
6082: case REFINER_HYBRID_HEX_3D:
6083: if ((p >= vStart) && (p < vEnd)) {
6084: /* Interior vertices stay the same */
6085: localPointsNew[m] = vStartNew + (p - vStart);
6086: remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
6087: remotePointsNew[m].rank = rrank;
6088: ++m;
6089: } else if ((p >= eStart) && (p < eMax)) {
6090: /* Interior edges add new edges and vertex */
6091: for (r = 0; r < 2; ++r, ++m) {
6092: localPointsNew[m] = eStartNew + (p - eStart)*2 + r;
6093: remotePointsNew[m].index = reStartNew[n] + (rp - reStart[n])*2 + r;
6094: remotePointsNew[m].rank = rrank;
6095: }
6096: localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - eStart);
6097: remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - reStart[n]);
6098: remotePointsNew[m].rank = rrank;
6099: ++m;
6100: } else if ((p >= eMax) && (p < eEnd)) {
6101: /* Hybrid edges stay the same */
6102: localPointsNew[m] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (p - eMax);
6103: 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]);
6104: remotePointsNew[m].rank = rrank;
6105: ++m;
6106: } else if ((p >= fStart) && (p < fMax)) {
6107: /* Interior faces add new faces, edges, and vertex */
6108: for (r = 0; r < 4; ++r, ++m) {
6109: localPointsNew[m] = fStartNew + (p - fStart)*4 + r;
6110: remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*4 + r;
6111: remotePointsNew[m].rank = rrank;
6112: }
6113: for (r = 0; r < 4; ++r, ++m) {
6114: localPointsNew[m] = eStartNew + (eMax - eStart)*2 + (p - fStart)*4 + r;
6115: remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rp - rfStart[n])*4 + r;
6116: remotePointsNew[m].rank = rrank;
6117: }
6118: localPointsNew[m] = vStartNew + (vEnd - vStart) + (eMax - eStart) + (p - fStart);
6119: remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n]) + (rp - rfStart[n]);
6120: remotePointsNew[m].rank = rrank;
6121: ++m;
6122: } else if ((p >= fMax) && (p < fEnd)) {
6123: /* Hybrid faces add new faces and edges */
6124: for (r = 0; r < 2; ++r, ++m) {
6125: localPointsNew[m] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (p - fMax)*2 + r;
6126: 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;
6127: remotePointsNew[m].rank = rrank;
6128: }
6129: localPointsNew[m] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (p - fMax);
6130: 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]);
6131: remotePointsNew[m].rank = rrank;
6132: ++m;
6133: } else if ((p >= cStart) && (p < cMax)) {
6134: /* Interior cells add new cells, faces, edges, and vertex */
6135: for (r = 0; r < 8; ++r, ++m) {
6136: localPointsNew[m] = cStartNew + (p - cStart)*8 + r;
6137: remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*8 + r;
6138: remotePointsNew[m].rank = rrank;
6139: }
6140: for (r = 0; r < 12; ++r, ++m) {
6141: localPointsNew[m] = fStartNew + (fMax - fStart)*4 + (p - cStart)*12 + r;
6142: remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rp - rcStart[n])*12 + r;
6143: remotePointsNew[m].rank = rrank;
6144: }
6145: for (r = 0; r < 6; ++r, ++m) {
6146: localPointsNew[m] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (p - cStart)*6 + r;
6147: 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;
6148: remotePointsNew[m].rank = rrank;
6149: }
6150: for (r = 0; r < 1; ++r, ++m) {
6151: localPointsNew[m] = vStartNew + (eMax - eStart) + (fMax - fStart) + (p - cStart) + r;
6152: remotePointsNew[m].index = rvStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n]) + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n]) + (rp - rcStart[n]) + r;
6153: remotePointsNew[m].rank = rrank;
6154: }
6155: } else if ((p >= cMax) && (p < cEnd)) {
6156: /* Hybrid cells add new cells, faces, and edges */
6157: for (r = 0; r < 4; ++r, ++m) {
6158: localPointsNew[m] = cStartNew + (cMax - cStart)*8 + (p - cMax)*4 + r;
6159: remotePointsNew[m].index = rcStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*8 + (rp - rdepthMaxOld[n*(depth+1)+depth])*4 + r;
6160: remotePointsNew[m].rank = rrank;
6161: }
6162: for (r = 0; r < 4; ++r, ++m) {
6163: localPointsNew[m] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (p - cMax)*4 + r;
6164: 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;
6165: remotePointsNew[m].rank = rrank;
6166: }
6167: localPointsNew[m] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (fEnd - fMax) + (p - cMax);
6168: 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]);
6169: remotePointsNew[m].rank = rrank;
6170: ++m;
6171: }
6172: break;
6173: default:
6174: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
6175: }
6176: }
6177: if (m != numLeavesNew) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of leaf point %d should be %d", m, numLeavesNew);
6178: ISRestoreIndices(processRanks, &neighbors);
6179: ISDestroy(&processRanks);
6180: {
6181: PetscSFNode *rp, *rtmp;
6182: PetscInt *lp, *idx, *ltmp, i;
6184: /* SF needs sorted leaves to correct calculate Gather */
6185: PetscMalloc1(numLeavesNew,&idx);
6186: PetscMalloc1(numLeavesNew, &lp);
6187: PetscMalloc1(numLeavesNew, &rp);
6188: for (i = 0; i < numLeavesNew; ++i) {
6189: 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);
6190: idx[i] = i;
6191: }
6192: PetscSortIntWithPermutation(numLeavesNew, localPointsNew, idx);
6193: for (i = 0; i < numLeavesNew; ++i) {
6194: lp[i] = localPointsNew[idx[i]];
6195: rp[i] = remotePointsNew[idx[i]];
6196: }
6197: ltmp = localPointsNew;
6198: localPointsNew = lp;
6199: rtmp = remotePointsNew;
6200: remotePointsNew = rp;
6201: PetscFree(idx);
6202: PetscFree(ltmp);
6203: PetscFree(rtmp);
6204: }
6205: PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);
6206: PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);
6207: PetscFree7(depthSizeOld,rdepthSizeOld,rdepthMaxOld,rvStart,reStart,rfStart,rcStart);
6208: return(0);
6209: }
6213: static PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
6214: {
6215: PetscInt numLabels, l;
6216: PetscInt depth, newp, cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax, r;
6217: PetscInt cStartNew = 0, vStartNew = 0, fStartNew = 0, eStartNew = 0;
6221: DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
6222: DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);
6223: DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
6224: DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);
6225: DMPlexGetDepth(dm, &depth);
6226: if (refiner) {GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);}
6227: DMGetNumLabels(dm, &numLabels);
6228: DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);
6229: switch (refiner) {
6230: case REFINER_NOOP:
6231: case REFINER_SIMPLEX_1D:
6232: case REFINER_SIMPLEX_2D:
6233: case REFINER_HEX_2D:
6234: case REFINER_SIMPLEX_3D:
6235: case REFINER_HEX_3D:
6236: break;
6237: case REFINER_HYBRID_SIMPLEX_3D:
6238: case REFINER_HYBRID_HEX_3D:
6239: if (eMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No edge maximum specified in hybrid mesh");
6240: case REFINER_HYBRID_SIMPLEX_2D:
6241: case REFINER_HYBRID_HEX_2D:
6242: if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
6243: if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
6244: break;
6245: default:
6246: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
6247: }
6248: for (l = 0; l < numLabels; ++l) {
6249: DMLabel label, labelNew;
6250: const char *lname;
6251: PetscBool isDepth;
6252: IS valueIS;
6253: const PetscInt *values;
6254: PetscInt defVal;
6255: PetscInt numValues, val;
6257: DMGetLabelName(dm, l, &lname);
6258: PetscStrcmp(lname, "depth", &isDepth);
6259: if (isDepth) continue;
6260: DMCreateLabel(rdm, lname);
6261: DMGetLabel(dm, lname, &label);
6262: DMGetLabel(rdm, lname, &labelNew);
6263: DMLabelGetDefaultValue(label,&defVal);
6264: DMLabelSetDefaultValue(labelNew,defVal);
6265: DMLabelGetValueIS(label, &valueIS);
6266: ISGetLocalSize(valueIS, &numValues);
6267: ISGetIndices(valueIS, &values);
6268: for (val = 0; val < numValues; ++val) {
6269: IS pointIS;
6270: const PetscInt *points;
6271: PetscInt numPoints, n;
6273: DMLabelGetStratumIS(label, values[val], &pointIS);
6274: ISGetLocalSize(pointIS, &numPoints);
6275: ISGetIndices(pointIS, &points);
6276: /* Ensure refined label is created with same number of strata as
6277: * original (even if no entries here). */
6278: if (!numPoints) {
6279: DMLabelSetValue(labelNew, 0, values[val]);
6280: DMLabelClearValue(labelNew, 0, values[val]);
6281: }
6282: for (n = 0; n < numPoints; ++n) {
6283: const PetscInt p = points[n];
6284: switch (refiner) {
6285: case REFINER_SIMPLEX_1D:
6286: if ((p >= vStart) && (p < vEnd)) {
6287: /* Old vertices stay the same */
6288: newp = vStartNew + (p - vStart);
6289: DMLabelSetValue(labelNew, newp, values[val]);
6290: } else if ((p >= cStart) && (p < cEnd)) {
6291: /* Old cells add new cells and vertex */
6292: newp = vStartNew + (vEnd - vStart) + (p - cStart);
6293: DMLabelSetValue(labelNew, newp, values[val]);
6294: for (r = 0; r < 2; ++r) {
6295: newp = cStartNew + (p - cStart)*2 + r;
6296: DMLabelSetValue(labelNew, newp, values[val]);
6297: }
6298: }
6299: break;
6300: case REFINER_SIMPLEX_2D:
6301: if ((p >= vStart) && (p < vEnd)) {
6302: /* Old vertices stay the same */
6303: newp = vStartNew + (p - vStart);
6304: DMLabelSetValue(labelNew, newp, values[val]);
6305: } else if ((p >= fStart) && (p < fEnd)) {
6306: /* Old faces add new faces and vertex */
6307: newp = vStartNew + (vEnd - vStart) + (p - fStart);
6308: DMLabelSetValue(labelNew, newp, values[val]);
6309: for (r = 0; r < 2; ++r) {
6310: newp = fStartNew + (p - fStart)*2 + r;
6311: DMLabelSetValue(labelNew, newp, values[val]);
6312: }
6313: } else if ((p >= cStart) && (p < cEnd)) {
6314: /* Old cells add new cells and interior faces */
6315: for (r = 0; r < 4; ++r) {
6316: newp = cStartNew + (p - cStart)*4 + r;
6317: DMLabelSetValue(labelNew, newp, values[val]);
6318: }
6319: for (r = 0; r < 3; ++r) {
6320: newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r;
6321: DMLabelSetValue(labelNew, newp, values[val]);
6322: }
6323: }
6324: break;
6325: case REFINER_HEX_2D:
6326: if ((p >= vStart) && (p < vEnd)) {
6327: /* Old vertices stay the same */
6328: newp = vStartNew + (p - vStart);
6329: DMLabelSetValue(labelNew, newp, values[val]);
6330: } else if ((p >= fStart) && (p < fEnd)) {
6331: /* Old faces add new faces and vertex */
6332: newp = vStartNew + (vEnd - vStart) + (p - fStart);
6333: DMLabelSetValue(labelNew, newp, values[val]);
6334: for (r = 0; r < 2; ++r) {
6335: newp = fStartNew + (p - fStart)*2 + r;
6336: DMLabelSetValue(labelNew, newp, values[val]);
6337: }
6338: } else if ((p >= cStart) && (p < cEnd)) {
6339: /* Old cells add new cells and interior faces and vertex */
6340: for (r = 0; r < 4; ++r) {
6341: newp = cStartNew + (p - cStart)*4 + r;
6342: DMLabelSetValue(labelNew, newp, values[val]);
6343: }
6344: for (r = 0; r < 4; ++r) {
6345: newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r;
6346: DMLabelSetValue(labelNew, newp, values[val]);
6347: }
6348: newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart);
6349: DMLabelSetValue(labelNew, newp, values[val]);
6350: }
6351: break;
6352: case REFINER_HYBRID_SIMPLEX_2D:
6353: if ((p >= vStart) && (p < vEnd)) {
6354: /* Old vertices stay the same */
6355: newp = vStartNew + (p - vStart);
6356: DMLabelSetValue(labelNew, newp, values[val]);
6357: } else if ((p >= fStart) && (p < fMax)) {
6358: /* Old interior faces add new faces and vertex */
6359: newp = vStartNew + (vEnd - vStart) + (p - fStart);
6360: DMLabelSetValue(labelNew, newp, values[val]);
6361: for (r = 0; r < 2; ++r) {
6362: newp = fStartNew + (p - fStart)*2 + r;
6363: DMLabelSetValue(labelNew, newp, values[val]);
6364: }
6365: } else if ((p >= fMax) && (p < fEnd)) {
6366: /* Old hybrid faces stay the same */
6367: newp = fStartNew + (fMax - fStart)*2 + (p - fMax);
6368: DMLabelSetValue(labelNew, newp, values[val]);
6369: } else if ((p >= cStart) && (p < cMax)) {
6370: /* Old interior cells add new cells and interior faces */
6371: for (r = 0; r < 4; ++r) {
6372: newp = cStartNew + (p - cStart)*4 + r;
6373: DMLabelSetValue(labelNew, newp, values[val]);
6374: }
6375: for (r = 0; r < 3; ++r) {
6376: newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r;
6377: DMLabelSetValue(labelNew, newp, values[val]);
6378: }
6379: } else if ((p >= cMax) && (p < cEnd)) {
6380: /* Old hybrid cells add new cells and hybrid face */
6381: for (r = 0; r < 2; ++r) {
6382: newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r;
6383: DMLabelSetValue(labelNew, newp, values[val]);
6384: }
6385: newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax);
6386: DMLabelSetValue(labelNew, newp, values[val]);
6387: }
6388: break;
6389: case REFINER_HYBRID_HEX_2D:
6390: if ((p >= vStart) && (p < vEnd)) {
6391: /* Old vertices stay the same */
6392: newp = vStartNew + (p - vStart);
6393: DMLabelSetValue(labelNew, newp, values[val]);
6394: } else if ((p >= fStart) && (p < fMax)) {
6395: /* Old interior faces add new faces and vertex */
6396: newp = vStartNew + (vEnd - vStart) + (p - fStart);
6397: DMLabelSetValue(labelNew, newp, values[val]);
6398: for (r = 0; r < 2; ++r) {
6399: newp = fStartNew + (p - fStart)*2 + r;
6400: DMLabelSetValue(labelNew, newp, values[val]);
6401: }
6402: } else if ((p >= fMax) && (p < fEnd)) {
6403: /* Old hybrid faces stay the same */
6404: newp = fStartNew + (fMax - fStart)*2 + (p - fMax);
6405: DMLabelSetValue(labelNew, newp, values[val]);
6406: } else if ((p >= cStart) && (p < cMax)) {
6407: /* Old interior cells add new cells, interior faces, and vertex */
6408: for (r = 0; r < 4; ++r) {
6409: newp = cStartNew + (p - cStart)*4 + r;
6410: DMLabelSetValue(labelNew, newp, values[val]);
6411: }
6412: for (r = 0; r < 4; ++r) {
6413: newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r;
6414: DMLabelSetValue(labelNew, newp, values[val]);
6415: }
6416: newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart);
6417: DMLabelSetValue(labelNew, newp, values[val]);
6418: } else if ((p >= cMax) && (p < cEnd)) {
6419: /* Old hybrid cells add new cells and hybrid face */
6420: for (r = 0; r < 2; ++r) {
6421: newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r;
6422: DMLabelSetValue(labelNew, newp, values[val]);
6423: }
6424: newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (p - cMax);
6425: DMLabelSetValue(labelNew, newp, values[val]);
6426: }
6427: break;
6428: case REFINER_SIMPLEX_3D:
6429: if ((p >= vStart) && (p < vEnd)) {
6430: /* Old vertices stay the same */
6431: newp = vStartNew + (p - vStart);
6432: DMLabelSetValue(labelNew, newp, values[val]);
6433: } else if ((p >= eStart) && (p < eEnd)) {
6434: /* Old edges add new edges and vertex */
6435: for (r = 0; r < 2; ++r) {
6436: newp = eStartNew + (p - eStart)*2 + r;
6437: DMLabelSetValue(labelNew, newp, values[val]);
6438: }
6439: newp = vStartNew + (vEnd - vStart) + (p - eStart);
6440: DMLabelSetValue(labelNew, newp, values[val]);
6441: } else if ((p >= fStart) && (p < fEnd)) {
6442: /* Old faces add new faces and edges */
6443: for (r = 0; r < 4; ++r) {
6444: newp = fStartNew + (p - fStart)*4 + r;
6445: DMLabelSetValue(labelNew, newp, values[val]);
6446: }
6447: for (r = 0; r < 3; ++r) {
6448: newp = eStartNew + (eEnd - eStart)*2 + (p - fStart)*3 + r;
6449: DMLabelSetValue(labelNew, newp, values[val]);
6450: }
6451: } else if ((p >= cStart) && (p < cEnd)) {
6452: /* Old cells add new cells and interior faces and edges */
6453: for (r = 0; r < 8; ++r) {
6454: newp = cStartNew + (p - cStart)*8 + r;
6455: DMLabelSetValue(labelNew, newp, values[val]);
6456: }
6457: for (r = 0; r < 8; ++r) {
6458: newp = fStartNew + (fEnd - fStart)*4 + (p - cStart)*8 + r;
6459: DMLabelSetValue(labelNew, newp, values[val]);
6460: }
6461: for (r = 0; r < 1; ++r) {
6462: newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (p - cStart)*1 + r;
6463: DMLabelSetValue(labelNew, newp, values[val]);
6464: }
6465: }
6466: break;
6467: case REFINER_HYBRID_SIMPLEX_3D:
6468: if ((p >= vStart) && (p < vEnd)) {
6469: /* Interior vertices stay the same */
6470: newp = vStartNew + (p - vStart);
6471: DMLabelSetValue(labelNew, newp, values[val]);
6472: } else if ((p >= eStart) && (p < eMax)) {
6473: /* Interior edges add new edges and vertex */
6474: for (r = 0; r < 2; ++r) {
6475: newp = eStartNew + (p - eStart)*2 + r;
6476: DMLabelSetValue(labelNew, newp, values[val]);
6477: }
6478: newp = vStartNew + (vEnd - vStart) + (p - eStart);
6479: DMLabelSetValue(labelNew, newp, values[val]);
6480: } else if ((p >= eMax) && (p < eEnd)) {
6481: /* Hybrid edges stay the same */
6482: newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (p - eMax);
6483: DMLabelSetValue(labelNew, newp, values[val]);
6484: } else if ((p >= fStart) && (p < fMax)) {
6485: /* Interior faces add new faces and edges */
6486: for (r = 0; r < 4; ++r) {
6487: newp = fStartNew + (p - fStart)*4 + r;
6488: DMLabelSetValue(labelNew, newp, values[val]);
6489: }
6490: for (r = 0; r < 3; ++r) {
6491: newp = eStartNew + (eMax - eStart)*2 + (p - fStart)*3 + r;
6492: DMLabelSetValue(labelNew, newp, values[val]);
6493: }
6494: } else if ((p >= fMax) && (p < fEnd)) {
6495: /* Hybrid faces add new faces and edges */
6496: for (r = 0; r < 2; ++r) {
6497: newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (p - fMax)*2 + r;
6498: DMLabelSetValue(labelNew, newp, values[val]);
6499: }
6500: newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (p - fMax);
6501: DMLabelSetValue(labelNew, newp, values[val]);
6502: } else if ((p >= cStart) && (p < cMax)) {
6503: /* Interior cells add new cells, faces, and edges */
6504: for (r = 0; r < 8; ++r) {
6505: newp = cStartNew + (p - cStart)*8 + r;
6506: DMLabelSetValue(labelNew, newp, values[val]);
6507: }
6508: for (r = 0; r < 8; ++r) {
6509: newp = fStartNew + (fMax - fStart)*4 + (p - cStart)*8 + r;
6510: DMLabelSetValue(labelNew, newp, values[val]);
6511: }
6512: newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (p - cStart);
6513: DMLabelSetValue(labelNew, newp, values[val]);
6514: } else if ((p >= cMax) && (p < cEnd)) {
6515: /* Hybrid cells add new cells and faces */
6516: for (r = 0; r < 4; ++r) {
6517: newp = cStartNew + (cMax - cStart)*8 + (p - cMax)*4 + r;
6518: DMLabelSetValue(labelNew, newp, values[val]);
6519: }
6520: for (r = 0; r < 3; ++r) {
6521: newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (p - cMax)*3 + r;
6522: DMLabelSetValue(labelNew, newp, values[val]);
6523: }
6524: }
6525: break;
6526: case REFINER_HEX_3D:
6527: if ((p >= vStart) && (p < vEnd)) {
6528: /* Old vertices stay the same */
6529: newp = vStartNew + (p - vStart);
6530: DMLabelSetValue(labelNew, newp, values[val]);
6531: } else if ((p >= eStart) && (p < eEnd)) {
6532: /* Old edges add new edges and vertex */
6533: for (r = 0; r < 2; ++r) {
6534: newp = eStartNew + (p - eStart)*2 + r;
6535: DMLabelSetValue(labelNew, newp, values[val]);
6536: }
6537: newp = vStartNew + (vEnd - vStart) + (p - eStart);
6538: DMLabelSetValue(labelNew, newp, values[val]);
6539: } else if ((p >= fStart) && (p < fEnd)) {
6540: /* Old faces add new faces, edges, and vertex */
6541: for (r = 0; r < 4; ++r) {
6542: newp = fStartNew + (p - fStart)*4 + r;
6543: DMLabelSetValue(labelNew, newp, values[val]);
6544: }
6545: for (r = 0; r < 4; ++r) {
6546: newp = eStartNew + (eEnd - eStart)*2 + (p - fStart)*4 + r;
6547: DMLabelSetValue(labelNew, newp, values[val]);
6548: }
6549: newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (p - fStart);
6550: DMLabelSetValue(labelNew, newp, values[val]);
6551: } else if ((p >= cStart) && (p < cEnd)) {
6552: /* Old cells add new cells, faces, edges, and vertex */
6553: for (r = 0; r < 8; ++r) {
6554: newp = cStartNew + (p - cStart)*8 + r;
6555: DMLabelSetValue(labelNew, newp, values[val]);
6556: }
6557: for (r = 0; r < 12; ++r) {
6558: newp = fStartNew + (fEnd - fStart)*4 + (p - cStart)*12 + r;
6559: DMLabelSetValue(labelNew, newp, values[val]);
6560: }
6561: for (r = 0; r < 6; ++r) {
6562: newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (p - cStart)*6 + r;
6563: DMLabelSetValue(labelNew, newp, values[val]);
6564: }
6565: newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (p - cStart);
6566: DMLabelSetValue(labelNew, newp, values[val]);
6567: }
6568: break;
6569: case REFINER_HYBRID_HEX_3D:
6570: if ((p >= vStart) && (p < vEnd)) {
6571: /* Interior vertices stay the same */
6572: newp = vStartNew + (p - vStart);
6573: DMLabelSetValue(labelNew, newp, values[val]);
6574: } else if ((p >= eStart) && (p < eMax)) {
6575: /* Interior edges add new edges and vertex */
6576: for (r = 0; r < 2; ++r) {
6577: newp = eStartNew + (p - eStart)*2 + r;
6578: DMLabelSetValue(labelNew, newp, values[val]);
6579: }
6580: newp = vStartNew + (vEnd - vStart) + (p - eStart);
6581: DMLabelSetValue(labelNew, newp, values[val]);
6582: } else if ((p >= eMax) && (p < eEnd)) {
6583: /* Hybrid edges stay the same */
6584: newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (p - eMax);
6585: DMLabelSetValue(labelNew, newp, values[val]);
6586: } else if ((p >= fStart) && (p < fMax)) {
6587: /* Interior faces add new faces, edges, and vertex */
6588: for (r = 0; r < 4; ++r) {
6589: newp = fStartNew + (p - fStart)*4 + r;
6590: DMLabelSetValue(labelNew, newp, values[val]);
6591: }
6592: for (r = 0; r < 4; ++r) {
6593: newp = eStartNew + (eMax - eStart)*2 + (p - fStart)*4 + r;
6594: DMLabelSetValue(labelNew, newp, values[val]);
6595: }
6596: newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (p - fStart);
6597: DMLabelSetValue(labelNew, newp, values[val]);
6598: } else if ((p >= fMax) && (p < fEnd)) {
6599: /* Hybrid faces add new faces and edges */
6600: for (r = 0; r < 2; ++r) {
6601: newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (p - fMax)*2 + r;
6602: DMLabelSetValue(labelNew, newp, values[val]);
6603: }
6604: newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (p - fMax);
6605: DMLabelSetValue(labelNew, newp, values[val]);
6606: } else if ((p >= cStart) && (p < cMax)) {
6607: /* Interior cells add new cells, faces, edges, and vertex */
6608: for (r = 0; r < 8; ++r) {
6609: newp = cStartNew + (p - cStart)*8 + r;
6610: DMLabelSetValue(labelNew, newp, values[val]);
6611: }
6612: for (r = 0; r < 12; ++r) {
6613: newp = fStartNew + (fMax - fStart)*4 + (p - cStart)*12 + r;
6614: DMLabelSetValue(labelNew, newp, values[val]);
6615: }
6616: for (r = 0; r < 6; ++r) {
6617: newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (p - cStart)*6 + r;
6618: DMLabelSetValue(labelNew, newp, values[val]);
6619: }
6620: newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (fMax - fStart) + (p - cStart);
6621: DMLabelSetValue(labelNew, newp, values[val]);
6622: } else if ((p >= cMax) && (p < cEnd)) {
6623: /* Hybrid cells add new cells, faces, and edges */
6624: for (r = 0; r < 4; ++r) {
6625: newp = cStartNew + (cMax - cStart)*8 + (p - cMax)*4 + r;
6626: DMLabelSetValue(labelNew, newp, values[val]);
6627: }
6628: for (r = 0; r < 4; ++r) {
6629: newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (p - cMax)*4 + r;
6630: DMLabelSetValue(labelNew, newp, values[val]);
6631: }
6632: newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (fEnd - fMax) + (p - cMax);
6633: DMLabelSetValue(labelNew, newp, values[val]);
6634: }
6635: break;
6636: default:
6637: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
6638: }
6639: }
6640: ISRestoreIndices(pointIS, &points);
6641: ISDestroy(&pointIS);
6642: }
6643: ISRestoreIndices(valueIS, &values);
6644: ISDestroy(&valueIS);
6645: if (0) {
6646: DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);
6647: }
6648: }
6649: return(0);
6650: }
6654: /* This will only work for interpolated meshes */
6655: PetscErrorCode DMPlexRefineUniform_Internal(DM dm, CellRefiner cellRefiner, DM *dmRefined)
6656: {
6657: DM rdm;
6658: PetscInt *depthSize;
6659: PetscInt dim, depth = 0, d, pStart = 0, pEnd = 0;
6663: DMCreate(PetscObjectComm((PetscObject)dm), &rdm);
6664: DMSetType(rdm, DMPLEX);
6665: DMGetDimension(dm, &dim);
6666: DMSetDimension(rdm, dim);
6667: /* Calculate number of new points of each depth */
6668: DMPlexGetDepth(dm, &depth);
6669: if (depth >= 0 && dim != depth) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Mesh must be interpolated for regular refinement");
6670: PetscMalloc1(depth+1, &depthSize);
6671: PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));
6672: CellRefinerGetSizes(cellRefiner, dm, depthSize);
6673: /* Step 1: Set chart */
6674: for (d = 0; d <= depth; ++d) pEnd += depthSize[d];
6675: DMPlexSetChart(rdm, pStart, pEnd);
6676: /* Step 2: Set cone/support sizes */
6677: CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);
6678: /* Step 3: Setup refined DM */
6679: DMSetUp(rdm);
6680: /* Step 4: Set cones and supports */
6681: CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);
6682: /* Step 5: Stratify */
6683: DMPlexStratify(rdm);
6684: /* Step 6: Create pointSF */
6685: CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);
6686: /* Step 7: Set coordinates for vertices */
6687: CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);
6688: /* Step 8: Create labels */
6689: CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);
6690: PetscFree(depthSize);
6692: *dmRefined = rdm;
6693: return(0);
6694: }
6698: /*@
6699: DMPlexCreateCoarsePointIS - Creates an IS covering the coarse DM chart with the fine points as data
6701: Input Parameter:
6702: . dm - The coarse DM
6704: Output Parameter:
6705: . fpointIS - The IS of all the fine points which exist in the original coarse mesh
6707: Level: developer
6709: .seealso: DMRefine(), DMPlexSetRefinementUniform(), DMPlexCreateSubpointIS()
6710: @*/
6711: PetscErrorCode DMPlexCreateCoarsePointIS(DM dm, IS *fpointIS)
6712: {
6713: CellRefiner cellRefiner;
6714: PetscInt *depthSize, *fpoints;
6715: PetscInt cStartNew = 0, vStartNew = 0, fStartNew = 0, eStartNew = 0;
6716: PetscInt depth, pStart, pEnd, p, vStart, vEnd, v;
6720: DMPlexGetDepth(dm, &depth);
6721: DMPlexGetChart(dm, &pStart, &pEnd);
6722: DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
6723: DMPlexGetCellRefiner_Internal(dm, &cellRefiner);
6724: PetscMalloc1(depth+1, &depthSize);
6725: CellRefinerGetSizes(cellRefiner, dm, depthSize);
6726: if (cellRefiner) {GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);}
6727: PetscMalloc1(pEnd-pStart,&fpoints);
6728: for (p = 0; p < pEnd-pStart; ++p) fpoints[p] = -1;
6729: switch (cellRefiner) {
6730: case REFINER_SIMPLEX_1D:
6731: case REFINER_SIMPLEX_2D:
6732: case REFINER_HYBRID_SIMPLEX_2D:
6733: case REFINER_HEX_2D:
6734: case REFINER_HYBRID_HEX_2D:
6735: case REFINER_SIMPLEX_3D:
6736: case REFINER_HYBRID_SIMPLEX_3D:
6737: case REFINER_HEX_3D:
6738: case REFINER_HYBRID_HEX_3D:
6739: for (v = vStart; v < vEnd; ++v) fpoints[v-pStart] = vStartNew + (v - vStart);
6740: break;
6741: default:
6742: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", cellRefiner);
6743: }
6744: ISCreateGeneral(PETSC_COMM_SELF, pEnd-pStart, fpoints, PETSC_OWN_POINTER, fpointIS);
6745: PetscFree(depthSize);
6746: return(0);
6747: }
6751: /*@
6752: DMPlexSetRefinementUniform - Set the flag for uniform refinement
6754: Input Parameters:
6755: + dm - The DM
6756: - refinementUniform - The flag for uniform refinement
6758: Level: developer
6760: .seealso: DMRefine(), DMPlexGetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
6761: @*/
6762: PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform)
6763: {
6764: DM_Plex *mesh = (DM_Plex*) dm->data;
6768: mesh->refinementUniform = refinementUniform;
6769: return(0);
6770: }
6774: /*@
6775: DMPlexGetRefinementUniform - Retrieve the flag for uniform refinement
6777: Input Parameter:
6778: . dm - The DM
6780: Output Parameter:
6781: . refinementUniform - The flag for uniform refinement
6783: Level: developer
6785: .seealso: DMRefine(), DMPlexSetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
6786: @*/
6787: PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform)
6788: {
6789: DM_Plex *mesh = (DM_Plex*) dm->data;
6794: *refinementUniform = mesh->refinementUniform;
6795: return(0);
6796: }
6800: /*@
6801: DMPlexSetRefinementLimit - Set the maximum cell volume for refinement
6803: Input Parameters:
6804: + dm - The DM
6805: - refinementLimit - The maximum cell volume in the refined mesh
6807: Level: developer
6809: .seealso: DMRefine(), DMPlexGetRefinementLimit(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform()
6810: @*/
6811: PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit)
6812: {
6813: DM_Plex *mesh = (DM_Plex*) dm->data;
6817: mesh->refinementLimit = refinementLimit;
6818: return(0);
6819: }
6823: /*@
6824: DMPlexGetRefinementLimit - Retrieve the maximum cell volume for refinement
6826: Input Parameter:
6827: . dm - The DM
6829: Output Parameter:
6830: . refinementLimit - The maximum cell volume in the refined mesh
6832: Level: developer
6834: .seealso: DMRefine(), DMPlexSetRefinementLimit(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform()
6835: @*/
6836: PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit)
6837: {
6838: DM_Plex *mesh = (DM_Plex*) dm->data;
6843: /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */
6844: *refinementLimit = mesh->refinementLimit;
6845: return(0);
6846: }
6850: /*@
6851: DMPlexSetRefinementFunction - Set the function giving the maximum cell volume for refinement
6853: Input Parameters:
6854: + dm - The DM
6855: - refinementFunc - Function giving the maximum cell volume in the refined mesh
6857: Note: The calling sequence is refinementFunc(coords, limit)
6858: $ coords - Coordinates of the current point, usually a cell centroid
6859: $ limit - The maximum cell volume for a cell containing this point
6861: Level: developer
6863: .seealso: DMRefine(), DMPlexGetRefinementFunction(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
6864: @*/
6865: PetscErrorCode DMPlexSetRefinementFunction(DM dm, PetscErrorCode (*refinementFunc)(const PetscReal [], PetscReal *))
6866: {
6867: DM_Plex *mesh = (DM_Plex*) dm->data;
6871: mesh->refinementFunc = refinementFunc;
6872: return(0);
6873: }
6877: /*@
6878: DMPlexGetRefinementFunction - Get the function giving the maximum cell volume for refinement
6880: Input Parameter:
6881: . dm - The DM
6883: Output Parameter:
6884: . refinementFunc - Function giving the maximum cell volume in the refined mesh
6886: Note: The calling sequence is refinementFunc(coords, limit)
6887: $ coords - Coordinates of the current point, usually a cell centroid
6888: $ limit - The maximum cell volume for a cell containing this point
6890: Level: developer
6892: .seealso: DMRefine(), DMPlexSetRefinementFunction(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
6893: @*/
6894: PetscErrorCode DMPlexGetRefinementFunction(DM dm, PetscErrorCode (**refinementFunc)(const PetscReal [], PetscReal *))
6895: {
6896: DM_Plex *mesh = (DM_Plex*) dm->data;
6901: *refinementFunc = mesh->refinementFunc;
6902: return(0);
6903: }
6907: PetscErrorCode DMPlexGetCellRefiner_Internal(DM dm, CellRefiner *cellRefiner)
6908: {
6909: PetscInt dim, cStart, cEnd, coneSize, cMax, fMax;
6913: DMGetDimension(dm, &dim);
6914: DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
6915: if (cEnd <= cStart) {*cellRefiner = REFINER_NOOP; return(0);}
6916: DMPlexGetConeSize(dm, cStart, &coneSize);
6917: DMPlexGetHybridBounds(dm, &cMax, &fMax, NULL, NULL);
6918: switch (dim) {
6919: case 1:
6920: switch (coneSize) {
6921: case 2:
6922: *cellRefiner = REFINER_SIMPLEX_1D;
6923: break;
6924: default:
6925: SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim);
6926: }
6927: break;
6928: case 2:
6929: switch (coneSize) {
6930: case 3:
6931: if (cMax >= 0) *cellRefiner = REFINER_HYBRID_SIMPLEX_2D;
6932: else *cellRefiner = REFINER_SIMPLEX_2D;
6933: break;
6934: case 4:
6935: if (cMax >= 0 && fMax >= 0) *cellRefiner = REFINER_HYBRID_HEX_2D;
6936: else *cellRefiner = REFINER_HEX_2D;
6937: break;
6938: default:
6939: SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim);
6940: }
6941: break;
6942: case 3:
6943: switch (coneSize) {
6944: case 4:
6945: if (cMax >= 0) *cellRefiner = REFINER_HYBRID_SIMPLEX_3D;
6946: else *cellRefiner = REFINER_SIMPLEX_3D;
6947: break;
6948: case 6:
6949: if (cMax >= 0) *cellRefiner = REFINER_HYBRID_HEX_3D;
6950: else *cellRefiner = REFINER_HEX_3D;
6951: break;
6952: default:
6953: SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim);
6954: }
6955: break;
6956: default:
6957: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim);
6958: }
6959: return(0);
6960: }