Actual source code: plexrefine.c
petsc-3.7.7 2017-09-25
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;
5493: VecType vtype;
5497: DMGetDimension(dm, &dim);
5498: DMPlexGetDepth(dm, &depth);
5499: DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
5500: DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);
5501: DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
5502: DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);
5503: DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, NULL);
5504: if (refiner) {GetDepthStart_Private(depth, depthSize, NULL, NULL, NULL, &vStartNew);}
5505: GetDepthStart_Private(depth, depthSize, NULL, NULL, NULL, &vStartNew);
5506: DMGetCoordinateSection(dm, &coordSection);
5507: PetscSectionGetFieldComponents(coordSection, 0, &spaceDim);
5508: PetscSectionCreate(PetscObjectComm((PetscObject)dm), &coordSectionNew);
5509: PetscSectionSetNumFields(coordSectionNew, 1);
5510: PetscSectionSetFieldComponents(coordSectionNew, 0, spaceDim);
5511: PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+numVertices);
5512: if (cMax < 0) cMax = cEnd;
5513: if (fMax < 0) fMax = fEnd;
5514: if (eMax < 0) eMax = eEnd;
5515: /* All vertices have the spaceDim coordinates */
5516: for (v = vStartNew; v < vStartNew+numVertices; ++v) {
5517: PetscSectionSetDof(coordSectionNew, v, spaceDim);
5518: PetscSectionSetFieldDof(coordSectionNew, v, 0, spaceDim);
5519: }
5520: PetscSectionSetUp(coordSectionNew);
5521: DMSetCoordinateSection(rdm, PETSC_DETERMINE, coordSectionNew);
5522: DMGetCoordinatesLocal(dm, &coordinates);
5523: PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);
5524: VecCreate(PETSC_COMM_SELF, &coordinatesNew);
5525: PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");
5526: VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);
5527: VecGetBlockSize(coordinates, &bs);
5528: VecSetBlockSize(coordinatesNew, bs);
5529: VecGetType(coordinates, &vtype);
5530: VecSetType(coordinatesNew, vtype);
5531: VecGetArray(coordinates, &coords);
5532: VecGetArray(coordinatesNew, &coordsNew);
5533: switch (refiner) {
5534: case REFINER_NOOP: break;
5535: case REFINER_HEX_3D:
5536: case REFINER_HYBRID_HEX_3D:
5537: /* Face vertices have the average of corner coordinates */
5538: for (f = fStart; f < fMax; ++f) {
5539: const PetscInt newv = vStartNew + (vEnd - vStart) + (eMax - eStart) + (f - fStart);
5540: PetscInt *cone = NULL;
5541: PetscInt closureSize, coneSize = 0, off[8], offnew, p, d;
5543: DMPlexGetTransitiveClosure(dm, f, PETSC_TRUE, &closureSize, &cone);
5544: for (p = 0; p < closureSize*2; p += 2) {
5545: const PetscInt point = cone[p];
5546: if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point;
5547: }
5548: for (v = 0; v < coneSize; ++v) {
5549: PetscSectionGetOffset(coordSection, cone[v], &off[v]);
5550: }
5551: PetscSectionGetOffset(coordSectionNew, newv, &offnew);
5552: for (d = 0; d < spaceDim; ++d) coordsNew[offnew+d] = 0.0;
5553: for (v = 0; v < coneSize; ++v) {DMLocalizeAddCoordinate_Internal(dm, spaceDim, &coords[off[0]], &coords[off[v]], &coordsNew[offnew]);}
5554: for (d = 0; d < spaceDim; ++d) coordsNew[offnew+d] /= coneSize;
5555: DMPlexRestoreTransitiveClosure(dm, f, PETSC_TRUE, &closureSize, &cone);
5556: }
5557: case REFINER_HEX_2D:
5558: case REFINER_HYBRID_HEX_2D:
5559: case REFINER_SIMPLEX_1D:
5560: /* Cell vertices have the average of corner coordinates */
5561: for (c = cStart; c < cMax; ++c) {
5562: const PetscInt newv = vStartNew + (vEnd - vStart) + (dim > 1 ? (eMax - eStart) : 0) + (c - cStart) + (dim > 2 ? (fMax - fStart) : 0);
5563: PetscInt *cone = NULL;
5564: PetscInt closureSize, coneSize = 0, off[8], offnew, p, d;
5566: DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);
5567: for (p = 0; p < closureSize*2; p += 2) {
5568: const PetscInt point = cone[p];
5569: if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point;
5570: }
5571: for (v = 0; v < coneSize; ++v) {
5572: PetscSectionGetOffset(coordSection, cone[v], &off[v]);
5573: }
5574: PetscSectionGetOffset(coordSectionNew, newv, &offnew);
5575: for (d = 0; d < spaceDim; ++d) coordsNew[offnew+d] = 0.0;
5576: for (v = 0; v < coneSize; ++v) {DMLocalizeAddCoordinate_Internal(dm, spaceDim, &coords[off[0]], &coords[off[v]], &coordsNew[offnew]);}
5577: for (d = 0; d < spaceDim; ++d) coordsNew[offnew+d] /= coneSize;
5578: DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);
5579: }
5580: case REFINER_SIMPLEX_2D:
5581: case REFINER_HYBRID_SIMPLEX_2D:
5582: case REFINER_SIMPLEX_3D:
5583: case REFINER_HYBRID_SIMPLEX_3D:
5584: /* Edge vertices have the average of endpoint coordinates */
5585: for (e = eStart; e < eMax; ++e) {
5586: const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);
5587: const PetscInt *cone;
5588: PetscInt coneSize, offA, offB, offnew, d;
5590: DMPlexGetConeSize(dm, e, &coneSize);
5591: if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %d cone should have two vertices, not %d", e, coneSize);
5592: DMPlexGetCone(dm, e, &cone);
5593: PetscSectionGetOffset(coordSection, cone[0], &offA);
5594: PetscSectionGetOffset(coordSection, cone[1], &offB);
5595: PetscSectionGetOffset(coordSectionNew, newv, &offnew);
5596: DMLocalizeCoordinate_Internal(dm, spaceDim, &coords[offA], &coords[offB], &coordsNew[offnew]);
5597: for (d = 0; d < spaceDim; ++d) {
5598: coordsNew[offnew+d] = 0.5*(coords[offA+d] + coordsNew[offnew+d]);
5599: }
5600: }
5601: /* Old vertices have the same coordinates */
5602: for (v = vStart; v < vEnd; ++v) {
5603: const PetscInt newv = vStartNew + (v - vStart);
5604: PetscInt off, offnew, d;
5606: PetscSectionGetOffset(coordSection, v, &off);
5607: PetscSectionGetOffset(coordSectionNew, newv, &offnew);
5608: for (d = 0; d < spaceDim; ++d) {
5609: coordsNew[offnew+d] = coords[off+d];
5610: }
5611: }
5612: break;
5613: default:
5614: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
5615: }
5616: VecRestoreArray(coordinates, &coords);
5617: VecRestoreArray(coordinatesNew, &coordsNew);
5618: DMSetCoordinatesLocal(rdm, coordinatesNew);
5619: VecDestroy(&coordinatesNew);
5620: PetscSectionDestroy(&coordSectionNew);
5621: if (dm->maxCell) {
5622: const PetscReal *maxCell, *L;
5623: const DMBoundaryType *bd;
5624: DMGetPeriodicity(dm, &maxCell, &L, &bd);
5625: DMSetPeriodicity(rdm, maxCell, L, bd);
5626: }
5627: return(0);
5628: }
5632: /*@
5633: DMPlexCreateProcessSF - Create an SF which just has process connectivity
5635: Collective on DM
5637: Input Parameters:
5638: + dm - The DM
5639: - sfPoint - The PetscSF which encodes point connectivity
5641: Output Parameters:
5642: + processRanks - A list of process neighbors, or NULL
5643: - sfProcess - An SF encoding the process connectivity, or NULL
5645: Level: developer
5647: .seealso: PetscSFCreate(), DMPlexCreateTwoSidedProcessSF()
5648: @*/
5649: PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess)
5650: {
5651: PetscInt numRoots, numLeaves, l;
5652: const PetscInt *localPoints;
5653: const PetscSFNode *remotePoints;
5654: PetscInt *localPointsNew;
5655: PetscSFNode *remotePointsNew;
5656: PetscInt *ranks, *ranksNew;
5657: PetscMPIInt numProcs;
5658: PetscErrorCode ierr;
5665: MPI_Comm_size(PetscObjectComm((PetscObject) dm), &numProcs);
5666: PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);
5667: PetscMalloc1(numLeaves, &ranks);
5668: for (l = 0; l < numLeaves; ++l) {
5669: ranks[l] = remotePoints[l].rank;
5670: }
5671: PetscSortRemoveDupsInt(&numLeaves, ranks);
5672: PetscMalloc1(numLeaves, &ranksNew);
5673: PetscMalloc1(numLeaves, &localPointsNew);
5674: PetscMalloc1(numLeaves, &remotePointsNew);
5675: for (l = 0; l < numLeaves; ++l) {
5676: ranksNew[l] = ranks[l];
5677: localPointsNew[l] = l;
5678: remotePointsNew[l].index = 0;
5679: remotePointsNew[l].rank = ranksNew[l];
5680: }
5681: PetscFree(ranks);
5682: if (processRanks) {ISCreateGeneral(PetscObjectComm((PetscObject)dm), numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);}
5683: else {PetscFree(ranksNew);}
5684: if (sfProcess) {
5685: PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess);
5686: PetscObjectSetName((PetscObject) *sfProcess, "Process SF");
5687: PetscSFSetFromOptions(*sfProcess);
5688: PetscSFSetGraph(*sfProcess, numProcs, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);
5689: }
5690: return(0);
5691: }
5695: static PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
5696: {
5697: PetscSF sf, sfNew, sfProcess;
5698: IS processRanks;
5699: MPI_Datatype depthType;
5700: PetscInt numRoots, numLeaves, numLeavesNew = 0, l, m;
5701: const PetscInt *localPoints, *neighbors;
5702: const PetscSFNode *remotePoints;
5703: PetscInt *localPointsNew;
5704: PetscSFNode *remotePointsNew;
5705: PetscInt *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew;
5706: PetscInt ldepth, depth, numNeighbors, pStartNew, pEndNew, cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax, r, n;
5707: PetscInt cStartNew = 0, vStartNew = 0, fStartNew = 0, eStartNew = 0;
5708: PetscErrorCode ierr;
5711: DMPlexGetChart(rdm, &pStartNew, &pEndNew);
5712: DMPlexGetDepth(dm, &ldepth);
5713: MPIU_Allreduce(&ldepth, &depth, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject) dm));
5714: if ((ldepth >= 0) && (depth != ldepth)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Inconsistent Plex depth %d != %d", ldepth, depth);
5715: DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
5716: DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);
5717: DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
5718: DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);
5719: DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);
5720: cMax = cMax < 0 ? cEnd : cMax;
5721: fMax = fMax < 0 ? fEnd : fMax;
5722: eMax = eMax < 0 ? eEnd : eMax;
5723: if (refiner) {GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);}
5724: DMGetPointSF(dm, &sf);
5725: DMGetPointSF(rdm, &sfNew);
5726: /* Calculate size of new SF */
5727: PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);
5728: if (numRoots < 0) return(0);
5729: for (l = 0; l < numLeaves; ++l) {
5730: const PetscInt p = localPoints[l];
5732: switch (refiner) {
5733: case REFINER_SIMPLEX_1D:
5734: if ((p >= vStart) && (p < vEnd)) {
5735: /* Interior vertices stay the same */
5736: ++numLeavesNew;
5737: } else if ((p >= cStart && p < cMax)) {
5738: /* Interior cells add new cells and interior vertices */
5739: numLeavesNew += 2 + 1;
5740: }
5741: break;
5742: case REFINER_SIMPLEX_2D:
5743: case REFINER_HYBRID_SIMPLEX_2D:
5744: if ((p >= vStart) && (p < vEnd)) {
5745: /* Interior vertices stay the same */
5746: ++numLeavesNew;
5747: } else if ((p >= fStart) && (p < fMax)) {
5748: /* Interior faces add new faces and vertex */
5749: numLeavesNew += 2 + 1;
5750: } else if ((p >= fMax) && (p < fEnd)) {
5751: /* Hybrid faces stay the same */
5752: ++numLeavesNew;
5753: } else if ((p >= cStart) && (p < cMax)) {
5754: /* Interior cells add new cells and interior faces */
5755: numLeavesNew += 4 + 3;
5756: } else if ((p >= cMax) && (p < cEnd)) {
5757: /* Hybrid cells add new cells and hybrid face */
5758: numLeavesNew += 2 + 1;
5759: }
5760: break;
5761: case REFINER_HEX_2D:
5762: case REFINER_HYBRID_HEX_2D:
5763: if ((p >= vStart) && (p < vEnd)) {
5764: /* Interior vertices stay the same */
5765: ++numLeavesNew;
5766: } else if ((p >= fStart) && (p < fMax)) {
5767: /* Interior faces add new faces and vertex */
5768: numLeavesNew += 2 + 1;
5769: } else if ((p >= fMax) && (p < fEnd)) {
5770: /* Hybrid faces stay the same */
5771: ++numLeavesNew;
5772: } else if ((p >= cStart) && (p < cMax)) {
5773: /* Interior cells add new cells, interior faces, and vertex */
5774: numLeavesNew += 4 + 4 + 1;
5775: } else if ((p >= cMax) && (p < cEnd)) {
5776: /* Hybrid cells add new cells and hybrid face */
5777: numLeavesNew += 2 + 1;
5778: }
5779: break;
5780: case REFINER_SIMPLEX_3D:
5781: case REFINER_HYBRID_SIMPLEX_3D:
5782: if ((p >= vStart) && (p < vEnd)) {
5783: /* Interior vertices stay the same */
5784: ++numLeavesNew;
5785: } else if ((p >= eStart) && (p < eMax)) {
5786: /* Interior edges add new edges and vertex */
5787: numLeavesNew += 2 + 1;
5788: } else if ((p >= eMax) && (p < eEnd)) {
5789: /* Hybrid edges stay the same */
5790: ++numLeavesNew;
5791: } else if ((p >= fStart) && (p < fMax)) {
5792: /* Interior faces add new faces and edges */
5793: numLeavesNew += 4 + 3;
5794: } else if ((p >= fMax) && (p < fEnd)) {
5795: /* Hybrid faces add new faces and edges */
5796: numLeavesNew += 2 + 1;
5797: } else if ((p >= cStart) && (p < cMax)) {
5798: /* Interior cells add new cells, faces, and edges */
5799: numLeavesNew += 8 + 8 + 1;
5800: } else if ((p >= cMax) && (p < cEnd)) {
5801: /* Hybrid cells add new cells and faces */
5802: numLeavesNew += 4 + 3;
5803: }
5804: break;
5805: case REFINER_HEX_3D:
5806: case REFINER_HYBRID_HEX_3D:
5807: if ((p >= vStart) && (p < vEnd)) {
5808: /* Old vertices stay the same */
5809: ++numLeavesNew;
5810: } else if ((p >= eStart) && (p < eMax)) {
5811: /* Interior edges add new edges, and vertex */
5812: numLeavesNew += 2 + 1;
5813: } else if ((p >= eMax) && (p < eEnd)) {
5814: /* Hybrid edges stay the same */
5815: ++numLeavesNew;
5816: } else if ((p >= fStart) && (p < fMax)) {
5817: /* Interior faces add new faces, edges, and vertex */
5818: numLeavesNew += 4 + 4 + 1;
5819: } else if ((p >= fMax) && (p < fEnd)) {
5820: /* Hybrid faces add new faces and edges */
5821: numLeavesNew += 2 + 1;
5822: } else if ((p >= cStart) && (p < cMax)) {
5823: /* Interior cells add new cells, faces, edges, and vertex */
5824: numLeavesNew += 8 + 12 + 6 + 1;
5825: } else if ((p >= cStart) && (p < cEnd)) {
5826: /* Hybrid cells add new cells, faces, and edges */
5827: numLeavesNew += 4 + 4 + 1;
5828: }
5829: break;
5830: default:
5831: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
5832: }
5833: }
5834: /* Communicate depthSizes for each remote rank */
5835: DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);
5836: ISGetLocalSize(processRanks, &numNeighbors);
5837: PetscMalloc5((depth+1)*numNeighbors,&rdepthSize,numNeighbors,&rvStartNew,numNeighbors,&reStartNew,numNeighbors,&rfStartNew,numNeighbors,&rcStartNew);
5838: PetscMalloc7(depth+1,&depthSizeOld,(depth+1)*numNeighbors,&rdepthSizeOld,(depth+1)*numNeighbors,&rdepthMaxOld,numNeighbors,&rvStart,numNeighbors,&reStart,numNeighbors,&rfStart,numNeighbors,&rcStart);
5839: MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);
5840: MPI_Type_commit(&depthType);
5841: PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);
5842: PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);
5843: for (n = 0; n < numNeighbors; ++n) {
5844: GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);
5845: }
5846: depthSizeOld[depth] = cMax;
5847: depthSizeOld[0] = vMax;
5848: depthSizeOld[depth-1] = fMax;
5849: depthSizeOld[1] = eMax;
5851: PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);
5852: PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);
5854: depthSizeOld[depth] = cEnd - cStart;
5855: depthSizeOld[0] = vEnd - vStart;
5856: depthSizeOld[depth-1] = fEnd - fStart;
5857: depthSizeOld[1] = eEnd - eStart;
5859: PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);
5860: PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);
5861: for (n = 0; n < numNeighbors; ++n) {
5862: GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);
5863: rdepthMaxOld[n*(depth+1)+depth] = rdepthMaxOld[n*(depth+1)+depth] < 0 ? rdepthSizeOld[n*(depth+1)+depth] +rcStart[n]: rdepthMaxOld[n*(depth+1)+depth];
5864: 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];
5865: rdepthMaxOld[n*(depth+1)+1] = rdepthMaxOld[n*(depth+1)+1] < 0 ? rdepthSizeOld[n*(depth+1)+1] +reStart[n]: rdepthMaxOld[n*(depth+1)+1];
5866: }
5867: MPI_Type_free(&depthType);
5868: PetscSFDestroy(&sfProcess);
5869: /* Calculate new point SF */
5870: PetscMalloc1(numLeavesNew, &localPointsNew);
5871: PetscMalloc1(numLeavesNew, &remotePointsNew);
5872: ISGetIndices(processRanks, &neighbors);
5873: for (l = 0, m = 0; l < numLeaves; ++l) {
5874: PetscInt p = localPoints[l];
5875: PetscInt rp = remotePoints[l].index, n;
5876: PetscMPIInt rrank = remotePoints[l].rank;
5878: PetscFindInt(rrank, numNeighbors, neighbors, &n);
5879: if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank);
5880: switch (refiner) {
5881: case REFINER_SIMPLEX_1D:
5882: if ((p >= vStart) && (p < vEnd)) {
5883: /* Old vertices stay the same */
5884: localPointsNew[m] = vStartNew + (p - vStart);
5885: remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
5886: remotePointsNew[m].rank = rrank;
5887: ++m;
5888: } else if ((p >= cStart) && (p < cMax)) {
5889: /* Old interior cells add new cells and vertex */
5890: for (r = 0; r < 2; ++r, ++m) {
5891: localPointsNew[m] = cStartNew + (p - cStart)*2 + r;
5892: remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*2 + r;
5893: remotePointsNew[m].rank = rrank;
5894: }
5895: localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - cStart);
5896: remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rcStart[n]);
5897: remotePointsNew[m].rank = rrank;
5898: ++m;
5899: }
5900: break;
5901: case REFINER_SIMPLEX_2D:
5902: case REFINER_HYBRID_SIMPLEX_2D:
5903: if ((p >= vStart) && (p < vEnd)) {
5904: /* Old vertices stay the same */
5905: localPointsNew[m] = vStartNew + (p - vStart);
5906: remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
5907: remotePointsNew[m].rank = rrank;
5908: ++m;
5909: } else if ((p >= fStart) && (p < fMax)) {
5910: /* Old interior faces add new faces and vertex */
5911: for (r = 0; r < 2; ++r, ++m) {
5912: localPointsNew[m] = fStartNew + (p - fStart)*2 + r;
5913: remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
5914: remotePointsNew[m].rank = rrank;
5915: }
5916: localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart);
5917: remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
5918: remotePointsNew[m].rank = rrank;
5919: ++m;
5920: } else if ((p >= fMax) && (p < fEnd)) {
5921: /* Old hybrid faces stay the same */
5922: localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - fMax);
5923: remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]);
5924: remotePointsNew[m].rank = rrank;
5925: ++m;
5926: } else if ((p >= cStart) && (p < cMax)) {
5927: /* Old interior cells add new cells and interior faces */
5928: for (r = 0; r < 4; ++r, ++m) {
5929: localPointsNew[m] = cStartNew + (p - cStart)*4 + r;
5930: remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
5931: remotePointsNew[m].rank = rrank;
5932: }
5933: for (r = 0; r < 3; ++r, ++m) {
5934: localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - cStart)*3 + r;
5935: remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r;
5936: remotePointsNew[m].rank = rrank;
5937: }
5938: } else if ((p >= cMax) && (p < cEnd)) {
5939: /* Old hybrid cells add new cells and hybrid face */
5940: for (r = 0; r < 2; ++r, ++m) {
5941: localPointsNew[m] = cStartNew + (p - cStart)*4 + r;
5942: remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
5943: remotePointsNew[m].rank = rrank;
5944: }
5945: localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax);
5946: 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]);
5947: remotePointsNew[m].rank = rrank;
5948: ++m;
5949: }
5950: break;
5951: case REFINER_HEX_2D:
5952: case REFINER_HYBRID_HEX_2D:
5953: if ((p >= vStart) && (p < vEnd)) {
5954: /* Old vertices stay the same */
5955: localPointsNew[m] = vStartNew + (p - vStart);
5956: remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
5957: remotePointsNew[m].rank = rrank;
5958: ++m;
5959: } else if ((p >= fStart) && (p < fMax)) {
5960: /* Old interior faces add new faces and vertex */
5961: for (r = 0; r < 2; ++r, ++m) {
5962: localPointsNew[m] = fStartNew + (p - fStart)*2 + r;
5963: remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
5964: remotePointsNew[m].rank = rrank;
5965: }
5966: localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart);
5967: remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
5968: remotePointsNew[m].rank = rrank;
5969: ++m;
5970: } else if ((p >= fMax) && (p < fEnd)) {
5971: /* Old hybrid faces stay the same */
5972: localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - fMax);
5973: remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]);
5974: remotePointsNew[m].rank = rrank;
5975: ++m;
5976: } else if ((p >= cStart) && (p < cMax)) {
5977: /* Old interior cells add new cells, interior faces, and vertex */
5978: for (r = 0; r < 4; ++r, ++m) {
5979: localPointsNew[m] = cStartNew + (p - cStart)*4 + r;
5980: remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
5981: remotePointsNew[m].rank = rrank;
5982: }
5983: for (r = 0; r < 4; ++r, ++m) {
5984: localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (p - cStart)*4 + r;
5985: remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*4 + r;
5986: remotePointsNew[m].rank = rrank;
5987: }
5988: localPointsNew[m] = vStartNew + (vEnd - vStart) + (fMax - fStart) + (p - cStart);
5989: remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n]) + (rp - rcStart[n]);
5990: remotePointsNew[m].rank = rrank;
5991: ++m;
5992: } else if ((p >= cStart) && (p < cMax)) {
5993: /* Old hybrid cells add new cells and hybrid face */
5994: for (r = 0; r < 2; ++r, ++m) {
5995: localPointsNew[m] = cStartNew + (p - cStart)*4 + r;
5996: remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
5997: remotePointsNew[m].rank = rrank;
5998: }
5999: localPointsNew[m] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (p - cMax);
6000: 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]);
6001: remotePointsNew[m].rank = rrank;
6002: ++m;
6003: }
6004: break;
6005: case REFINER_SIMPLEX_3D:
6006: case REFINER_HYBRID_SIMPLEX_3D:
6007: if ((p >= vStart) && (p < vEnd)) {
6008: /* Interior vertices stay the same */
6009: localPointsNew[m] = vStartNew + (p - vStart);
6010: remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
6011: remotePointsNew[m].rank = rrank;
6012: ++m;
6013: } else if ((p >= eStart) && (p < eMax)) {
6014: /* Interior edges add new edges and vertex */
6015: for (r = 0; r < 2; ++r, ++m) {
6016: localPointsNew[m] = eStartNew + (p - eStart)*2 + r;
6017: remotePointsNew[m].index = reStartNew[n] + (rp - reStart[n])*2 + r;
6018: remotePointsNew[m].rank = rrank;
6019: }
6020: localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - eStart);
6021: remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - reStart[n]);
6022: remotePointsNew[m].rank = rrank;
6023: ++m;
6024: } else if ((p >= eMax) && (p < eEnd)) {
6025: /* Hybrid edges stay the same */
6026: localPointsNew[m] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (p - eMax);
6027: 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]);
6028: remotePointsNew[m].rank = rrank;
6029: ++m;
6030: } else if ((p >= fStart) && (p < fMax)) {
6031: /* Interior faces add new faces and edges */
6032: for (r = 0; r < 4; ++r, ++m) {
6033: localPointsNew[m] = fStartNew + (p - fStart)*4 + r;
6034: remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*4 + r;
6035: remotePointsNew[m].rank = rrank;
6036: }
6037: for (r = 0; r < 3; ++r, ++m) {
6038: localPointsNew[m] = eStartNew + (eMax - eStart)*2 + (p - fStart)*3 + r;
6039: remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rp - rfStart[n])*3 + r;
6040: remotePointsNew[m].rank = rrank;
6041: }
6042: } else if ((p >= fMax) && (p < fEnd)) {
6043: /* Hybrid faces add new faces and edges */
6044: for (r = 0; r < 2; ++r, ++m) {
6045: localPointsNew[m] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (p - fMax)*2 + r;
6046: 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;
6047: remotePointsNew[m].rank = rrank;
6048: }
6049: localPointsNew[m] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (eEnd - eMax) + (p - fMax);
6050: 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]);
6051: remotePointsNew[m].rank = rrank;
6052: ++m;
6053: } else if ((p >= cStart) && (p < cMax)) {
6054: /* Interior cells add new cells, faces, and edges */
6055: for (r = 0; r < 8; ++r, ++m) {
6056: localPointsNew[m] = cStartNew + (p - cStart)*8 + r;
6057: remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*8 + r;
6058: remotePointsNew[m].rank = rrank;
6059: }
6060: for (r = 0; r < 8; ++r, ++m) {
6061: localPointsNew[m] = fStartNew + (fMax - fStart)*4 + (p - cStart)*8 + r;
6062: remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rp - rcStart[n])*8 + r;
6063: remotePointsNew[m].rank = rrank;
6064: }
6065: localPointsNew[m] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (p - cStart)*1 + 0;
6066: 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;
6067: remotePointsNew[m].rank = rrank;
6068: ++m;
6069: } else if ((p >= cMax) && (p < cEnd)) {
6070: /* Hybrid cells add new cells and faces */
6071: for (r = 0; r < 4; ++r, ++m) {
6072: localPointsNew[m] = cStartNew + (cMax - cStart)*8 + (p - cMax)*4 + r;
6073: remotePointsNew[m].index = rcStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*8 + (rp - rdepthMaxOld[n*(depth+1)+depth])*4 + r;
6074: remotePointsNew[m].rank = rrank;
6075: }
6076: for (r = 0; r < 3; ++r, ++m) {
6077: localPointsNew[m] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (p - cMax)*3 + r;
6078: 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;
6079: remotePointsNew[m].rank = rrank;
6080: }
6081: }
6082: break;
6083: case REFINER_HEX_3D:
6084: case REFINER_HYBRID_HEX_3D:
6085: if ((p >= vStart) && (p < vEnd)) {
6086: /* Interior vertices stay the same */
6087: localPointsNew[m] = vStartNew + (p - vStart);
6088: remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
6089: remotePointsNew[m].rank = rrank;
6090: ++m;
6091: } else if ((p >= eStart) && (p < eMax)) {
6092: /* Interior edges add new edges and vertex */
6093: for (r = 0; r < 2; ++r, ++m) {
6094: localPointsNew[m] = eStartNew + (p - eStart)*2 + r;
6095: remotePointsNew[m].index = reStartNew[n] + (rp - reStart[n])*2 + r;
6096: remotePointsNew[m].rank = rrank;
6097: }
6098: localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - eStart);
6099: remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - reStart[n]);
6100: remotePointsNew[m].rank = rrank;
6101: ++m;
6102: } else if ((p >= eMax) && (p < eEnd)) {
6103: /* Hybrid edges stay the same */
6104: localPointsNew[m] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (p - eMax);
6105: 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]);
6106: remotePointsNew[m].rank = rrank;
6107: ++m;
6108: } else if ((p >= fStart) && (p < fMax)) {
6109: /* Interior faces add new faces, edges, and vertex */
6110: for (r = 0; r < 4; ++r, ++m) {
6111: localPointsNew[m] = fStartNew + (p - fStart)*4 + r;
6112: remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*4 + r;
6113: remotePointsNew[m].rank = rrank;
6114: }
6115: for (r = 0; r < 4; ++r, ++m) {
6116: localPointsNew[m] = eStartNew + (eMax - eStart)*2 + (p - fStart)*4 + r;
6117: remotePointsNew[m].index = reStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n])*2 + (rp - rfStart[n])*4 + r;
6118: remotePointsNew[m].rank = rrank;
6119: }
6120: localPointsNew[m] = vStartNew + (vEnd - vStart) + (eMax - eStart) + (p - fStart);
6121: remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n]) + (rp - rfStart[n]);
6122: remotePointsNew[m].rank = rrank;
6123: ++m;
6124: } else if ((p >= fMax) && (p < fEnd)) {
6125: /* Hybrid faces add new faces and edges */
6126: for (r = 0; r < 2; ++r, ++m) {
6127: localPointsNew[m] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (p - fMax)*2 + r;
6128: 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;
6129: remotePointsNew[m].rank = rrank;
6130: }
6131: localPointsNew[m] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (p - fMax);
6132: 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]);
6133: remotePointsNew[m].rank = rrank;
6134: ++m;
6135: } else if ((p >= cStart) && (p < cMax)) {
6136: /* Interior cells add new cells, faces, edges, and vertex */
6137: for (r = 0; r < 8; ++r, ++m) {
6138: localPointsNew[m] = cStartNew + (p - cStart)*8 + r;
6139: remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*8 + r;
6140: remotePointsNew[m].rank = rrank;
6141: }
6142: for (r = 0; r < 12; ++r, ++m) {
6143: localPointsNew[m] = fStartNew + (fMax - fStart)*4 + (p - cStart)*12 + r;
6144: remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*4 + (rp - rcStart[n])*12 + r;
6145: remotePointsNew[m].rank = rrank;
6146: }
6147: for (r = 0; r < 6; ++r, ++m) {
6148: localPointsNew[m] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (p - cStart)*6 + r;
6149: 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;
6150: remotePointsNew[m].rank = rrank;
6151: }
6152: for (r = 0; r < 1; ++r, ++m) {
6153: localPointsNew[m] = vStartNew + (eMax - eStart) + (fMax - fStart) + (p - cStart) + r;
6154: remotePointsNew[m].index = rvStartNew[n] + (rdepthMaxOld[n*(depth+1)+1] - reStart[n]) + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n]) + (rp - rcStart[n]) + r;
6155: remotePointsNew[m].rank = rrank;
6156: }
6157: } else if ((p >= cMax) && (p < cEnd)) {
6158: /* Hybrid cells add new cells, faces, and edges */
6159: for (r = 0; r < 4; ++r, ++m) {
6160: localPointsNew[m] = cStartNew + (cMax - cStart)*8 + (p - cMax)*4 + r;
6161: remotePointsNew[m].index = rcStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth] - rcStart[n])*8 + (rp - rdepthMaxOld[n*(depth+1)+depth])*4 + r;
6162: remotePointsNew[m].rank = rrank;
6163: }
6164: for (r = 0; r < 4; ++r, ++m) {
6165: localPointsNew[m] = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (p - cMax)*4 + r;
6166: 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;
6167: remotePointsNew[m].rank = rrank;
6168: }
6169: localPointsNew[m] = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (eEnd - eMax) + (fEnd - fMax) + (p - cMax);
6170: 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]);
6171: remotePointsNew[m].rank = rrank;
6172: ++m;
6173: }
6174: break;
6175: default:
6176: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
6177: }
6178: }
6179: if (m != numLeavesNew) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of leaf point %d should be %d", m, numLeavesNew);
6180: ISRestoreIndices(processRanks, &neighbors);
6181: ISDestroy(&processRanks);
6182: {
6183: PetscSFNode *rp, *rtmp;
6184: PetscInt *lp, *idx, *ltmp, i;
6186: /* SF needs sorted leaves to correct calculate Gather */
6187: PetscMalloc1(numLeavesNew,&idx);
6188: PetscMalloc1(numLeavesNew, &lp);
6189: PetscMalloc1(numLeavesNew, &rp);
6190: for (i = 0; i < numLeavesNew; ++i) {
6191: 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);
6192: idx[i] = i;
6193: }
6194: PetscSortIntWithPermutation(numLeavesNew, localPointsNew, idx);
6195: for (i = 0; i < numLeavesNew; ++i) {
6196: lp[i] = localPointsNew[idx[i]];
6197: rp[i] = remotePointsNew[idx[i]];
6198: }
6199: ltmp = localPointsNew;
6200: localPointsNew = lp;
6201: rtmp = remotePointsNew;
6202: remotePointsNew = rp;
6203: PetscFree(idx);
6204: PetscFree(ltmp);
6205: PetscFree(rtmp);
6206: }
6207: PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);
6208: PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);
6209: PetscFree7(depthSizeOld,rdepthSizeOld,rdepthMaxOld,rvStart,reStart,rfStart,rcStart);
6210: return(0);
6211: }
6215: static PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
6216: {
6217: PetscInt numLabels, l;
6218: PetscInt depth, newp, cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax, r;
6219: PetscInt cStartNew = 0, vStartNew = 0, fStartNew = 0, eStartNew = 0;
6223: DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
6224: DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);
6225: DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
6226: DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);
6227: DMPlexGetDepth(dm, &depth);
6228: if (refiner) {GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);}
6229: DMGetNumLabels(dm, &numLabels);
6230: DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);
6231: switch (refiner) {
6232: case REFINER_NOOP:
6233: case REFINER_SIMPLEX_1D:
6234: case REFINER_SIMPLEX_2D:
6235: case REFINER_HEX_2D:
6236: case REFINER_SIMPLEX_3D:
6237: case REFINER_HEX_3D:
6238: break;
6239: case REFINER_HYBRID_SIMPLEX_3D:
6240: case REFINER_HYBRID_HEX_3D:
6241: if (eMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No edge maximum specified in hybrid mesh");
6242: case REFINER_HYBRID_SIMPLEX_2D:
6243: case REFINER_HYBRID_HEX_2D:
6244: if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
6245: if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
6246: break;
6247: default:
6248: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
6249: }
6250: for (l = 0; l < numLabels; ++l) {
6251: DMLabel label, labelNew;
6252: const char *lname;
6253: PetscBool isDepth;
6254: IS valueIS;
6255: const PetscInt *values;
6256: PetscInt defVal;
6257: PetscInt numValues, val;
6259: DMGetLabelName(dm, l, &lname);
6260: PetscStrcmp(lname, "depth", &isDepth);
6261: if (isDepth) continue;
6262: DMCreateLabel(rdm, lname);
6263: DMGetLabel(dm, lname, &label);
6264: DMGetLabel(rdm, lname, &labelNew);
6265: DMLabelGetDefaultValue(label,&defVal);
6266: DMLabelSetDefaultValue(labelNew,defVal);
6267: DMLabelGetValueIS(label, &valueIS);
6268: ISGetLocalSize(valueIS, &numValues);
6269: ISGetIndices(valueIS, &values);
6270: for (val = 0; val < numValues; ++val) {
6271: IS pointIS;
6272: const PetscInt *points;
6273: PetscInt numPoints, n;
6275: DMLabelGetStratumIS(label, values[val], &pointIS);
6276: ISGetLocalSize(pointIS, &numPoints);
6277: ISGetIndices(pointIS, &points);
6278: /* Ensure refined label is created with same number of strata as
6279: * original (even if no entries here). */
6280: if (!numPoints) {
6281: DMLabelSetValue(labelNew, 0, values[val]);
6282: DMLabelClearValue(labelNew, 0, values[val]);
6283: }
6284: for (n = 0; n < numPoints; ++n) {
6285: const PetscInt p = points[n];
6286: switch (refiner) {
6287: case REFINER_SIMPLEX_1D:
6288: if ((p >= vStart) && (p < vEnd)) {
6289: /* Old vertices stay the same */
6290: newp = vStartNew + (p - vStart);
6291: DMLabelSetValue(labelNew, newp, values[val]);
6292: } else if ((p >= cStart) && (p < cEnd)) {
6293: /* Old cells add new cells and vertex */
6294: newp = vStartNew + (vEnd - vStart) + (p - cStart);
6295: DMLabelSetValue(labelNew, newp, values[val]);
6296: for (r = 0; r < 2; ++r) {
6297: newp = cStartNew + (p - cStart)*2 + r;
6298: DMLabelSetValue(labelNew, newp, values[val]);
6299: }
6300: }
6301: break;
6302: case REFINER_SIMPLEX_2D:
6303: if ((p >= vStart) && (p < vEnd)) {
6304: /* Old vertices stay the same */
6305: newp = vStartNew + (p - vStart);
6306: DMLabelSetValue(labelNew, newp, values[val]);
6307: } else if ((p >= fStart) && (p < fEnd)) {
6308: /* Old faces add new faces and vertex */
6309: newp = vStartNew + (vEnd - vStart) + (p - fStart);
6310: DMLabelSetValue(labelNew, newp, values[val]);
6311: for (r = 0; r < 2; ++r) {
6312: newp = fStartNew + (p - fStart)*2 + r;
6313: DMLabelSetValue(labelNew, newp, values[val]);
6314: }
6315: } else if ((p >= cStart) && (p < cEnd)) {
6316: /* Old cells add new cells and interior faces */
6317: for (r = 0; r < 4; ++r) {
6318: newp = cStartNew + (p - cStart)*4 + r;
6319: DMLabelSetValue(labelNew, newp, values[val]);
6320: }
6321: for (r = 0; r < 3; ++r) {
6322: newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r;
6323: DMLabelSetValue(labelNew, newp, values[val]);
6324: }
6325: }
6326: break;
6327: case REFINER_HEX_2D:
6328: if ((p >= vStart) && (p < vEnd)) {
6329: /* Old vertices stay the same */
6330: newp = vStartNew + (p - vStart);
6331: DMLabelSetValue(labelNew, newp, values[val]);
6332: } else if ((p >= fStart) && (p < fEnd)) {
6333: /* Old faces add new faces and vertex */
6334: newp = vStartNew + (vEnd - vStart) + (p - fStart);
6335: DMLabelSetValue(labelNew, newp, values[val]);
6336: for (r = 0; r < 2; ++r) {
6337: newp = fStartNew + (p - fStart)*2 + r;
6338: DMLabelSetValue(labelNew, newp, values[val]);
6339: }
6340: } else if ((p >= cStart) && (p < cEnd)) {
6341: /* Old cells add new cells and interior faces and vertex */
6342: for (r = 0; r < 4; ++r) {
6343: newp = cStartNew + (p - cStart)*4 + r;
6344: DMLabelSetValue(labelNew, newp, values[val]);
6345: }
6346: for (r = 0; r < 4; ++r) {
6347: newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r;
6348: DMLabelSetValue(labelNew, newp, values[val]);
6349: }
6350: newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart);
6351: DMLabelSetValue(labelNew, newp, values[val]);
6352: }
6353: break;
6354: case REFINER_HYBRID_SIMPLEX_2D:
6355: if ((p >= vStart) && (p < vEnd)) {
6356: /* Old vertices stay the same */
6357: newp = vStartNew + (p - vStart);
6358: DMLabelSetValue(labelNew, newp, values[val]);
6359: } else if ((p >= fStart) && (p < fMax)) {
6360: /* Old interior faces add new faces and vertex */
6361: newp = vStartNew + (vEnd - vStart) + (p - fStart);
6362: DMLabelSetValue(labelNew, newp, values[val]);
6363: for (r = 0; r < 2; ++r) {
6364: newp = fStartNew + (p - fStart)*2 + r;
6365: DMLabelSetValue(labelNew, newp, values[val]);
6366: }
6367: } else if ((p >= fMax) && (p < fEnd)) {
6368: /* Old hybrid faces stay the same */
6369: newp = fStartNew + (fMax - fStart)*2 + (p - fMax);
6370: DMLabelSetValue(labelNew, newp, values[val]);
6371: } else if ((p >= cStart) && (p < cMax)) {
6372: /* Old interior cells add new cells and interior faces */
6373: for (r = 0; r < 4; ++r) {
6374: newp = cStartNew + (p - cStart)*4 + r;
6375: DMLabelSetValue(labelNew, newp, values[val]);
6376: }
6377: for (r = 0; r < 3; ++r) {
6378: newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r;
6379: DMLabelSetValue(labelNew, newp, values[val]);
6380: }
6381: } else if ((p >= cMax) && (p < cEnd)) {
6382: /* Old hybrid cells add new cells and hybrid face */
6383: for (r = 0; r < 2; ++r) {
6384: newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r;
6385: DMLabelSetValue(labelNew, newp, values[val]);
6386: }
6387: newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax);
6388: DMLabelSetValue(labelNew, newp, values[val]);
6389: }
6390: break;
6391: case REFINER_HYBRID_HEX_2D:
6392: if ((p >= vStart) && (p < vEnd)) {
6393: /* Old vertices stay the same */
6394: newp = vStartNew + (p - vStart);
6395: DMLabelSetValue(labelNew, newp, values[val]);
6396: } else if ((p >= fStart) && (p < fMax)) {
6397: /* Old interior faces add new faces and vertex */
6398: newp = vStartNew + (vEnd - vStart) + (p - fStart);
6399: DMLabelSetValue(labelNew, newp, values[val]);
6400: for (r = 0; r < 2; ++r) {
6401: newp = fStartNew + (p - fStart)*2 + r;
6402: DMLabelSetValue(labelNew, newp, values[val]);
6403: }
6404: } else if ((p >= fMax) && (p < fEnd)) {
6405: /* Old hybrid faces stay the same */
6406: newp = fStartNew + (fMax - fStart)*2 + (p - fMax);
6407: DMLabelSetValue(labelNew, newp, values[val]);
6408: } else if ((p >= cStart) && (p < cMax)) {
6409: /* Old interior cells add new cells, interior faces, and vertex */
6410: for (r = 0; r < 4; ++r) {
6411: newp = cStartNew + (p - cStart)*4 + r;
6412: DMLabelSetValue(labelNew, newp, values[val]);
6413: }
6414: for (r = 0; r < 4; ++r) {
6415: newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r;
6416: DMLabelSetValue(labelNew, newp, values[val]);
6417: }
6418: newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart);
6419: DMLabelSetValue(labelNew, newp, values[val]);
6420: } else if ((p >= cMax) && (p < cEnd)) {
6421: /* Old hybrid cells add new cells and hybrid face */
6422: for (r = 0; r < 2; ++r) {
6423: newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r;
6424: DMLabelSetValue(labelNew, newp, values[val]);
6425: }
6426: newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*4 + (p - cMax);
6427: DMLabelSetValue(labelNew, newp, values[val]);
6428: }
6429: break;
6430: case REFINER_SIMPLEX_3D:
6431: if ((p >= vStart) && (p < vEnd)) {
6432: /* Old vertices stay the same */
6433: newp = vStartNew + (p - vStart);
6434: DMLabelSetValue(labelNew, newp, values[val]);
6435: } else if ((p >= eStart) && (p < eEnd)) {
6436: /* Old edges add new edges and vertex */
6437: for (r = 0; r < 2; ++r) {
6438: newp = eStartNew + (p - eStart)*2 + r;
6439: DMLabelSetValue(labelNew, newp, values[val]);
6440: }
6441: newp = vStartNew + (vEnd - vStart) + (p - eStart);
6442: DMLabelSetValue(labelNew, newp, values[val]);
6443: } else if ((p >= fStart) && (p < fEnd)) {
6444: /* Old faces add new faces and edges */
6445: for (r = 0; r < 4; ++r) {
6446: newp = fStartNew + (p - fStart)*4 + r;
6447: DMLabelSetValue(labelNew, newp, values[val]);
6448: }
6449: for (r = 0; r < 3; ++r) {
6450: newp = eStartNew + (eEnd - eStart)*2 + (p - fStart)*3 + r;
6451: DMLabelSetValue(labelNew, newp, values[val]);
6452: }
6453: } else if ((p >= cStart) && (p < cEnd)) {
6454: /* Old cells add new cells and interior faces and edges */
6455: for (r = 0; r < 8; ++r) {
6456: newp = cStartNew + (p - cStart)*8 + r;
6457: DMLabelSetValue(labelNew, newp, values[val]);
6458: }
6459: for (r = 0; r < 8; ++r) {
6460: newp = fStartNew + (fEnd - fStart)*4 + (p - cStart)*8 + r;
6461: DMLabelSetValue(labelNew, newp, values[val]);
6462: }
6463: for (r = 0; r < 1; ++r) {
6464: newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (p - cStart)*1 + r;
6465: DMLabelSetValue(labelNew, newp, values[val]);
6466: }
6467: }
6468: break;
6469: case REFINER_HYBRID_SIMPLEX_3D:
6470: if ((p >= vStart) && (p < vEnd)) {
6471: /* Interior vertices stay the same */
6472: newp = vStartNew + (p - vStart);
6473: DMLabelSetValue(labelNew, newp, values[val]);
6474: } else if ((p >= eStart) && (p < eMax)) {
6475: /* Interior edges add new edges and vertex */
6476: for (r = 0; r < 2; ++r) {
6477: newp = eStartNew + (p - eStart)*2 + r;
6478: DMLabelSetValue(labelNew, newp, values[val]);
6479: }
6480: newp = vStartNew + (vEnd - vStart) + (p - eStart);
6481: DMLabelSetValue(labelNew, newp, values[val]);
6482: } else if ((p >= eMax) && (p < eEnd)) {
6483: /* Hybrid edges stay the same */
6484: newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (p - eMax);
6485: DMLabelSetValue(labelNew, newp, values[val]);
6486: } else if ((p >= fStart) && (p < fMax)) {
6487: /* Interior faces add new faces and edges */
6488: for (r = 0; r < 4; ++r) {
6489: newp = fStartNew + (p - fStart)*4 + r;
6490: DMLabelSetValue(labelNew, newp, values[val]);
6491: }
6492: for (r = 0; r < 3; ++r) {
6493: newp = eStartNew + (eMax - eStart)*2 + (p - fStart)*3 + r;
6494: DMLabelSetValue(labelNew, newp, values[val]);
6495: }
6496: } else if ((p >= fMax) && (p < fEnd)) {
6497: /* Hybrid faces add new faces and edges */
6498: for (r = 0; r < 2; ++r) {
6499: newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (p - fMax)*2 + r;
6500: DMLabelSetValue(labelNew, newp, values[val]);
6501: }
6502: newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (cMax - cStart) + (p - fMax);
6503: DMLabelSetValue(labelNew, newp, values[val]);
6504: } else if ((p >= cStart) && (p < cMax)) {
6505: /* Interior cells add new cells, faces, and edges */
6506: for (r = 0; r < 8; ++r) {
6507: newp = cStartNew + (p - cStart)*8 + r;
6508: DMLabelSetValue(labelNew, newp, values[val]);
6509: }
6510: for (r = 0; r < 8; ++r) {
6511: newp = fStartNew + (fMax - fStart)*4 + (p - cStart)*8 + r;
6512: DMLabelSetValue(labelNew, newp, values[val]);
6513: }
6514: newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*3 + (p - cStart);
6515: DMLabelSetValue(labelNew, newp, values[val]);
6516: } else if ((p >= cMax) && (p < cEnd)) {
6517: /* Hybrid cells add new cells and faces */
6518: for (r = 0; r < 4; ++r) {
6519: newp = cStartNew + (cMax - cStart)*8 + (p - cMax)*4 + r;
6520: DMLabelSetValue(labelNew, newp, values[val]);
6521: }
6522: for (r = 0; r < 3; ++r) {
6523: newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*8 + (fEnd - fMax)*2 + (p - cMax)*3 + r;
6524: DMLabelSetValue(labelNew, newp, values[val]);
6525: }
6526: }
6527: break;
6528: case REFINER_HEX_3D:
6529: if ((p >= vStart) && (p < vEnd)) {
6530: /* Old vertices stay the same */
6531: newp = vStartNew + (p - vStart);
6532: DMLabelSetValue(labelNew, newp, values[val]);
6533: } else if ((p >= eStart) && (p < eEnd)) {
6534: /* Old edges add new edges and vertex */
6535: for (r = 0; r < 2; ++r) {
6536: newp = eStartNew + (p - eStart)*2 + r;
6537: DMLabelSetValue(labelNew, newp, values[val]);
6538: }
6539: newp = vStartNew + (vEnd - vStart) + (p - eStart);
6540: DMLabelSetValue(labelNew, newp, values[val]);
6541: } else if ((p >= fStart) && (p < fEnd)) {
6542: /* Old faces add new faces, edges, and vertex */
6543: for (r = 0; r < 4; ++r) {
6544: newp = fStartNew + (p - fStart)*4 + r;
6545: DMLabelSetValue(labelNew, newp, values[val]);
6546: }
6547: for (r = 0; r < 4; ++r) {
6548: newp = eStartNew + (eEnd - eStart)*2 + (p - fStart)*4 + r;
6549: DMLabelSetValue(labelNew, newp, values[val]);
6550: }
6551: newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (p - fStart);
6552: DMLabelSetValue(labelNew, newp, values[val]);
6553: } else if ((p >= cStart) && (p < cEnd)) {
6554: /* Old cells add new cells, faces, edges, and vertex */
6555: for (r = 0; r < 8; ++r) {
6556: newp = cStartNew + (p - cStart)*8 + r;
6557: DMLabelSetValue(labelNew, newp, values[val]);
6558: }
6559: for (r = 0; r < 12; ++r) {
6560: newp = fStartNew + (fEnd - fStart)*4 + (p - cStart)*12 + r;
6561: DMLabelSetValue(labelNew, newp, values[val]);
6562: }
6563: for (r = 0; r < 6; ++r) {
6564: newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*4 + (p - cStart)*6 + r;
6565: DMLabelSetValue(labelNew, newp, values[val]);
6566: }
6567: newp = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (fEnd - fStart) + (p - cStart);
6568: DMLabelSetValue(labelNew, newp, values[val]);
6569: }
6570: break;
6571: case REFINER_HYBRID_HEX_3D:
6572: if ((p >= vStart) && (p < vEnd)) {
6573: /* Interior vertices stay the same */
6574: newp = vStartNew + (p - vStart);
6575: DMLabelSetValue(labelNew, newp, values[val]);
6576: } else if ((p >= eStart) && (p < eMax)) {
6577: /* Interior edges add new edges and vertex */
6578: for (r = 0; r < 2; ++r) {
6579: newp = eStartNew + (p - eStart)*2 + r;
6580: DMLabelSetValue(labelNew, newp, values[val]);
6581: }
6582: newp = vStartNew + (vEnd - vStart) + (p - eStart);
6583: DMLabelSetValue(labelNew, newp, values[val]);
6584: } else if ((p >= eMax) && (p < eEnd)) {
6585: /* Hybrid edges stay the same */
6586: newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (p - eMax);
6587: DMLabelSetValue(labelNew, newp, values[val]);
6588: } else if ((p >= fStart) && (p < fMax)) {
6589: /* Interior faces add new faces, edges, and vertex */
6590: for (r = 0; r < 4; ++r) {
6591: newp = fStartNew + (p - fStart)*4 + r;
6592: DMLabelSetValue(labelNew, newp, values[val]);
6593: }
6594: for (r = 0; r < 4; ++r) {
6595: newp = eStartNew + (eMax - eStart)*2 + (p - fStart)*4 + r;
6596: DMLabelSetValue(labelNew, newp, values[val]);
6597: }
6598: newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (p - fStart);
6599: DMLabelSetValue(labelNew, newp, values[val]);
6600: } else if ((p >= fMax) && (p < fEnd)) {
6601: /* Hybrid faces add new faces and edges */
6602: for (r = 0; r < 2; ++r) {
6603: newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (p - fMax)*2 + r;
6604: DMLabelSetValue(labelNew, newp, values[val]);
6605: }
6606: newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (p - fMax);
6607: DMLabelSetValue(labelNew, newp, values[val]);
6608: } else if ((p >= cStart) && (p < cMax)) {
6609: /* Interior cells add new cells, faces, edges, and vertex */
6610: for (r = 0; r < 8; ++r) {
6611: newp = cStartNew + (p - cStart)*8 + r;
6612: DMLabelSetValue(labelNew, newp, values[val]);
6613: }
6614: for (r = 0; r < 12; ++r) {
6615: newp = fStartNew + (fMax - fStart)*4 + (p - cStart)*12 + r;
6616: DMLabelSetValue(labelNew, newp, values[val]);
6617: }
6618: for (r = 0; r < 6; ++r) {
6619: newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (p - cStart)*6 + r;
6620: DMLabelSetValue(labelNew, newp, values[val]);
6621: }
6622: newp = vStartNew + (vEnd - vStart) + (eMax - eStart) + (fMax - fStart) + (p - cStart);
6623: DMLabelSetValue(labelNew, newp, values[val]);
6624: } else if ((p >= cMax) && (p < cEnd)) {
6625: /* Hybrid cells add new cells, faces, and edges */
6626: for (r = 0; r < 4; ++r) {
6627: newp = cStartNew + (cMax - cStart)*8 + (p - cMax)*4 + r;
6628: DMLabelSetValue(labelNew, newp, values[val]);
6629: }
6630: for (r = 0; r < 4; ++r) {
6631: newp = fStartNew + (fMax - fStart)*4 + (cMax - cStart)*12 + (fEnd - fMax)*2 + (p - cMax)*4 + r;
6632: DMLabelSetValue(labelNew, newp, values[val]);
6633: }
6634: newp = eStartNew + (eMax - eStart)*2 + (fMax - fStart)*4 + (cMax - cStart)*6 + (fEnd - fMax) + (p - cMax);
6635: DMLabelSetValue(labelNew, newp, values[val]);
6636: }
6637: break;
6638: default:
6639: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
6640: }
6641: }
6642: ISRestoreIndices(pointIS, &points);
6643: ISDestroy(&pointIS);
6644: }
6645: ISRestoreIndices(valueIS, &values);
6646: ISDestroy(&valueIS);
6647: if (0) {
6648: DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);
6649: }
6650: }
6651: return(0);
6652: }
6656: /* This will only work for interpolated meshes */
6657: PetscErrorCode DMPlexRefineUniform_Internal(DM dm, CellRefiner cellRefiner, DM *dmRefined)
6658: {
6659: DM rdm;
6660: PetscInt *depthSize;
6661: PetscInt dim, depth = 0, d, pStart = 0, pEnd = 0;
6665: DMCreate(PetscObjectComm((PetscObject)dm), &rdm);
6666: DMSetType(rdm, DMPLEX);
6667: DMGetDimension(dm, &dim);
6668: DMSetDimension(rdm, dim);
6669: /* Calculate number of new points of each depth */
6670: DMPlexGetDepth(dm, &depth);
6671: if (depth >= 0 && dim != depth) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Mesh must be interpolated for regular refinement");
6672: PetscMalloc1(depth+1, &depthSize);
6673: PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));
6674: CellRefinerGetSizes(cellRefiner, dm, depthSize);
6675: /* Step 1: Set chart */
6676: for (d = 0; d <= depth; ++d) pEnd += depthSize[d];
6677: DMPlexSetChart(rdm, pStart, pEnd);
6678: /* Step 2: Set cone/support sizes */
6679: CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);
6680: /* Step 3: Setup refined DM */
6681: DMSetUp(rdm);
6682: /* Step 4: Set cones and supports */
6683: CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);
6684: /* Step 5: Stratify */
6685: DMPlexStratify(rdm);
6686: /* Step 6: Create pointSF */
6687: CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);
6688: /* Step 7: Set coordinates for vertices */
6689: CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);
6690: /* Step 8: Create labels */
6691: CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);
6692: PetscFree(depthSize);
6694: *dmRefined = rdm;
6695: return(0);
6696: }
6700: /*@
6701: DMPlexCreateCoarsePointIS - Creates an IS covering the coarse DM chart with the fine points as data
6703: Input Parameter:
6704: . dm - The coarse DM
6706: Output Parameter:
6707: . fpointIS - The IS of all the fine points which exist in the original coarse mesh
6709: Level: developer
6711: .seealso: DMRefine(), DMPlexSetRefinementUniform(), DMPlexCreateSubpointIS()
6712: @*/
6713: PetscErrorCode DMPlexCreateCoarsePointIS(DM dm, IS *fpointIS)
6714: {
6715: CellRefiner cellRefiner;
6716: PetscInt *depthSize, *fpoints;
6717: PetscInt cStartNew = 0, vStartNew = 0, fStartNew = 0, eStartNew = 0;
6718: PetscInt depth, pStart, pEnd, p, vStart, vEnd, v;
6722: DMPlexGetDepth(dm, &depth);
6723: DMPlexGetChart(dm, &pStart, &pEnd);
6724: DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);
6725: DMPlexGetCellRefiner_Internal(dm, &cellRefiner);
6726: PetscMalloc1(depth+1, &depthSize);
6727: CellRefinerGetSizes(cellRefiner, dm, depthSize);
6728: if (cellRefiner) {GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);}
6729: PetscMalloc1(pEnd-pStart,&fpoints);
6730: for (p = 0; p < pEnd-pStart; ++p) fpoints[p] = -1;
6731: switch (cellRefiner) {
6732: case REFINER_SIMPLEX_1D:
6733: case REFINER_SIMPLEX_2D:
6734: case REFINER_HYBRID_SIMPLEX_2D:
6735: case REFINER_HEX_2D:
6736: case REFINER_HYBRID_HEX_2D:
6737: case REFINER_SIMPLEX_3D:
6738: case REFINER_HYBRID_SIMPLEX_3D:
6739: case REFINER_HEX_3D:
6740: case REFINER_HYBRID_HEX_3D:
6741: for (v = vStart; v < vEnd; ++v) fpoints[v-pStart] = vStartNew + (v - vStart);
6742: break;
6743: default:
6744: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", cellRefiner);
6745: }
6746: ISCreateGeneral(PETSC_COMM_SELF, pEnd-pStart, fpoints, PETSC_OWN_POINTER, fpointIS);
6747: PetscFree(depthSize);
6748: return(0);
6749: }
6753: /*@
6754: DMPlexSetRefinementUniform - Set the flag for uniform refinement
6756: Input Parameters:
6757: + dm - The DM
6758: - refinementUniform - The flag for uniform refinement
6760: Level: developer
6762: .seealso: DMRefine(), DMPlexGetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
6763: @*/
6764: PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform)
6765: {
6766: DM_Plex *mesh = (DM_Plex*) dm->data;
6770: mesh->refinementUniform = refinementUniform;
6771: return(0);
6772: }
6776: /*@
6777: DMPlexGetRefinementUniform - Retrieve the flag for uniform refinement
6779: Input Parameter:
6780: . dm - The DM
6782: Output Parameter:
6783: . refinementUniform - The flag for uniform refinement
6785: Level: developer
6787: .seealso: DMRefine(), DMPlexSetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
6788: @*/
6789: PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform)
6790: {
6791: DM_Plex *mesh = (DM_Plex*) dm->data;
6796: *refinementUniform = mesh->refinementUniform;
6797: return(0);
6798: }
6802: /*@
6803: DMPlexSetRefinementLimit - Set the maximum cell volume for refinement
6805: Input Parameters:
6806: + dm - The DM
6807: - refinementLimit - The maximum cell volume in the refined mesh
6809: Level: developer
6811: .seealso: DMRefine(), DMPlexGetRefinementLimit(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform()
6812: @*/
6813: PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit)
6814: {
6815: DM_Plex *mesh = (DM_Plex*) dm->data;
6819: mesh->refinementLimit = refinementLimit;
6820: return(0);
6821: }
6825: /*@
6826: DMPlexGetRefinementLimit - Retrieve the maximum cell volume for refinement
6828: Input Parameter:
6829: . dm - The DM
6831: Output Parameter:
6832: . refinementLimit - The maximum cell volume in the refined mesh
6834: Level: developer
6836: .seealso: DMRefine(), DMPlexSetRefinementLimit(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform()
6837: @*/
6838: PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit)
6839: {
6840: DM_Plex *mesh = (DM_Plex*) dm->data;
6845: /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */
6846: *refinementLimit = mesh->refinementLimit;
6847: return(0);
6848: }
6852: /*@
6853: DMPlexSetRefinementFunction - Set the function giving the maximum cell volume for refinement
6855: Input Parameters:
6856: + dm - The DM
6857: - refinementFunc - Function giving the maximum cell volume in the refined mesh
6859: Note: The calling sequence is refinementFunc(coords, limit)
6860: $ coords - Coordinates of the current point, usually a cell centroid
6861: $ limit - The maximum cell volume for a cell containing this point
6863: Level: developer
6865: .seealso: DMRefine(), DMPlexGetRefinementFunction(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
6866: @*/
6867: PetscErrorCode DMPlexSetRefinementFunction(DM dm, PetscErrorCode (*refinementFunc)(const PetscReal [], PetscReal *))
6868: {
6869: DM_Plex *mesh = (DM_Plex*) dm->data;
6873: mesh->refinementFunc = refinementFunc;
6874: return(0);
6875: }
6879: /*@
6880: DMPlexGetRefinementFunction - Get the function giving the maximum cell volume for refinement
6882: Input Parameter:
6883: . dm - The DM
6885: Output Parameter:
6886: . refinementFunc - Function giving the maximum cell volume in the refined mesh
6888: Note: The calling sequence is refinementFunc(coords, limit)
6889: $ coords - Coordinates of the current point, usually a cell centroid
6890: $ limit - The maximum cell volume for a cell containing this point
6892: Level: developer
6894: .seealso: DMRefine(), DMPlexSetRefinementFunction(), DMPlexGetRefinementUniform(), DMPlexSetRefinementUniform(), DMPlexGetRefinementLimit(), DMPlexSetRefinementLimit()
6895: @*/
6896: PetscErrorCode DMPlexGetRefinementFunction(DM dm, PetscErrorCode (**refinementFunc)(const PetscReal [], PetscReal *))
6897: {
6898: DM_Plex *mesh = (DM_Plex*) dm->data;
6903: *refinementFunc = mesh->refinementFunc;
6904: return(0);
6905: }
6909: PetscErrorCode DMPlexGetCellRefiner_Internal(DM dm, CellRefiner *cellRefiner)
6910: {
6911: PetscInt dim, cStart, cEnd, coneSize, cMax, fMax;
6915: DMGetDimension(dm, &dim);
6916: DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);
6917: if (cEnd <= cStart) {*cellRefiner = REFINER_NOOP; return(0);}
6918: DMPlexGetConeSize(dm, cStart, &coneSize);
6919: DMPlexGetHybridBounds(dm, &cMax, &fMax, NULL, NULL);
6920: switch (dim) {
6921: case 1:
6922: switch (coneSize) {
6923: case 2:
6924: *cellRefiner = REFINER_SIMPLEX_1D;
6925: break;
6926: default:
6927: SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim);
6928: }
6929: break;
6930: case 2:
6931: switch (coneSize) {
6932: case 3:
6933: if (cMax >= 0) *cellRefiner = REFINER_HYBRID_SIMPLEX_2D;
6934: else *cellRefiner = REFINER_SIMPLEX_2D;
6935: break;
6936: case 4:
6937: if (cMax >= 0 && fMax >= 0) *cellRefiner = REFINER_HYBRID_HEX_2D;
6938: else *cellRefiner = REFINER_HEX_2D;
6939: break;
6940: default:
6941: SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim);
6942: }
6943: break;
6944: case 3:
6945: switch (coneSize) {
6946: case 4:
6947: if (cMax >= 0) *cellRefiner = REFINER_HYBRID_SIMPLEX_3D;
6948: else *cellRefiner = REFINER_SIMPLEX_3D;
6949: break;
6950: case 6:
6951: if (cMax >= 0) *cellRefiner = REFINER_HYBRID_HEX_3D;
6952: else *cellRefiner = REFINER_HEX_3D;
6953: break;
6954: default:
6955: SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim);
6956: }
6957: break;
6958: default:
6959: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim);
6960: }
6961: return(0);
6962: }