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