xref: /petsc/src/dm/impls/plex/plexrefine.c (revision 75d3a19a3ad3747780b2a234045fa023d1fd2909)
1*75d3a19aSMatthew G. Knepley #include <petsc-private/dmpleximpl.h>   /*I      "petscdmplex.h"   I*/
2*75d3a19aSMatthew G. Knepley #include <petscsf.h>
3*75d3a19aSMatthew G. Knepley 
4*75d3a19aSMatthew G. Knepley #undef __FUNCT__
5*75d3a19aSMatthew G. Knepley #define __FUNCT__ "GetDepthStart_Private"
6*75d3a19aSMatthew G. Knepley PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart)
7*75d3a19aSMatthew G. Knepley {
8*75d3a19aSMatthew G. Knepley   PetscFunctionBegin;
9*75d3a19aSMatthew G. Knepley   if (cStart) *cStart = 0;
10*75d3a19aSMatthew G. Knepley   if (vStart) *vStart = depthSize[depth];
11*75d3a19aSMatthew G. Knepley   if (fStart) *fStart = depthSize[depth] + depthSize[0];
12*75d3a19aSMatthew G. Knepley   if (eStart) *eStart = depthSize[depth] + depthSize[0] + depthSize[depth-1];
13*75d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
14*75d3a19aSMatthew G. Knepley }
15*75d3a19aSMatthew G. Knepley 
16*75d3a19aSMatthew G. Knepley #undef __FUNCT__
17*75d3a19aSMatthew G. Knepley #define __FUNCT__ "GetDepthEnd_Private"
18*75d3a19aSMatthew G. Knepley PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd)
19*75d3a19aSMatthew G. Knepley {
20*75d3a19aSMatthew G. Knepley   PetscFunctionBegin;
21*75d3a19aSMatthew G. Knepley   if (cEnd) *cEnd = depthSize[depth];
22*75d3a19aSMatthew G. Knepley   if (vEnd) *vEnd = depthSize[depth] + depthSize[0];
23*75d3a19aSMatthew G. Knepley   if (fEnd) *fEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1];
24*75d3a19aSMatthew G. Knepley   if (eEnd) *eEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1];
25*75d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
26*75d3a19aSMatthew G. Knepley }
27*75d3a19aSMatthew G. Knepley 
28*75d3a19aSMatthew G. Knepley #undef __FUNCT__
29*75d3a19aSMatthew G. Knepley #define __FUNCT__ "CellRefinerGetSizes"
30*75d3a19aSMatthew G. Knepley PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[])
31*75d3a19aSMatthew G. Knepley {
32*75d3a19aSMatthew G. Knepley   PetscInt       cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax;
33*75d3a19aSMatthew G. Knepley   PetscErrorCode ierr;
34*75d3a19aSMatthew G. Knepley 
35*75d3a19aSMatthew G. Knepley   PetscFunctionBegin;
36*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
37*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
38*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
39*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
40*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr);
41*75d3a19aSMatthew G. Knepley   switch (refiner) {
42*75d3a19aSMatthew G. Knepley   case 1:
43*75d3a19aSMatthew G. Knepley     /* Simplicial 2D */
44*75d3a19aSMatthew G. Knepley     depthSize[0] = vEnd - vStart + fEnd - fStart;         /* Add a vertex on every face */
45*75d3a19aSMatthew G. Knepley     depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */
46*75d3a19aSMatthew G. Knepley     depthSize[2] = 4*(cEnd - cStart);                     /* Every cell split into 4 cells */
47*75d3a19aSMatthew G. Knepley     break;
48*75d3a19aSMatthew G. Knepley   case 3:
49*75d3a19aSMatthew G. Knepley     /* Hybrid 2D */
50*75d3a19aSMatthew G. Knepley     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
51*75d3a19aSMatthew G. Knepley     cMax = PetscMin(cEnd, cMax);
52*75d3a19aSMatthew G. Knepley     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
53*75d3a19aSMatthew G. Knepley     fMax         = PetscMin(fEnd, fMax);
54*75d3a19aSMatthew G. Knepley     depthSize[0] = vEnd - vStart + fMax - fStart;                                         /* Add a vertex on every face, but not hybrid faces */
55*75d3a19aSMatthew G. Knepley     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 */
56*75d3a19aSMatthew G. Knepley     depthSize[2] = 4*(cMax - cStart) + 2*(cEnd - cMax);                                   /* Interior cells split into 4 cells, Hybrid cells split into 2 cells */
57*75d3a19aSMatthew G. Knepley     break;
58*75d3a19aSMatthew G. Knepley   case 2:
59*75d3a19aSMatthew G. Knepley     /* Hex 2D */
60*75d3a19aSMatthew G. Knepley     depthSize[0] = vEnd - vStart + cEnd - cStart + fEnd - fStart; /* Add a vertex on every face and cell */
61*75d3a19aSMatthew G. Knepley     depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart);         /* Every face is split into 2 faces and 4 faces are added for each cell */
62*75d3a19aSMatthew G. Knepley     depthSize[2] = 4*(cEnd - cStart);                             /* Every cell split into 4 cells */
63*75d3a19aSMatthew G. Knepley     break;
64*75d3a19aSMatthew G. Knepley   default:
65*75d3a19aSMatthew G. Knepley     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
66*75d3a19aSMatthew G. Knepley   }
67*75d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
68*75d3a19aSMatthew G. Knepley }
69*75d3a19aSMatthew G. Knepley 
70*75d3a19aSMatthew G. Knepley #undef __FUNCT__
71*75d3a19aSMatthew G. Knepley #define __FUNCT__ "CellRefinerSetConeSizes"
72*75d3a19aSMatthew G. Knepley PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
73*75d3a19aSMatthew G. Knepley {
74*75d3a19aSMatthew G. Knepley   PetscInt       depth, cStart, cStartNew, cEnd, cMax, c, vStart, vStartNew, vEnd, vMax, v, fStart, fStartNew, fEnd, fMax, f, eStart, eStartNew, eEnd, eMax, r;
75*75d3a19aSMatthew G. Knepley   PetscErrorCode ierr;
76*75d3a19aSMatthew G. Knepley 
77*75d3a19aSMatthew G. Knepley   PetscFunctionBegin;
78*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
79*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
80*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
81*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
82*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
83*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr);
84*75d3a19aSMatthew G. Knepley   ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr);
85*75d3a19aSMatthew G. Knepley   switch (refiner) {
86*75d3a19aSMatthew G. Knepley   case 1:
87*75d3a19aSMatthew G. Knepley     /* Simplicial 2D */
88*75d3a19aSMatthew G. Knepley     /* All cells have 3 faces */
89*75d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
90*75d3a19aSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
91*75d3a19aSMatthew G. Knepley         const PetscInt newp = (c - cStart)*4 + r;
92*75d3a19aSMatthew G. Knepley 
93*75d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr);
94*75d3a19aSMatthew G. Knepley       }
95*75d3a19aSMatthew G. Knepley     }
96*75d3a19aSMatthew G. Knepley     /* Split faces have 2 vertices and the same cells as the parent */
97*75d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
98*75d3a19aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
99*75d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (f - fStart)*2 + r;
100*75d3a19aSMatthew G. Knepley         PetscInt       size;
101*75d3a19aSMatthew G. Knepley 
102*75d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
103*75d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
104*75d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
105*75d3a19aSMatthew G. Knepley       }
106*75d3a19aSMatthew G. Knepley     }
107*75d3a19aSMatthew G. Knepley     /* Interior faces have 2 vertices and 2 cells */
108*75d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
109*75d3a19aSMatthew G. Knepley       for (r = 0; r < 3; ++r) {
110*75d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r;
111*75d3a19aSMatthew G. Knepley 
112*75d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
113*75d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
114*75d3a19aSMatthew G. Knepley       }
115*75d3a19aSMatthew G. Knepley     }
116*75d3a19aSMatthew G. Knepley     /* Old vertices have identical supports */
117*75d3a19aSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
118*75d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (v - vStart);
119*75d3a19aSMatthew G. Knepley       PetscInt       size;
120*75d3a19aSMatthew G. Knepley 
121*75d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
122*75d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
123*75d3a19aSMatthew G. Knepley     }
124*75d3a19aSMatthew G. Knepley     /* Face vertices have 2 + cells*2 supports */
125*75d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
126*75d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
127*75d3a19aSMatthew G. Knepley       PetscInt       size;
128*75d3a19aSMatthew G. Knepley 
129*75d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
130*75d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2);CHKERRQ(ierr);
131*75d3a19aSMatthew G. Knepley     }
132*75d3a19aSMatthew G. Knepley     break;
133*75d3a19aSMatthew G. Knepley   case 2:
134*75d3a19aSMatthew G. Knepley     /* Hex 2D */
135*75d3a19aSMatthew G. Knepley     /* All cells have 4 faces */
136*75d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
137*75d3a19aSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
138*75d3a19aSMatthew G. Knepley         const PetscInt newp = (c - cStart)*4 + r;
139*75d3a19aSMatthew G. Knepley 
140*75d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
141*75d3a19aSMatthew G. Knepley       }
142*75d3a19aSMatthew G. Knepley     }
143*75d3a19aSMatthew G. Knepley     /* Split faces have 2 vertices and the same cells as the parent */
144*75d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
145*75d3a19aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
146*75d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (f - fStart)*2 + r;
147*75d3a19aSMatthew G. Knepley         PetscInt       size;
148*75d3a19aSMatthew G. Knepley 
149*75d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
150*75d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
151*75d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
152*75d3a19aSMatthew G. Knepley       }
153*75d3a19aSMatthew G. Knepley     }
154*75d3a19aSMatthew G. Knepley     /* Interior faces have 2 vertices and 2 cells */
155*75d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
156*75d3a19aSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
157*75d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r;
158*75d3a19aSMatthew G. Knepley 
159*75d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
160*75d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
161*75d3a19aSMatthew G. Knepley       }
162*75d3a19aSMatthew G. Knepley     }
163*75d3a19aSMatthew G. Knepley     /* Old vertices have identical supports */
164*75d3a19aSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
165*75d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (v - vStart);
166*75d3a19aSMatthew G. Knepley       PetscInt       size;
167*75d3a19aSMatthew G. Knepley 
168*75d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
169*75d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
170*75d3a19aSMatthew G. Knepley     }
171*75d3a19aSMatthew G. Knepley     /* Face vertices have 2 + cells supports */
172*75d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
173*75d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
174*75d3a19aSMatthew G. Knepley       PetscInt       size;
175*75d3a19aSMatthew G. Knepley 
176*75d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
177*75d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr);
178*75d3a19aSMatthew G. Knepley     }
179*75d3a19aSMatthew G. Knepley     /* Cell vertices have 4 supports */
180*75d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
181*75d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart);
182*75d3a19aSMatthew G. Knepley 
183*75d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr);
184*75d3a19aSMatthew G. Knepley     }
185*75d3a19aSMatthew G. Knepley     break;
186*75d3a19aSMatthew G. Knepley   case 3:
187*75d3a19aSMatthew G. Knepley     /* Hybrid 2D */
188*75d3a19aSMatthew G. Knepley     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
189*75d3a19aSMatthew G. Knepley     cMax = PetscMin(cEnd, cMax);
190*75d3a19aSMatthew G. Knepley     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
191*75d3a19aSMatthew G. Knepley     fMax = PetscMin(fEnd, fMax);
192*75d3a19aSMatthew G. Knepley     ierr = DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
193*75d3a19aSMatthew G. Knepley     /* Interior cells have 3 faces */
194*75d3a19aSMatthew G. Knepley     for (c = cStart; c < cMax; ++c) {
195*75d3a19aSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
196*75d3a19aSMatthew G. Knepley         const PetscInt newp = cStartNew + (c - cStart)*4 + r;
197*75d3a19aSMatthew G. Knepley 
198*75d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr);
199*75d3a19aSMatthew G. Knepley       }
200*75d3a19aSMatthew G. Knepley     }
201*75d3a19aSMatthew G. Knepley     /* Hybrid cells have 4 faces */
202*75d3a19aSMatthew G. Knepley     for (c = cMax; c < cEnd; ++c) {
203*75d3a19aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
204*75d3a19aSMatthew G. Knepley         const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r;
205*75d3a19aSMatthew G. Knepley 
206*75d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
207*75d3a19aSMatthew G. Knepley       }
208*75d3a19aSMatthew G. Knepley     }
209*75d3a19aSMatthew G. Knepley     /* Interior split faces have 2 vertices and the same cells as the parent */
210*75d3a19aSMatthew G. Knepley     for (f = fStart; f < fMax; ++f) {
211*75d3a19aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
212*75d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (f - fStart)*2 + r;
213*75d3a19aSMatthew G. Knepley         PetscInt       size;
214*75d3a19aSMatthew G. Knepley 
215*75d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
216*75d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
217*75d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
218*75d3a19aSMatthew G. Knepley       }
219*75d3a19aSMatthew G. Knepley     }
220*75d3a19aSMatthew G. Knepley     /* Interior cell faces have 2 vertices and 2 cells */
221*75d3a19aSMatthew G. Knepley     for (c = cStart; c < cMax; ++c) {
222*75d3a19aSMatthew G. Knepley       for (r = 0; r < 3; ++r) {
223*75d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r;
224*75d3a19aSMatthew G. Knepley 
225*75d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
226*75d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
227*75d3a19aSMatthew G. Knepley       }
228*75d3a19aSMatthew G. Knepley     }
229*75d3a19aSMatthew G. Knepley     /* Hybrid faces have 2 vertices and the same cells */
230*75d3a19aSMatthew G. Knepley     for (f = fMax; f < fEnd; ++f) {
231*75d3a19aSMatthew G. Knepley       const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax);
232*75d3a19aSMatthew G. Knepley       PetscInt       size;
233*75d3a19aSMatthew G. Knepley 
234*75d3a19aSMatthew G. Knepley       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
235*75d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
236*75d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
237*75d3a19aSMatthew G. Knepley     }
238*75d3a19aSMatthew G. Knepley     /* Hybrid cell faces have 2 vertices and 2 cells */
239*75d3a19aSMatthew G. Knepley     for (c = cMax; c < cEnd; ++c) {
240*75d3a19aSMatthew G. Knepley       const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax);
241*75d3a19aSMatthew G. Knepley 
242*75d3a19aSMatthew G. Knepley       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
243*75d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
244*75d3a19aSMatthew G. Knepley     }
245*75d3a19aSMatthew G. Knepley     /* Old vertices have identical supports */
246*75d3a19aSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
247*75d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (v - vStart);
248*75d3a19aSMatthew G. Knepley       PetscInt       size;
249*75d3a19aSMatthew G. Knepley 
250*75d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
251*75d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
252*75d3a19aSMatthew G. Knepley     }
253*75d3a19aSMatthew G. Knepley     /* Face vertices have 2 + (2 interior, 1 hybrid) supports */
254*75d3a19aSMatthew G. Knepley     for (f = fStart; f < fMax; ++f) {
255*75d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
256*75d3a19aSMatthew G. Knepley       const PetscInt *support;
257*75d3a19aSMatthew G. Knepley       PetscInt       size, newSize = 2, s;
258*75d3a19aSMatthew G. Knepley 
259*75d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
260*75d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
261*75d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
262*75d3a19aSMatthew G. Knepley         if (support[s] >= cMax) newSize += 1;
263*75d3a19aSMatthew G. Knepley         else newSize += 2;
264*75d3a19aSMatthew G. Knepley       }
265*75d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, newSize);CHKERRQ(ierr);
266*75d3a19aSMatthew G. Knepley     }
267*75d3a19aSMatthew G. Knepley     break;
268*75d3a19aSMatthew G. Knepley   default:
269*75d3a19aSMatthew G. Knepley     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
270*75d3a19aSMatthew G. Knepley   }
271*75d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
272*75d3a19aSMatthew G. Knepley }
273*75d3a19aSMatthew G. Knepley 
274*75d3a19aSMatthew G. Knepley #undef __FUNCT__
275*75d3a19aSMatthew G. Knepley #define __FUNCT__ "CellRefinerSetCones"
276*75d3a19aSMatthew G. Knepley PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
277*75d3a19aSMatthew G. Knepley {
278*75d3a19aSMatthew G. Knepley   PetscInt       depth, cStart, cEnd, cMax, cStartNew, cEndNew, c, vStart, vEnd, vMax, vStartNew, vEndNew, v, fStart, fEnd, fMax, fStartNew, fEndNew, f, eStart, eEnd, eMax, eStartNew, eEndNew, r, p;
279*75d3a19aSMatthew G. Knepley   PetscInt       maxSupportSize, *supportRef;
280*75d3a19aSMatthew G. Knepley   PetscErrorCode ierr;
281*75d3a19aSMatthew G. Knepley 
282*75d3a19aSMatthew G. Knepley   PetscFunctionBegin;
283*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
284*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
285*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
286*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
287*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
288*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr);
289*75d3a19aSMatthew G. Knepley   ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr);
290*75d3a19aSMatthew G. Knepley   ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr);
291*75d3a19aSMatthew G. Knepley   switch (refiner) {
292*75d3a19aSMatthew G. Knepley   case 1:
293*75d3a19aSMatthew G. Knepley     /* Simplicial 2D */
294*75d3a19aSMatthew G. Knepley     /*
295*75d3a19aSMatthew G. Knepley      2
296*75d3a19aSMatthew G. Knepley      |\
297*75d3a19aSMatthew G. Knepley      | \
298*75d3a19aSMatthew G. Knepley      |  \
299*75d3a19aSMatthew G. Knepley      |   \
300*75d3a19aSMatthew G. Knepley      | C  \
301*75d3a19aSMatthew G. Knepley      |     \
302*75d3a19aSMatthew G. Knepley      |      \
303*75d3a19aSMatthew G. Knepley      2---1---1
304*75d3a19aSMatthew G. Knepley      |\  D  / \
305*75d3a19aSMatthew G. Knepley      | 2   0   \
306*75d3a19aSMatthew G. Knepley      |A \ /  B  \
307*75d3a19aSMatthew G. Knepley      0---0-------1
308*75d3a19aSMatthew G. Knepley      */
309*75d3a19aSMatthew G. Knepley     /* All cells have 3 faces */
310*75d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
311*75d3a19aSMatthew G. Knepley       const PetscInt  newp = cStartNew + (c - cStart)*4;
312*75d3a19aSMatthew G. Knepley       const PetscInt *cone, *ornt;
313*75d3a19aSMatthew G. Knepley       PetscInt        coneNew[3], orntNew[3];
314*75d3a19aSMatthew G. Knepley 
315*75d3a19aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
316*75d3a19aSMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
317*75d3a19aSMatthew G. Knepley       /* A triangle */
318*75d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
319*75d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
320*75d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 2;
321*75d3a19aSMatthew G. Knepley       orntNew[1] = -2;
322*75d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
323*75d3a19aSMatthew G. Knepley       orntNew[2] = ornt[2];
324*75d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
325*75d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
326*75d3a19aSMatthew G. Knepley #if 1
327*75d3a19aSMatthew G. Knepley       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);
328*75d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
329*75d3a19aSMatthew G. Knepley         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);
330*75d3a19aSMatthew G. Knepley       }
331*75d3a19aSMatthew G. Knepley #endif
332*75d3a19aSMatthew G. Knepley       /* B triangle */
333*75d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
334*75d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
335*75d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
336*75d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
337*75d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 0;
338*75d3a19aSMatthew G. Knepley       orntNew[2] = -2;
339*75d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
340*75d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
341*75d3a19aSMatthew G. Knepley #if 1
342*75d3a19aSMatthew G. Knepley       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);
343*75d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
344*75d3a19aSMatthew G. Knepley         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);
345*75d3a19aSMatthew G. Knepley       }
346*75d3a19aSMatthew G. Knepley #endif
347*75d3a19aSMatthew G. Knepley       /* C triangle */
348*75d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 1;
349*75d3a19aSMatthew G. Knepley       orntNew[0] = -2;
350*75d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
351*75d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
352*75d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
353*75d3a19aSMatthew G. Knepley       orntNew[2] = ornt[2];
354*75d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
355*75d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
356*75d3a19aSMatthew G. Knepley #if 1
357*75d3a19aSMatthew G. Knepley       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);
358*75d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
359*75d3a19aSMatthew G. Knepley         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);
360*75d3a19aSMatthew G. Knepley       }
361*75d3a19aSMatthew G. Knepley #endif
362*75d3a19aSMatthew G. Knepley       /* D triangle */
363*75d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 0;
364*75d3a19aSMatthew G. Knepley       orntNew[0] = 0;
365*75d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 1;
366*75d3a19aSMatthew G. Knepley       orntNew[1] = 0;
367*75d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 2;
368*75d3a19aSMatthew G. Knepley       orntNew[2] = 0;
369*75d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
370*75d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
371*75d3a19aSMatthew G. Knepley #if 1
372*75d3a19aSMatthew G. Knepley       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);
373*75d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
374*75d3a19aSMatthew G. Knepley         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);
375*75d3a19aSMatthew G. Knepley       }
376*75d3a19aSMatthew G. Knepley #endif
377*75d3a19aSMatthew G. Knepley     }
378*75d3a19aSMatthew G. Knepley     /* Split faces have 2 vertices and the same cells as the parent */
379*75d3a19aSMatthew G. Knepley     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
380*75d3a19aSMatthew G. Knepley     ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr);
381*75d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
382*75d3a19aSMatthew G. Knepley       const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
383*75d3a19aSMatthew G. Knepley 
384*75d3a19aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
385*75d3a19aSMatthew G. Knepley         const PetscInt  newp = fStartNew + (f - fStart)*2 + r;
386*75d3a19aSMatthew G. Knepley         const PetscInt *cone, *support;
387*75d3a19aSMatthew G. Knepley         PetscInt        coneNew[2], coneSize, c, supportSize, s;
388*75d3a19aSMatthew G. Knepley 
389*75d3a19aSMatthew G. Knepley         ierr             = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
390*75d3a19aSMatthew G. Knepley         coneNew[0]       = vStartNew + (cone[0] - vStart);
391*75d3a19aSMatthew G. Knepley         coneNew[1]       = vStartNew + (cone[1] - vStart);
392*75d3a19aSMatthew G. Knepley         coneNew[(r+1)%2] = newv;
393*75d3a19aSMatthew G. Knepley         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
394*75d3a19aSMatthew G. Knepley #if 1
395*75d3a19aSMatthew G. Knepley         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
396*75d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
397*75d3a19aSMatthew G. Knepley           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);
398*75d3a19aSMatthew G. Knepley         }
399*75d3a19aSMatthew G. Knepley #endif
400*75d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
401*75d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
402*75d3a19aSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
403*75d3a19aSMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
404*75d3a19aSMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
405*75d3a19aSMatthew G. Knepley           for (c = 0; c < coneSize; ++c) {
406*75d3a19aSMatthew G. Knepley             if (cone[c] == f) break;
407*75d3a19aSMatthew G. Knepley           }
408*75d3a19aSMatthew G. Knepley           supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3;
409*75d3a19aSMatthew G. Knepley         }
410*75d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
411*75d3a19aSMatthew G. Knepley #if 1
412*75d3a19aSMatthew G. Knepley         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
413*75d3a19aSMatthew G. Knepley         for (p = 0; p < supportSize; ++p) {
414*75d3a19aSMatthew G. Knepley           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);
415*75d3a19aSMatthew G. Knepley         }
416*75d3a19aSMatthew G. Knepley #endif
417*75d3a19aSMatthew G. Knepley       }
418*75d3a19aSMatthew G. Knepley     }
419*75d3a19aSMatthew G. Knepley     /* Interior faces have 2 vertices and 2 cells */
420*75d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
421*75d3a19aSMatthew G. Knepley       const PetscInt *cone;
422*75d3a19aSMatthew G. Knepley 
423*75d3a19aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
424*75d3a19aSMatthew G. Knepley       for (r = 0; r < 3; ++r) {
425*75d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r;
426*75d3a19aSMatthew G. Knepley         PetscInt       coneNew[2];
427*75d3a19aSMatthew G. Knepley         PetscInt       supportNew[2];
428*75d3a19aSMatthew G. Knepley 
429*75d3a19aSMatthew G. Knepley         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r]       - fStart);
430*75d3a19aSMatthew G. Knepley         coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart);
431*75d3a19aSMatthew G. Knepley         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
432*75d3a19aSMatthew G. Knepley #if 1
433*75d3a19aSMatthew G. Knepley         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
434*75d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
435*75d3a19aSMatthew G. Knepley           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);
436*75d3a19aSMatthew G. Knepley         }
437*75d3a19aSMatthew G. Knepley #endif
438*75d3a19aSMatthew G. Knepley         supportNew[0] = (c - cStart)*4 + (r+1)%3;
439*75d3a19aSMatthew G. Knepley         supportNew[1] = (c - cStart)*4 + 3;
440*75d3a19aSMatthew G. Knepley         ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
441*75d3a19aSMatthew G. Knepley #if 1
442*75d3a19aSMatthew G. Knepley         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
443*75d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
444*75d3a19aSMatthew G. Knepley           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);
445*75d3a19aSMatthew G. Knepley         }
446*75d3a19aSMatthew G. Knepley #endif
447*75d3a19aSMatthew G. Knepley       }
448*75d3a19aSMatthew G. Knepley     }
449*75d3a19aSMatthew G. Knepley     /* Old vertices have identical supports */
450*75d3a19aSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
451*75d3a19aSMatthew G. Knepley       const PetscInt  newp = vStartNew + (v - vStart);
452*75d3a19aSMatthew G. Knepley       const PetscInt *support, *cone;
453*75d3a19aSMatthew G. Knepley       PetscInt        size, s;
454*75d3a19aSMatthew G. Knepley 
455*75d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
456*75d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
457*75d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
458*75d3a19aSMatthew G. Knepley         PetscInt r = 0;
459*75d3a19aSMatthew G. Knepley 
460*75d3a19aSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
461*75d3a19aSMatthew G. Knepley         if (cone[1] == v) r = 1;
462*75d3a19aSMatthew G. Knepley         supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
463*75d3a19aSMatthew G. Knepley       }
464*75d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
465*75d3a19aSMatthew G. Knepley #if 1
466*75d3a19aSMatthew G. Knepley       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
467*75d3a19aSMatthew G. Knepley       for (p = 0; p < size; ++p) {
468*75d3a19aSMatthew G. Knepley         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);
469*75d3a19aSMatthew G. Knepley       }
470*75d3a19aSMatthew G. Knepley #endif
471*75d3a19aSMatthew G. Knepley     }
472*75d3a19aSMatthew G. Knepley     /* Face vertices have 2 + cells*2 supports */
473*75d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
474*75d3a19aSMatthew G. Knepley       const PetscInt  newp = vStartNew + (vEnd - vStart) + (f - fStart);
475*75d3a19aSMatthew G. Knepley       const PetscInt *cone, *support;
476*75d3a19aSMatthew G. Knepley       PetscInt        size, s;
477*75d3a19aSMatthew G. Knepley 
478*75d3a19aSMatthew G. Knepley       ierr          = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
479*75d3a19aSMatthew G. Knepley       ierr          = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
480*75d3a19aSMatthew G. Knepley       supportRef[0] = fStartNew + (f - fStart)*2 + 0;
481*75d3a19aSMatthew G. Knepley       supportRef[1] = fStartNew + (f - fStart)*2 + 1;
482*75d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
483*75d3a19aSMatthew G. Knepley         PetscInt r = 0;
484*75d3a19aSMatthew G. Knepley 
485*75d3a19aSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
486*75d3a19aSMatthew G. Knepley         if      (cone[1] == f) r = 1;
487*75d3a19aSMatthew G. Knepley         else if (cone[2] == f) r = 2;
488*75d3a19aSMatthew G. Knepley         supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3;
489*75d3a19aSMatthew G. Knepley         supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r;
490*75d3a19aSMatthew G. Knepley       }
491*75d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
492*75d3a19aSMatthew G. Knepley #if 1
493*75d3a19aSMatthew G. Knepley       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
494*75d3a19aSMatthew G. Knepley       for (p = 0; p < 2+size*2; ++p) {
495*75d3a19aSMatthew G. Knepley         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);
496*75d3a19aSMatthew G. Knepley       }
497*75d3a19aSMatthew G. Knepley #endif
498*75d3a19aSMatthew G. Knepley     }
499*75d3a19aSMatthew G. Knepley     ierr = PetscFree(supportRef);CHKERRQ(ierr);
500*75d3a19aSMatthew G. Knepley     break;
501*75d3a19aSMatthew G. Knepley   case 2:
502*75d3a19aSMatthew G. Knepley     /* Hex 2D */
503*75d3a19aSMatthew G. Knepley     /*
504*75d3a19aSMatthew G. Knepley      3---------2---------2
505*75d3a19aSMatthew G. Knepley      |         |         |
506*75d3a19aSMatthew G. Knepley      |    D    2    C    |
507*75d3a19aSMatthew G. Knepley      |         |         |
508*75d3a19aSMatthew G. Knepley      3----3----0----1----1
509*75d3a19aSMatthew G. Knepley      |         |         |
510*75d3a19aSMatthew G. Knepley      |    A    0    B    |
511*75d3a19aSMatthew G. Knepley      |         |         |
512*75d3a19aSMatthew G. Knepley      0---------0---------1
513*75d3a19aSMatthew G. Knepley      */
514*75d3a19aSMatthew G. Knepley     /* All cells have 4 faces */
515*75d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
516*75d3a19aSMatthew G. Knepley       const PetscInt  newp = (c - cStart)*4;
517*75d3a19aSMatthew G. Knepley       const PetscInt *cone, *ornt;
518*75d3a19aSMatthew G. Knepley       PetscInt        coneNew[4], orntNew[4];
519*75d3a19aSMatthew G. Knepley 
520*75d3a19aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
521*75d3a19aSMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
522*75d3a19aSMatthew G. Knepley       /* A quad */
523*75d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
524*75d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
525*75d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 0;
526*75d3a19aSMatthew G. Knepley       orntNew[1] = 0;
527*75d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 3;
528*75d3a19aSMatthew G. Knepley       orntNew[2] = -2;
529*75d3a19aSMatthew G. Knepley       coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1);
530*75d3a19aSMatthew G. Knepley       orntNew[3] = ornt[3];
531*75d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
532*75d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
533*75d3a19aSMatthew G. Knepley #if 1
534*75d3a19aSMatthew G. Knepley       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);
535*75d3a19aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
536*75d3a19aSMatthew G. Knepley         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);
537*75d3a19aSMatthew G. Knepley       }
538*75d3a19aSMatthew G. Knepley #endif
539*75d3a19aSMatthew G. Knepley       /* B quad */
540*75d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
541*75d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
542*75d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
543*75d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
544*75d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 1;
545*75d3a19aSMatthew G. Knepley       orntNew[2] = 0;
546*75d3a19aSMatthew G. Knepley       coneNew[3] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 0;
547*75d3a19aSMatthew G. Knepley       orntNew[3] = -2;
548*75d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
549*75d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
550*75d3a19aSMatthew G. Knepley #if 1
551*75d3a19aSMatthew G. Knepley       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);
552*75d3a19aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
553*75d3a19aSMatthew G. Knepley         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);
554*75d3a19aSMatthew G. Knepley       }
555*75d3a19aSMatthew G. Knepley #endif
556*75d3a19aSMatthew G. Knepley       /* C quad */
557*75d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 1;
558*75d3a19aSMatthew G. Knepley       orntNew[0] = -2;
559*75d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
560*75d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
561*75d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
562*75d3a19aSMatthew G. Knepley       orntNew[2] = ornt[2];
563*75d3a19aSMatthew G. Knepley       coneNew[3] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 2;
564*75d3a19aSMatthew G. Knepley       orntNew[3] = 0;
565*75d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
566*75d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
567*75d3a19aSMatthew G. Knepley #if 1
568*75d3a19aSMatthew G. Knepley       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);
569*75d3a19aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
570*75d3a19aSMatthew G. Knepley         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);
571*75d3a19aSMatthew G. Knepley       }
572*75d3a19aSMatthew G. Knepley #endif
573*75d3a19aSMatthew G. Knepley       /* D quad */
574*75d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 3;
575*75d3a19aSMatthew G. Knepley       orntNew[0] = 0;
576*75d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 2;
577*75d3a19aSMatthew G. Knepley       orntNew[1] = -2;
578*75d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
579*75d3a19aSMatthew G. Knepley       orntNew[2] = ornt[2];
580*75d3a19aSMatthew G. Knepley       coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0);
581*75d3a19aSMatthew G. Knepley       orntNew[3] = ornt[3];
582*75d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
583*75d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
584*75d3a19aSMatthew G. Knepley #if 1
585*75d3a19aSMatthew G. Knepley       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);
586*75d3a19aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
587*75d3a19aSMatthew G. Knepley         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);
588*75d3a19aSMatthew G. Knepley       }
589*75d3a19aSMatthew G. Knepley #endif
590*75d3a19aSMatthew G. Knepley     }
591*75d3a19aSMatthew G. Knepley     /* Split faces have 2 vertices and the same cells as the parent */
592*75d3a19aSMatthew G. Knepley     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
593*75d3a19aSMatthew G. Knepley     ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr);
594*75d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
595*75d3a19aSMatthew G. Knepley       const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
596*75d3a19aSMatthew G. Knepley 
597*75d3a19aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
598*75d3a19aSMatthew G. Knepley         const PetscInt  newp = fStartNew + (f - fStart)*2 + r;
599*75d3a19aSMatthew G. Knepley         const PetscInt *cone, *support;
600*75d3a19aSMatthew G. Knepley         PetscInt        coneNew[2], coneSize, c, supportSize, s;
601*75d3a19aSMatthew G. Knepley 
602*75d3a19aSMatthew G. Knepley         ierr             = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
603*75d3a19aSMatthew G. Knepley         coneNew[0]       = vStartNew + (cone[0] - vStart);
604*75d3a19aSMatthew G. Knepley         coneNew[1]       = vStartNew + (cone[1] - vStart);
605*75d3a19aSMatthew G. Knepley         coneNew[(r+1)%2] = newv;
606*75d3a19aSMatthew G. Knepley         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
607*75d3a19aSMatthew G. Knepley #if 1
608*75d3a19aSMatthew G. Knepley         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
609*75d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
610*75d3a19aSMatthew G. Knepley           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);
611*75d3a19aSMatthew G. Knepley         }
612*75d3a19aSMatthew G. Knepley #endif
613*75d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
614*75d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
615*75d3a19aSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
616*75d3a19aSMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
617*75d3a19aSMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
618*75d3a19aSMatthew G. Knepley           for (c = 0; c < coneSize; ++c) {
619*75d3a19aSMatthew G. Knepley             if (cone[c] == f) break;
620*75d3a19aSMatthew G. Knepley           }
621*75d3a19aSMatthew G. Knepley           supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%4;
622*75d3a19aSMatthew G. Knepley         }
623*75d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
624*75d3a19aSMatthew G. Knepley #if 1
625*75d3a19aSMatthew G. Knepley         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
626*75d3a19aSMatthew G. Knepley         for (p = 0; p < supportSize; ++p) {
627*75d3a19aSMatthew G. Knepley           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);
628*75d3a19aSMatthew G. Knepley         }
629*75d3a19aSMatthew G. Knepley #endif
630*75d3a19aSMatthew G. Knepley       }
631*75d3a19aSMatthew G. Knepley     }
632*75d3a19aSMatthew G. Knepley     /* Interior faces have 2 vertices and 2 cells */
633*75d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
634*75d3a19aSMatthew G. Knepley       const PetscInt *cone;
635*75d3a19aSMatthew G. Knepley       PetscInt        coneNew[2], supportNew[2];
636*75d3a19aSMatthew G. Knepley 
637*75d3a19aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
638*75d3a19aSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
639*75d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r;
640*75d3a19aSMatthew G. Knepley 
641*75d3a19aSMatthew G. Knepley         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart);
642*75d3a19aSMatthew G. Knepley         coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd    - fStart) + (c - cStart);
643*75d3a19aSMatthew G. Knepley         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
644*75d3a19aSMatthew G. Knepley #if 1
645*75d3a19aSMatthew G. Knepley         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
646*75d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
647*75d3a19aSMatthew G. Knepley           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);
648*75d3a19aSMatthew G. Knepley         }
649*75d3a19aSMatthew G. Knepley #endif
650*75d3a19aSMatthew G. Knepley         supportNew[0] = (c - cStart)*4 + r;
651*75d3a19aSMatthew G. Knepley         supportNew[1] = (c - cStart)*4 + (r+1)%4;
652*75d3a19aSMatthew G. Knepley         ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
653*75d3a19aSMatthew G. Knepley #if 1
654*75d3a19aSMatthew G. Knepley         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
655*75d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
656*75d3a19aSMatthew G. Knepley           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);
657*75d3a19aSMatthew G. Knepley         }
658*75d3a19aSMatthew G. Knepley #endif
659*75d3a19aSMatthew G. Knepley       }
660*75d3a19aSMatthew G. Knepley     }
661*75d3a19aSMatthew G. Knepley     /* Old vertices have identical supports */
662*75d3a19aSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
663*75d3a19aSMatthew G. Knepley       const PetscInt  newp = vStartNew + (v - vStart);
664*75d3a19aSMatthew G. Knepley       const PetscInt *support, *cone;
665*75d3a19aSMatthew G. Knepley       PetscInt        size, s;
666*75d3a19aSMatthew G. Knepley 
667*75d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
668*75d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
669*75d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
670*75d3a19aSMatthew G. Knepley         PetscInt r = 0;
671*75d3a19aSMatthew G. Knepley 
672*75d3a19aSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
673*75d3a19aSMatthew G. Knepley         if (cone[1] == v) r = 1;
674*75d3a19aSMatthew G. Knepley         supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
675*75d3a19aSMatthew G. Knepley       }
676*75d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
677*75d3a19aSMatthew G. Knepley #if 1
678*75d3a19aSMatthew G. Knepley       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
679*75d3a19aSMatthew G. Knepley       for (p = 0; p < size; ++p) {
680*75d3a19aSMatthew G. Knepley         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);
681*75d3a19aSMatthew G. Knepley       }
682*75d3a19aSMatthew G. Knepley #endif
683*75d3a19aSMatthew G. Knepley     }
684*75d3a19aSMatthew G. Knepley     /* Face vertices have 2 + cells supports */
685*75d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
686*75d3a19aSMatthew G. Knepley       const PetscInt  newp = vStartNew + (vEnd - vStart) + (f - fStart);
687*75d3a19aSMatthew G. Knepley       const PetscInt *cone, *support;
688*75d3a19aSMatthew G. Knepley       PetscInt        size, s;
689*75d3a19aSMatthew G. Knepley 
690*75d3a19aSMatthew G. Knepley       ierr          = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
691*75d3a19aSMatthew G. Knepley       ierr          = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
692*75d3a19aSMatthew G. Knepley       supportRef[0] = fStartNew + (f - fStart)*2 + 0;
693*75d3a19aSMatthew G. Knepley       supportRef[1] = fStartNew + (f - fStart)*2 + 1;
694*75d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
695*75d3a19aSMatthew G. Knepley         PetscInt r = 0;
696*75d3a19aSMatthew G. Knepley 
697*75d3a19aSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
698*75d3a19aSMatthew G. Knepley         if      (cone[1] == f) r = 1;
699*75d3a19aSMatthew G. Knepley         else if (cone[2] == f) r = 2;
700*75d3a19aSMatthew G. Knepley         else if (cone[3] == f) r = 3;
701*75d3a19aSMatthew G. Knepley         supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r;
702*75d3a19aSMatthew G. Knepley       }
703*75d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
704*75d3a19aSMatthew G. Knepley #if 1
705*75d3a19aSMatthew G. Knepley       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
706*75d3a19aSMatthew G. Knepley       for (p = 0; p < 2+size; ++p) {
707*75d3a19aSMatthew G. Knepley         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);
708*75d3a19aSMatthew G. Knepley       }
709*75d3a19aSMatthew G. Knepley #endif
710*75d3a19aSMatthew G. Knepley     }
711*75d3a19aSMatthew G. Knepley     /* Cell vertices have 4 supports */
712*75d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
713*75d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart);
714*75d3a19aSMatthew G. Knepley       PetscInt       supportNew[4];
715*75d3a19aSMatthew G. Knepley 
716*75d3a19aSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
717*75d3a19aSMatthew G. Knepley         supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r;
718*75d3a19aSMatthew G. Knepley       }
719*75d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
720*75d3a19aSMatthew G. Knepley     }
721*75d3a19aSMatthew G. Knepley     break;
722*75d3a19aSMatthew G. Knepley   case 3:
723*75d3a19aSMatthew G. Knepley     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
724*75d3a19aSMatthew G. Knepley     cMax = PetscMin(cEnd, cMax);
725*75d3a19aSMatthew G. Knepley     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
726*75d3a19aSMatthew G. Knepley     fMax = PetscMin(fEnd, fMax);
727*75d3a19aSMatthew G. Knepley     /* Interior cells have 3 faces */
728*75d3a19aSMatthew G. Knepley     for (c = cStart; c < cMax; ++c) {
729*75d3a19aSMatthew G. Knepley       const PetscInt  newp = cStartNew + (c - cStart)*4;
730*75d3a19aSMatthew G. Knepley       const PetscInt *cone, *ornt;
731*75d3a19aSMatthew G. Knepley       PetscInt        coneNew[3], orntNew[3];
732*75d3a19aSMatthew G. Knepley 
733*75d3a19aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
734*75d3a19aSMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
735*75d3a19aSMatthew G. Knepley       /* A triangle */
736*75d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
737*75d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
738*75d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 2;
739*75d3a19aSMatthew G. Knepley       orntNew[1] = -2;
740*75d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
741*75d3a19aSMatthew G. Knepley       orntNew[2] = ornt[2];
742*75d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
743*75d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
744*75d3a19aSMatthew G. Knepley #if 1
745*75d3a19aSMatthew G. Knepley       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);
746*75d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
747*75d3a19aSMatthew G. Knepley         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);
748*75d3a19aSMatthew G. Knepley       }
749*75d3a19aSMatthew G. Knepley #endif
750*75d3a19aSMatthew G. Knepley       /* B triangle */
751*75d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
752*75d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
753*75d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
754*75d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
755*75d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 0;
756*75d3a19aSMatthew G. Knepley       orntNew[2] = -2;
757*75d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
758*75d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
759*75d3a19aSMatthew G. Knepley #if 1
760*75d3a19aSMatthew G. Knepley       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);
761*75d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
762*75d3a19aSMatthew G. Knepley         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);
763*75d3a19aSMatthew G. Knepley       }
764*75d3a19aSMatthew G. Knepley #endif
765*75d3a19aSMatthew G. Knepley       /* C triangle */
766*75d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 1;
767*75d3a19aSMatthew G. Knepley       orntNew[0] = -2;
768*75d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
769*75d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
770*75d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
771*75d3a19aSMatthew G. Knepley       orntNew[2] = ornt[2];
772*75d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
773*75d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
774*75d3a19aSMatthew G. Knepley #if 1
775*75d3a19aSMatthew G. Knepley       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);
776*75d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
777*75d3a19aSMatthew G. Knepley         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);
778*75d3a19aSMatthew G. Knepley       }
779*75d3a19aSMatthew G. Knepley #endif
780*75d3a19aSMatthew G. Knepley       /* D triangle */
781*75d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 0;
782*75d3a19aSMatthew G. Knepley       orntNew[0] = 0;
783*75d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 1;
784*75d3a19aSMatthew G. Knepley       orntNew[1] = 0;
785*75d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 2;
786*75d3a19aSMatthew G. Knepley       orntNew[2] = 0;
787*75d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
788*75d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
789*75d3a19aSMatthew G. Knepley #if 1
790*75d3a19aSMatthew G. Knepley       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);
791*75d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
792*75d3a19aSMatthew G. Knepley         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);
793*75d3a19aSMatthew G. Knepley       }
794*75d3a19aSMatthew G. Knepley #endif
795*75d3a19aSMatthew G. Knepley     }
796*75d3a19aSMatthew G. Knepley     /*
797*75d3a19aSMatthew G. Knepley      2----3----3
798*75d3a19aSMatthew G. Knepley      |         |
799*75d3a19aSMatthew G. Knepley      |    B    |
800*75d3a19aSMatthew G. Knepley      |         |
801*75d3a19aSMatthew G. Knepley      0----4--- 1
802*75d3a19aSMatthew G. Knepley      |         |
803*75d3a19aSMatthew G. Knepley      |    A    |
804*75d3a19aSMatthew G. Knepley      |         |
805*75d3a19aSMatthew G. Knepley      0----2----1
806*75d3a19aSMatthew G. Knepley      */
807*75d3a19aSMatthew G. Knepley     /* Hybrid cells have 4 faces */
808*75d3a19aSMatthew G. Knepley     for (c = cMax; c < cEnd; ++c) {
809*75d3a19aSMatthew G. Knepley       const PetscInt  newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2;
810*75d3a19aSMatthew G. Knepley       const PetscInt *cone, *ornt;
811*75d3a19aSMatthew G. Knepley       PetscInt        coneNew[4], orntNew[4];
812*75d3a19aSMatthew G. Knepley 
813*75d3a19aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
814*75d3a19aSMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
815*75d3a19aSMatthew G. Knepley       /* A quad */
816*75d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
817*75d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
818*75d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
819*75d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
820*75d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*3 + (cone[2] - fMax);
821*75d3a19aSMatthew G. Knepley       orntNew[2] = 0;
822*75d3a19aSMatthew G. Knepley       coneNew[3] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*3 + (fEnd    - fMax) + (c - cMax);
823*75d3a19aSMatthew G. Knepley       orntNew[3] = 0;
824*75d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
825*75d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
826*75d3a19aSMatthew G. Knepley #if 1
827*75d3a19aSMatthew G. Knepley       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);
828*75d3a19aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
829*75d3a19aSMatthew G. Knepley         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);
830*75d3a19aSMatthew G. Knepley       }
831*75d3a19aSMatthew G. Knepley #endif
832*75d3a19aSMatthew G. Knepley       /* B quad */
833*75d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
834*75d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
835*75d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
836*75d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
837*75d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*3 + (fEnd    - fMax) + (c - cMax);
838*75d3a19aSMatthew G. Knepley       orntNew[2] = 0;
839*75d3a19aSMatthew G. Knepley       coneNew[3] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*3 + (cone[3] - fMax);
840*75d3a19aSMatthew G. Knepley       orntNew[3] = 0;
841*75d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
842*75d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
843*75d3a19aSMatthew G. Knepley #if 1
844*75d3a19aSMatthew G. Knepley       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);
845*75d3a19aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
846*75d3a19aSMatthew G. Knepley         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);
847*75d3a19aSMatthew G. Knepley       }
848*75d3a19aSMatthew G. Knepley #endif
849*75d3a19aSMatthew G. Knepley     }
850*75d3a19aSMatthew G. Knepley     /* Interior split faces have 2 vertices and the same cells as the parent */
851*75d3a19aSMatthew G. Knepley     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
852*75d3a19aSMatthew G. Knepley     ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr);
853*75d3a19aSMatthew G. Knepley     for (f = fStart; f < fMax; ++f) {
854*75d3a19aSMatthew G. Knepley       const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
855*75d3a19aSMatthew G. Knepley 
856*75d3a19aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
857*75d3a19aSMatthew G. Knepley         const PetscInt  newp = fStartNew + (f - fStart)*2 + r;
858*75d3a19aSMatthew G. Knepley         const PetscInt *cone, *support;
859*75d3a19aSMatthew G. Knepley         PetscInt        coneNew[2], coneSize, c, supportSize, s;
860*75d3a19aSMatthew G. Knepley 
861*75d3a19aSMatthew G. Knepley         ierr             = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
862*75d3a19aSMatthew G. Knepley         coneNew[0]       = vStartNew + (cone[0] - vStart);
863*75d3a19aSMatthew G. Knepley         coneNew[1]       = vStartNew + (cone[1] - vStart);
864*75d3a19aSMatthew G. Knepley         coneNew[(r+1)%2] = newv;
865*75d3a19aSMatthew G. Knepley         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
866*75d3a19aSMatthew G. Knepley #if 1
867*75d3a19aSMatthew G. Knepley         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
868*75d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
869*75d3a19aSMatthew G. Knepley           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);
870*75d3a19aSMatthew G. Knepley         }
871*75d3a19aSMatthew G. Knepley #endif
872*75d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
873*75d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
874*75d3a19aSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
875*75d3a19aSMatthew G. Knepley           if (support[s] >= cMax) {
876*75d3a19aSMatthew G. Knepley             supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r;
877*75d3a19aSMatthew G. Knepley           } else {
878*75d3a19aSMatthew G. Knepley             ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
879*75d3a19aSMatthew G. Knepley             ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
880*75d3a19aSMatthew G. Knepley             for (c = 0; c < coneSize; ++c) {
881*75d3a19aSMatthew G. Knepley               if (cone[c] == f) break;
882*75d3a19aSMatthew G. Knepley             }
883*75d3a19aSMatthew G. Knepley             supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3;
884*75d3a19aSMatthew G. Knepley           }
885*75d3a19aSMatthew G. Knepley         }
886*75d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
887*75d3a19aSMatthew G. Knepley #if 1
888*75d3a19aSMatthew G. Knepley         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
889*75d3a19aSMatthew G. Knepley         for (p = 0; p < supportSize; ++p) {
890*75d3a19aSMatthew G. Knepley           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);
891*75d3a19aSMatthew G. Knepley         }
892*75d3a19aSMatthew G. Knepley #endif
893*75d3a19aSMatthew G. Knepley       }
894*75d3a19aSMatthew G. Knepley     }
895*75d3a19aSMatthew G. Knepley     /* Interior cell faces have 2 vertices and 2 cells */
896*75d3a19aSMatthew G. Knepley     for (c = cStart; c < cMax; ++c) {
897*75d3a19aSMatthew G. Knepley       const PetscInt *cone;
898*75d3a19aSMatthew G. Knepley 
899*75d3a19aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
900*75d3a19aSMatthew G. Knepley       for (r = 0; r < 3; ++r) {
901*75d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r;
902*75d3a19aSMatthew G. Knepley         PetscInt       coneNew[2];
903*75d3a19aSMatthew G. Knepley         PetscInt       supportNew[2];
904*75d3a19aSMatthew G. Knepley 
905*75d3a19aSMatthew G. Knepley         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r]       - fStart);
906*75d3a19aSMatthew G. Knepley         coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart);
907*75d3a19aSMatthew G. Knepley         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
908*75d3a19aSMatthew G. Knepley #if 1
909*75d3a19aSMatthew G. Knepley         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
910*75d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
911*75d3a19aSMatthew G. Knepley           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);
912*75d3a19aSMatthew G. Knepley         }
913*75d3a19aSMatthew G. Knepley #endif
914*75d3a19aSMatthew G. Knepley         supportNew[0] = (c - cStart)*4 + (r+1)%3;
915*75d3a19aSMatthew G. Knepley         supportNew[1] = (c - cStart)*4 + 3;
916*75d3a19aSMatthew G. Knepley         ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
917*75d3a19aSMatthew G. Knepley #if 1
918*75d3a19aSMatthew G. Knepley         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
919*75d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
920*75d3a19aSMatthew G. Knepley           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);
921*75d3a19aSMatthew G. Knepley         }
922*75d3a19aSMatthew G. Knepley #endif
923*75d3a19aSMatthew G. Knepley       }
924*75d3a19aSMatthew G. Knepley     }
925*75d3a19aSMatthew G. Knepley     /* Interior hybrid faces have 2 vertices and the same cells */
926*75d3a19aSMatthew G. Knepley     for (f = fMax; f < fEnd; ++f) {
927*75d3a19aSMatthew G. Knepley       const PetscInt  newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax);
928*75d3a19aSMatthew G. Knepley       const PetscInt *cone;
929*75d3a19aSMatthew G. Knepley       const PetscInt *support;
930*75d3a19aSMatthew G. Knepley       PetscInt        coneNew[2];
931*75d3a19aSMatthew G. Knepley       PetscInt        supportNew[2];
932*75d3a19aSMatthew G. Knepley       PetscInt        size, s, r;
933*75d3a19aSMatthew G. Knepley 
934*75d3a19aSMatthew G. Knepley       ierr       = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
935*75d3a19aSMatthew G. Knepley       coneNew[0] = vStartNew + (cone[0] - vStart);
936*75d3a19aSMatthew G. Knepley       coneNew[1] = vStartNew + (cone[1] - vStart);
937*75d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
938*75d3a19aSMatthew G. Knepley #if 1
939*75d3a19aSMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
940*75d3a19aSMatthew G. Knepley       for (p = 0; p < 2; ++p) {
941*75d3a19aSMatthew G. Knepley         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);
942*75d3a19aSMatthew G. Knepley       }
943*75d3a19aSMatthew G. Knepley #endif
944*75d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
945*75d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
946*75d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
947*75d3a19aSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
948*75d3a19aSMatthew G. Knepley         for (r = 0; r < 2; ++r) {
949*75d3a19aSMatthew G. Knepley           if (cone[r+2] == f) break;
950*75d3a19aSMatthew G. Knepley         }
951*75d3a19aSMatthew G. Knepley         supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r;
952*75d3a19aSMatthew G. Knepley       }
953*75d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
954*75d3a19aSMatthew G. Knepley #if 1
955*75d3a19aSMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
956*75d3a19aSMatthew G. Knepley       for (p = 0; p < size; ++p) {
957*75d3a19aSMatthew G. Knepley         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);
958*75d3a19aSMatthew G. Knepley       }
959*75d3a19aSMatthew G. Knepley #endif
960*75d3a19aSMatthew G. Knepley     }
961*75d3a19aSMatthew G. Knepley     /* Cell hybrid faces have 2 vertices and 2 cells */
962*75d3a19aSMatthew G. Knepley     for (c = cMax; c < cEnd; ++c) {
963*75d3a19aSMatthew G. Knepley       const PetscInt  newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax);
964*75d3a19aSMatthew G. Knepley       const PetscInt *cone;
965*75d3a19aSMatthew G. Knepley       PetscInt        coneNew[2];
966*75d3a19aSMatthew G. Knepley       PetscInt        supportNew[2];
967*75d3a19aSMatthew G. Knepley 
968*75d3a19aSMatthew G. Knepley       ierr       = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
969*75d3a19aSMatthew G. Knepley       coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart);
970*75d3a19aSMatthew G. Knepley       coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart);
971*75d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
972*75d3a19aSMatthew G. Knepley #if 1
973*75d3a19aSMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
974*75d3a19aSMatthew G. Knepley       for (p = 0; p < 2; ++p) {
975*75d3a19aSMatthew G. Knepley         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);
976*75d3a19aSMatthew G. Knepley       }
977*75d3a19aSMatthew G. Knepley #endif
978*75d3a19aSMatthew G. Knepley       supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0;
979*75d3a19aSMatthew G. Knepley       supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1;
980*75d3a19aSMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
981*75d3a19aSMatthew G. Knepley #if 1
982*75d3a19aSMatthew G. Knepley       if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
983*75d3a19aSMatthew G. Knepley       for (p = 0; p < 2; ++p) {
984*75d3a19aSMatthew G. Knepley         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);
985*75d3a19aSMatthew G. Knepley       }
986*75d3a19aSMatthew G. Knepley #endif
987*75d3a19aSMatthew G. Knepley     }
988*75d3a19aSMatthew G. Knepley     /* Old vertices have identical supports */
989*75d3a19aSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
990*75d3a19aSMatthew G. Knepley       const PetscInt  newp = vStartNew + (v - vStart);
991*75d3a19aSMatthew G. Knepley       const PetscInt *support, *cone;
992*75d3a19aSMatthew G. Knepley       PetscInt        size, s;
993*75d3a19aSMatthew G. Knepley 
994*75d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
995*75d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
996*75d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
997*75d3a19aSMatthew G. Knepley         if (support[s] >= fMax) {
998*75d3a19aSMatthew G. Knepley           supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax);
999*75d3a19aSMatthew G. Knepley         } else {
1000*75d3a19aSMatthew G. Knepley           PetscInt r = 0;
1001*75d3a19aSMatthew G. Knepley 
1002*75d3a19aSMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
1003*75d3a19aSMatthew G. Knepley           if (cone[1] == v) r = 1;
1004*75d3a19aSMatthew G. Knepley           supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
1005*75d3a19aSMatthew G. Knepley         }
1006*75d3a19aSMatthew G. Knepley       }
1007*75d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
1008*75d3a19aSMatthew G. Knepley #if 1
1009*75d3a19aSMatthew G. Knepley       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
1010*75d3a19aSMatthew G. Knepley       for (p = 0; p < size; ++p) {
1011*75d3a19aSMatthew G. Knepley         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);
1012*75d3a19aSMatthew G. Knepley       }
1013*75d3a19aSMatthew G. Knepley #endif
1014*75d3a19aSMatthew G. Knepley     }
1015*75d3a19aSMatthew G. Knepley     /* Face vertices have 2 + (2 interior, 1 hybrid) supports */
1016*75d3a19aSMatthew G. Knepley     for (f = fStart; f < fMax; ++f) {
1017*75d3a19aSMatthew G. Knepley       const PetscInt  newp = vStartNew + (vEnd - vStart) + (f - fStart);
1018*75d3a19aSMatthew G. Knepley       const PetscInt *cone, *support;
1019*75d3a19aSMatthew G. Knepley       PetscInt        size, newSize = 2, s;
1020*75d3a19aSMatthew G. Knepley 
1021*75d3a19aSMatthew G. Knepley       ierr          = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
1022*75d3a19aSMatthew G. Knepley       ierr          = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
1023*75d3a19aSMatthew G. Knepley       supportRef[0] = fStartNew + (f - fStart)*2 + 0;
1024*75d3a19aSMatthew G. Knepley       supportRef[1] = fStartNew + (f - fStart)*2 + 1;
1025*75d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
1026*75d3a19aSMatthew G. Knepley         PetscInt r = 0;
1027*75d3a19aSMatthew G. Knepley 
1028*75d3a19aSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
1029*75d3a19aSMatthew G. Knepley         if (support[s] >= cMax) {
1030*75d3a19aSMatthew G. Knepley           supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (support[s] - cMax);
1031*75d3a19aSMatthew G. Knepley 
1032*75d3a19aSMatthew G. Knepley           newSize += 1;
1033*75d3a19aSMatthew G. Knepley         } else {
1034*75d3a19aSMatthew G. Knepley           if      (cone[1] == f) r = 1;
1035*75d3a19aSMatthew G. Knepley           else if (cone[2] == f) r = 2;
1036*75d3a19aSMatthew G. Knepley           supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3;
1037*75d3a19aSMatthew G. Knepley           supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r;
1038*75d3a19aSMatthew G. Knepley 
1039*75d3a19aSMatthew G. Knepley           newSize += 2;
1040*75d3a19aSMatthew G. Knepley         }
1041*75d3a19aSMatthew G. Knepley       }
1042*75d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
1043*75d3a19aSMatthew G. Knepley #if 1
1044*75d3a19aSMatthew G. Knepley       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
1045*75d3a19aSMatthew G. Knepley       for (p = 0; p < newSize; ++p) {
1046*75d3a19aSMatthew G. Knepley         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);
1047*75d3a19aSMatthew G. Knepley       }
1048*75d3a19aSMatthew G. Knepley #endif
1049*75d3a19aSMatthew G. Knepley     }
1050*75d3a19aSMatthew G. Knepley     ierr = PetscFree(supportRef);CHKERRQ(ierr);
1051*75d3a19aSMatthew G. Knepley     break;
1052*75d3a19aSMatthew G. Knepley   default:
1053*75d3a19aSMatthew G. Knepley     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
1054*75d3a19aSMatthew G. Knepley   }
1055*75d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
1056*75d3a19aSMatthew G. Knepley }
1057*75d3a19aSMatthew G. Knepley 
1058*75d3a19aSMatthew G. Knepley #undef __FUNCT__
1059*75d3a19aSMatthew G. Knepley #define __FUNCT__ "CellRefinerSetCoordinates"
1060*75d3a19aSMatthew G. Knepley PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
1061*75d3a19aSMatthew G. Knepley {
1062*75d3a19aSMatthew G. Knepley   PetscSection   coordSection, coordSectionNew;
1063*75d3a19aSMatthew G. Knepley   Vec            coordinates, coordinatesNew;
1064*75d3a19aSMatthew G. Knepley   PetscScalar   *coords, *coordsNew;
1065*75d3a19aSMatthew G. Knepley   PetscInt       dim, depth, coordSizeNew, cStart, cEnd, c, vStart, vStartNew, vEnd, v, fStart, fEnd, fMax, f;
1066*75d3a19aSMatthew G. Knepley   PetscErrorCode ierr;
1067*75d3a19aSMatthew G. Knepley 
1068*75d3a19aSMatthew G. Knepley   PetscFunctionBegin;
1069*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
1070*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
1071*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
1072*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
1073*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
1074*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetHybridBounds(dm, NULL, &fMax, NULL, NULL);CHKERRQ(ierr);
1075*75d3a19aSMatthew G. Knepley   ierr = GetDepthStart_Private(depth, depthSize, NULL, NULL, NULL, &vStartNew);CHKERRQ(ierr);
1076*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr);
1077*75d3a19aSMatthew G. Knepley   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &coordSectionNew);CHKERRQ(ierr);
1078*75d3a19aSMatthew G. Knepley   ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr);
1079*75d3a19aSMatthew G. Knepley   ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dim);CHKERRQ(ierr);
1080*75d3a19aSMatthew G. Knepley   ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+depthSize[0]);CHKERRQ(ierr);
1081*75d3a19aSMatthew G. Knepley   if (fMax < 0) fMax = fEnd;
1082*75d3a19aSMatthew G. Knepley   switch (refiner) {
1083*75d3a19aSMatthew G. Knepley   case 1:
1084*75d3a19aSMatthew G. Knepley   case 2:
1085*75d3a19aSMatthew G. Knepley   case 3:
1086*75d3a19aSMatthew G. Knepley     /* Simplicial and Hex 2D */
1087*75d3a19aSMatthew G. Knepley     /* All vertices have the dim coordinates */
1088*75d3a19aSMatthew G. Knepley     for (v = vStartNew; v < vStartNew+depthSize[0]; ++v) {
1089*75d3a19aSMatthew G. Knepley       ierr = PetscSectionSetDof(coordSectionNew, v, dim);CHKERRQ(ierr);
1090*75d3a19aSMatthew G. Knepley       ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dim);CHKERRQ(ierr);
1091*75d3a19aSMatthew G. Knepley     }
1092*75d3a19aSMatthew G. Knepley     ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr);
1093*75d3a19aSMatthew G. Knepley     ierr = DMPlexSetCoordinateSection(rdm, coordSectionNew);CHKERRQ(ierr);
1094*75d3a19aSMatthew G. Knepley     ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
1095*75d3a19aSMatthew G. Knepley     ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr);
1096*75d3a19aSMatthew G. Knepley     ierr = VecCreate(PetscObjectComm((PetscObject)dm), &coordinatesNew);CHKERRQ(ierr);
1097*75d3a19aSMatthew G. Knepley     ierr = PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");CHKERRQ(ierr);
1098*75d3a19aSMatthew G. Knepley     ierr = VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr);
1099*75d3a19aSMatthew G. Knepley     ierr = VecSetFromOptions(coordinatesNew);CHKERRQ(ierr);
1100*75d3a19aSMatthew G. Knepley     ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr);
1101*75d3a19aSMatthew G. Knepley     ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr);
1102*75d3a19aSMatthew G. Knepley     /* Old vertices have the same coordinates */
1103*75d3a19aSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
1104*75d3a19aSMatthew G. Knepley       const PetscInt newv = vStartNew + (v - vStart);
1105*75d3a19aSMatthew G. Knepley       PetscInt       off, offnew, d;
1106*75d3a19aSMatthew G. Knepley 
1107*75d3a19aSMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr);
1108*75d3a19aSMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr);
1109*75d3a19aSMatthew G. Knepley       for (d = 0; d < dim; ++d) {
1110*75d3a19aSMatthew G. Knepley         coordsNew[offnew+d] = coords[off+d];
1111*75d3a19aSMatthew G. Knepley       }
1112*75d3a19aSMatthew G. Knepley     }
1113*75d3a19aSMatthew G. Knepley     /* Face vertices have the average of endpoint coordinates */
1114*75d3a19aSMatthew G. Knepley     for (f = fStart; f < fMax; ++f) {
1115*75d3a19aSMatthew G. Knepley       const PetscInt  newv = vStartNew + (vEnd - vStart) + (f - fStart);
1116*75d3a19aSMatthew G. Knepley       const PetscInt *cone;
1117*75d3a19aSMatthew G. Knepley       PetscInt        coneSize, offA, offB, offnew, d;
1118*75d3a19aSMatthew G. Knepley 
1119*75d3a19aSMatthew G. Knepley       ierr = DMPlexGetConeSize(dm, f, &coneSize);CHKERRQ(ierr);
1120*75d3a19aSMatthew G. Knepley       if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Face %d cone should have two vertices, not %d", f, coneSize);
1121*75d3a19aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
1122*75d3a19aSMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr);
1123*75d3a19aSMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr);
1124*75d3a19aSMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr);
1125*75d3a19aSMatthew G. Knepley       for (d = 0; d < dim; ++d) {
1126*75d3a19aSMatthew G. Knepley         coordsNew[offnew+d] = 0.5*(coords[offA+d] + coords[offB+d]);
1127*75d3a19aSMatthew G. Knepley       }
1128*75d3a19aSMatthew G. Knepley     }
1129*75d3a19aSMatthew G. Knepley     /* Just Hex 2D */
1130*75d3a19aSMatthew G. Knepley     if (refiner == 2) {
1131*75d3a19aSMatthew G. Knepley       /* Cell vertices have the average of corner coordinates */
1132*75d3a19aSMatthew G. Knepley       for (c = cStart; c < cEnd; ++c) {
1133*75d3a19aSMatthew G. Knepley         const PetscInt newv = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart);
1134*75d3a19aSMatthew G. Knepley         PetscInt      *cone = NULL;
1135*75d3a19aSMatthew G. Knepley         PetscInt       closureSize, coneSize = 0, offA, offB, offC, offD, offnew, p, d;
1136*75d3a19aSMatthew G. Knepley 
1137*75d3a19aSMatthew G. Knepley         ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr);
1138*75d3a19aSMatthew G. Knepley         for (p = 0; p < closureSize*2; p += 2) {
1139*75d3a19aSMatthew G. Knepley           const PetscInt point = cone[p];
1140*75d3a19aSMatthew G. Knepley           if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point;
1141*75d3a19aSMatthew G. Knepley         }
1142*75d3a19aSMatthew G. Knepley         if (coneSize != 4) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Quad %d cone should have four vertices, not %d", c, coneSize);
1143*75d3a19aSMatthew G. Knepley         ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr);
1144*75d3a19aSMatthew G. Knepley         ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr);
1145*75d3a19aSMatthew G. Knepley         ierr = PetscSectionGetOffset(coordSection, cone[2], &offC);CHKERRQ(ierr);
1146*75d3a19aSMatthew G. Knepley         ierr = PetscSectionGetOffset(coordSection, cone[3], &offD);CHKERRQ(ierr);
1147*75d3a19aSMatthew G. Knepley         ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr);
1148*75d3a19aSMatthew G. Knepley         for (d = 0; d < dim; ++d) {
1149*75d3a19aSMatthew G. Knepley           coordsNew[offnew+d] = 0.25*(coords[offA+d] + coords[offB+d] + coords[offC+d] + coords[offD+d]);
1150*75d3a19aSMatthew G. Knepley         }
1151*75d3a19aSMatthew G. Knepley         ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr);
1152*75d3a19aSMatthew G. Knepley       }
1153*75d3a19aSMatthew G. Knepley     }
1154*75d3a19aSMatthew G. Knepley     ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr);
1155*75d3a19aSMatthew G. Knepley     ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr);
1156*75d3a19aSMatthew G. Knepley     ierr = DMSetCoordinatesLocal(rdm, coordinatesNew);CHKERRQ(ierr);
1157*75d3a19aSMatthew G. Knepley     ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr);
1158*75d3a19aSMatthew G. Knepley     ierr = PetscSectionDestroy(&coordSectionNew);CHKERRQ(ierr);
1159*75d3a19aSMatthew G. Knepley     break;
1160*75d3a19aSMatthew G. Knepley   default:
1161*75d3a19aSMatthew G. Knepley     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
1162*75d3a19aSMatthew G. Knepley   }
1163*75d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
1164*75d3a19aSMatthew G. Knepley }
1165*75d3a19aSMatthew G. Knepley 
1166*75d3a19aSMatthew G. Knepley #undef __FUNCT__
1167*75d3a19aSMatthew G. Knepley #define __FUNCT__ "DMPlexCreateProcessSF"
1168*75d3a19aSMatthew G. Knepley PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess)
1169*75d3a19aSMatthew G. Knepley {
1170*75d3a19aSMatthew G. Knepley   PetscInt           numRoots, numLeaves, l;
1171*75d3a19aSMatthew G. Knepley   const PetscInt    *localPoints;
1172*75d3a19aSMatthew G. Knepley   const PetscSFNode *remotePoints;
1173*75d3a19aSMatthew G. Knepley   PetscInt          *localPointsNew;
1174*75d3a19aSMatthew G. Knepley   PetscSFNode       *remotePointsNew;
1175*75d3a19aSMatthew G. Knepley   PetscInt          *ranks, *ranksNew;
1176*75d3a19aSMatthew G. Knepley   PetscErrorCode     ierr;
1177*75d3a19aSMatthew G. Knepley 
1178*75d3a19aSMatthew G. Knepley   PetscFunctionBegin;
1179*75d3a19aSMatthew G. Knepley   ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr);
1180*75d3a19aSMatthew G. Knepley   ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranks);CHKERRQ(ierr);
1181*75d3a19aSMatthew G. Knepley   for (l = 0; l < numLeaves; ++l) {
1182*75d3a19aSMatthew G. Knepley     ranks[l] = remotePoints[l].rank;
1183*75d3a19aSMatthew G. Knepley   }
1184*75d3a19aSMatthew G. Knepley   ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr);
1185*75d3a19aSMatthew G. Knepley   ierr = PetscMalloc(numLeaves * sizeof(PetscInt),    &ranksNew);CHKERRQ(ierr);
1186*75d3a19aSMatthew G. Knepley   ierr = PetscMalloc(numLeaves * sizeof(PetscInt),    &localPointsNew);CHKERRQ(ierr);
1187*75d3a19aSMatthew G. Knepley   ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr);
1188*75d3a19aSMatthew G. Knepley   for (l = 0; l < numLeaves; ++l) {
1189*75d3a19aSMatthew G. Knepley     ranksNew[l]              = ranks[l];
1190*75d3a19aSMatthew G. Knepley     localPointsNew[l]        = l;
1191*75d3a19aSMatthew G. Knepley     remotePointsNew[l].index = 0;
1192*75d3a19aSMatthew G. Knepley     remotePointsNew[l].rank  = ranksNew[l];
1193*75d3a19aSMatthew G. Knepley   }
1194*75d3a19aSMatthew G. Knepley   ierr = PetscFree(ranks);CHKERRQ(ierr);
1195*75d3a19aSMatthew G. Knepley   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr);
1196*75d3a19aSMatthew G. Knepley   ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess);CHKERRQ(ierr);
1197*75d3a19aSMatthew G. Knepley   ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr);
1198*75d3a19aSMatthew G. Knepley   ierr = PetscSFSetGraph(*sfProcess, 1, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr);
1199*75d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
1200*75d3a19aSMatthew G. Knepley }
1201*75d3a19aSMatthew G. Knepley 
1202*75d3a19aSMatthew G. Knepley #undef __FUNCT__
1203*75d3a19aSMatthew G. Knepley #define __FUNCT__ "CellRefinerCreateSF"
1204*75d3a19aSMatthew G. Knepley PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
1205*75d3a19aSMatthew G. Knepley {
1206*75d3a19aSMatthew G. Knepley   PetscSF            sf, sfNew, sfProcess;
1207*75d3a19aSMatthew G. Knepley   IS                 processRanks;
1208*75d3a19aSMatthew G. Knepley   MPI_Datatype       depthType;
1209*75d3a19aSMatthew G. Knepley   PetscInt           numRoots, numLeaves, numLeavesNew = 0, l, m;
1210*75d3a19aSMatthew G. Knepley   const PetscInt    *localPoints, *neighbors;
1211*75d3a19aSMatthew G. Knepley   const PetscSFNode *remotePoints;
1212*75d3a19aSMatthew G. Knepley   PetscInt          *localPointsNew;
1213*75d3a19aSMatthew G. Knepley   PetscSFNode       *remotePointsNew;
1214*75d3a19aSMatthew G. Knepley   PetscInt          *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew;
1215*75d3a19aSMatthew G. Knepley   PetscInt           depth, numNeighbors, pStartNew, pEndNew, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eStartNew, eEnd, eMax, r, n;
1216*75d3a19aSMatthew G. Knepley   PetscErrorCode     ierr;
1217*75d3a19aSMatthew G. Knepley 
1218*75d3a19aSMatthew G. Knepley   PetscFunctionBegin;
1219*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr);
1220*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
1221*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
1222*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
1223*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
1224*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
1225*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr);
1226*75d3a19aSMatthew G. Knepley   ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr);
1227*75d3a19aSMatthew G. Knepley   switch (refiner) {
1228*75d3a19aSMatthew G. Knepley   case 3:
1229*75d3a19aSMatthew G. Knepley     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
1230*75d3a19aSMatthew G. Knepley     cMax = PetscMin(cEnd, cMax);
1231*75d3a19aSMatthew G. Knepley     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
1232*75d3a19aSMatthew G. Knepley     fMax = PetscMin(fEnd, fMax);
1233*75d3a19aSMatthew G. Knepley   }
1234*75d3a19aSMatthew G. Knepley   ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr);
1235*75d3a19aSMatthew G. Knepley   ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr);
1236*75d3a19aSMatthew G. Knepley   /* Caculate size of new SF */
1237*75d3a19aSMatthew G. Knepley   ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr);
1238*75d3a19aSMatthew G. Knepley   if (numRoots < 0) PetscFunctionReturn(0);
1239*75d3a19aSMatthew G. Knepley   for (l = 0; l < numLeaves; ++l) {
1240*75d3a19aSMatthew G. Knepley     const PetscInt p = localPoints[l];
1241*75d3a19aSMatthew G. Knepley 
1242*75d3a19aSMatthew G. Knepley     switch (refiner) {
1243*75d3a19aSMatthew G. Knepley     case 1:
1244*75d3a19aSMatthew G. Knepley       /* Simplicial 2D */
1245*75d3a19aSMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
1246*75d3a19aSMatthew G. Knepley         /* Old vertices stay the same */
1247*75d3a19aSMatthew G. Knepley         ++numLeavesNew;
1248*75d3a19aSMatthew G. Knepley       } else if ((p >= fStart) && (p < fEnd)) {
1249*75d3a19aSMatthew G. Knepley         /* Old faces add new faces and vertex */
1250*75d3a19aSMatthew G. Knepley         numLeavesNew += 1 + 2;
1251*75d3a19aSMatthew G. Knepley       } else if ((p >= cStart) && (p < cEnd)) {
1252*75d3a19aSMatthew G. Knepley         /* Old cells add new cells and interior faces */
1253*75d3a19aSMatthew G. Knepley         numLeavesNew += 4 + 3;
1254*75d3a19aSMatthew G. Knepley       }
1255*75d3a19aSMatthew G. Knepley       break;
1256*75d3a19aSMatthew G. Knepley     case 2:
1257*75d3a19aSMatthew G. Knepley       /* Hex 2D */
1258*75d3a19aSMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
1259*75d3a19aSMatthew G. Knepley         /* Old vertices stay the same */
1260*75d3a19aSMatthew G. Knepley         ++numLeavesNew;
1261*75d3a19aSMatthew G. Knepley       } else if ((p >= fStart) && (p < fEnd)) {
1262*75d3a19aSMatthew G. Knepley         /* Old faces add new faces and vertex */
1263*75d3a19aSMatthew G. Knepley         numLeavesNew += 1 + 2;
1264*75d3a19aSMatthew G. Knepley       } else if ((p >= cStart) && (p < cEnd)) {
1265*75d3a19aSMatthew G. Knepley         /* Old cells add new cells and interior faces */
1266*75d3a19aSMatthew G. Knepley         numLeavesNew += 4 + 4;
1267*75d3a19aSMatthew G. Knepley       }
1268*75d3a19aSMatthew G. Knepley       break;
1269*75d3a19aSMatthew G. Knepley     default:
1270*75d3a19aSMatthew G. Knepley       SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
1271*75d3a19aSMatthew G. Knepley     }
1272*75d3a19aSMatthew G. Knepley   }
1273*75d3a19aSMatthew G. Knepley   /* Communicate depthSizes for each remote rank */
1274*75d3a19aSMatthew G. Knepley   ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr);
1275*75d3a19aSMatthew G. Knepley   ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr);
1276*75d3a19aSMatthew G. Knepley   ierr = PetscMalloc5((depth+1)*numNeighbors,PetscInt,&rdepthSize,numNeighbors,PetscInt,&rvStartNew,numNeighbors,PetscInt,&reStartNew,numNeighbors,PetscInt,&rfStartNew,numNeighbors,PetscInt,&rcStartNew);CHKERRQ(ierr);
1277*75d3a19aSMatthew G. Knepley   ierr = PetscMalloc7(depth+1,PetscInt,&depthSizeOld,(depth+1)*numNeighbors,PetscInt,&rdepthSizeOld,(depth+1)*numNeighbors,PetscInt,&rdepthMaxOld,numNeighbors,PetscInt,&rvStart,numNeighbors,PetscInt,&reStart,numNeighbors,PetscInt,&rfStart,numNeighbors,PetscInt,&rcStart);CHKERRQ(ierr);
1278*75d3a19aSMatthew G. Knepley   ierr = MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);CHKERRQ(ierr);
1279*75d3a19aSMatthew G. Knepley   ierr = MPI_Type_commit(&depthType);CHKERRQ(ierr);
1280*75d3a19aSMatthew G. Knepley   ierr = PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr);
1281*75d3a19aSMatthew G. Knepley   ierr = PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr);
1282*75d3a19aSMatthew G. Knepley   for (n = 0; n < numNeighbors; ++n) {
1283*75d3a19aSMatthew G. Knepley     ierr = GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);CHKERRQ(ierr);
1284*75d3a19aSMatthew G. Knepley   }
1285*75d3a19aSMatthew G. Knepley   depthSizeOld[depth]   = cMax;
1286*75d3a19aSMatthew G. Knepley   depthSizeOld[0]       = vMax;
1287*75d3a19aSMatthew G. Knepley   depthSizeOld[depth-1] = fMax;
1288*75d3a19aSMatthew G. Knepley   depthSizeOld[1]       = eMax;
1289*75d3a19aSMatthew G. Knepley 
1290*75d3a19aSMatthew G. Knepley   ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr);
1291*75d3a19aSMatthew G. Knepley   ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr);
1292*75d3a19aSMatthew G. Knepley 
1293*75d3a19aSMatthew G. Knepley   depthSizeOld[depth]   = cEnd - cStart;
1294*75d3a19aSMatthew G. Knepley   depthSizeOld[0]       = vEnd - vStart;
1295*75d3a19aSMatthew G. Knepley   depthSizeOld[depth-1] = fEnd - fStart;
1296*75d3a19aSMatthew G. Knepley   depthSizeOld[1]       = eEnd - eStart;
1297*75d3a19aSMatthew G. Knepley 
1298*75d3a19aSMatthew G. Knepley   ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr);
1299*75d3a19aSMatthew G. Knepley   ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr);
1300*75d3a19aSMatthew G. Knepley   for (n = 0; n < numNeighbors; ++n) {
1301*75d3a19aSMatthew G. Knepley     ierr = GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);CHKERRQ(ierr);
1302*75d3a19aSMatthew G. Knepley   }
1303*75d3a19aSMatthew G. Knepley   ierr = MPI_Type_free(&depthType);CHKERRQ(ierr);
1304*75d3a19aSMatthew G. Knepley   ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr);
1305*75d3a19aSMatthew G. Knepley   /* Calculate new point SF */
1306*75d3a19aSMatthew G. Knepley   ierr = PetscMalloc(numLeavesNew * sizeof(PetscInt),    &localPointsNew);CHKERRQ(ierr);
1307*75d3a19aSMatthew G. Knepley   ierr = PetscMalloc(numLeavesNew * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr);
1308*75d3a19aSMatthew G. Knepley   ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr);
1309*75d3a19aSMatthew G. Knepley   for (l = 0, m = 0; l < numLeaves; ++l) {
1310*75d3a19aSMatthew G. Knepley     PetscInt    p     = localPoints[l];
1311*75d3a19aSMatthew G. Knepley     PetscInt    rp    = remotePoints[l].index, n;
1312*75d3a19aSMatthew G. Knepley     PetscMPIInt rrank = remotePoints[l].rank;
1313*75d3a19aSMatthew G. Knepley 
1314*75d3a19aSMatthew G. Knepley     ierr = PetscFindInt(rrank, numNeighbors, neighbors, &n);CHKERRQ(ierr);
1315*75d3a19aSMatthew G. Knepley     if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank);
1316*75d3a19aSMatthew G. Knepley     switch (refiner) {
1317*75d3a19aSMatthew G. Knepley     case 1:
1318*75d3a19aSMatthew G. Knepley       /* Simplicial 2D */
1319*75d3a19aSMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
1320*75d3a19aSMatthew G. Knepley         /* Old vertices stay the same */
1321*75d3a19aSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (p  - vStart);
1322*75d3a19aSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
1323*75d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
1324*75d3a19aSMatthew G. Knepley         ++m;
1325*75d3a19aSMatthew G. Knepley       } else if ((p >= fStart) && (p < fEnd)) {
1326*75d3a19aSMatthew G. Knepley         /* Old faces add new faces and vertex */
1327*75d3a19aSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - fStart);
1328*75d3a19aSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
1329*75d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
1330*75d3a19aSMatthew G. Knepley         ++m;
1331*75d3a19aSMatthew G. Knepley         for (r = 0; r < 2; ++r, ++m) {
1332*75d3a19aSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (p  - fStart)*2     + r;
1333*75d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
1334*75d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
1335*75d3a19aSMatthew G. Knepley         }
1336*75d3a19aSMatthew G. Knepley       } else if ((p >= cStart) && (p < cEnd)) {
1337*75d3a19aSMatthew G. Knepley         /* Old cells add new cells and interior faces */
1338*75d3a19aSMatthew G. Knepley         for (r = 0; r < 4; ++r, ++m) {
1339*75d3a19aSMatthew G. Knepley           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r;
1340*75d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
1341*75d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
1342*75d3a19aSMatthew G. Knepley         }
1343*75d3a19aSMatthew G. Knepley         for (r = 0; r < 3; ++r, ++m) {
1344*75d3a19aSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (fEnd - fStart)*2                    + (p  - cStart)*3     + r;
1345*75d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r;
1346*75d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
1347*75d3a19aSMatthew G. Knepley         }
1348*75d3a19aSMatthew G. Knepley       }
1349*75d3a19aSMatthew G. Knepley       break;
1350*75d3a19aSMatthew G. Knepley     case 2:
1351*75d3a19aSMatthew G. Knepley       /* Hex 2D */
1352*75d3a19aSMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
1353*75d3a19aSMatthew G. Knepley         /* Old vertices stay the same */
1354*75d3a19aSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (p  - vStart);
1355*75d3a19aSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
1356*75d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
1357*75d3a19aSMatthew G. Knepley         ++m;
1358*75d3a19aSMatthew G. Knepley       } else if ((p >= fStart) && (p < fEnd)) {
1359*75d3a19aSMatthew G. Knepley         /* Old faces add new faces and vertex */
1360*75d3a19aSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - fStart);
1361*75d3a19aSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
1362*75d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
1363*75d3a19aSMatthew G. Knepley         ++m;
1364*75d3a19aSMatthew G. Knepley         for (r = 0; r < 2; ++r, ++m) {
1365*75d3a19aSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (p  - fStart)*2     + r;
1366*75d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
1367*75d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
1368*75d3a19aSMatthew G. Knepley         }
1369*75d3a19aSMatthew G. Knepley       } else if ((p >= cStart) && (p < cEnd)) {
1370*75d3a19aSMatthew G. Knepley         /* Old cells add new cells and interior faces */
1371*75d3a19aSMatthew G. Knepley         for (r = 0; r < 4; ++r, ++m) {
1372*75d3a19aSMatthew G. Knepley           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r;
1373*75d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
1374*75d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
1375*75d3a19aSMatthew G. Knepley         }
1376*75d3a19aSMatthew G. Knepley         for (r = 0; r < 4; ++r, ++m) {
1377*75d3a19aSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (fEnd - fStart)*2                    + (p  - cStart)*4     + r;
1378*75d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*4 + r;
1379*75d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
1380*75d3a19aSMatthew G. Knepley         }
1381*75d3a19aSMatthew G. Knepley       }
1382*75d3a19aSMatthew G. Knepley       break;
1383*75d3a19aSMatthew G. Knepley     case 3:
1384*75d3a19aSMatthew G. Knepley       /* Hybrid simplicial 2D */
1385*75d3a19aSMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
1386*75d3a19aSMatthew G. Knepley         /* Old vertices stay the same */
1387*75d3a19aSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (p  - vStart);
1388*75d3a19aSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
1389*75d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
1390*75d3a19aSMatthew G. Knepley         ++m;
1391*75d3a19aSMatthew G. Knepley       } else if ((p >= fStart) && (p < fMax)) {
1392*75d3a19aSMatthew G. Knepley         /* Old interior faces add new faces and vertex */
1393*75d3a19aSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - fStart);
1394*75d3a19aSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
1395*75d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
1396*75d3a19aSMatthew G. Knepley         ++m;
1397*75d3a19aSMatthew G. Knepley         for (r = 0; r < 2; ++r, ++m) {
1398*75d3a19aSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (p  - fStart)*2     + r;
1399*75d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
1400*75d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
1401*75d3a19aSMatthew G. Knepley         }
1402*75d3a19aSMatthew G. Knepley       } else if ((p >= fMax) && (p < fEnd)) {
1403*75d3a19aSMatthew G. Knepley         /* Old hybrid faces stay the same */
1404*75d3a19aSMatthew G. Knepley         localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*2     + (p  - fMax);
1405*75d3a19aSMatthew G. Knepley         remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]);
1406*75d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
1407*75d3a19aSMatthew G. Knepley         ++m;
1408*75d3a19aSMatthew G. Knepley       } else if ((p >= cStart) && (p < cMax)) {
1409*75d3a19aSMatthew G. Knepley         /* Old interior cells add new cells and interior faces */
1410*75d3a19aSMatthew G. Knepley         for (r = 0; r < 4; ++r, ++m) {
1411*75d3a19aSMatthew G. Knepley           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r;
1412*75d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
1413*75d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
1414*75d3a19aSMatthew G. Knepley         }
1415*75d3a19aSMatthew G. Knepley         for (r = 0; r < 3; ++r, ++m) {
1416*75d3a19aSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*2     + (p  - cStart)*3     + r;
1417*75d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r;
1418*75d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
1419*75d3a19aSMatthew G. Knepley         }
1420*75d3a19aSMatthew G. Knepley       } else if ((p >= cStart) && (p < cMax)) {
1421*75d3a19aSMatthew G. Knepley         /* Old hybrid cells add new cells and hybrid face */
1422*75d3a19aSMatthew G. Knepley         for (r = 0; r < 2; ++r, ++m) {
1423*75d3a19aSMatthew G. Knepley           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r;
1424*75d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
1425*75d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
1426*75d3a19aSMatthew G. Knepley         }
1427*75d3a19aSMatthew G. Knepley         localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*2     + (cMax                            - cStart)*3     + (p  - cMax);
1428*75d3a19aSMatthew G. Knepley         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]);
1429*75d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
1430*75d3a19aSMatthew G. Knepley         ++m;
1431*75d3a19aSMatthew G. Knepley       }
1432*75d3a19aSMatthew G. Knepley       break;
1433*75d3a19aSMatthew G. Knepley     default:
1434*75d3a19aSMatthew G. Knepley       SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
1435*75d3a19aSMatthew G. Knepley     }
1436*75d3a19aSMatthew G. Knepley   }
1437*75d3a19aSMatthew G. Knepley   ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr);
1438*75d3a19aSMatthew G. Knepley   ierr = ISDestroy(&processRanks);CHKERRQ(ierr);
1439*75d3a19aSMatthew G. Knepley   ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr);
1440*75d3a19aSMatthew G. Knepley   ierr = PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);CHKERRQ(ierr);
1441*75d3a19aSMatthew G. Knepley   ierr = PetscFree6(depthSizeOld,rdepthSizeOld,rvStart,reStart,rfStart,rcStart);CHKERRQ(ierr);
1442*75d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
1443*75d3a19aSMatthew G. Knepley }
1444*75d3a19aSMatthew G. Knepley 
1445*75d3a19aSMatthew G. Knepley #undef __FUNCT__
1446*75d3a19aSMatthew G. Knepley #define __FUNCT__ "CellRefinerCreateLabels"
1447*75d3a19aSMatthew G. Knepley PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
1448*75d3a19aSMatthew G. Knepley {
1449*75d3a19aSMatthew G. Knepley   PetscInt       numLabels, l;
1450*75d3a19aSMatthew G. Knepley   PetscInt       newp, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eEnd, eMax, r;
1451*75d3a19aSMatthew G. Knepley   PetscErrorCode ierr;
1452*75d3a19aSMatthew G. Knepley 
1453*75d3a19aSMatthew G. Knepley   PetscFunctionBegin;
1454*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
1455*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
1456*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
1457*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
1458*75d3a19aSMatthew G. Knepley 
1459*75d3a19aSMatthew G. Knepley   cStartNew = 0;
1460*75d3a19aSMatthew G. Knepley   vStartNew = depthSize[2];
1461*75d3a19aSMatthew G. Knepley   fStartNew = depthSize[2] + depthSize[0];
1462*75d3a19aSMatthew G. Knepley 
1463*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr);
1464*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr);
1465*75d3a19aSMatthew G. Knepley   switch (refiner) {
1466*75d3a19aSMatthew G. Knepley   case 3:
1467*75d3a19aSMatthew G. Knepley     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
1468*75d3a19aSMatthew G. Knepley     cMax = PetscMin(cEnd, cMax);
1469*75d3a19aSMatthew G. Knepley     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
1470*75d3a19aSMatthew G. Knepley     fMax = PetscMin(fEnd, fMax);
1471*75d3a19aSMatthew G. Knepley   }
1472*75d3a19aSMatthew G. Knepley   for (l = 0; l < numLabels; ++l) {
1473*75d3a19aSMatthew G. Knepley     DMLabel         label, labelNew;
1474*75d3a19aSMatthew G. Knepley     const char     *lname;
1475*75d3a19aSMatthew G. Knepley     PetscBool       isDepth;
1476*75d3a19aSMatthew G. Knepley     IS              valueIS;
1477*75d3a19aSMatthew G. Knepley     const PetscInt *values;
1478*75d3a19aSMatthew G. Knepley     PetscInt        numValues, val;
1479*75d3a19aSMatthew G. Knepley 
1480*75d3a19aSMatthew G. Knepley     ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr);
1481*75d3a19aSMatthew G. Knepley     ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr);
1482*75d3a19aSMatthew G. Knepley     if (isDepth) continue;
1483*75d3a19aSMatthew G. Knepley     ierr = DMPlexCreateLabel(rdm, lname);CHKERRQ(ierr);
1484*75d3a19aSMatthew G. Knepley     ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr);
1485*75d3a19aSMatthew G. Knepley     ierr = DMPlexGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr);
1486*75d3a19aSMatthew G. Knepley     ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr);
1487*75d3a19aSMatthew G. Knepley     ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr);
1488*75d3a19aSMatthew G. Knepley     ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr);
1489*75d3a19aSMatthew G. Knepley     for (val = 0; val < numValues; ++val) {
1490*75d3a19aSMatthew G. Knepley       IS              pointIS;
1491*75d3a19aSMatthew G. Knepley       const PetscInt *points;
1492*75d3a19aSMatthew G. Knepley       PetscInt        numPoints, n;
1493*75d3a19aSMatthew G. Knepley 
1494*75d3a19aSMatthew G. Knepley       ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr);
1495*75d3a19aSMatthew G. Knepley       ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr);
1496*75d3a19aSMatthew G. Knepley       ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr);
1497*75d3a19aSMatthew G. Knepley       for (n = 0; n < numPoints; ++n) {
1498*75d3a19aSMatthew G. Knepley         const PetscInt p = points[n];
1499*75d3a19aSMatthew G. Knepley         switch (refiner) {
1500*75d3a19aSMatthew G. Knepley         case 1:
1501*75d3a19aSMatthew G. Knepley           /* Simplicial 2D */
1502*75d3a19aSMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) {
1503*75d3a19aSMatthew G. Knepley             /* Old vertices stay the same */
1504*75d3a19aSMatthew G. Knepley             newp = vStartNew + (p - vStart);
1505*75d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
1506*75d3a19aSMatthew G. Knepley           } else if ((p >= fStart) && (p < fEnd)) {
1507*75d3a19aSMatthew G. Knepley             /* Old faces add new faces and vertex */
1508*75d3a19aSMatthew G. Knepley             newp = vStartNew + (vEnd - vStart) + (p - fStart);
1509*75d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
1510*75d3a19aSMatthew G. Knepley             for (r = 0; r < 2; ++r) {
1511*75d3a19aSMatthew G. Knepley               newp = fStartNew + (p - fStart)*2 + r;
1512*75d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
1513*75d3a19aSMatthew G. Knepley             }
1514*75d3a19aSMatthew G. Knepley           } else if ((p >= cStart) && (p < cEnd)) {
1515*75d3a19aSMatthew G. Knepley             /* Old cells add new cells and interior faces */
1516*75d3a19aSMatthew G. Knepley             for (r = 0; r < 4; ++r) {
1517*75d3a19aSMatthew G. Knepley               newp = cStartNew + (p - cStart)*4 + r;
1518*75d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
1519*75d3a19aSMatthew G. Knepley             }
1520*75d3a19aSMatthew G. Knepley             for (r = 0; r < 3; ++r) {
1521*75d3a19aSMatthew G. Knepley               newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r;
1522*75d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
1523*75d3a19aSMatthew G. Knepley             }
1524*75d3a19aSMatthew G. Knepley           }
1525*75d3a19aSMatthew G. Knepley           break;
1526*75d3a19aSMatthew G. Knepley         case 2:
1527*75d3a19aSMatthew G. Knepley           /* Hex 2D */
1528*75d3a19aSMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) {
1529*75d3a19aSMatthew G. Knepley             /* Old vertices stay the same */
1530*75d3a19aSMatthew G. Knepley             newp = vStartNew + (p - vStart);
1531*75d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
1532*75d3a19aSMatthew G. Knepley           } else if ((p >= fStart) && (p < fEnd)) {
1533*75d3a19aSMatthew G. Knepley             /* Old faces add new faces and vertex */
1534*75d3a19aSMatthew G. Knepley             newp = vStartNew + (vEnd - vStart) + (p - fStart);
1535*75d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
1536*75d3a19aSMatthew G. Knepley             for (r = 0; r < 2; ++r) {
1537*75d3a19aSMatthew G. Knepley               newp = fStartNew + (p - fStart)*2 + r;
1538*75d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
1539*75d3a19aSMatthew G. Knepley             }
1540*75d3a19aSMatthew G. Knepley           } else if ((p >= cStart) && (p < cEnd)) {
1541*75d3a19aSMatthew G. Knepley             /* Old cells add new cells and interior faces and vertex */
1542*75d3a19aSMatthew G. Knepley             for (r = 0; r < 4; ++r) {
1543*75d3a19aSMatthew G. Knepley               newp = cStartNew + (p - cStart)*4 + r;
1544*75d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
1545*75d3a19aSMatthew G. Knepley             }
1546*75d3a19aSMatthew G. Knepley             for (r = 0; r < 4; ++r) {
1547*75d3a19aSMatthew G. Knepley               newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r;
1548*75d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
1549*75d3a19aSMatthew G. Knepley             }
1550*75d3a19aSMatthew G. Knepley             newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart);
1551*75d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
1552*75d3a19aSMatthew G. Knepley           }
1553*75d3a19aSMatthew G. Knepley           break;
1554*75d3a19aSMatthew G. Knepley         case 3:
1555*75d3a19aSMatthew G. Knepley           /* Hybrid simplicial 2D */
1556*75d3a19aSMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) {
1557*75d3a19aSMatthew G. Knepley             /* Old vertices stay the same */
1558*75d3a19aSMatthew G. Knepley             newp = vStartNew + (p - vStart);
1559*75d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
1560*75d3a19aSMatthew G. Knepley           } else if ((p >= fStart) && (p < fMax)) {
1561*75d3a19aSMatthew G. Knepley             /* Old interior faces add new faces and vertex */
1562*75d3a19aSMatthew G. Knepley             newp = vStartNew + (vEnd - vStart) + (p - fStart);
1563*75d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
1564*75d3a19aSMatthew G. Knepley             for (r = 0; r < 2; ++r) {
1565*75d3a19aSMatthew G. Knepley               newp = fStartNew + (p - fStart)*2 + r;
1566*75d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
1567*75d3a19aSMatthew G. Knepley             }
1568*75d3a19aSMatthew G. Knepley           } else if ((p >= fMax) && (p < fEnd)) {
1569*75d3a19aSMatthew G. Knepley             /* Old hybrid faces stay the same */
1570*75d3a19aSMatthew G. Knepley             newp = fStartNew + (fMax - fStart)*2 + (p - fMax);
1571*75d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
1572*75d3a19aSMatthew G. Knepley           } else if ((p >= cStart) && (p < cMax)) {
1573*75d3a19aSMatthew G. Knepley             /* Old interior cells add new cells and interior faces */
1574*75d3a19aSMatthew G. Knepley             for (r = 0; r < 4; ++r) {
1575*75d3a19aSMatthew G. Knepley               newp = cStartNew + (p - cStart)*4 + r;
1576*75d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
1577*75d3a19aSMatthew G. Knepley             }
1578*75d3a19aSMatthew G. Knepley             for (r = 0; r < 3; ++r) {
1579*75d3a19aSMatthew G. Knepley               newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r;
1580*75d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
1581*75d3a19aSMatthew G. Knepley             }
1582*75d3a19aSMatthew G. Knepley           } else if ((p >= cMax) && (p < cEnd)) {
1583*75d3a19aSMatthew G. Knepley             /* Old hybrid cells add new cells and hybrid face */
1584*75d3a19aSMatthew G. Knepley             for (r = 0; r < 2; ++r) {
1585*75d3a19aSMatthew G. Knepley               newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r;
1586*75d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
1587*75d3a19aSMatthew G. Knepley             }
1588*75d3a19aSMatthew G. Knepley             newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax);
1589*75d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
1590*75d3a19aSMatthew G. Knepley           }
1591*75d3a19aSMatthew G. Knepley           break;
1592*75d3a19aSMatthew G. Knepley         default:
1593*75d3a19aSMatthew G. Knepley           SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
1594*75d3a19aSMatthew G. Knepley         }
1595*75d3a19aSMatthew G. Knepley       }
1596*75d3a19aSMatthew G. Knepley       ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr);
1597*75d3a19aSMatthew G. Knepley       ierr = ISDestroy(&pointIS);CHKERRQ(ierr);
1598*75d3a19aSMatthew G. Knepley     }
1599*75d3a19aSMatthew G. Knepley     ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr);
1600*75d3a19aSMatthew G. Knepley     ierr = ISDestroy(&valueIS);CHKERRQ(ierr);
1601*75d3a19aSMatthew G. Knepley     if (0) {
1602*75d3a19aSMatthew G. Knepley       ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr);
1603*75d3a19aSMatthew G. Knepley       ierr = DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
1604*75d3a19aSMatthew G. Knepley       ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
1605*75d3a19aSMatthew G. Knepley     }
1606*75d3a19aSMatthew G. Knepley   }
1607*75d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
1608*75d3a19aSMatthew G. Knepley }
1609*75d3a19aSMatthew G. Knepley 
1610*75d3a19aSMatthew G. Knepley #undef __FUNCT__
1611*75d3a19aSMatthew G. Knepley #define __FUNCT__ "DMPlexRefine_Uniform"
1612*75d3a19aSMatthew G. Knepley /* This will only work for interpolated meshes */
1613*75d3a19aSMatthew G. Knepley PetscErrorCode DMPlexRefine_Uniform(DM dm, CellRefiner cellRefiner, DM *dmRefined)
1614*75d3a19aSMatthew G. Knepley {
1615*75d3a19aSMatthew G. Knepley   DM             rdm;
1616*75d3a19aSMatthew G. Knepley   PetscInt      *depthSize;
1617*75d3a19aSMatthew G. Knepley   PetscInt       dim, depth = 0, d, pStart = 0, pEnd = 0;
1618*75d3a19aSMatthew G. Knepley   PetscErrorCode ierr;
1619*75d3a19aSMatthew G. Knepley 
1620*75d3a19aSMatthew G. Knepley   PetscFunctionBegin;
1621*75d3a19aSMatthew G. Knepley   ierr = DMCreate(PetscObjectComm((PetscObject)dm), &rdm);CHKERRQ(ierr);
1622*75d3a19aSMatthew G. Knepley   ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr);
1623*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
1624*75d3a19aSMatthew G. Knepley   ierr = DMPlexSetDimension(rdm, dim);CHKERRQ(ierr);
1625*75d3a19aSMatthew G. Knepley   /* Calculate number of new points of each depth */
1626*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
1627*75d3a19aSMatthew G. Knepley   ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthSize);CHKERRQ(ierr);
1628*75d3a19aSMatthew G. Knepley   ierr = PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr);
1629*75d3a19aSMatthew G. Knepley   ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr);
1630*75d3a19aSMatthew G. Knepley   /* Step 1: Set chart */
1631*75d3a19aSMatthew G. Knepley   for (d = 0; d <= depth; ++d) pEnd += depthSize[d];
1632*75d3a19aSMatthew G. Knepley   ierr = DMPlexSetChart(rdm, pStart, pEnd);CHKERRQ(ierr);
1633*75d3a19aSMatthew G. Knepley   /* Step 2: Set cone/support sizes */
1634*75d3a19aSMatthew G. Knepley   ierr = CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
1635*75d3a19aSMatthew G. Knepley   /* Step 3: Setup refined DM */
1636*75d3a19aSMatthew G. Knepley   ierr = DMSetUp(rdm);CHKERRQ(ierr);
1637*75d3a19aSMatthew G. Knepley   /* Step 4: Set cones and supports */
1638*75d3a19aSMatthew G. Knepley   ierr = CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
1639*75d3a19aSMatthew G. Knepley   /* Step 5: Stratify */
1640*75d3a19aSMatthew G. Knepley   ierr = DMPlexStratify(rdm);CHKERRQ(ierr);
1641*75d3a19aSMatthew G. Knepley   /* Step 6: Set coordinates for vertices */
1642*75d3a19aSMatthew G. Knepley   ierr = CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
1643*75d3a19aSMatthew G. Knepley   /* Step 7: Create pointSF */
1644*75d3a19aSMatthew G. Knepley   ierr = CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
1645*75d3a19aSMatthew G. Knepley   /* Step 8: Create labels */
1646*75d3a19aSMatthew G. Knepley   ierr = CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
1647*75d3a19aSMatthew G. Knepley   ierr = PetscFree(depthSize);CHKERRQ(ierr);
1648*75d3a19aSMatthew G. Knepley 
1649*75d3a19aSMatthew G. Knepley   *dmRefined = rdm;
1650*75d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
1651*75d3a19aSMatthew G. Knepley }
1652*75d3a19aSMatthew G. Knepley 
1653*75d3a19aSMatthew G. Knepley #undef __FUNCT__
1654*75d3a19aSMatthew G. Knepley #define __FUNCT__ "DMPlexSetRefinementUniform"
1655*75d3a19aSMatthew G. Knepley PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform)
1656*75d3a19aSMatthew G. Knepley {
1657*75d3a19aSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
1658*75d3a19aSMatthew G. Knepley 
1659*75d3a19aSMatthew G. Knepley   PetscFunctionBegin;
1660*75d3a19aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1661*75d3a19aSMatthew G. Knepley   mesh->refinementUniform = refinementUniform;
1662*75d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
1663*75d3a19aSMatthew G. Knepley }
1664*75d3a19aSMatthew G. Knepley 
1665*75d3a19aSMatthew G. Knepley #undef __FUNCT__
1666*75d3a19aSMatthew G. Knepley #define __FUNCT__ "DMPlexGetRefinementUniform"
1667*75d3a19aSMatthew G. Knepley PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform)
1668*75d3a19aSMatthew G. Knepley {
1669*75d3a19aSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
1670*75d3a19aSMatthew G. Knepley 
1671*75d3a19aSMatthew G. Knepley   PetscFunctionBegin;
1672*75d3a19aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1673*75d3a19aSMatthew G. Knepley   PetscValidPointer(refinementUniform,  2);
1674*75d3a19aSMatthew G. Knepley   *refinementUniform = mesh->refinementUniform;
1675*75d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
1676*75d3a19aSMatthew G. Knepley }
1677*75d3a19aSMatthew G. Knepley 
1678*75d3a19aSMatthew G. Knepley #undef __FUNCT__
1679*75d3a19aSMatthew G. Knepley #define __FUNCT__ "DMPlexSetRefinementLimit"
1680*75d3a19aSMatthew G. Knepley PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit)
1681*75d3a19aSMatthew G. Knepley {
1682*75d3a19aSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
1683*75d3a19aSMatthew G. Knepley 
1684*75d3a19aSMatthew G. Knepley   PetscFunctionBegin;
1685*75d3a19aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1686*75d3a19aSMatthew G. Knepley   mesh->refinementLimit = refinementLimit;
1687*75d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
1688*75d3a19aSMatthew G. Knepley }
1689*75d3a19aSMatthew G. Knepley 
1690*75d3a19aSMatthew G. Knepley #undef __FUNCT__
1691*75d3a19aSMatthew G. Knepley #define __FUNCT__ "DMPlexGetRefinementLimit"
1692*75d3a19aSMatthew G. Knepley PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit)
1693*75d3a19aSMatthew G. Knepley {
1694*75d3a19aSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
1695*75d3a19aSMatthew G. Knepley 
1696*75d3a19aSMatthew G. Knepley   PetscFunctionBegin;
1697*75d3a19aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1698*75d3a19aSMatthew G. Knepley   PetscValidPointer(refinementLimit,  2);
1699*75d3a19aSMatthew G. Knepley   /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */
1700*75d3a19aSMatthew G. Knepley   *refinementLimit = mesh->refinementLimit;
1701*75d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
1702*75d3a19aSMatthew G. Knepley }
1703*75d3a19aSMatthew G. Knepley 
1704*75d3a19aSMatthew G. Knepley #undef __FUNCT__
1705*75d3a19aSMatthew G. Knepley #define __FUNCT__ "DMPlexGetCellRefiner_Private"
1706*75d3a19aSMatthew G. Knepley PetscErrorCode DMPlexGetCellRefiner_Private(DM dm, CellRefiner *cellRefiner)
1707*75d3a19aSMatthew G. Knepley {
1708*75d3a19aSMatthew G. Knepley   PetscInt       dim, cStart, coneSize, cMax;
1709*75d3a19aSMatthew G. Knepley   PetscErrorCode ierr;
1710*75d3a19aSMatthew G. Knepley 
1711*75d3a19aSMatthew G. Knepley   PetscFunctionBegin;
1712*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
1713*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, NULL);CHKERRQ(ierr);
1714*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr);
1715*75d3a19aSMatthew G. Knepley   ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr);
1716*75d3a19aSMatthew G. Knepley   switch (dim) {
1717*75d3a19aSMatthew G. Knepley   case 2:
1718*75d3a19aSMatthew G. Knepley     switch (coneSize) {
1719*75d3a19aSMatthew G. Knepley     case 3:
1720*75d3a19aSMatthew G. Knepley       if (cMax >= 0) *cellRefiner = 3; /* Hybrid */
1721*75d3a19aSMatthew G. Knepley       else *cellRefiner = 1; /* Triangular */
1722*75d3a19aSMatthew G. Knepley       break;
1723*75d3a19aSMatthew G. Knepley     case 4:
1724*75d3a19aSMatthew G. Knepley       if (cMax >= 0) *cellRefiner = 4; /* Hybrid */
1725*75d3a19aSMatthew G. Knepley       else *cellRefiner = 2; /* Quadrilateral */
1726*75d3a19aSMatthew G. Knepley       break;
1727*75d3a19aSMatthew G. Knepley     default:
1728*75d3a19aSMatthew G. Knepley       SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim);
1729*75d3a19aSMatthew G. Knepley     }
1730*75d3a19aSMatthew G. Knepley     break;
1731*75d3a19aSMatthew G. Knepley   default:
1732*75d3a19aSMatthew G. Knepley     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim);
1733*75d3a19aSMatthew G. Knepley   }
1734*75d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
1735*75d3a19aSMatthew G. Knepley }
1736