xref: /petsc/src/dm/impls/plex/plexrefine.c (revision b5da94994c42bf1bef3d301ed91e9e089fa00757)
175d3a19aSMatthew G. Knepley #include <petsc-private/dmpleximpl.h>   /*I      "petscdmplex.h"   I*/
275d3a19aSMatthew G. Knepley #include <petscsf.h>
375d3a19aSMatthew G. Knepley 
475d3a19aSMatthew G. Knepley #undef __FUNCT__
575d3a19aSMatthew G. Knepley #define __FUNCT__ "GetDepthStart_Private"
675d3a19aSMatthew G. Knepley PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart)
775d3a19aSMatthew G. Knepley {
875d3a19aSMatthew G. Knepley   PetscFunctionBegin;
975d3a19aSMatthew G. Knepley   if (cStart) *cStart = 0;
1075d3a19aSMatthew G. Knepley   if (vStart) *vStart = depthSize[depth];
1175d3a19aSMatthew G. Knepley   if (fStart) *fStart = depthSize[depth] + depthSize[0];
1275d3a19aSMatthew G. Knepley   if (eStart) *eStart = depthSize[depth] + depthSize[0] + depthSize[depth-1];
1375d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
1475d3a19aSMatthew G. Knepley }
1575d3a19aSMatthew G. Knepley 
1675d3a19aSMatthew G. Knepley #undef __FUNCT__
1775d3a19aSMatthew G. Knepley #define __FUNCT__ "GetDepthEnd_Private"
1875d3a19aSMatthew G. Knepley PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd)
1975d3a19aSMatthew G. Knepley {
2075d3a19aSMatthew G. Knepley   PetscFunctionBegin;
2175d3a19aSMatthew G. Knepley   if (cEnd) *cEnd = depthSize[depth];
2275d3a19aSMatthew G. Knepley   if (vEnd) *vEnd = depthSize[depth] + depthSize[0];
2375d3a19aSMatthew G. Knepley   if (fEnd) *fEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1];
2475d3a19aSMatthew G. Knepley   if (eEnd) *eEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1];
2575d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
2675d3a19aSMatthew G. Knepley }
2775d3a19aSMatthew G. Knepley 
2875d3a19aSMatthew G. Knepley #undef __FUNCT__
29*b5da9499SMatthew G. Knepley #define __FUNCT__ "DMPlexGetNumHybridFaces_Internal"
30*b5da9499SMatthew G. Knepley /* This is a stopgap since we do not currently keep track of faces for hybrid cells */
31*b5da9499SMatthew G. Knepley static PetscErrorCode DMPlexGetNumHybridFaces_Internal(DM dm, PetscInt *numHybridFaces)
32*b5da9499SMatthew G. Knepley {
33*b5da9499SMatthew G. Knepley   PetscInt       eStart, eEnd, eMax, cEnd, cMax, c, hEdges = 0;
34*b5da9499SMatthew G. Knepley   PetscErrorCode ierr;
35*b5da9499SMatthew G. Knepley 
36*b5da9499SMatthew G. Knepley   PetscFunctionBegin;
37*b5da9499SMatthew G. Knepley   *numHybridFaces = 0;
38*b5da9499SMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
39*b5da9499SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, NULL, &cEnd);CHKERRQ(ierr);
40*b5da9499SMatthew G. Knepley   ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, &eMax, NULL);CHKERRQ(ierr);
41*b5da9499SMatthew G. Knepley   if (cMax < 0) PetscFunctionReturn(0);
42*b5da9499SMatthew G. Knepley   /* Count interior edges in hybrid cells */
43*b5da9499SMatthew G. Knepley   for (c = cMax; c < cEnd; ++c) {
44*b5da9499SMatthew G. Knepley     PetscInt *closure = NULL, closureSize, cl;
45*b5da9499SMatthew G. Knepley 
46*b5da9499SMatthew G. Knepley     ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
47*b5da9499SMatthew G. Knepley     for (cl = 0; cl < closureSize*2; cl += 2) {
48*b5da9499SMatthew G. Knepley       const PetscInt p = closure[cl];
49*b5da9499SMatthew G. Knepley 
50*b5da9499SMatthew G. Knepley       if ((p >= eStart) && (p < eMax)) ++hEdges;
51*b5da9499SMatthew G. Knepley     }
52*b5da9499SMatthew G. Knepley     ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
53*b5da9499SMatthew G. Knepley   }
54*b5da9499SMatthew G. Knepley   if (hEdges%2) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of interior edges in hybrid cells cannot be odd: %d", hEdges);
55*b5da9499SMatthew G. Knepley   *numHybridFaces = hEdges/2;
56*b5da9499SMatthew G. Knepley   PetscFunctionReturn(0);
57*b5da9499SMatthew G. Knepley }
58*b5da9499SMatthew G. Knepley 
59*b5da9499SMatthew G. Knepley #undef __FUNCT__
6075d3a19aSMatthew G. Knepley #define __FUNCT__ "CellRefinerGetSizes"
6175d3a19aSMatthew G. Knepley PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[])
6275d3a19aSMatthew G. Knepley {
63*b5da9499SMatthew G. Knepley   PetscInt       numHybridFaces, cStart, cEnd, cMax, vStart, vEnd, vMax, fStart, fEnd, fMax, eStart, eEnd, eMax;
6475d3a19aSMatthew G. Knepley   PetscErrorCode ierr;
6575d3a19aSMatthew G. Knepley 
6675d3a19aSMatthew G. Knepley   PetscFunctionBegin;
6775d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
6875d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
6975d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
7075d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
7175d3a19aSMatthew G. Knepley   ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr);
7275d3a19aSMatthew G. Knepley   switch (refiner) {
7375d3a19aSMatthew G. Knepley   case 1:
7475d3a19aSMatthew G. Knepley     /* Simplicial 2D */
7575d3a19aSMatthew G. Knepley     depthSize[0] = vEnd - vStart + fEnd - fStart;         /* Add a vertex on every face */
7675d3a19aSMatthew 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 */
7775d3a19aSMatthew G. Knepley     depthSize[2] = 4*(cEnd - cStart);                     /* Every cell split into 4 cells */
7875d3a19aSMatthew G. Knepley     break;
7975d3a19aSMatthew G. Knepley   case 3:
80d963de37SMatthew G. Knepley     /* Hybrid Simplicial 2D */
8175d3a19aSMatthew G. Knepley     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
8275d3a19aSMatthew G. Knepley     cMax = PetscMin(cEnd, cMax);
8375d3a19aSMatthew G. Knepley     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
8475d3a19aSMatthew G. Knepley     fMax         = PetscMin(fEnd, fMax);
8575d3a19aSMatthew G. Knepley     depthSize[0] = vEnd - vStart + fMax - fStart;                                         /* Add a vertex on every face, but not hybrid faces */
8675d3a19aSMatthew 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 */
8775d3a19aSMatthew G. Knepley     depthSize[2] = 4*(cMax - cStart) + 2*(cEnd - cMax);                                   /* Interior cells split into 4 cells, Hybrid cells split into 2 cells */
8875d3a19aSMatthew G. Knepley     break;
8975d3a19aSMatthew G. Knepley   case 2:
9075d3a19aSMatthew G. Knepley     /* Hex 2D */
9175d3a19aSMatthew G. Knepley     depthSize[0] = vEnd - vStart + cEnd - cStart + fEnd - fStart; /* Add a vertex on every face and cell */
9275d3a19aSMatthew 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 */
9375d3a19aSMatthew G. Knepley     depthSize[2] = 4*(cEnd - cStart);                             /* Every cell split into 4 cells */
9475d3a19aSMatthew G. Knepley     break;
95*b5da9499SMatthew G. Knepley   case 5:
96*b5da9499SMatthew G. Knepley     /* Simplicial 3D */
97*b5da9499SMatthew G. Knepley     depthSize[0] =    vEnd - vStart  +    eEnd - eStart;                    /* Add a vertex on every edge */
98*b5da9499SMatthew G. Knepley     depthSize[1] = 2*(eEnd - eStart) + 3*(fEnd - fStart) + (cEnd - cStart); /* Every edge is split into 2 edges, 3 edges are added for each face, and 1 edge for each cell */
99*b5da9499SMatthew G. Knepley     depthSize[2] = 4*(fEnd - fStart) + 8*(cEnd - cStart);                   /* Every face split into 4 faces and 8 faces are added for each cell */
100*b5da9499SMatthew G. Knepley     depthSize[3] = 8*(cEnd - cStart);                                       /* Every cell split into 8 cells */
101*b5da9499SMatthew G. Knepley     break;
102*b5da9499SMatthew G. Knepley   case 7:
103*b5da9499SMatthew G. Knepley     /* Hybrid Simplicial 3D */
104*b5da9499SMatthew G. Knepley     ierr = DMPlexGetNumHybridFaces_Internal(dm, &numHybridFaces);CHKERRQ(ierr);
105*b5da9499SMatthew G. Knepley     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
106*b5da9499SMatthew G. Knepley     cMax = PetscMin(cEnd, cMax);
107*b5da9499SMatthew G. Knepley     if (eMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No edge maximum specified in hybrid mesh");
108*b5da9499SMatthew G. Knepley     eMax = PetscMin(eEnd, eMax);
109*b5da9499SMatthew G. Knepley     depthSize[0] =    vEnd - vStart  +     eMax - eStart;  /* Add a vertex on every edge, but not hybrid edges */
110*b5da9499SMatthew G. Knepley     depthSize[1] = 2*(eMax - eStart) + 13*(cMax - cStart) + (eEnd - eMax) + numHybridFaces; /* Every interior edge is split into 2 edges and 13 edges are added for each interior cell, each hybrid edge stays intact, and one new hybrid edge for each two interior edges (hybrid face) on a hybrid cell */
111*b5da9499SMatthew G. Knepley     depthSize[2] = 4*(fEnd - fStart) +  8*(cEnd - cStart); /* Every face split into 4 faces and 8 faces are added for each cell */
112*b5da9499SMatthew G. Knepley     depthSize[3] = 8*(cMax - cStart) +  4*(cEnd - cMax);   /* Every interior cell split into 8 cells, and every hybrid cell split into 4 cells */
113*b5da9499SMatthew G. Knepley     break;
11475d3a19aSMatthew G. Knepley   default:
11575d3a19aSMatthew G. Knepley     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
11675d3a19aSMatthew G. Knepley   }
11775d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
11875d3a19aSMatthew G. Knepley }
11975d3a19aSMatthew G. Knepley 
12075d3a19aSMatthew G. Knepley #undef __FUNCT__
12175d3a19aSMatthew G. Knepley #define __FUNCT__ "CellRefinerSetConeSizes"
12275d3a19aSMatthew G. Knepley PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
12375d3a19aSMatthew G. Knepley {
124*b5da9499SMatthew G. Knepley   PetscInt       depth, cStart, cStartNew, cEnd, cMax, c, vStart, vStartNew, vEnd, vMax, v, fStart, fStartNew, fEnd, fMax, f, eStart, eStartNew, eEnd, eMax, e, r;
12575d3a19aSMatthew G. Knepley   PetscErrorCode ierr;
12675d3a19aSMatthew G. Knepley 
12775d3a19aSMatthew G. Knepley   PetscFunctionBegin;
12875d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
12975d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
13075d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
13175d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
13275d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
13375d3a19aSMatthew G. Knepley   ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr);
13475d3a19aSMatthew G. Knepley   ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr);
13575d3a19aSMatthew G. Knepley   switch (refiner) {
13675d3a19aSMatthew G. Knepley   case 1:
13775d3a19aSMatthew G. Knepley     /* Simplicial 2D */
13875d3a19aSMatthew G. Knepley     /* All cells have 3 faces */
13975d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
14075d3a19aSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
14175d3a19aSMatthew G. Knepley         const PetscInt newp = (c - cStart)*4 + r;
14275d3a19aSMatthew G. Knepley 
14375d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr);
14475d3a19aSMatthew G. Knepley       }
14575d3a19aSMatthew G. Knepley     }
14675d3a19aSMatthew G. Knepley     /* Split faces have 2 vertices and the same cells as the parent */
14775d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
14875d3a19aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
14975d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (f - fStart)*2 + r;
15075d3a19aSMatthew G. Knepley         PetscInt       size;
15175d3a19aSMatthew G. Knepley 
15275d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
15375d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
15475d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
15575d3a19aSMatthew G. Knepley       }
15675d3a19aSMatthew G. Knepley     }
15775d3a19aSMatthew G. Knepley     /* Interior faces have 2 vertices and 2 cells */
15875d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
15975d3a19aSMatthew G. Knepley       for (r = 0; r < 3; ++r) {
16075d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r;
16175d3a19aSMatthew G. Knepley 
16275d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
16375d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
16475d3a19aSMatthew G. Knepley       }
16575d3a19aSMatthew G. Knepley     }
16675d3a19aSMatthew G. Knepley     /* Old vertices have identical supports */
16775d3a19aSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
16875d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (v - vStart);
16975d3a19aSMatthew G. Knepley       PetscInt       size;
17075d3a19aSMatthew G. Knepley 
17175d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
17275d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
17375d3a19aSMatthew G. Knepley     }
17475d3a19aSMatthew G. Knepley     /* Face vertices have 2 + cells*2 supports */
17575d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
17675d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
17775d3a19aSMatthew G. Knepley       PetscInt       size;
17875d3a19aSMatthew G. Knepley 
17975d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
18075d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2);CHKERRQ(ierr);
18175d3a19aSMatthew G. Knepley     }
18275d3a19aSMatthew G. Knepley     break;
18375d3a19aSMatthew G. Knepley   case 2:
18475d3a19aSMatthew G. Knepley     /* Hex 2D */
18575d3a19aSMatthew G. Knepley     /* All cells have 4 faces */
18675d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
18775d3a19aSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
18875d3a19aSMatthew G. Knepley         const PetscInt newp = (c - cStart)*4 + r;
18975d3a19aSMatthew G. Knepley 
19075d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
19175d3a19aSMatthew G. Knepley       }
19275d3a19aSMatthew G. Knepley     }
19375d3a19aSMatthew G. Knepley     /* Split faces have 2 vertices and the same cells as the parent */
19475d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
19575d3a19aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
19675d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (f - fStart)*2 + r;
19775d3a19aSMatthew G. Knepley         PetscInt       size;
19875d3a19aSMatthew G. Knepley 
19975d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
20075d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
20175d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
20275d3a19aSMatthew G. Knepley       }
20375d3a19aSMatthew G. Knepley     }
20475d3a19aSMatthew G. Knepley     /* Interior faces have 2 vertices and 2 cells */
20575d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
20675d3a19aSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
20775d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r;
20875d3a19aSMatthew G. Knepley 
20975d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
21075d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
21175d3a19aSMatthew G. Knepley       }
21275d3a19aSMatthew G. Knepley     }
21375d3a19aSMatthew G. Knepley     /* Old vertices have identical supports */
21475d3a19aSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
21575d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (v - vStart);
21675d3a19aSMatthew G. Knepley       PetscInt       size;
21775d3a19aSMatthew G. Knepley 
21875d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
21975d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
22075d3a19aSMatthew G. Knepley     }
22175d3a19aSMatthew G. Knepley     /* Face vertices have 2 + cells supports */
22275d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
22375d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
22475d3a19aSMatthew G. Knepley       PetscInt       size;
22575d3a19aSMatthew G. Knepley 
22675d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
22775d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr);
22875d3a19aSMatthew G. Knepley     }
22975d3a19aSMatthew G. Knepley     /* Cell vertices have 4 supports */
23075d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
23175d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart);
23275d3a19aSMatthew G. Knepley 
23375d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr);
23475d3a19aSMatthew G. Knepley     }
23575d3a19aSMatthew G. Knepley     break;
23675d3a19aSMatthew G. Knepley   case 3:
237d963de37SMatthew G. Knepley     /* Hybrid Simplicial 2D */
23875d3a19aSMatthew G. Knepley     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
23975d3a19aSMatthew G. Knepley     cMax = PetscMin(cEnd, cMax);
24075d3a19aSMatthew G. Knepley     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
24175d3a19aSMatthew G. Knepley     fMax = PetscMin(fEnd, fMax);
24275d3a19aSMatthew G. Knepley     ierr = DMPlexSetHybridBounds(rdm, cStartNew + (cMax - cStart)*4, fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
24375d3a19aSMatthew G. Knepley     /* Interior cells have 3 faces */
24475d3a19aSMatthew G. Knepley     for (c = cStart; c < cMax; ++c) {
24575d3a19aSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
24675d3a19aSMatthew G. Knepley         const PetscInt newp = cStartNew + (c - cStart)*4 + r;
24775d3a19aSMatthew G. Knepley 
24875d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr);
24975d3a19aSMatthew G. Knepley       }
25075d3a19aSMatthew G. Knepley     }
25175d3a19aSMatthew G. Knepley     /* Hybrid cells have 4 faces */
25275d3a19aSMatthew G. Knepley     for (c = cMax; c < cEnd; ++c) {
25375d3a19aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
25475d3a19aSMatthew G. Knepley         const PetscInt newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2 + r;
25575d3a19aSMatthew G. Knepley 
25675d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
25775d3a19aSMatthew G. Knepley       }
25875d3a19aSMatthew G. Knepley     }
25975d3a19aSMatthew G. Knepley     /* Interior split faces have 2 vertices and the same cells as the parent */
26075d3a19aSMatthew G. Knepley     for (f = fStart; f < fMax; ++f) {
26175d3a19aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
26275d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (f - fStart)*2 + r;
26375d3a19aSMatthew G. Knepley         PetscInt       size;
26475d3a19aSMatthew G. Knepley 
26575d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
26675d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
26775d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
26875d3a19aSMatthew G. Knepley       }
26975d3a19aSMatthew G. Knepley     }
27075d3a19aSMatthew G. Knepley     /* Interior cell faces have 2 vertices and 2 cells */
27175d3a19aSMatthew G. Knepley     for (c = cStart; c < cMax; ++c) {
27275d3a19aSMatthew G. Knepley       for (r = 0; r < 3; ++r) {
27375d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r;
27475d3a19aSMatthew G. Knepley 
27575d3a19aSMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
27675d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
27775d3a19aSMatthew G. Knepley       }
27875d3a19aSMatthew G. Knepley     }
27975d3a19aSMatthew G. Knepley     /* Hybrid faces have 2 vertices and the same cells */
28075d3a19aSMatthew G. Knepley     for (f = fMax; f < fEnd; ++f) {
28175d3a19aSMatthew G. Knepley       const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax);
28275d3a19aSMatthew G. Knepley       PetscInt       size;
28375d3a19aSMatthew G. Knepley 
28475d3a19aSMatthew G. Knepley       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
28575d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
28675d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
28775d3a19aSMatthew G. Knepley     }
28875d3a19aSMatthew G. Knepley     /* Hybrid cell faces have 2 vertices and 2 cells */
28975d3a19aSMatthew G. Knepley     for (c = cMax; c < cEnd; ++c) {
29075d3a19aSMatthew G. Knepley       const PetscInt newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax);
29175d3a19aSMatthew G. Knepley 
29275d3a19aSMatthew G. Knepley       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
29375d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
29475d3a19aSMatthew G. Knepley     }
29575d3a19aSMatthew G. Knepley     /* Old vertices have identical supports */
29675d3a19aSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
29775d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (v - vStart);
29875d3a19aSMatthew G. Knepley       PetscInt       size;
29975d3a19aSMatthew G. Knepley 
30075d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
30175d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
30275d3a19aSMatthew G. Knepley     }
30375d3a19aSMatthew G. Knepley     /* Face vertices have 2 + (2 interior, 1 hybrid) supports */
30475d3a19aSMatthew G. Knepley     for (f = fStart; f < fMax; ++f) {
30575d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
30675d3a19aSMatthew G. Knepley       const PetscInt *support;
30775d3a19aSMatthew G. Knepley       PetscInt       size, newSize = 2, s;
30875d3a19aSMatthew G. Knepley 
30975d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
31075d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
31175d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
31275d3a19aSMatthew G. Knepley         if (support[s] >= cMax) newSize += 1;
31375d3a19aSMatthew G. Knepley         else newSize += 2;
31475d3a19aSMatthew G. Knepley       }
31575d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, newSize);CHKERRQ(ierr);
31675d3a19aSMatthew G. Knepley     }
31775d3a19aSMatthew G. Knepley     break;
318*b5da9499SMatthew G. Knepley   case 5:
319*b5da9499SMatthew G. Knepley     /* Simplicial 3D */
320*b5da9499SMatthew G. Knepley     /* All cells have 4 faces */
321*b5da9499SMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
322*b5da9499SMatthew G. Knepley       for (r = 0; r < 8; ++r) {
323*b5da9499SMatthew G. Knepley         const PetscInt newp = (c - cStart)*8 + r;
324*b5da9499SMatthew G. Knepley 
325*b5da9499SMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
326*b5da9499SMatthew G. Knepley       }
327*b5da9499SMatthew G. Knepley     }
328*b5da9499SMatthew G. Knepley     /* Split faces have 3 edges and the same cells as the parent */
329*b5da9499SMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
330*b5da9499SMatthew G. Knepley       for (r = 0; r < 4; ++r) {
331*b5da9499SMatthew G. Knepley         const PetscInt newp = fStartNew + (f - fStart)*4 + r;
332*b5da9499SMatthew G. Knepley         PetscInt       size;
333*b5da9499SMatthew G. Knepley 
334*b5da9499SMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr);
335*b5da9499SMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
336*b5da9499SMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
337*b5da9499SMatthew G. Knepley       }
338*b5da9499SMatthew G. Knepley     }
339*b5da9499SMatthew G. Knepley     /* Interior faces have 3 edges and 2 cells */
340*b5da9499SMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
341*b5da9499SMatthew G. Knepley       for (r = 0; r < 8; ++r) {
342*b5da9499SMatthew G. Knepley         const PetscInt newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + r;
343*b5da9499SMatthew G. Knepley 
344*b5da9499SMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr);
345*b5da9499SMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
346*b5da9499SMatthew G. Knepley       }
347*b5da9499SMatthew G. Knepley     }
348*b5da9499SMatthew G. Knepley     /* Split edges have 2 vertices and the same faces */
349*b5da9499SMatthew G. Knepley     for (e = eStart; e < eEnd; ++e) {
350*b5da9499SMatthew G. Knepley       for (r = 0; r < 2; ++r) {
351*b5da9499SMatthew G. Knepley         const PetscInt newp = eStartNew + (e - eStart)*2 + r;
352*b5da9499SMatthew G. Knepley         PetscInt       size;
353*b5da9499SMatthew G. Knepley 
354*b5da9499SMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
355*b5da9499SMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
356*b5da9499SMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
357*b5da9499SMatthew G. Knepley       }
358*b5da9499SMatthew G. Knepley     }
359*b5da9499SMatthew G. Knepley     /* Face edges have 2 vertices and 2+cells*(1/2) faces */
360*b5da9499SMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
361*b5da9499SMatthew G. Knepley       for (r = 0; r < 3; ++r) {
362*b5da9499SMatthew G. Knepley         const PetscInt  newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + r;
363*b5da9499SMatthew G. Knepley         const PetscInt *cone, *ornt, *support, eint[4] = {1, 0, 2, 0};
364*b5da9499SMatthew G. Knepley         PetscInt        coneSize, c, supportSize, s, er, intFaces = 0;
365*b5da9499SMatthew G. Knepley 
366*b5da9499SMatthew G. Knepley         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
367*b5da9499SMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
368*b5da9499SMatthew G. Knepley         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
369*b5da9499SMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
370*b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
371*b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
372*b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
373*b5da9499SMatthew G. Knepley           for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
374*b5da9499SMatthew G. Knepley WRONG          er = ornt[c] < 0 ? (-(ornt[c]+1) + r)%3 : (ornt[c] + r)%3;
375*b5da9499SMatthew G. Knepley           if (er == eint[c]) {
376*b5da9499SMatthew G. Knepley             intFaces += 1;
377*b5da9499SMatthew G. Knepley           } else {
378*b5da9499SMatthew G. Knepley             intFaces += 2;
379*b5da9499SMatthew G. Knepley           }
380*b5da9499SMatthew G. Knepley         }
381*b5da9499SMatthew G. Knepley         ierr = DMPlexSetSupportSize(rdm, newp, 2+intFaces);CHKERRQ(ierr);
382*b5da9499SMatthew G. Knepley       }
383*b5da9499SMatthew G. Knepley     }
384*b5da9499SMatthew G. Knepley     /* Interior edges have 2 vertices and 4 faces */
385*b5da9499SMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
386*b5da9499SMatthew G. Knepley       const PetscInt newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
387*b5da9499SMatthew G. Knepley 
388*b5da9499SMatthew G. Knepley       ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
389*b5da9499SMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr);
390*b5da9499SMatthew G. Knepley     }
391*b5da9499SMatthew G. Knepley     /* Old vertices have identical supports */
392*b5da9499SMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
393*b5da9499SMatthew G. Knepley       const PetscInt newp = vStartNew + (v - vStart);
394*b5da9499SMatthew G. Knepley       PetscInt       size;
395*b5da9499SMatthew G. Knepley 
396*b5da9499SMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
397*b5da9499SMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
398*b5da9499SMatthew G. Knepley     }
399*b5da9499SMatthew G. Knepley     /* Edge vertices have 2 + faces*2 + cells*0/1 supports */
400*b5da9499SMatthew G. Knepley     for (e = eStart; e < eEnd; ++e) {
401*b5da9499SMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (e - eStart);
402*b5da9499SMatthew G. Knepley       PetscInt       size, *star = NULL, starSize, s, cellSize = 0;
403*b5da9499SMatthew G. Knepley 
404*b5da9499SMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
405*b5da9499SMatthew G. Knepley       ierr = DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr);
406*b5da9499SMatthew G. Knepley       for (s = 0; s < starSize*2; s += 2) {
407*b5da9499SMatthew G. Knepley         const PetscInt *cone, *ornt;
408*b5da9499SMatthew G. Knepley         PetscInt        e01, e23;
409*b5da9499SMatthew G. Knepley 
410*b5da9499SMatthew G. Knepley         if ((star[s] >= cStart) && (star[s] < cEnd)) {
411*b5da9499SMatthew G. Knepley           /* Check edge 0-1 */
412*b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, star[s], &cone);CHKERRQ(ierr);
413*b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, star[s], &ornt);CHKERRQ(ierr);
414*b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, cone[0], &cone);CHKERRQ(ierr);
415*b5da9499SMatthew G. Knepley           e01  = cone[ornt[0] < 0 ? (-(ornt[0]+1) + 0)%3 : ornt[0]];
416*b5da9499SMatthew G. Knepley           /* Check edge 2-3 */
417*b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, star[s], &cone);CHKERRQ(ierr);
418*b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, star[s], &ornt);CHKERRQ(ierr);
419*b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, cone[3], &cone);CHKERRQ(ierr);
420*b5da9499SMatthew G. Knepley           e23  = cone[ornt[3] < 0 ? (-(ornt[3]+1) + 2)%3 : (ornt[3] + 2)%3];
421*b5da9499SMatthew G. Knepley           if ((e01 == e) || (e23 == e)) ++cellSize;
422*b5da9499SMatthew G. Knepley         }
423*b5da9499SMatthew G. Knepley       }
424*b5da9499SMatthew G. Knepley       ierr = DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr);
425*b5da9499SMatthew G. Knepley       ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2 + cellSize);CHKERRQ(ierr);
426*b5da9499SMatthew G. Knepley     }
427*b5da9499SMatthew G. Knepley     break;
42875d3a19aSMatthew G. Knepley   default:
42975d3a19aSMatthew G. Knepley     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
43075d3a19aSMatthew G. Knepley   }
43175d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
43275d3a19aSMatthew G. Knepley }
43375d3a19aSMatthew G. Knepley 
43475d3a19aSMatthew G. Knepley #undef __FUNCT__
43575d3a19aSMatthew G. Knepley #define __FUNCT__ "CellRefinerSetCones"
43675d3a19aSMatthew G. Knepley PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
43775d3a19aSMatthew G. Knepley {
438*b5da9499SMatthew G. Knepley   const PetscInt *faces, cellInd[4] = {0, 1, 2, 3};
439*b5da9499SMatthew 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, e, r, p;
44075d3a19aSMatthew G. Knepley   PetscInt        maxSupportSize, *supportRef;
44175d3a19aSMatthew G. Knepley   PetscErrorCode  ierr;
44275d3a19aSMatthew G. Knepley 
44375d3a19aSMatthew G. Knepley   PetscFunctionBegin;
44475d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
44575d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
44675d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
44775d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
44875d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
44975d3a19aSMatthew G. Knepley   ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr);
45075d3a19aSMatthew G. Knepley   ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr);
45175d3a19aSMatthew G. Knepley   ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr);
45275d3a19aSMatthew G. Knepley   switch (refiner) {
45375d3a19aSMatthew G. Knepley   case 1:
45475d3a19aSMatthew G. Knepley     /* Simplicial 2D */
45575d3a19aSMatthew G. Knepley     /*
45675d3a19aSMatthew G. Knepley      2
45775d3a19aSMatthew G. Knepley      |\
45875d3a19aSMatthew G. Knepley      | \
45975d3a19aSMatthew G. Knepley      |  \
46075d3a19aSMatthew G. Knepley      |   \
46175d3a19aSMatthew G. Knepley      | C  \
46275d3a19aSMatthew G. Knepley      |     \
46375d3a19aSMatthew G. Knepley      |      \
46475d3a19aSMatthew G. Knepley      2---1---1
46575d3a19aSMatthew G. Knepley      |\  D  / \
46675d3a19aSMatthew G. Knepley      | 2   0   \
46775d3a19aSMatthew G. Knepley      |A \ /  B  \
46875d3a19aSMatthew G. Knepley      0---0-------1
46975d3a19aSMatthew G. Knepley      */
47075d3a19aSMatthew G. Knepley     /* All cells have 3 faces */
47175d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
47275d3a19aSMatthew G. Knepley       const PetscInt  newp = cStartNew + (c - cStart)*4;
47375d3a19aSMatthew G. Knepley       const PetscInt *cone, *ornt;
47475d3a19aSMatthew G. Knepley       PetscInt        coneNew[3], orntNew[3];
47575d3a19aSMatthew G. Knepley 
47675d3a19aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
47775d3a19aSMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
47875d3a19aSMatthew G. Knepley       /* A triangle */
47975d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
48075d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
48175d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 2;
48275d3a19aSMatthew G. Knepley       orntNew[1] = -2;
48375d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
48475d3a19aSMatthew G. Knepley       orntNew[2] = ornt[2];
48575d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
48675d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
48775d3a19aSMatthew G. Knepley #if 1
48875d3a19aSMatthew 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);
48975d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
49075d3a19aSMatthew 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);
49175d3a19aSMatthew G. Knepley       }
49275d3a19aSMatthew G. Knepley #endif
49375d3a19aSMatthew G. Knepley       /* B triangle */
49475d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
49575d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
49675d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
49775d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
49875d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 0;
49975d3a19aSMatthew G. Knepley       orntNew[2] = -2;
50075d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
50175d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
50275d3a19aSMatthew G. Knepley #if 1
50375d3a19aSMatthew 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);
50475d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
50575d3a19aSMatthew 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);
50675d3a19aSMatthew G. Knepley       }
50775d3a19aSMatthew G. Knepley #endif
50875d3a19aSMatthew G. Knepley       /* C triangle */
50975d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 1;
51075d3a19aSMatthew G. Knepley       orntNew[0] = -2;
51175d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
51275d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
51375d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
51475d3a19aSMatthew G. Knepley       orntNew[2] = ornt[2];
51575d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
51675d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
51775d3a19aSMatthew G. Knepley #if 1
51875d3a19aSMatthew 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);
51975d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
52075d3a19aSMatthew 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);
52175d3a19aSMatthew G. Knepley       }
52275d3a19aSMatthew G. Knepley #endif
52375d3a19aSMatthew G. Knepley       /* D triangle */
52475d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 0;
52575d3a19aSMatthew G. Knepley       orntNew[0] = 0;
52675d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 1;
52775d3a19aSMatthew G. Knepley       orntNew[1] = 0;
52875d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 2;
52975d3a19aSMatthew G. Knepley       orntNew[2] = 0;
53075d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
53175d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
53275d3a19aSMatthew G. Knepley #if 1
53375d3a19aSMatthew 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);
53475d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
53575d3a19aSMatthew 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);
53675d3a19aSMatthew G. Knepley       }
53775d3a19aSMatthew G. Knepley #endif
53875d3a19aSMatthew G. Knepley     }
53975d3a19aSMatthew G. Knepley     /* Split faces have 2 vertices and the same cells as the parent */
54075d3a19aSMatthew G. Knepley     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
54175d3a19aSMatthew G. Knepley     ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr);
54275d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
54375d3a19aSMatthew G. Knepley       const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
54475d3a19aSMatthew G. Knepley 
54575d3a19aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
54675d3a19aSMatthew G. Knepley         const PetscInt  newp = fStartNew + (f - fStart)*2 + r;
54775d3a19aSMatthew G. Knepley         const PetscInt *cone, *support;
54875d3a19aSMatthew G. Knepley         PetscInt        coneNew[2], coneSize, c, supportSize, s;
54975d3a19aSMatthew G. Knepley 
55075d3a19aSMatthew G. Knepley         ierr             = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
55175d3a19aSMatthew G. Knepley         coneNew[0]       = vStartNew + (cone[0] - vStart);
55275d3a19aSMatthew G. Knepley         coneNew[1]       = vStartNew + (cone[1] - vStart);
55375d3a19aSMatthew G. Knepley         coneNew[(r+1)%2] = newv;
55475d3a19aSMatthew G. Knepley         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
55575d3a19aSMatthew G. Knepley #if 1
55675d3a19aSMatthew 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);
55775d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
55875d3a19aSMatthew 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);
55975d3a19aSMatthew G. Knepley         }
56075d3a19aSMatthew G. Knepley #endif
56175d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
56275d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
56375d3a19aSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
56475d3a19aSMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
56575d3a19aSMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
56675d3a19aSMatthew G. Knepley           for (c = 0; c < coneSize; ++c) {
56775d3a19aSMatthew G. Knepley             if (cone[c] == f) break;
56875d3a19aSMatthew G. Knepley           }
56975d3a19aSMatthew G. Knepley           supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3;
57075d3a19aSMatthew G. Knepley         }
57175d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
57275d3a19aSMatthew G. Knepley #if 1
57375d3a19aSMatthew 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);
57475d3a19aSMatthew G. Knepley         for (p = 0; p < supportSize; ++p) {
57575d3a19aSMatthew 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);
57675d3a19aSMatthew G. Knepley         }
57775d3a19aSMatthew G. Knepley #endif
57875d3a19aSMatthew G. Knepley       }
57975d3a19aSMatthew G. Knepley     }
58075d3a19aSMatthew G. Knepley     /* Interior faces have 2 vertices and 2 cells */
58175d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
58275d3a19aSMatthew G. Knepley       const PetscInt *cone;
58375d3a19aSMatthew G. Knepley 
58475d3a19aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
58575d3a19aSMatthew G. Knepley       for (r = 0; r < 3; ++r) {
58675d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r;
58775d3a19aSMatthew G. Knepley         PetscInt       coneNew[2];
58875d3a19aSMatthew G. Knepley         PetscInt       supportNew[2];
58975d3a19aSMatthew G. Knepley 
59075d3a19aSMatthew G. Knepley         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r]       - fStart);
59175d3a19aSMatthew G. Knepley         coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart);
59275d3a19aSMatthew G. Knepley         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
59375d3a19aSMatthew G. Knepley #if 1
59475d3a19aSMatthew 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);
59575d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
59675d3a19aSMatthew 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);
59775d3a19aSMatthew G. Knepley         }
59875d3a19aSMatthew G. Knepley #endif
59975d3a19aSMatthew G. Knepley         supportNew[0] = (c - cStart)*4 + (r+1)%3;
60075d3a19aSMatthew G. Knepley         supportNew[1] = (c - cStart)*4 + 3;
60175d3a19aSMatthew G. Knepley         ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
60275d3a19aSMatthew G. Knepley #if 1
60375d3a19aSMatthew 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);
60475d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
60575d3a19aSMatthew 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);
60675d3a19aSMatthew G. Knepley         }
60775d3a19aSMatthew G. Knepley #endif
60875d3a19aSMatthew G. Knepley       }
60975d3a19aSMatthew G. Knepley     }
61075d3a19aSMatthew G. Knepley     /* Old vertices have identical supports */
61175d3a19aSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
61275d3a19aSMatthew G. Knepley       const PetscInt  newp = vStartNew + (v - vStart);
61375d3a19aSMatthew G. Knepley       const PetscInt *support, *cone;
61475d3a19aSMatthew G. Knepley       PetscInt        size, s;
61575d3a19aSMatthew G. Knepley 
61675d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
61775d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
61875d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
61975d3a19aSMatthew G. Knepley         PetscInt r = 0;
62075d3a19aSMatthew G. Knepley 
62175d3a19aSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
62275d3a19aSMatthew G. Knepley         if (cone[1] == v) r = 1;
62375d3a19aSMatthew G. Knepley         supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
62475d3a19aSMatthew G. Knepley       }
62575d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
62675d3a19aSMatthew G. Knepley #if 1
62775d3a19aSMatthew 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);
62875d3a19aSMatthew G. Knepley       for (p = 0; p < size; ++p) {
62975d3a19aSMatthew 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);
63075d3a19aSMatthew G. Knepley       }
63175d3a19aSMatthew G. Knepley #endif
63275d3a19aSMatthew G. Knepley     }
63375d3a19aSMatthew G. Knepley     /* Face vertices have 2 + cells*2 supports */
63475d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
63575d3a19aSMatthew G. Knepley       const PetscInt  newp = vStartNew + (vEnd - vStart) + (f - fStart);
63675d3a19aSMatthew G. Knepley       const PetscInt *cone, *support;
63775d3a19aSMatthew G. Knepley       PetscInt        size, s;
63875d3a19aSMatthew G. Knepley 
63975d3a19aSMatthew G. Knepley       ierr          = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
64075d3a19aSMatthew G. Knepley       ierr          = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
64175d3a19aSMatthew G. Knepley       supportRef[0] = fStartNew + (f - fStart)*2 + 0;
64275d3a19aSMatthew G. Knepley       supportRef[1] = fStartNew + (f - fStart)*2 + 1;
64375d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
64475d3a19aSMatthew G. Knepley         PetscInt r = 0;
64575d3a19aSMatthew G. Knepley 
64675d3a19aSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
64775d3a19aSMatthew G. Knepley         if      (cone[1] == f) r = 1;
64875d3a19aSMatthew G. Knepley         else if (cone[2] == f) r = 2;
64975d3a19aSMatthew G. Knepley         supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3;
65075d3a19aSMatthew G. Knepley         supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r;
65175d3a19aSMatthew G. Knepley       }
65275d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
65375d3a19aSMatthew G. Knepley #if 1
65475d3a19aSMatthew 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);
65575d3a19aSMatthew G. Knepley       for (p = 0; p < 2+size*2; ++p) {
65675d3a19aSMatthew 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);
65775d3a19aSMatthew G. Knepley       }
65875d3a19aSMatthew G. Knepley #endif
65975d3a19aSMatthew G. Knepley     }
66075d3a19aSMatthew G. Knepley     ierr = PetscFree(supportRef);CHKERRQ(ierr);
66175d3a19aSMatthew G. Knepley     break;
66275d3a19aSMatthew G. Knepley   case 2:
66375d3a19aSMatthew G. Knepley     /* Hex 2D */
66475d3a19aSMatthew G. Knepley     /*
66575d3a19aSMatthew G. Knepley      3---------2---------2
66675d3a19aSMatthew G. Knepley      |         |         |
66775d3a19aSMatthew G. Knepley      |    D    2    C    |
66875d3a19aSMatthew G. Knepley      |         |         |
66975d3a19aSMatthew G. Knepley      3----3----0----1----1
67075d3a19aSMatthew G. Knepley      |         |         |
67175d3a19aSMatthew G. Knepley      |    A    0    B    |
67275d3a19aSMatthew G. Knepley      |         |         |
67375d3a19aSMatthew G. Knepley      0---------0---------1
67475d3a19aSMatthew G. Knepley      */
67575d3a19aSMatthew G. Knepley     /* All cells have 4 faces */
67675d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
67775d3a19aSMatthew G. Knepley       const PetscInt  newp = (c - cStart)*4;
67875d3a19aSMatthew G. Knepley       const PetscInt *cone, *ornt;
67975d3a19aSMatthew G. Knepley       PetscInt        coneNew[4], orntNew[4];
68075d3a19aSMatthew G. Knepley 
68175d3a19aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
68275d3a19aSMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
68375d3a19aSMatthew G. Knepley       /* A quad */
68475d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
68575d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
68675d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 0;
68775d3a19aSMatthew G. Knepley       orntNew[1] = 0;
68875d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 3;
68975d3a19aSMatthew G. Knepley       orntNew[2] = -2;
69075d3a19aSMatthew G. Knepley       coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1);
69175d3a19aSMatthew G. Knepley       orntNew[3] = ornt[3];
69275d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
69375d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
69475d3a19aSMatthew G. Knepley #if 1
69575d3a19aSMatthew 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);
69675d3a19aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
69775d3a19aSMatthew 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);
69875d3a19aSMatthew G. Knepley       }
69975d3a19aSMatthew G. Knepley #endif
70075d3a19aSMatthew G. Knepley       /* B quad */
70175d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
70275d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
70375d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
70475d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
70575d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 1;
70675d3a19aSMatthew G. Knepley       orntNew[2] = 0;
70775d3a19aSMatthew G. Knepley       coneNew[3] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 0;
70875d3a19aSMatthew G. Knepley       orntNew[3] = -2;
70975d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
71075d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
71175d3a19aSMatthew G. Knepley #if 1
71275d3a19aSMatthew 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);
71375d3a19aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
71475d3a19aSMatthew 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);
71575d3a19aSMatthew G. Knepley       }
71675d3a19aSMatthew G. Knepley #endif
71775d3a19aSMatthew G. Knepley       /* C quad */
71875d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 1;
71975d3a19aSMatthew G. Knepley       orntNew[0] = -2;
72075d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
72175d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
72275d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
72375d3a19aSMatthew G. Knepley       orntNew[2] = ornt[2];
72475d3a19aSMatthew G. Knepley       coneNew[3] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 2;
72575d3a19aSMatthew G. Knepley       orntNew[3] = 0;
72675d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
72775d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
72875d3a19aSMatthew G. Knepley #if 1
72975d3a19aSMatthew 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);
73075d3a19aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
73175d3a19aSMatthew 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);
73275d3a19aSMatthew G. Knepley       }
73375d3a19aSMatthew G. Knepley #endif
73475d3a19aSMatthew G. Knepley       /* D quad */
73575d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 3;
73675d3a19aSMatthew G. Knepley       orntNew[0] = 0;
73775d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 2;
73875d3a19aSMatthew G. Knepley       orntNew[1] = -2;
73975d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
74075d3a19aSMatthew G. Knepley       orntNew[2] = ornt[2];
74175d3a19aSMatthew G. Knepley       coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0);
74275d3a19aSMatthew G. Knepley       orntNew[3] = ornt[3];
74375d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
74475d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
74575d3a19aSMatthew G. Knepley #if 1
74675d3a19aSMatthew 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);
74775d3a19aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
74875d3a19aSMatthew 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);
74975d3a19aSMatthew G. Knepley       }
75075d3a19aSMatthew G. Knepley #endif
75175d3a19aSMatthew G. Knepley     }
75275d3a19aSMatthew G. Knepley     /* Split faces have 2 vertices and the same cells as the parent */
75375d3a19aSMatthew G. Knepley     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
75475d3a19aSMatthew G. Knepley     ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr);
75575d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
75675d3a19aSMatthew G. Knepley       const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
75775d3a19aSMatthew G. Knepley 
75875d3a19aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
75975d3a19aSMatthew G. Knepley         const PetscInt  newp = fStartNew + (f - fStart)*2 + r;
76075d3a19aSMatthew G. Knepley         const PetscInt *cone, *support;
76175d3a19aSMatthew G. Knepley         PetscInt        coneNew[2], coneSize, c, supportSize, s;
76275d3a19aSMatthew G. Knepley 
76375d3a19aSMatthew G. Knepley         ierr             = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
76475d3a19aSMatthew G. Knepley         coneNew[0]       = vStartNew + (cone[0] - vStart);
76575d3a19aSMatthew G. Knepley         coneNew[1]       = vStartNew + (cone[1] - vStart);
76675d3a19aSMatthew G. Knepley         coneNew[(r+1)%2] = newv;
76775d3a19aSMatthew G. Knepley         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
76875d3a19aSMatthew G. Knepley #if 1
76975d3a19aSMatthew 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);
77075d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
77175d3a19aSMatthew 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);
77275d3a19aSMatthew G. Knepley         }
77375d3a19aSMatthew G. Knepley #endif
77475d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
77575d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
77675d3a19aSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
77775d3a19aSMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
77875d3a19aSMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
77975d3a19aSMatthew G. Knepley           for (c = 0; c < coneSize; ++c) {
78075d3a19aSMatthew G. Knepley             if (cone[c] == f) break;
78175d3a19aSMatthew G. Knepley           }
78275d3a19aSMatthew G. Knepley           supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%4;
78375d3a19aSMatthew G. Knepley         }
78475d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
78575d3a19aSMatthew G. Knepley #if 1
78675d3a19aSMatthew 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);
78775d3a19aSMatthew G. Knepley         for (p = 0; p < supportSize; ++p) {
78875d3a19aSMatthew 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);
78975d3a19aSMatthew G. Knepley         }
79075d3a19aSMatthew G. Knepley #endif
79175d3a19aSMatthew G. Knepley       }
79275d3a19aSMatthew G. Knepley     }
79375d3a19aSMatthew G. Knepley     /* Interior faces have 2 vertices and 2 cells */
79475d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
79575d3a19aSMatthew G. Knepley       const PetscInt *cone;
79675d3a19aSMatthew G. Knepley       PetscInt        coneNew[2], supportNew[2];
79775d3a19aSMatthew G. Knepley 
79875d3a19aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
79975d3a19aSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
80075d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r;
80175d3a19aSMatthew G. Knepley 
80275d3a19aSMatthew G. Knepley         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart);
80375d3a19aSMatthew G. Knepley         coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd    - fStart) + (c - cStart);
80475d3a19aSMatthew G. Knepley         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
80575d3a19aSMatthew G. Knepley #if 1
80675d3a19aSMatthew 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);
80775d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
80875d3a19aSMatthew 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);
80975d3a19aSMatthew G. Knepley         }
81075d3a19aSMatthew G. Knepley #endif
81175d3a19aSMatthew G. Knepley         supportNew[0] = (c - cStart)*4 + r;
81275d3a19aSMatthew G. Knepley         supportNew[1] = (c - cStart)*4 + (r+1)%4;
81375d3a19aSMatthew G. Knepley         ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
81475d3a19aSMatthew G. Knepley #if 1
81575d3a19aSMatthew 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);
81675d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
81775d3a19aSMatthew 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);
81875d3a19aSMatthew G. Knepley         }
81975d3a19aSMatthew G. Knepley #endif
82075d3a19aSMatthew G. Knepley       }
82175d3a19aSMatthew G. Knepley     }
82275d3a19aSMatthew G. Knepley     /* Old vertices have identical supports */
82375d3a19aSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
82475d3a19aSMatthew G. Knepley       const PetscInt  newp = vStartNew + (v - vStart);
82575d3a19aSMatthew G. Knepley       const PetscInt *support, *cone;
82675d3a19aSMatthew G. Knepley       PetscInt        size, s;
82775d3a19aSMatthew G. Knepley 
82875d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
82975d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
83075d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
83175d3a19aSMatthew G. Knepley         PetscInt r = 0;
83275d3a19aSMatthew G. Knepley 
83375d3a19aSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
83475d3a19aSMatthew G. Knepley         if (cone[1] == v) r = 1;
83575d3a19aSMatthew G. Knepley         supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
83675d3a19aSMatthew G. Knepley       }
83775d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
83875d3a19aSMatthew G. Knepley #if 1
83975d3a19aSMatthew 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);
84075d3a19aSMatthew G. Knepley       for (p = 0; p < size; ++p) {
84175d3a19aSMatthew 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);
84275d3a19aSMatthew G. Knepley       }
84375d3a19aSMatthew G. Knepley #endif
84475d3a19aSMatthew G. Knepley     }
84575d3a19aSMatthew G. Knepley     /* Face vertices have 2 + cells supports */
84675d3a19aSMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
84775d3a19aSMatthew G. Knepley       const PetscInt  newp = vStartNew + (vEnd - vStart) + (f - fStart);
84875d3a19aSMatthew G. Knepley       const PetscInt *cone, *support;
84975d3a19aSMatthew G. Knepley       PetscInt        size, s;
85075d3a19aSMatthew G. Knepley 
85175d3a19aSMatthew G. Knepley       ierr          = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
85275d3a19aSMatthew G. Knepley       ierr          = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
85375d3a19aSMatthew G. Knepley       supportRef[0] = fStartNew + (f - fStart)*2 + 0;
85475d3a19aSMatthew G. Knepley       supportRef[1] = fStartNew + (f - fStart)*2 + 1;
85575d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
85675d3a19aSMatthew G. Knepley         PetscInt r = 0;
85775d3a19aSMatthew G. Knepley 
85875d3a19aSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
85975d3a19aSMatthew G. Knepley         if      (cone[1] == f) r = 1;
86075d3a19aSMatthew G. Knepley         else if (cone[2] == f) r = 2;
86175d3a19aSMatthew G. Knepley         else if (cone[3] == f) r = 3;
86275d3a19aSMatthew G. Knepley         supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r;
86375d3a19aSMatthew G. Knepley       }
86475d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
86575d3a19aSMatthew G. Knepley #if 1
86675d3a19aSMatthew 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);
86775d3a19aSMatthew G. Knepley       for (p = 0; p < 2+size; ++p) {
86875d3a19aSMatthew 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);
86975d3a19aSMatthew G. Knepley       }
87075d3a19aSMatthew G. Knepley #endif
87175d3a19aSMatthew G. Knepley     }
87275d3a19aSMatthew G. Knepley     /* Cell vertices have 4 supports */
87375d3a19aSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
87475d3a19aSMatthew G. Knepley       const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart);
87575d3a19aSMatthew G. Knepley       PetscInt       supportNew[4];
87675d3a19aSMatthew G. Knepley 
87775d3a19aSMatthew G. Knepley       for (r = 0; r < 4; ++r) {
87875d3a19aSMatthew G. Knepley         supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r;
87975d3a19aSMatthew G. Knepley       }
88075d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
88175d3a19aSMatthew G. Knepley     }
88275d3a19aSMatthew G. Knepley     break;
88375d3a19aSMatthew G. Knepley   case 3:
88475d3a19aSMatthew G. Knepley     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
88575d3a19aSMatthew G. Knepley     cMax = PetscMin(cEnd, cMax);
88675d3a19aSMatthew G. Knepley     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
88775d3a19aSMatthew G. Knepley     fMax = PetscMin(fEnd, fMax);
88875d3a19aSMatthew G. Knepley     /* Interior cells have 3 faces */
88975d3a19aSMatthew G. Knepley     for (c = cStart; c < cMax; ++c) {
89075d3a19aSMatthew G. Knepley       const PetscInt  newp = cStartNew + (c - cStart)*4;
89175d3a19aSMatthew G. Knepley       const PetscInt *cone, *ornt;
89275d3a19aSMatthew G. Knepley       PetscInt        coneNew[3], orntNew[3];
89375d3a19aSMatthew G. Knepley 
89475d3a19aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
89575d3a19aSMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
89675d3a19aSMatthew G. Knepley       /* A triangle */
89775d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
89875d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
89975d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 2;
90075d3a19aSMatthew G. Knepley       orntNew[1] = -2;
90175d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
90275d3a19aSMatthew G. Knepley       orntNew[2] = ornt[2];
90375d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
90475d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
90575d3a19aSMatthew G. Knepley #if 1
90675d3a19aSMatthew 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);
90775d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
90875d3a19aSMatthew 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);
90975d3a19aSMatthew G. Knepley       }
91075d3a19aSMatthew G. Knepley #endif
91175d3a19aSMatthew G. Knepley       /* B triangle */
91275d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
91375d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
91475d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
91575d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
91675d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 0;
91775d3a19aSMatthew G. Knepley       orntNew[2] = -2;
91875d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
91975d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
92075d3a19aSMatthew G. Knepley #if 1
92175d3a19aSMatthew 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);
92275d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
92375d3a19aSMatthew 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);
92475d3a19aSMatthew G. Knepley       }
92575d3a19aSMatthew G. Knepley #endif
92675d3a19aSMatthew G. Knepley       /* C triangle */
92775d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 1;
92875d3a19aSMatthew G. Knepley       orntNew[0] = -2;
92975d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
93075d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
93175d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
93275d3a19aSMatthew G. Knepley       orntNew[2] = ornt[2];
93375d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
93475d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
93575d3a19aSMatthew G. Knepley #if 1
93675d3a19aSMatthew 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);
93775d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
93875d3a19aSMatthew 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);
93975d3a19aSMatthew G. Knepley       }
94075d3a19aSMatthew G. Knepley #endif
94175d3a19aSMatthew G. Knepley       /* D triangle */
94275d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 0;
94375d3a19aSMatthew G. Knepley       orntNew[0] = 0;
94475d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 1;
94575d3a19aSMatthew G. Knepley       orntNew[1] = 0;
94675d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (c - cStart)*3 + 2;
94775d3a19aSMatthew G. Knepley       orntNew[2] = 0;
94875d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
94975d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
95075d3a19aSMatthew G. Knepley #if 1
95175d3a19aSMatthew 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);
95275d3a19aSMatthew G. Knepley       for (p = 0; p < 3; ++p) {
95375d3a19aSMatthew 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);
95475d3a19aSMatthew G. Knepley       }
95575d3a19aSMatthew G. Knepley #endif
95675d3a19aSMatthew G. Knepley     }
95775d3a19aSMatthew G. Knepley     /*
95875d3a19aSMatthew G. Knepley      2----3----3
95975d3a19aSMatthew G. Knepley      |         |
96075d3a19aSMatthew G. Knepley      |    B    |
96175d3a19aSMatthew G. Knepley      |         |
96275d3a19aSMatthew G. Knepley      0----4--- 1
96375d3a19aSMatthew G. Knepley      |         |
96475d3a19aSMatthew G. Knepley      |    A    |
96575d3a19aSMatthew G. Knepley      |         |
96675d3a19aSMatthew G. Knepley      0----2----1
96775d3a19aSMatthew G. Knepley      */
96875d3a19aSMatthew G. Knepley     /* Hybrid cells have 4 faces */
96975d3a19aSMatthew G. Knepley     for (c = cMax; c < cEnd; ++c) {
97075d3a19aSMatthew G. Knepley       const PetscInt  newp = cStartNew + (cMax - cStart)*4 + (c - cMax)*2;
97175d3a19aSMatthew G. Knepley       const PetscInt *cone, *ornt;
97275d3a19aSMatthew G. Knepley       PetscInt        coneNew[4], orntNew[4];
97375d3a19aSMatthew G. Knepley 
97475d3a19aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
97575d3a19aSMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
97675d3a19aSMatthew G. Knepley       /* A quad */
97775d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
97875d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
97975d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
98075d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
98175d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*3 + (cone[2] - fMax);
98275d3a19aSMatthew G. Knepley       orntNew[2] = 0;
98375d3a19aSMatthew G. Knepley       coneNew[3] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*3 + (fEnd    - fMax) + (c - cMax);
98475d3a19aSMatthew G. Knepley       orntNew[3] = 0;
98575d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
98675d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
98775d3a19aSMatthew G. Knepley #if 1
98875d3a19aSMatthew 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);
98975d3a19aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
99075d3a19aSMatthew 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);
99175d3a19aSMatthew G. Knepley       }
99275d3a19aSMatthew G. Knepley #endif
99375d3a19aSMatthew G. Knepley       /* B quad */
99475d3a19aSMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
99575d3a19aSMatthew G. Knepley       orntNew[0] = ornt[0];
99675d3a19aSMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
99775d3a19aSMatthew G. Knepley       orntNew[1] = ornt[1];
99875d3a19aSMatthew G. Knepley       coneNew[2] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*3 + (fEnd    - fMax) + (c - cMax);
99975d3a19aSMatthew G. Knepley       orntNew[2] = 0;
100075d3a19aSMatthew G. Knepley       coneNew[3] = fStartNew + (fMax    - fStart)*2 + (cMax - cStart)*3 + (cone[3] - fMax);
100175d3a19aSMatthew G. Knepley       orntNew[3] = 0;
100275d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
100375d3a19aSMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
100475d3a19aSMatthew G. Knepley #if 1
100575d3a19aSMatthew 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);
100675d3a19aSMatthew G. Knepley       for (p = 0; p < 4; ++p) {
100775d3a19aSMatthew 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);
100875d3a19aSMatthew G. Knepley       }
100975d3a19aSMatthew G. Knepley #endif
101075d3a19aSMatthew G. Knepley     }
101175d3a19aSMatthew G. Knepley     /* Interior split faces have 2 vertices and the same cells as the parent */
101275d3a19aSMatthew G. Knepley     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
101375d3a19aSMatthew G. Knepley     ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr);
101475d3a19aSMatthew G. Knepley     for (f = fStart; f < fMax; ++f) {
101575d3a19aSMatthew G. Knepley       const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
101675d3a19aSMatthew G. Knepley 
101775d3a19aSMatthew G. Knepley       for (r = 0; r < 2; ++r) {
101875d3a19aSMatthew G. Knepley         const PetscInt  newp = fStartNew + (f - fStart)*2 + r;
101975d3a19aSMatthew G. Knepley         const PetscInt *cone, *support;
102075d3a19aSMatthew G. Knepley         PetscInt        coneNew[2], coneSize, c, supportSize, s;
102175d3a19aSMatthew G. Knepley 
102275d3a19aSMatthew G. Knepley         ierr             = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
102375d3a19aSMatthew G. Knepley         coneNew[0]       = vStartNew + (cone[0] - vStart);
102475d3a19aSMatthew G. Knepley         coneNew[1]       = vStartNew + (cone[1] - vStart);
102575d3a19aSMatthew G. Knepley         coneNew[(r+1)%2] = newv;
102675d3a19aSMatthew G. Knepley         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
102775d3a19aSMatthew G. Knepley #if 1
102875d3a19aSMatthew 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);
102975d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
103075d3a19aSMatthew 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);
103175d3a19aSMatthew G. Knepley         }
103275d3a19aSMatthew G. Knepley #endif
103375d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
103475d3a19aSMatthew G. Knepley         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
103575d3a19aSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
103675d3a19aSMatthew G. Knepley           if (support[s] >= cMax) {
103775d3a19aSMatthew G. Knepley             supportRef[s] = cStartNew + (cMax - cStart)*4 + (support[s] - cMax)*2 + r;
103875d3a19aSMatthew G. Knepley           } else {
103975d3a19aSMatthew G. Knepley             ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
104075d3a19aSMatthew G. Knepley             ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
104175d3a19aSMatthew G. Knepley             for (c = 0; c < coneSize; ++c) {
104275d3a19aSMatthew G. Knepley               if (cone[c] == f) break;
104375d3a19aSMatthew G. Knepley             }
104475d3a19aSMatthew G. Knepley             supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3;
104575d3a19aSMatthew G. Knepley           }
104675d3a19aSMatthew G. Knepley         }
104775d3a19aSMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
104875d3a19aSMatthew G. Knepley #if 1
104975d3a19aSMatthew 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);
105075d3a19aSMatthew G. Knepley         for (p = 0; p < supportSize; ++p) {
105175d3a19aSMatthew 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);
105275d3a19aSMatthew G. Knepley         }
105375d3a19aSMatthew G. Knepley #endif
105475d3a19aSMatthew G. Knepley       }
105575d3a19aSMatthew G. Knepley     }
105675d3a19aSMatthew G. Knepley     /* Interior cell faces have 2 vertices and 2 cells */
105775d3a19aSMatthew G. Knepley     for (c = cStart; c < cMax; ++c) {
105875d3a19aSMatthew G. Knepley       const PetscInt *cone;
105975d3a19aSMatthew G. Knepley 
106075d3a19aSMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
106175d3a19aSMatthew G. Knepley       for (r = 0; r < 3; ++r) {
106275d3a19aSMatthew G. Knepley         const PetscInt newp = fStartNew + (fMax - fStart)*2 + (c - cStart)*3 + r;
106375d3a19aSMatthew G. Knepley         PetscInt       coneNew[2];
106475d3a19aSMatthew G. Knepley         PetscInt       supportNew[2];
106575d3a19aSMatthew G. Knepley 
106675d3a19aSMatthew G. Knepley         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r]       - fStart);
106775d3a19aSMatthew G. Knepley         coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart);
106875d3a19aSMatthew G. Knepley         ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
106975d3a19aSMatthew G. Knepley #if 1
107075d3a19aSMatthew 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);
107175d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
107275d3a19aSMatthew 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);
107375d3a19aSMatthew G. Knepley         }
107475d3a19aSMatthew G. Knepley #endif
107575d3a19aSMatthew G. Knepley         supportNew[0] = (c - cStart)*4 + (r+1)%3;
107675d3a19aSMatthew G. Knepley         supportNew[1] = (c - cStart)*4 + 3;
107775d3a19aSMatthew G. Knepley         ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
107875d3a19aSMatthew G. Knepley #if 1
107975d3a19aSMatthew 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);
108075d3a19aSMatthew G. Knepley         for (p = 0; p < 2; ++p) {
108175d3a19aSMatthew 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);
108275d3a19aSMatthew G. Knepley         }
108375d3a19aSMatthew G. Knepley #endif
108475d3a19aSMatthew G. Knepley       }
108575d3a19aSMatthew G. Knepley     }
108675d3a19aSMatthew G. Knepley     /* Interior hybrid faces have 2 vertices and the same cells */
108775d3a19aSMatthew G. Knepley     for (f = fMax; f < fEnd; ++f) {
108875d3a19aSMatthew G. Knepley       const PetscInt  newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (f - fMax);
108975d3a19aSMatthew G. Knepley       const PetscInt *cone;
109075d3a19aSMatthew G. Knepley       const PetscInt *support;
109175d3a19aSMatthew G. Knepley       PetscInt        coneNew[2];
109275d3a19aSMatthew G. Knepley       PetscInt        supportNew[2];
109375d3a19aSMatthew G. Knepley       PetscInt        size, s, r;
109475d3a19aSMatthew G. Knepley 
109575d3a19aSMatthew G. Knepley       ierr       = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
109675d3a19aSMatthew G. Knepley       coneNew[0] = vStartNew + (cone[0] - vStart);
109775d3a19aSMatthew G. Knepley       coneNew[1] = vStartNew + (cone[1] - vStart);
109875d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
109975d3a19aSMatthew G. Knepley #if 1
110075d3a19aSMatthew 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);
110175d3a19aSMatthew G. Knepley       for (p = 0; p < 2; ++p) {
110275d3a19aSMatthew 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);
110375d3a19aSMatthew G. Knepley       }
110475d3a19aSMatthew G. Knepley #endif
110575d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
110675d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
110775d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
110875d3a19aSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
110975d3a19aSMatthew G. Knepley         for (r = 0; r < 2; ++r) {
111075d3a19aSMatthew G. Knepley           if (cone[r+2] == f) break;
111175d3a19aSMatthew G. Knepley         }
111275d3a19aSMatthew G. Knepley         supportNew[s] = (cMax - cStart)*4 + (support[s] - cMax)*2 + r;
111375d3a19aSMatthew G. Knepley       }
111475d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
111575d3a19aSMatthew G. Knepley #if 1
111675d3a19aSMatthew 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);
111775d3a19aSMatthew G. Knepley       for (p = 0; p < size; ++p) {
111875d3a19aSMatthew 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);
111975d3a19aSMatthew G. Knepley       }
112075d3a19aSMatthew G. Knepley #endif
112175d3a19aSMatthew G. Knepley     }
112275d3a19aSMatthew G. Knepley     /* Cell hybrid faces have 2 vertices and 2 cells */
112375d3a19aSMatthew G. Knepley     for (c = cMax; c < cEnd; ++c) {
112475d3a19aSMatthew G. Knepley       const PetscInt  newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (c - cMax);
112575d3a19aSMatthew G. Knepley       const PetscInt *cone;
112675d3a19aSMatthew G. Knepley       PetscInt        coneNew[2];
112775d3a19aSMatthew G. Knepley       PetscInt        supportNew[2];
112875d3a19aSMatthew G. Knepley 
112975d3a19aSMatthew G. Knepley       ierr       = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
113075d3a19aSMatthew G. Knepley       coneNew[0] = vStartNew + (vEnd - vStart) + (cone[0] - fStart);
113175d3a19aSMatthew G. Knepley       coneNew[1] = vStartNew + (vEnd - vStart) + (cone[1] - fStart);
113275d3a19aSMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
113375d3a19aSMatthew G. Knepley #if 1
113475d3a19aSMatthew 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);
113575d3a19aSMatthew G. Knepley       for (p = 0; p < 2; ++p) {
113675d3a19aSMatthew 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);
113775d3a19aSMatthew G. Knepley       }
113875d3a19aSMatthew G. Knepley #endif
113975d3a19aSMatthew G. Knepley       supportNew[0] = (cMax - cStart)*4 + (c - cMax)*2 + 0;
114075d3a19aSMatthew G. Knepley       supportNew[1] = (cMax - cStart)*4 + (c - cMax)*2 + 1;
114175d3a19aSMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
114275d3a19aSMatthew G. Knepley #if 1
114375d3a19aSMatthew 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);
114475d3a19aSMatthew G. Knepley       for (p = 0; p < 2; ++p) {
114575d3a19aSMatthew 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);
114675d3a19aSMatthew G. Knepley       }
114775d3a19aSMatthew G. Knepley #endif
114875d3a19aSMatthew G. Knepley     }
114975d3a19aSMatthew G. Knepley     /* Old vertices have identical supports */
115075d3a19aSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
115175d3a19aSMatthew G. Knepley       const PetscInt  newp = vStartNew + (v - vStart);
115275d3a19aSMatthew G. Knepley       const PetscInt *support, *cone;
115375d3a19aSMatthew G. Knepley       PetscInt        size, s;
115475d3a19aSMatthew G. Knepley 
115575d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
115675d3a19aSMatthew G. Knepley       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
115775d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
115875d3a19aSMatthew G. Knepley         if (support[s] >= fMax) {
115975d3a19aSMatthew G. Knepley           supportRef[s] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (support[s] - fMax);
116075d3a19aSMatthew G. Knepley         } else {
116175d3a19aSMatthew G. Knepley           PetscInt r = 0;
116275d3a19aSMatthew G. Knepley 
116375d3a19aSMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
116475d3a19aSMatthew G. Knepley           if (cone[1] == v) r = 1;
116575d3a19aSMatthew G. Knepley           supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
116675d3a19aSMatthew G. Knepley         }
116775d3a19aSMatthew G. Knepley       }
116875d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
116975d3a19aSMatthew G. Knepley #if 1
117075d3a19aSMatthew 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);
117175d3a19aSMatthew G. Knepley       for (p = 0; p < size; ++p) {
117275d3a19aSMatthew 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);
117375d3a19aSMatthew G. Knepley       }
117475d3a19aSMatthew G. Knepley #endif
117575d3a19aSMatthew G. Knepley     }
117675d3a19aSMatthew G. Knepley     /* Face vertices have 2 + (2 interior, 1 hybrid) supports */
117775d3a19aSMatthew G. Knepley     for (f = fStart; f < fMax; ++f) {
117875d3a19aSMatthew G. Knepley       const PetscInt  newp = vStartNew + (vEnd - vStart) + (f - fStart);
117975d3a19aSMatthew G. Knepley       const PetscInt *cone, *support;
118075d3a19aSMatthew G. Knepley       PetscInt        size, newSize = 2, s;
118175d3a19aSMatthew G. Knepley 
118275d3a19aSMatthew G. Knepley       ierr          = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
118375d3a19aSMatthew G. Knepley       ierr          = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
118475d3a19aSMatthew G. Knepley       supportRef[0] = fStartNew + (f - fStart)*2 + 0;
118575d3a19aSMatthew G. Knepley       supportRef[1] = fStartNew + (f - fStart)*2 + 1;
118675d3a19aSMatthew G. Knepley       for (s = 0; s < size; ++s) {
118775d3a19aSMatthew G. Knepley         PetscInt r = 0;
118875d3a19aSMatthew G. Knepley 
118975d3a19aSMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
119075d3a19aSMatthew G. Knepley         if (support[s] >= cMax) {
119175d3a19aSMatthew G. Knepley           supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (fEnd - fMax) + (support[s] - cMax);
119275d3a19aSMatthew G. Knepley 
119375d3a19aSMatthew G. Knepley           newSize += 1;
119475d3a19aSMatthew G. Knepley         } else {
119575d3a19aSMatthew G. Knepley           if      (cone[1] == f) r = 1;
119675d3a19aSMatthew G. Knepley           else if (cone[2] == f) r = 2;
119775d3a19aSMatthew G. Knepley           supportRef[newSize+0] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3;
119875d3a19aSMatthew G. Knepley           supportRef[newSize+1] = fStartNew + (fMax - fStart)*2 + (support[s] - cStart)*3 + r;
119975d3a19aSMatthew G. Knepley 
120075d3a19aSMatthew G. Knepley           newSize += 2;
120175d3a19aSMatthew G. Knepley         }
120275d3a19aSMatthew G. Knepley       }
120375d3a19aSMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
120475d3a19aSMatthew G. Knepley #if 1
120575d3a19aSMatthew 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);
120675d3a19aSMatthew G. Knepley       for (p = 0; p < newSize; ++p) {
120775d3a19aSMatthew 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);
120875d3a19aSMatthew G. Knepley       }
120975d3a19aSMatthew G. Knepley #endif
121075d3a19aSMatthew G. Knepley     }
121175d3a19aSMatthew G. Knepley     ierr = PetscFree(supportRef);CHKERRQ(ierr);
121275d3a19aSMatthew G. Knepley     break;
1213*b5da9499SMatthew G. Knepley   case 5:
1214*b5da9499SMatthew G. Knepley     /* Simplicial 3D */
1215*b5da9499SMatthew G. Knepley     /* All cells have 4 faces: Tet face order is prescribed in DMPlexGetFaces_Internal() */
1216*b5da9499SMatthew G. Knepley     ierr = DMPlexGetRawFaces_Internal(dm, 3, 4, cellInd, NULL, NULL, &faces);CHKERRQ(ierr);
1217*b5da9499SMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
1218*b5da9499SMatthew G. Knepley       const PetscInt  newp = cStartNew + (c - cStart)*8;
1219*b5da9499SMatthew G. Knepley       const PetscInt *cone, *ornt;
1220*b5da9499SMatthew G. Knepley       PetscInt        coneNew[4], orntNew[4];
1221*b5da9499SMatthew G. Knepley 
1222*b5da9499SMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
1223*b5da9499SMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
1224*b5da9499SMatthew G. Knepley       /* A tetrahedron: {0, a, c, d} */
1225*b5da9499SMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + (ornt[0] < 0 ? (-(ornt[0]+1)+1)%3 : ornt[0]); /* A */
1226*b5da9499SMatthew G. Knepley       orntNew[0] = ornt[0];
1227*b5da9499SMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + (ornt[1] < 0 ? (-(ornt[1]+1)+1)%3 : ornt[1]); /* A */
1228*b5da9499SMatthew G. Knepley       orntNew[1] = ornt[1];
1229*b5da9499SMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + (ornt[2] < 0 ? (-(ornt[2]+1)+1)%3 : ornt[2]); /* A */
1230*b5da9499SMatthew G. Knepley       orntNew[2] = ornt[2];
1231*b5da9499SMatthew G. Knepley       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 0;
1232*b5da9499SMatthew G. Knepley       orntNew[3] = 0;
1233*b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
1234*b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
1235*b5da9499SMatthew G. Knepley #if 1
1236*b5da9499SMatthew 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);
1237*b5da9499SMatthew G. Knepley       for (p = 0; p < 4; ++p) {
1238*b5da9499SMatthew 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);
1239*b5da9499SMatthew G. Knepley       }
1240*b5da9499SMatthew G. Knepley #endif
1241*b5da9499SMatthew G. Knepley       /* B tetrahedron: {a, 1, b, e} */
1242*b5da9499SMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + (ornt[0] < 0 ? (-(ornt[0]+1)+0)%3 : (ornt[0]+1)%3); /* B */
1243*b5da9499SMatthew G. Knepley       orntNew[0] = ornt[0];
1244*b5da9499SMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + (ornt[1] < 0 ? (-(ornt[1]+1)+2)%3 : (ornt[1]+2)%3); /* C */
1245*b5da9499SMatthew G. Knepley       orntNew[1] = ornt[1];
1246*b5da9499SMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 1;
1247*b5da9499SMatthew G. Knepley       orntNew[2] = 0;
1248*b5da9499SMatthew G. Knepley       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + (ornt[3] < 0 ? (-(ornt[3]+1)+0)%3 : (ornt[3]+1)%3); /* B */
1249*b5da9499SMatthew G. Knepley       orntNew[3] = ornt[3];
1250*b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
1251*b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
1252*b5da9499SMatthew G. Knepley #if 1
1253*b5da9499SMatthew 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);
1254*b5da9499SMatthew G. Knepley       for (p = 0; p < 4; ++p) {
1255*b5da9499SMatthew 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);
1256*b5da9499SMatthew G. Knepley       }
1257*b5da9499SMatthew G. Knepley #endif
1258*b5da9499SMatthew G. Knepley       /* C tetrahedron: {c, b, 2, f} */
1259*b5da9499SMatthew G. Knepley       coneNew[0] = fStartNew + (cone[0] - fStart)*4 + (ornt[0] < 0 ? (-(ornt[0]+1)+2)%3 : (ornt[0]+2)%3); /* C */
1260*b5da9499SMatthew G. Knepley       orntNew[0] = ornt[0];
1261*b5da9499SMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 2;
1262*b5da9499SMatthew G. Knepley       orntNew[1] = 0;
1263*b5da9499SMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + (ornt[2] < 0 ? (-(ornt[2]+1)+0)%3 : (ornt[2]+1)%3); /* B */
1264*b5da9499SMatthew G. Knepley       orntNew[2] = ornt[2];
1265*b5da9499SMatthew G. Knepley       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + (ornt[3] < 0 ? (-(ornt[3]+1)+1)%3 : (ornt[3]+0)%3); /* A */
1266*b5da9499SMatthew G. Knepley       orntNew[3] = ornt[3];
1267*b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
1268*b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
1269*b5da9499SMatthew G. Knepley #if 1
1270*b5da9499SMatthew 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);
1271*b5da9499SMatthew G. Knepley       for (p = 0; p < 4; ++p) {
1272*b5da9499SMatthew 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);
1273*b5da9499SMatthew G. Knepley       }
1274*b5da9499SMatthew G. Knepley #endif
1275*b5da9499SMatthew G. Knepley       /* D tetrahedron: {d, e, f, 3} */
1276*b5da9499SMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 3;
1277*b5da9499SMatthew G. Knepley       orntNew[0] = 0;
1278*b5da9499SMatthew G. Knepley       coneNew[1] = fStartNew + (cone[1] - fStart)*4 + (ornt[1] < 0 ? (-(ornt[1]+1)+0)%3 : (ornt[1]+1)%3); /* B */
1279*b5da9499SMatthew G. Knepley       orntNew[1] = ornt[1];
1280*b5da9499SMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + (ornt[2] < 0 ? (-(ornt[2]+1)+2)%3 : (ornt[2]+2)%3); /* C */
1281*b5da9499SMatthew G. Knepley       orntNew[2] = ornt[2];
1282*b5da9499SMatthew G. Knepley       coneNew[3] = fStartNew + (cone[3] - fStart)*4 + (ornt[3] < 0 ? (-(ornt[3]+1)+2)%3 : (ornt[3]+2)%3); /* C */
1283*b5da9499SMatthew G. Knepley       orntNew[3] = ornt[3];
1284*b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
1285*b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
1286*b5da9499SMatthew G. Knepley #if 1
1287*b5da9499SMatthew 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);
1288*b5da9499SMatthew G. Knepley       for (p = 0; p < 4; ++p) {
1289*b5da9499SMatthew 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);
1290*b5da9499SMatthew G. Knepley       }
1291*b5da9499SMatthew G. Knepley #endif
1292*b5da9499SMatthew G. Knepley       /* A' tetrahedron: {d, a, c, f} */
1293*b5da9499SMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 0;
1294*b5da9499SMatthew G. Knepley       orntNew[0] = -3;
1295*b5da9499SMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 4;
1296*b5da9499SMatthew G. Knepley       orntNew[1] = 0;
1297*b5da9499SMatthew G. Knepley       coneNew[2] = fStartNew + (cone[2] - fStart)*4 + 3;
1298*b5da9499SMatthew G. Knepley       orntNew[2] = ornt[2] < 0 ? -((-(ornt[2]+1)+2)%3+1) : (ornt[2]+2)%3;
1299*b5da9499SMatthew G. Knepley       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 5;
1300*b5da9499SMatthew G. Knepley       orntNew[3] = 0;
1301*b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+4, coneNew);CHKERRQ(ierr);
1302*b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+4, orntNew);CHKERRQ(ierr);
1303*b5da9499SMatthew G. Knepley #if 1
1304*b5da9499SMatthew G. Knepley       if ((newp+4 < cStartNew) || (newp+4 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+4, cStartNew, cEndNew);
1305*b5da9499SMatthew G. Knepley       for (p = 0; p < 4; ++p) {
1306*b5da9499SMatthew 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);
1307*b5da9499SMatthew G. Knepley       }
1308*b5da9499SMatthew G. Knepley #endif
1309*b5da9499SMatthew G. Knepley       /* B' tetrahedron: {e, b, a, f} */
1310*b5da9499SMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 1;
1311*b5da9499SMatthew G. Knepley       orntNew[0] = -3;
1312*b5da9499SMatthew G. Knepley       coneNew[1] = fStartNew + (cone[3] - fStart)*4 + 3;
1313*b5da9499SMatthew G. Knepley       orntNew[1] = ornt[3] < 0 ? -((-(ornt[3]+1)+1)%3+1) : (ornt[3]+1)%3;
1314*b5da9499SMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 6;
1315*b5da9499SMatthew G. Knepley       orntNew[2] = 0;
1316*b5da9499SMatthew G. Knepley       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 7;
1317*b5da9499SMatthew G. Knepley       orntNew[3] = 0;
1318*b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+5, coneNew);CHKERRQ(ierr);
1319*b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+5, orntNew);CHKERRQ(ierr);
1320*b5da9499SMatthew G. Knepley #if 1
1321*b5da9499SMatthew G. Knepley       if ((newp+5 < cStartNew) || (newp+5 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+5, cStartNew, cEndNew);
1322*b5da9499SMatthew G. Knepley       for (p = 0; p < 4; ++p) {
1323*b5da9499SMatthew 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);
1324*b5da9499SMatthew G. Knepley       }
1325*b5da9499SMatthew G. Knepley #endif
1326*b5da9499SMatthew G. Knepley       /* C' tetrahedron: {b, f, c, a} */
1327*b5da9499SMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 2;
1328*b5da9499SMatthew G. Knepley       orntNew[0] = -3;
1329*b5da9499SMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 7;
1330*b5da9499SMatthew G. Knepley       orntNew[1] = -2;
1331*b5da9499SMatthew G. Knepley       coneNew[2] = fStartNew + (cone[0] - fStart)*4 + 3;
1332*b5da9499SMatthew G. Knepley       orntNew[2] = ornt[0] < 0 ? (-(ornt[0]+1)+1)%3 : -((ornt[0]+1)%3+1);
1333*b5da9499SMatthew G. Knepley       coneNew[3] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 5;
1334*b5da9499SMatthew G. Knepley       orntNew[3] = -1;
1335*b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+6, coneNew);CHKERRQ(ierr);
1336*b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+6, orntNew);CHKERRQ(ierr);
1337*b5da9499SMatthew G. Knepley #if 1
1338*b5da9499SMatthew G. Knepley       if ((newp+6 < cStartNew) || (newp+6 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+6, cStartNew, cEndNew);
1339*b5da9499SMatthew G. Knepley       for (p = 0; p < 4; ++p) {
1340*b5da9499SMatthew 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);
1341*b5da9499SMatthew G. Knepley       }
1342*b5da9499SMatthew G. Knepley #endif
1343*b5da9499SMatthew G. Knepley       /* D' tetrahedron: {f, e, d, a} */
1344*b5da9499SMatthew G. Knepley       coneNew[0] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 3;
1345*b5da9499SMatthew G. Knepley       orntNew[0] = -3;
1346*b5da9499SMatthew G. Knepley       coneNew[1] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 6;
1347*b5da9499SMatthew G. Knepley       orntNew[1] = -3;
1348*b5da9499SMatthew G. Knepley       coneNew[2] = fStartNew + (fEnd    - fStart)*4 + (c - cStart)*8 + 4;
1349*b5da9499SMatthew G. Knepley       orntNew[2] = -2;
1350*b5da9499SMatthew G. Knepley       coneNew[3] = fStartNew + (cone[1] - fStart)*4 + 3;
1351*b5da9499SMatthew G. Knepley       orntNew[3] = ornt[2];
1352*b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+7, coneNew);CHKERRQ(ierr);
1353*b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+7, orntNew);CHKERRQ(ierr);
1354*b5da9499SMatthew G. Knepley #if 1
1355*b5da9499SMatthew G. Knepley       if ((newp+7 < cStartNew) || (newp+7 >= cEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+7, cStartNew, cEndNew);
1356*b5da9499SMatthew G. Knepley       for (p = 0; p < 4; ++p) {
1357*b5da9499SMatthew 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);
1358*b5da9499SMatthew G. Knepley       }
1359*b5da9499SMatthew G. Knepley #endif
1360*b5da9499SMatthew G. Knepley     }
1361*b5da9499SMatthew G. Knepley     /* Split faces have 3 edges and the same cells as the parent */
1362*b5da9499SMatthew G. Knepley     ierr = DMPlexGetMaxSizes(dm, NULL, &maxSupportSize);CHKERRQ(ierr);
1363*b5da9499SMatthew G. Knepley     ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr);
1364*b5da9499SMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
1365*b5da9499SMatthew G. Knepley       const PetscInt  newp = fStartNew + (f - fStart)*4;
1366*b5da9499SMatthew G. Knepley       const PetscInt *cone, *ornt, *support;
1367*b5da9499SMatthew G. Knepley       PetscInt        coneNew[3], orntNew[3], coneSize, supportSize, s;
1368*b5da9499SMatthew G. Knepley 
1369*b5da9499SMatthew G. Knepley       ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
1370*b5da9499SMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, f, &ornt);CHKERRQ(ierr);
1371*b5da9499SMatthew G. Knepley       /* A triangle */
1372*b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 1 : 0);
1373*b5da9499SMatthew G. Knepley       orntNew[0] = ornt[0];
1374*b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 2;
1375*b5da9499SMatthew G. Knepley       orntNew[1] = -2;
1376*b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 0 : 1);
1377*b5da9499SMatthew G. Knepley       orntNew[2] = ornt[2];
1378*b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
1379*b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
1380*b5da9499SMatthew G. Knepley #if 1
1381*b5da9499SMatthew G. Knepley       if ((newp+0 < fStartNew) || (newp+0 >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+0, fStartNew, fEndNew);
1382*b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1383*b5da9499SMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
1384*b5da9499SMatthew G. Knepley       }
1385*b5da9499SMatthew G. Knepley #endif
1386*b5da9499SMatthew G. Knepley       /* B triangle */
1387*b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (cone[0] - eStart)*2 + (ornt[0] < 0 ? 0 : 1);
1388*b5da9499SMatthew G. Knepley       orntNew[0] = ornt[0];
1389*b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 1 : 0);
1390*b5da9499SMatthew G. Knepley       orntNew[1] = ornt[1];
1391*b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 0;
1392*b5da9499SMatthew G. Knepley       orntNew[2] = -2;
1393*b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
1394*b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
1395*b5da9499SMatthew G. Knepley #if 1
1396*b5da9499SMatthew G. Knepley       if ((newp+1 < fStartNew) || (newp+1 >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+1, fStartNew, fEndNew);
1397*b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1398*b5da9499SMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
1399*b5da9499SMatthew G. Knepley       }
1400*b5da9499SMatthew G. Knepley #endif
1401*b5da9499SMatthew G. Knepley       /* C triangle */
1402*b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 1;
1403*b5da9499SMatthew G. Knepley       orntNew[0] = -2;
1404*b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (cone[1] - eStart)*2 + (ornt[1] < 0 ? 0 : 1);
1405*b5da9499SMatthew G. Knepley       orntNew[1] = ornt[1];
1406*b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (cone[2] - eStart)*2 + (ornt[2] < 0 ? 1 : 0);
1407*b5da9499SMatthew G. Knepley       orntNew[2] = ornt[2];
1408*b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
1409*b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
1410*b5da9499SMatthew G. Knepley #if 1
1411*b5da9499SMatthew G. Knepley       if ((newp+2 < fStartNew) || (newp+2 >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+2, fStartNew, fEndNew);
1412*b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1413*b5da9499SMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
1414*b5da9499SMatthew G. Knepley       }
1415*b5da9499SMatthew G. Knepley #endif
1416*b5da9499SMatthew G. Knepley       /* D triangle */
1417*b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 0;
1418*b5da9499SMatthew G. Knepley       orntNew[0] = 0;
1419*b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 1;
1420*b5da9499SMatthew G. Knepley       orntNew[1] = 0;
1421*b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd    - eStart)*2 + (f - fStart)*3 + 2;
1422*b5da9499SMatthew G. Knepley       orntNew[2] = 0;
1423*b5da9499SMatthew G. Knepley       ierr       = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
1424*b5da9499SMatthew G. Knepley       ierr       = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
1425*b5da9499SMatthew G. Knepley #if 1
1426*b5da9499SMatthew G. Knepley       if ((newp+3 < fStartNew) || (newp+3 >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+3, fStartNew, fEndNew);
1427*b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1428*b5da9499SMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
1429*b5da9499SMatthew G. Knepley       }
1430*b5da9499SMatthew G. Knepley #endif
1431*b5da9499SMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
1432*b5da9499SMatthew G. Knepley       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
1433*b5da9499SMatthew G. Knepley       for (r = 0; r < 4; ++r) {
1434*b5da9499SMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
1435*b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
1436*b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
1437*b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
1438*b5da9499SMatthew G. Knepley           for (c = 0; c < coneSize; ++c) {
1439*b5da9499SMatthew G. Knepley             if (cone[c] == f) break;
1440*b5da9499SMatthew G. Knepley           }
1441*b5da9499SMatthew G. Knepley           supportRef[s] = cStartNew + (support[s] - cStart)*8 + (r==3 ? (c+2)%4 + 4 : (ornt[c] < 0 ? faces[c*3+(-(ornt[c]+1)+1+3-r)%3] : faces[c*3+r]));
1442*b5da9499SMatthew G. Knepley         }
1443*b5da9499SMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp+r, supportRef);CHKERRQ(ierr);
1444*b5da9499SMatthew G. Knepley #if 1
1445*b5da9499SMatthew 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);
1446*b5da9499SMatthew G. Knepley         for (p = 0; p < supportSize; ++p) {
1447*b5da9499SMatthew 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);
1448*b5da9499SMatthew G. Knepley         }
1449*b5da9499SMatthew G. Knepley #endif
1450*b5da9499SMatthew G. Knepley       }
1451*b5da9499SMatthew G. Knepley     }
1452*b5da9499SMatthew G. Knepley     /* Interior faces have 3 edges and 2 cells */
1453*b5da9499SMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
1454*b5da9499SMatthew G. Knepley       PetscInt        newp = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8;
1455*b5da9499SMatthew G. Knepley       const PetscInt *cone, *ornt;
1456*b5da9499SMatthew G. Knepley       PetscInt        coneNew[3], orntNew[3];
1457*b5da9499SMatthew G. Knepley       PetscInt        supportNew[2];
1458*b5da9499SMatthew G. Knepley 
1459*b5da9499SMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
1460*b5da9499SMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
1461*b5da9499SMatthew G. Knepley       /* Face A: {c, a, d} */
1462*b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + (ornt[0] < 0 ? (-(ornt[0]+1)+0)%3 : (ornt[0]+2)%3);
1463*b5da9499SMatthew G. Knepley       orntNew[0] = ornt[0] < 0 ? -2 : 0;
1464*b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + (ornt[1] < 0 ? (-(ornt[1]+1)+0)%3 : (ornt[1]+2)%3);
1465*b5da9499SMatthew G. Knepley       orntNew[1] = ornt[1] < 0 ? -2 : 0;
1466*b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + (ornt[2] < 0 ? (-(ornt[2]+1)+0)%3 : (ornt[2]+2)%3);
1467*b5da9499SMatthew G. Knepley       orntNew[2] = ornt[2] < 0 ? -2 : 0;
1468*b5da9499SMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1469*b5da9499SMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
1470*b5da9499SMatthew G. Knepley #if 1
1471*b5da9499SMatthew 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);
1472*b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1473*b5da9499SMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
1474*b5da9499SMatthew G. Knepley       }
1475*b5da9499SMatthew G. Knepley #endif
1476*b5da9499SMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 0;
1477*b5da9499SMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 0+4;
1478*b5da9499SMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1479*b5da9499SMatthew G. Knepley #if 1
1480*b5da9499SMatthew 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);
1481*b5da9499SMatthew G. Knepley       for (p = 0; p < 2; ++p) {
1482*b5da9499SMatthew 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);
1483*b5da9499SMatthew G. Knepley       }
1484*b5da9499SMatthew G. Knepley #endif
1485*b5da9499SMatthew G. Knepley       ++newp;
1486*b5da9499SMatthew G. Knepley       /* Face B: {a, b, e} */
1487*b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + (ornt[0] < 0 ? (-(ornt[0]+1)+2)%3 : (ornt[0]+0)%3);
1488*b5da9499SMatthew G. Knepley       orntNew[0] = ornt[0] < 0 ? -2 : 0;
1489*b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + (ornt[3] < 0 ? (-(ornt[3]+1)+2)%3 : (ornt[3]+0)%3);
1490*b5da9499SMatthew G. Knepley       orntNew[1] = ornt[3] < 0 ? -2 : 0;
1491*b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + (ornt[1] < 0 ? (-(ornt[1]+1)+1)%3 : (ornt[1]+1)%3);
1492*b5da9499SMatthew G. Knepley       orntNew[2] = ornt[1] < 0 ? -2 : 0;
1493*b5da9499SMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1494*b5da9499SMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
1495*b5da9499SMatthew G. Knepley #if 1
1496*b5da9499SMatthew G. Knepley       if ((newp+1 < fStartNew) || (newp+1 >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp+1, fStartNew, fEndNew);
1497*b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1498*b5da9499SMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
1499*b5da9499SMatthew G. Knepley       }
1500*b5da9499SMatthew G. Knepley #endif
1501*b5da9499SMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 1;
1502*b5da9499SMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 1+4;
1503*b5da9499SMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1504*b5da9499SMatthew G. Knepley #if 1
1505*b5da9499SMatthew 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);
1506*b5da9499SMatthew G. Knepley       for (p = 0; p < 2; ++p) {
1507*b5da9499SMatthew 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);
1508*b5da9499SMatthew G. Knepley       }
1509*b5da9499SMatthew G. Knepley #endif
1510*b5da9499SMatthew G. Knepley       ++newp;
1511*b5da9499SMatthew G. Knepley       /* Face C: {c, f, b} */
1512*b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + (ornt[2] < 0 ? (-(ornt[2]+1)+2)%3 : (ornt[2]+0)%3);
1513*b5da9499SMatthew G. Knepley       orntNew[0] = ornt[2] < 0 ? -2 : 0;
1514*b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + (ornt[3] < 0 ? (-(ornt[3]+1)+0)%3 : (ornt[3]+2)%3);
1515*b5da9499SMatthew G. Knepley       orntNew[1] = ornt[3] < 0 ? -2 : 0;
1516*b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + (ornt[0] < 0 ? (-(ornt[0]+1)+1)%3 : (ornt[0]+1)%3);
1517*b5da9499SMatthew G. Knepley       orntNew[2] = ornt[0] < 0 ? -2 : 0;
1518*b5da9499SMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1519*b5da9499SMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
1520*b5da9499SMatthew G. Knepley #if 1
1521*b5da9499SMatthew 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);
1522*b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1523*b5da9499SMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
1524*b5da9499SMatthew G. Knepley       }
1525*b5da9499SMatthew G. Knepley #endif
1526*b5da9499SMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 2;
1527*b5da9499SMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 2+4;
1528*b5da9499SMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1529*b5da9499SMatthew G. Knepley #if 1
1530*b5da9499SMatthew 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);
1531*b5da9499SMatthew G. Knepley       for (p = 0; p < 2; ++p) {
1532*b5da9499SMatthew 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);
1533*b5da9499SMatthew G. Knepley       }
1534*b5da9499SMatthew G. Knepley #endif
1535*b5da9499SMatthew G. Knepley       ++newp;
1536*b5da9499SMatthew G. Knepley       /* Face D: {d, e, f} */
1537*b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + (ornt[1] < 0 ? (-(ornt[1]+1)+2)%3 : (ornt[1]+0)%3);
1538*b5da9499SMatthew G. Knepley       orntNew[0] = ornt[1] < 0 ? -2 : 0;
1539*b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + (ornt[3] < 0 ? (-(ornt[3]+1)+1)%3 : (ornt[3]+1)%3);
1540*b5da9499SMatthew G. Knepley       orntNew[1] = ornt[3] < 0 ? -2 : 0;
1541*b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + (ornt[2] < 0 ? (-(ornt[2]+1)+1)%3 : (ornt[2]+1)%3);
1542*b5da9499SMatthew G. Knepley       orntNew[2] = ornt[2] < 0 ? -2 : 0;
1543*b5da9499SMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1544*b5da9499SMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
1545*b5da9499SMatthew G. Knepley #if 1
1546*b5da9499SMatthew 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);
1547*b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1548*b5da9499SMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
1549*b5da9499SMatthew G. Knepley       }
1550*b5da9499SMatthew G. Knepley #endif
1551*b5da9499SMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 3;
1552*b5da9499SMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 3+4;
1553*b5da9499SMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1554*b5da9499SMatthew G. Knepley #if 1
1555*b5da9499SMatthew 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);
1556*b5da9499SMatthew G. Knepley       for (p = 0; p < 2; ++p) {
1557*b5da9499SMatthew 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);
1558*b5da9499SMatthew G. Knepley       }
1559*b5da9499SMatthew G. Knepley #endif
1560*b5da9499SMatthew G. Knepley       ++newp;
1561*b5da9499SMatthew G. Knepley       /* Face E: {d, f, a} */
1562*b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + (ornt[2] < 0 ? (-(ornt[2]+1)+1)%3 : (ornt[2]+1)%3);
1563*b5da9499SMatthew G. Knepley       orntNew[0] = ornt[2] < 0 ? 0 : -2;
1564*b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
1565*b5da9499SMatthew G. Knepley       orntNew[1] = 0;
1566*b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + (ornt[1] < 0 ? (-(ornt[1]+1)+0)%3 : (ornt[1]+2)%3);
1567*b5da9499SMatthew G. Knepley       orntNew[2] = ornt[1] < 0 ? -2 : 0;
1568*b5da9499SMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1569*b5da9499SMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
1570*b5da9499SMatthew G. Knepley #if 1
1571*b5da9499SMatthew 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);
1572*b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1573*b5da9499SMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
1574*b5da9499SMatthew G. Knepley       }
1575*b5da9499SMatthew G. Knepley #endif
1576*b5da9499SMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 0+4;
1577*b5da9499SMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 3+4;
1578*b5da9499SMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1579*b5da9499SMatthew G. Knepley #if 1
1580*b5da9499SMatthew 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);
1581*b5da9499SMatthew G. Knepley       for (p = 0; p < 2; ++p) {
1582*b5da9499SMatthew 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);
1583*b5da9499SMatthew G. Knepley       }
1584*b5da9499SMatthew G. Knepley #endif
1585*b5da9499SMatthew G. Knepley       ++newp;
1586*b5da9499SMatthew G. Knepley       /* Face F: {c, a, f} */
1587*b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + (ornt[0] < 0 ? (-(ornt[0]+1)+0)%3 : (ornt[0]+2)%3);
1588*b5da9499SMatthew G. Knepley       orntNew[0] = ornt[0] < 0 ? -2 : 0;
1589*b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
1590*b5da9499SMatthew G. Knepley       orntNew[1] = -2;
1591*b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[2] - fStart)*3 + (ornt[2] < 0 ? (-(ornt[2]+1)+2)%3 : (ornt[2]+0)%3);
1592*b5da9499SMatthew G. Knepley       orntNew[2] = ornt[1] < 0 ? 0 : -2;
1593*b5da9499SMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1594*b5da9499SMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
1595*b5da9499SMatthew G. Knepley #if 1
1596*b5da9499SMatthew 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);
1597*b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1598*b5da9499SMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
1599*b5da9499SMatthew G. Knepley       }
1600*b5da9499SMatthew G. Knepley #endif
1601*b5da9499SMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 0+4;
1602*b5da9499SMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 2+4;
1603*b5da9499SMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1604*b5da9499SMatthew G. Knepley #if 1
1605*b5da9499SMatthew 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);
1606*b5da9499SMatthew G. Knepley       for (p = 0; p < 2; ++p) {
1607*b5da9499SMatthew 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);
1608*b5da9499SMatthew G. Knepley       }
1609*b5da9499SMatthew G. Knepley #endif
1610*b5da9499SMatthew G. Knepley       ++newp;
1611*b5da9499SMatthew G. Knepley       /* Face G: {e, a, f} */
1612*b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[1] - fStart)*3 + (ornt[1] < 0 ? (-(ornt[1]+1)+1)%3 : (ornt[1]+1)%3);
1613*b5da9499SMatthew G. Knepley       orntNew[0] = ornt[1] < 0 ? -2 : 0;
1614*b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
1615*b5da9499SMatthew G. Knepley       orntNew[1] = -2;
1616*b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + (ornt[3] < 0 ? (-(ornt[3]+1)+1)%3 : (ornt[3]+1)%3);
1617*b5da9499SMatthew G. Knepley       orntNew[2] = ornt[3] < 0 ? 0 : -2;
1618*b5da9499SMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1619*b5da9499SMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
1620*b5da9499SMatthew G. Knepley #if 1
1621*b5da9499SMatthew 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);
1622*b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1623*b5da9499SMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
1624*b5da9499SMatthew G. Knepley       }
1625*b5da9499SMatthew G. Knepley #endif
1626*b5da9499SMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 1+4;
1627*b5da9499SMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 3+4;
1628*b5da9499SMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1629*b5da9499SMatthew G. Knepley #if 1
1630*b5da9499SMatthew 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);
1631*b5da9499SMatthew G. Knepley       for (p = 0; p < 2; ++p) {
1632*b5da9499SMatthew 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);
1633*b5da9499SMatthew G. Knepley       }
1634*b5da9499SMatthew G. Knepley #endif
1635*b5da9499SMatthew G. Knepley       ++newp;
1636*b5da9499SMatthew G. Knepley       /* Face H: {a, b, f} */
1637*b5da9499SMatthew G. Knepley       coneNew[0] = eStartNew + (eEnd - eStart)*2 + (cone[0] - fStart)*3 + (ornt[0] < 0 ? (-(ornt[0]+1)+2)%3 : (ornt[0]+0)%3);
1638*b5da9499SMatthew G. Knepley       orntNew[0] = ornt[0] < 0 ? -2 : 0;
1639*b5da9499SMatthew G. Knepley       coneNew[1] = eStartNew + (eEnd - eStart)*2 + (cone[3] - fStart)*3 + (ornt[3] < 0 ? (-(ornt[3]+1)+0)%3 : (ornt[3]+2)%3);
1640*b5da9499SMatthew G. Knepley       orntNew[1] = ornt[3] < 0 ? 0 : -2;
1641*b5da9499SMatthew G. Knepley       coneNew[2] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
1642*b5da9499SMatthew G. Knepley       orntNew[2] = 0;
1643*b5da9499SMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1644*b5da9499SMatthew G. Knepley       ierr = DMPlexSetConeOrientation(rdm, newp, orntNew);CHKERRQ(ierr);
1645*b5da9499SMatthew G. Knepley #if 1
1646*b5da9499SMatthew 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);
1647*b5da9499SMatthew G. Knepley       for (p = 0; p < 3; ++p) {
1648*b5da9499SMatthew G. Knepley         if ((coneNew[p] < eStartNew) || (coneNew[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", coneNew[p], eStartNew, eEndNew);
1649*b5da9499SMatthew G. Knepley       }
1650*b5da9499SMatthew G. Knepley #endif
1651*b5da9499SMatthew G. Knepley       supportNew[0] = (c - cStart)*8 + 1+4;
1652*b5da9499SMatthew G. Knepley       supportNew[1] = (c - cStart)*8 + 2+4;
1653*b5da9499SMatthew G. Knepley       ierr          = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1654*b5da9499SMatthew G. Knepley #if 1
1655*b5da9499SMatthew 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);
1656*b5da9499SMatthew G. Knepley       for (p = 0; p < 2; ++p) {
1657*b5da9499SMatthew 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);
1658*b5da9499SMatthew G. Knepley       }
1659*b5da9499SMatthew G. Knepley #endif
1660*b5da9499SMatthew G. Knepley       ++newp;
1661*b5da9499SMatthew G. Knepley     }
1662*b5da9499SMatthew G. Knepley     /* Split Edges have 2 vertices and the same faces as the parent */
1663*b5da9499SMatthew G. Knepley     for (e = eStart; e < eEnd; ++e) {
1664*b5da9499SMatthew G. Knepley       const PetscInt newv = vStartNew + (vEnd - vStart) + (e - eStart);
1665*b5da9499SMatthew G. Knepley 
1666*b5da9499SMatthew G. Knepley       for (r = 0; r < 2; ++r) {
1667*b5da9499SMatthew G. Knepley         const PetscInt  newp = eStartNew + (e - eStart)*2 + r;
1668*b5da9499SMatthew G. Knepley         const PetscInt *cone, *ornt, *support;
1669*b5da9499SMatthew G. Knepley         PetscInt        coneNew[2], coneSize, c, supportSize, s;
1670*b5da9499SMatthew G. Knepley 
1671*b5da9499SMatthew G. Knepley         ierr             = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr);
1672*b5da9499SMatthew G. Knepley         coneNew[0]       = vStartNew + (cone[0] - vStart);
1673*b5da9499SMatthew G. Knepley         coneNew[1]       = vStartNew + (cone[1] - vStart);
1674*b5da9499SMatthew G. Knepley         coneNew[(r+1)%2] = newv;
1675*b5da9499SMatthew G. Knepley         ierr             = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1676*b5da9499SMatthew G. Knepley #if 1
1677*b5da9499SMatthew G. Knepley         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
1678*b5da9499SMatthew G. Knepley         for (p = 0; p < 2; ++p) {
1679*b5da9499SMatthew 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);
1680*b5da9499SMatthew G. Knepley         }
1681*b5da9499SMatthew G. Knepley #endif
1682*b5da9499SMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, e, &supportSize);CHKERRQ(ierr);
1683*b5da9499SMatthew G. Knepley         ierr = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
1684*b5da9499SMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
1685*b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
1686*b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
1687*b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
1688*b5da9499SMatthew G. Knepley           for (c = 0; c < coneSize; ++c) {
1689*b5da9499SMatthew G. Knepley             if (cone[c] == e) break;
1690*b5da9499SMatthew G. Knepley           }
1691*b5da9499SMatthew G. Knepley           supportRef[s] = fStartNew + (support[s] - fStart)*4 + (c + (ornt[c] < 0 ? 1-r : r))%3;
1692*b5da9499SMatthew G. Knepley         }
1693*b5da9499SMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
1694*b5da9499SMatthew G. Knepley #if 1
1695*b5da9499SMatthew G. Knepley         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
1696*b5da9499SMatthew G. Knepley         for (p = 0; p < supportSize; ++p) {
1697*b5da9499SMatthew 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);
1698*b5da9499SMatthew G. Knepley         }
1699*b5da9499SMatthew G. Knepley #endif
1700*b5da9499SMatthew G. Knepley       }
1701*b5da9499SMatthew G. Knepley     }
1702*b5da9499SMatthew G. Knepley     /* Face Edges have 2 vertices and 2+cells*(1/2) faces */
1703*b5da9499SMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
1704*b5da9499SMatthew G. Knepley       const PetscInt *cone, *ornt, *support;
1705*b5da9499SMatthew G. Knepley       PetscInt        coneSize, supportSize, s;
1706*b5da9499SMatthew G. Knepley 
1707*b5da9499SMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
1708*b5da9499SMatthew G. Knepley       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
1709*b5da9499SMatthew G. Knepley       for (r = 0; r < 3; ++r) {
1710*b5da9499SMatthew G. Knepley         const PetscInt  newp = eStartNew + (eEnd - eStart)*2 + (f - fStart)*3 + r;
1711*b5da9499SMatthew G. Knepley         PetscInt        coneNew[2], intFaces = 0, er, eint[4] = {1, 0, 2, 0};
1712*b5da9499SMatthew G. Knepley         PetscInt        fint[24] = { 1,  7, -1, -1,  0,  5,
1713*b5da9499SMatthew G. Knepley                                     -1, -1,  1,  6,  0,  4,
1714*b5da9499SMatthew G. Knepley                                      2,  5,  3,  4, -1, -1,
1715*b5da9499SMatthew G. Knepley                                     -1, -1,  3,  6,  2,  7};
1716*b5da9499SMatthew G. Knepley 
1717*b5da9499SMatthew G. Knepley         ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
1718*b5da9499SMatthew G. Knepley         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[(r+0)%3] - eStart);
1719*b5da9499SMatthew G. Knepley         coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - eStart);
1720*b5da9499SMatthew G. Knepley         ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1721*b5da9499SMatthew G. Knepley #if 1
1722*b5da9499SMatthew G. Knepley         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
1723*b5da9499SMatthew G. Knepley         for (p = 0; p < 2; ++p) {
1724*b5da9499SMatthew 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);
1725*b5da9499SMatthew G. Knepley         }
1726*b5da9499SMatthew G. Knepley #endif
1727*b5da9499SMatthew G. Knepley         supportRef[0] = fStartNew + (f - fStart)*4 + (r+1)%3;
1728*b5da9499SMatthew G. Knepley         supportRef[1] = fStartNew + (f - fStart)*4 + 3;
1729*b5da9499SMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
1730*b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
1731*b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
1732*b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, support[s], &ornt);CHKERRQ(ierr);
1733*b5da9499SMatthew G. Knepley           for (c = 0; c < coneSize; ++c) {if (cone[c] == f) break;}
1734*b5da9499SMatthew G. Knepley           er   = ornt[c] < 0 ? (-(ornt[c]+1) + r)%3 : (ornt[c] + r)%3;
1735*b5da9499SMatthew G. Knepley           if (er == eint[c]) {
1736*b5da9499SMatthew G. Knepley             supportRef[2+intFaces++] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*8 + (c + 2)%4;
1737*b5da9499SMatthew G. Knepley           } else {
1738*b5da9499SMatthew G. Knepley             supportRef[2+intFaces++] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*8 + fint[(c*3 + er)*2 + 0];
1739*b5da9499SMatthew G. Knepley             supportRef[2+intFaces++] = fStartNew + (fEnd - fStart)*4 + (support[s] - cStart)*8 + fint[(c*3 + er)*2 + 1];
1740*b5da9499SMatthew G. Knepley           }
1741*b5da9499SMatthew G. Knepley         }
1742*b5da9499SMatthew G. Knepley         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
1743*b5da9499SMatthew G. Knepley #if 1
1744*b5da9499SMatthew G. Knepley         if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
1745*b5da9499SMatthew G. Knepley         for (p = 0; p < intFaces; ++p) {
1746*b5da9499SMatthew 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);
1747*b5da9499SMatthew G. Knepley         }
1748*b5da9499SMatthew G. Knepley #endif
1749*b5da9499SMatthew G. Knepley       }
1750*b5da9499SMatthew G. Knepley     }
1751*b5da9499SMatthew G. Knepley     /* Interior edges have 2 vertices and 4 faces */
1752*b5da9499SMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
1753*b5da9499SMatthew G. Knepley       const PetscInt  newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (c - cStart);
1754*b5da9499SMatthew G. Knepley       const PetscInt *cone, *ornt, *fcone;
1755*b5da9499SMatthew G. Knepley       PetscInt        coneNew[2], supportNew[2], find;
1756*b5da9499SMatthew G. Knepley 
1757*b5da9499SMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
1758*b5da9499SMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
1759*b5da9499SMatthew G. Knepley       ierr = DMPlexGetCone(dm, cone[0], &fcone);CHKERRQ(ierr);
1760*b5da9499SMatthew G. Knepley       find = ornt[0] < 0 ? (-(ornt[0]+1) + 0)%3 : ornt[0];
1761*b5da9499SMatthew G. Knepley       coneNew[0] = vStartNew + (vEnd - vStart) + (fcone[find] - eStart);
1762*b5da9499SMatthew G. Knepley       ierr = DMPlexGetCone(dm, cone[2], &fcone);CHKERRQ(ierr);
1763*b5da9499SMatthew G. Knepley       find = ornt[2] < 0 ? (-(ornt[2]+1) + 1)%3 : (ornt[2]+1)%3;
1764*b5da9499SMatthew G. Knepley       coneNew[1] = vStartNew + (vEnd - vStart) + (fcone[find] - eStart);
1765*b5da9499SMatthew G. Knepley       ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
1766*b5da9499SMatthew G. Knepley #if 1
1767*b5da9499SMatthew G. Knepley       if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
1768*b5da9499SMatthew G. Knepley       for (p = 0; p < 2; ++p) {
1769*b5da9499SMatthew 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);
1770*b5da9499SMatthew G. Knepley       }
1771*b5da9499SMatthew G. Knepley #endif
1772*b5da9499SMatthew G. Knepley       supportNew[0] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 4;
1773*b5da9499SMatthew G. Knepley       supportNew[1] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 5;
1774*b5da9499SMatthew G. Knepley       supportNew[2] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 6;
1775*b5da9499SMatthew G. Knepley       supportNew[3] = fStartNew + (fEnd - fStart)*4 + (c - cStart)*8 + 7;
1776*b5da9499SMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
1777*b5da9499SMatthew G. Knepley #if 1
1778*b5da9499SMatthew G. Knepley       if ((newp < eStartNew) || (newp >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", newp, eStartNew, eEndNew);
1779*b5da9499SMatthew G. Knepley       for (p = 0; p < 4; ++p) {
1780*b5da9499SMatthew G. Knepley         if ((supportNew[p] < fStartNew) || (supportNew[p] >= fEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportNew[p], fStartNew, fEndNew);
1781*b5da9499SMatthew G. Knepley       }
1782*b5da9499SMatthew G. Knepley #endif
1783*b5da9499SMatthew G. Knepley     }
1784*b5da9499SMatthew G. Knepley     /* Old vertices have identical supports */
1785*b5da9499SMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
1786*b5da9499SMatthew G. Knepley       const PetscInt  newp = vStartNew + (v - vStart);
1787*b5da9499SMatthew G. Knepley       const PetscInt *support, *cone;
1788*b5da9499SMatthew G. Knepley       PetscInt        size, s;
1789*b5da9499SMatthew G. Knepley 
1790*b5da9499SMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
1791*b5da9499SMatthew G. Knepley       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
1792*b5da9499SMatthew G. Knepley       for (s = 0; s < size; ++s) {
1793*b5da9499SMatthew G. Knepley         PetscInt r = 0;
1794*b5da9499SMatthew G. Knepley 
1795*b5da9499SMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
1796*b5da9499SMatthew G. Knepley         if (cone[1] == v) r = 1;
1797*b5da9499SMatthew G. Knepley         supportRef[s] = eStartNew + (support[s] - eStart)*2 + r;
1798*b5da9499SMatthew G. Knepley       }
1799*b5da9499SMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
1800*b5da9499SMatthew G. Knepley #if 1
1801*b5da9499SMatthew 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);
1802*b5da9499SMatthew G. Knepley       for (p = 0; p < size; ++p) {
1803*b5da9499SMatthew G. Knepley         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", supportRef[p], eStartNew, eEndNew);
1804*b5da9499SMatthew G. Knepley       }
1805*b5da9499SMatthew G. Knepley #endif
1806*b5da9499SMatthew G. Knepley     }
1807*b5da9499SMatthew G. Knepley     /* Edge vertices have 2 + face*2 + 0/1 supports */
1808*b5da9499SMatthew G. Knepley     for (e = eStart; e < eEnd; ++e) {
1809*b5da9499SMatthew G. Knepley       const PetscInt  newp = vStartNew + (vEnd - vStart) + (e - eStart);
1810*b5da9499SMatthew G. Knepley       const PetscInt *cone, *support;
1811*b5da9499SMatthew G. Knepley       PetscInt       *star = NULL, starSize, cellSize = 0, coneSize, size, s;
1812*b5da9499SMatthew G. Knepley 
1813*b5da9499SMatthew G. Knepley       ierr          = DMPlexGetSupportSize(dm, e, &size);CHKERRQ(ierr);
1814*b5da9499SMatthew G. Knepley       ierr          = DMPlexGetSupport(dm, e, &support);CHKERRQ(ierr);
1815*b5da9499SMatthew G. Knepley       supportRef[0] = eStartNew + (e - eStart)*2 + 0;
1816*b5da9499SMatthew G. Knepley       supportRef[1] = eStartNew + (e - eStart)*2 + 1;
1817*b5da9499SMatthew G. Knepley       for (s = 0; s < size; ++s) {
1818*b5da9499SMatthew G. Knepley         PetscInt r = 0;
1819*b5da9499SMatthew G. Knepley 
1820*b5da9499SMatthew G. Knepley         ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
1821*b5da9499SMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
1822*b5da9499SMatthew G. Knepley         for (r = 0; r < coneSize; ++r) {if (cone[r] == e) break;}
1823*b5da9499SMatthew G. Knepley         supportRef[2+s*2+0] = eStartNew + (eEnd - eStart)*2 + (support[s] - fStart)*3 + (r+0)%3;
1824*b5da9499SMatthew G. Knepley         supportRef[2+s*2+1] = eStartNew + (eEnd - eStart)*2 + (support[s] - fStart)*3 + (r+2)%3;
1825*b5da9499SMatthew G. Knepley       }
1826*b5da9499SMatthew G. Knepley       ierr = DMPlexGetTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr);
1827*b5da9499SMatthew G. Knepley       for (s = 0; s < starSize*2; s += 2) {
1828*b5da9499SMatthew G. Knepley         const PetscInt *cone, *ornt;
1829*b5da9499SMatthew G. Knepley         PetscInt        e01, e23;
1830*b5da9499SMatthew G. Knepley 
1831*b5da9499SMatthew G. Knepley         if ((star[s] >= cStart) && (star[s] < cEnd)) {
1832*b5da9499SMatthew G. Knepley           /* Check edge 0-1 */
1833*b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, star[s], &cone);CHKERRQ(ierr);
1834*b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, star[s], &ornt);CHKERRQ(ierr);
1835*b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, cone[0], &cone);CHKERRQ(ierr);
1836*b5da9499SMatthew G. Knepley           e01  = cone[ornt[0] < 0 ? (-(ornt[0]+1) + 0)%3 : ornt[0]];
1837*b5da9499SMatthew G. Knepley           /* Check edge 2-3 */
1838*b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, star[s], &cone);CHKERRQ(ierr);
1839*b5da9499SMatthew G. Knepley           ierr = DMPlexGetConeOrientation(dm, star[s], &ornt);CHKERRQ(ierr);
1840*b5da9499SMatthew G. Knepley           ierr = DMPlexGetCone(dm, cone[3], &cone);CHKERRQ(ierr);
1841*b5da9499SMatthew G. Knepley           e23  = cone[ornt[3] < 0 ? (-(ornt[3]+1) + 2)%3 : (ornt[3] + 2)%3];
1842*b5da9499SMatthew G. Knepley           if ((e01 == e) || (e23 == e)) {supportRef[2+size*2+cellSize++] = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (star[s] - cStart);}
1843*b5da9499SMatthew G. Knepley         }
1844*b5da9499SMatthew G. Knepley       }
1845*b5da9499SMatthew G. Knepley       ierr = DMPlexRestoreTransitiveClosure(dm, e, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr);
1846*b5da9499SMatthew G. Knepley       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
1847*b5da9499SMatthew G. Knepley #if 1
1848*b5da9499SMatthew 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);
1849*b5da9499SMatthew G. Knepley       for (p = 0; p < 2+size*2+cellSize; ++p) {
1850*b5da9499SMatthew G. Knepley         if ((supportRef[p] < eStartNew) || (supportRef[p] >= eEndNew)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Point %d is not an edge [%d, %d)", supportRef[p], eStartNew, eEndNew);
1851*b5da9499SMatthew G. Knepley       }
1852*b5da9499SMatthew G. Knepley #endif
1853*b5da9499SMatthew G. Knepley     }
1854*b5da9499SMatthew G. Knepley     ierr = PetscFree(supportRef);CHKERRQ(ierr);
1855*b5da9499SMatthew G. Knepley     ierr = DMPlexRestoreFaces_Internal(dm, 3, cStart, NULL, NULL, &faces);CHKERRQ(ierr);
1856*b5da9499SMatthew G. Knepley     break;
185775d3a19aSMatthew G. Knepley   default:
185875d3a19aSMatthew G. Knepley     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
185975d3a19aSMatthew G. Knepley   }
186075d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
186175d3a19aSMatthew G. Knepley }
186275d3a19aSMatthew G. Knepley 
186375d3a19aSMatthew G. Knepley #undef __FUNCT__
186475d3a19aSMatthew G. Knepley #define __FUNCT__ "CellRefinerSetCoordinates"
186575d3a19aSMatthew G. Knepley PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
186675d3a19aSMatthew G. Knepley {
186775d3a19aSMatthew G. Knepley   PetscSection   coordSection, coordSectionNew;
186875d3a19aSMatthew G. Knepley   Vec            coordinates, coordinatesNew;
186975d3a19aSMatthew G. Knepley   PetscScalar   *coords, *coordsNew;
1870*b5da9499SMatthew G. Knepley   PetscInt       dim, depth, coordSizeNew, cStart, cEnd, c, vStart, vStartNew, vEnd, v, eStart, eEnd, eMax, e, fStart, fEnd, fMax, f;
187175d3a19aSMatthew G. Knepley   PetscErrorCode ierr;
187275d3a19aSMatthew G. Knepley 
187375d3a19aSMatthew G. Knepley   PetscFunctionBegin;
187475d3a19aSMatthew G. Knepley   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
187575d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
187675d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
1877*b5da9499SMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
187875d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
187975d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
1880*b5da9499SMatthew G. Knepley   ierr = DMPlexGetHybridBounds(dm, NULL, &fMax, &eMax, NULL);CHKERRQ(ierr);
188175d3a19aSMatthew G. Knepley   ierr = GetDepthStart_Private(depth, depthSize, NULL, NULL, NULL, &vStartNew);CHKERRQ(ierr);
188275d3a19aSMatthew G. Knepley   ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr);
188375d3a19aSMatthew G. Knepley   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &coordSectionNew);CHKERRQ(ierr);
188475d3a19aSMatthew G. Knepley   ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr);
188575d3a19aSMatthew G. Knepley   ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dim);CHKERRQ(ierr);
188675d3a19aSMatthew G. Knepley   ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+depthSize[0]);CHKERRQ(ierr);
188775d3a19aSMatthew G. Knepley   if (fMax < 0) fMax = fEnd;
1888*b5da9499SMatthew G. Knepley   if (eMax < 0) eMax = eEnd;
188975d3a19aSMatthew G. Knepley   /* All vertices have the dim coordinates */
189075d3a19aSMatthew G. Knepley   for (v = vStartNew; v < vStartNew+depthSize[0]; ++v) {
189175d3a19aSMatthew G. Knepley     ierr = PetscSectionSetDof(coordSectionNew, v, dim);CHKERRQ(ierr);
189275d3a19aSMatthew G. Knepley     ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dim);CHKERRQ(ierr);
189375d3a19aSMatthew G. Knepley   }
189475d3a19aSMatthew G. Knepley   ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr);
189575d3a19aSMatthew G. Knepley   ierr = DMPlexSetCoordinateSection(rdm, coordSectionNew);CHKERRQ(ierr);
189675d3a19aSMatthew G. Knepley   ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
189775d3a19aSMatthew G. Knepley   ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr);
189875d3a19aSMatthew G. Knepley   ierr = VecCreate(PetscObjectComm((PetscObject)dm), &coordinatesNew);CHKERRQ(ierr);
189975d3a19aSMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");CHKERRQ(ierr);
190075d3a19aSMatthew G. Knepley   ierr = VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr);
190175d3a19aSMatthew G. Knepley   ierr = VecSetFromOptions(coordinatesNew);CHKERRQ(ierr);
190275d3a19aSMatthew G. Knepley   ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr);
190375d3a19aSMatthew G. Knepley   ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr);
1904*b5da9499SMatthew G. Knepley   switch (refiner) {
1905*b5da9499SMatthew G. Knepley   case 6: /* Hex 3D */
1906*b5da9499SMatthew G. Knepley     /* Face vertices have the average of corner coordinates */
1907*b5da9499SMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
1908*b5da9499SMatthew G. Knepley       const PetscInt newv = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (cEnd - cStart) + (f - fStart);
1909*b5da9499SMatthew G. Knepley       PetscInt      *cone = NULL;
1910*b5da9499SMatthew G. Knepley       PetscInt       closureSize, coneSize = 0, off[8], offnew, p, d;
1911*b5da9499SMatthew G. Knepley 
1912*b5da9499SMatthew G. Knepley       ierr = DMPlexGetTransitiveClosure(dm, f, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr);
1913*b5da9499SMatthew G. Knepley       for (p = 0; p < closureSize*2; p += 2) {
1914*b5da9499SMatthew G. Knepley         const PetscInt point = cone[p];
1915*b5da9499SMatthew G. Knepley         if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point;
1916*b5da9499SMatthew G. Knepley       }
1917*b5da9499SMatthew G. Knepley       for (v = 0; v < coneSize; ++v) {
1918*b5da9499SMatthew G. Knepley         ierr = PetscSectionGetOffset(coordSection, cone[v], &off[v]);CHKERRQ(ierr);
1919*b5da9499SMatthew G. Knepley       }
1920*b5da9499SMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr);
1921*b5da9499SMatthew G. Knepley       for (d = 0; d < dim; ++d) {
1922*b5da9499SMatthew G. Knepley         coordsNew[offnew+d] = 0.0;
1923*b5da9499SMatthew G. Knepley         for (v = 0; v < coneSize; ++v) coordsNew[offnew+d] += coords[off[v]+d];
1924*b5da9499SMatthew G. Knepley         coordsNew[offnew+d] /= coneSize;
1925*b5da9499SMatthew G. Knepley       }
1926*b5da9499SMatthew G. Knepley       ierr = DMPlexRestoreTransitiveClosure(dm, f, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr);
1927*b5da9499SMatthew G. Knepley     }
1928*b5da9499SMatthew G. Knepley   case 2: /* Hex 2D */
1929*b5da9499SMatthew G. Knepley     /* Cell vertices have the average of corner coordinates */
1930*b5da9499SMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
1931*b5da9499SMatthew G. Knepley       const PetscInt newv = vStartNew + (vEnd - vStart) + (eEnd - eStart) + (c - cStart);
1932*b5da9499SMatthew G. Knepley       PetscInt      *cone = NULL;
1933*b5da9499SMatthew G. Knepley       PetscInt       closureSize, coneSize = 0, off[8], offnew, p, d;
1934*b5da9499SMatthew G. Knepley 
1935*b5da9499SMatthew G. Knepley       ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr);
1936*b5da9499SMatthew G. Knepley       for (p = 0; p < closureSize*2; p += 2) {
1937*b5da9499SMatthew G. Knepley         const PetscInt point = cone[p];
1938*b5da9499SMatthew G. Knepley         if ((point >= vStart) && (point < vEnd)) cone[coneSize++] = point;
1939*b5da9499SMatthew G. Knepley       }
1940*b5da9499SMatthew G. Knepley       for (v = 0; v < coneSize; ++v) {
1941*b5da9499SMatthew G. Knepley         ierr = PetscSectionGetOffset(coordSection, cone[v], &off[v]);CHKERRQ(ierr);
1942*b5da9499SMatthew G. Knepley       }
1943*b5da9499SMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr);
1944*b5da9499SMatthew G. Knepley       for (d = 0; d < dim; ++d) {
1945*b5da9499SMatthew G. Knepley         coordsNew[offnew+d] = 0.0;
1946*b5da9499SMatthew G. Knepley         for (v = 0; v < coneSize; ++v) coordsNew[offnew+d] += coords[off[v]+d];
1947*b5da9499SMatthew G. Knepley         coordsNew[offnew+d] /= coneSize;
1948*b5da9499SMatthew G. Knepley       }
1949*b5da9499SMatthew G. Knepley       ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr);
1950*b5da9499SMatthew G. Knepley     }
1951*b5da9499SMatthew G. Knepley   case 1: /* Simplicial 2D */
1952*b5da9499SMatthew G. Knepley   case 3: /* Hybrid Simplicial 2D */
1953*b5da9499SMatthew G. Knepley   case 5: /* Simplicial 3D */
1954*b5da9499SMatthew G. Knepley     /* Edge vertices have the average of endpoint coordinates */
1955*b5da9499SMatthew G. Knepley     for (e = eStart; e < eMax; ++e) {
1956*b5da9499SMatthew G. Knepley       const PetscInt  newv = vStartNew + (vEnd - vStart) + (e - eStart);
1957*b5da9499SMatthew G. Knepley       const PetscInt *cone;
1958*b5da9499SMatthew G. Knepley       PetscInt        coneSize, offA, offB, offnew, d;
1959*b5da9499SMatthew G. Knepley 
1960*b5da9499SMatthew G. Knepley       ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr);
1961*b5da9499SMatthew G. Knepley       if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %d cone should have two vertices, not %d", e, coneSize);
1962*b5da9499SMatthew G. Knepley       ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr);
1963*b5da9499SMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr);
1964*b5da9499SMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr);
1965*b5da9499SMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr);
1966*b5da9499SMatthew G. Knepley       for (d = 0; d < dim; ++d) {
1967*b5da9499SMatthew G. Knepley         coordsNew[offnew+d] = 0.5*(coords[offA+d] + coords[offB+d]);
1968*b5da9499SMatthew G. Knepley       }
1969*b5da9499SMatthew G. Knepley     }
197075d3a19aSMatthew G. Knepley     /* Old vertices have the same coordinates */
197175d3a19aSMatthew G. Knepley     for (v = vStart; v < vEnd; ++v) {
197275d3a19aSMatthew G. Knepley       const PetscInt newv = vStartNew + (v - vStart);
197375d3a19aSMatthew G. Knepley       PetscInt       off, offnew, d;
197475d3a19aSMatthew G. Knepley 
197575d3a19aSMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr);
197675d3a19aSMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr);
197775d3a19aSMatthew G. Knepley       for (d = 0; d < dim; ++d) {
197875d3a19aSMatthew G. Knepley         coordsNew[offnew+d] = coords[off+d];
197975d3a19aSMatthew G. Knepley       }
198075d3a19aSMatthew G. Knepley     }
1981*b5da9499SMatthew G. Knepley     break;
1982*b5da9499SMatthew G. Knepley   default:
1983*b5da9499SMatthew G. Knepley     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
198475d3a19aSMatthew G. Knepley   }
198575d3a19aSMatthew G. Knepley   ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr);
198675d3a19aSMatthew G. Knepley   ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr);
198775d3a19aSMatthew G. Knepley   ierr = DMSetCoordinatesLocal(rdm, coordinatesNew);CHKERRQ(ierr);
198875d3a19aSMatthew G. Knepley   ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr);
198975d3a19aSMatthew G. Knepley   ierr = PetscSectionDestroy(&coordSectionNew);CHKERRQ(ierr);
199075d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
199175d3a19aSMatthew G. Knepley }
199275d3a19aSMatthew G. Knepley 
199375d3a19aSMatthew G. Knepley #undef __FUNCT__
199475d3a19aSMatthew G. Knepley #define __FUNCT__ "DMPlexCreateProcessSF"
199575d3a19aSMatthew G. Knepley PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess)
199675d3a19aSMatthew G. Knepley {
199775d3a19aSMatthew G. Knepley   PetscInt           numRoots, numLeaves, l;
199875d3a19aSMatthew G. Knepley   const PetscInt    *localPoints;
199975d3a19aSMatthew G. Knepley   const PetscSFNode *remotePoints;
200075d3a19aSMatthew G. Knepley   PetscInt          *localPointsNew;
200175d3a19aSMatthew G. Knepley   PetscSFNode       *remotePointsNew;
200275d3a19aSMatthew G. Knepley   PetscInt          *ranks, *ranksNew;
200375d3a19aSMatthew G. Knepley   PetscErrorCode     ierr;
200475d3a19aSMatthew G. Knepley 
200575d3a19aSMatthew G. Knepley   PetscFunctionBegin;
200675d3a19aSMatthew G. Knepley   ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr);
200775d3a19aSMatthew G. Knepley   ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranks);CHKERRQ(ierr);
200875d3a19aSMatthew G. Knepley   for (l = 0; l < numLeaves; ++l) {
200975d3a19aSMatthew G. Knepley     ranks[l] = remotePoints[l].rank;
201075d3a19aSMatthew G. Knepley   }
201175d3a19aSMatthew G. Knepley   ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr);
201275d3a19aSMatthew G. Knepley   ierr = PetscMalloc(numLeaves * sizeof(PetscInt),    &ranksNew);CHKERRQ(ierr);
201375d3a19aSMatthew G. Knepley   ierr = PetscMalloc(numLeaves * sizeof(PetscInt),    &localPointsNew);CHKERRQ(ierr);
201475d3a19aSMatthew G. Knepley   ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr);
201575d3a19aSMatthew G. Knepley   for (l = 0; l < numLeaves; ++l) {
201675d3a19aSMatthew G. Knepley     ranksNew[l]              = ranks[l];
201775d3a19aSMatthew G. Knepley     localPointsNew[l]        = l;
201875d3a19aSMatthew G. Knepley     remotePointsNew[l].index = 0;
201975d3a19aSMatthew G. Knepley     remotePointsNew[l].rank  = ranksNew[l];
202075d3a19aSMatthew G. Knepley   }
202175d3a19aSMatthew G. Knepley   ierr = PetscFree(ranks);CHKERRQ(ierr);
202275d3a19aSMatthew G. Knepley   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr);
202375d3a19aSMatthew G. Knepley   ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess);CHKERRQ(ierr);
202475d3a19aSMatthew G. Knepley   ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr);
202575d3a19aSMatthew G. Knepley   ierr = PetscSFSetGraph(*sfProcess, 1, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr);
202675d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
202775d3a19aSMatthew G. Knepley }
202875d3a19aSMatthew G. Knepley 
202975d3a19aSMatthew G. Knepley #undef __FUNCT__
203075d3a19aSMatthew G. Knepley #define __FUNCT__ "CellRefinerCreateSF"
203175d3a19aSMatthew G. Knepley PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
203275d3a19aSMatthew G. Knepley {
203375d3a19aSMatthew G. Knepley   PetscSF            sf, sfNew, sfProcess;
203475d3a19aSMatthew G. Knepley   IS                 processRanks;
203575d3a19aSMatthew G. Knepley   MPI_Datatype       depthType;
203675d3a19aSMatthew G. Knepley   PetscInt           numRoots, numLeaves, numLeavesNew = 0, l, m;
203775d3a19aSMatthew G. Knepley   const PetscInt    *localPoints, *neighbors;
203875d3a19aSMatthew G. Knepley   const PetscSFNode *remotePoints;
203975d3a19aSMatthew G. Knepley   PetscInt          *localPointsNew;
204075d3a19aSMatthew G. Knepley   PetscSFNode       *remotePointsNew;
204175d3a19aSMatthew G. Knepley   PetscInt          *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rdepthMaxOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew;
204275d3a19aSMatthew 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;
204375d3a19aSMatthew G. Knepley   PetscErrorCode     ierr;
204475d3a19aSMatthew G. Knepley 
204575d3a19aSMatthew G. Knepley   PetscFunctionBegin;
204675d3a19aSMatthew G. Knepley   ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr);
204775d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
204875d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
204975d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
205075d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
205175d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
205275d3a19aSMatthew G. Knepley   ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr);
205375d3a19aSMatthew G. Knepley   ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr);
205475d3a19aSMatthew G. Knepley   switch (refiner) {
205575d3a19aSMatthew G. Knepley   case 3:
205675d3a19aSMatthew G. Knepley     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
205775d3a19aSMatthew G. Knepley     cMax = PetscMin(cEnd, cMax);
205875d3a19aSMatthew G. Knepley     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
205975d3a19aSMatthew G. Knepley     fMax = PetscMin(fEnd, fMax);
206075d3a19aSMatthew G. Knepley   }
206175d3a19aSMatthew G. Knepley   ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr);
206275d3a19aSMatthew G. Knepley   ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr);
206375d3a19aSMatthew G. Knepley   /* Caculate size of new SF */
206475d3a19aSMatthew G. Knepley   ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr);
206575d3a19aSMatthew G. Knepley   if (numRoots < 0) PetscFunctionReturn(0);
206675d3a19aSMatthew G. Knepley   for (l = 0; l < numLeaves; ++l) {
206775d3a19aSMatthew G. Knepley     const PetscInt p = localPoints[l];
206875d3a19aSMatthew G. Knepley 
206975d3a19aSMatthew G. Knepley     switch (refiner) {
207075d3a19aSMatthew G. Knepley     case 1:
207175d3a19aSMatthew G. Knepley       /* Simplicial 2D */
207275d3a19aSMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
207375d3a19aSMatthew G. Knepley         /* Old vertices stay the same */
207475d3a19aSMatthew G. Knepley         ++numLeavesNew;
207575d3a19aSMatthew G. Knepley       } else if ((p >= fStart) && (p < fEnd)) {
207675d3a19aSMatthew G. Knepley         /* Old faces add new faces and vertex */
2077d963de37SMatthew G. Knepley         numLeavesNew += 2 + 1;
207875d3a19aSMatthew G. Knepley       } else if ((p >= cStart) && (p < cEnd)) {
207975d3a19aSMatthew G. Knepley         /* Old cells add new cells and interior faces */
208075d3a19aSMatthew G. Knepley         numLeavesNew += 4 + 3;
208175d3a19aSMatthew G. Knepley       }
208275d3a19aSMatthew G. Knepley       break;
208375d3a19aSMatthew G. Knepley     case 2:
208475d3a19aSMatthew G. Knepley       /* Hex 2D */
208575d3a19aSMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
208675d3a19aSMatthew G. Knepley         /* Old vertices stay the same */
208775d3a19aSMatthew G. Knepley         ++numLeavesNew;
208875d3a19aSMatthew G. Knepley       } else if ((p >= fStart) && (p < fEnd)) {
208975d3a19aSMatthew G. Knepley         /* Old faces add new faces and vertex */
2090d963de37SMatthew G. Knepley         numLeavesNew += 2 + 1;
209175d3a19aSMatthew G. Knepley       } else if ((p >= cStart) && (p < cEnd)) {
209275d3a19aSMatthew G. Knepley         /* Old cells add new cells and interior faces */
209375d3a19aSMatthew G. Knepley         numLeavesNew += 4 + 4;
209475d3a19aSMatthew G. Knepley       }
209575d3a19aSMatthew G. Knepley       break;
2096*b5da9499SMatthew G. Knepley     case 5:
2097*b5da9499SMatthew G. Knepley       /* Simplicial 3D */
2098*b5da9499SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
2099*b5da9499SMatthew G. Knepley         /* Old vertices stay the same */
2100*b5da9499SMatthew G. Knepley         ++numLeavesNew;
2101*b5da9499SMatthew G. Knepley       } else if ((p >= eStart) && (p < eEnd)) {
2102*b5da9499SMatthew G. Knepley         /* Old edges add new edges and vertex */
2103*b5da9499SMatthew G. Knepley         numLeavesNew += 2 + 1;
2104*b5da9499SMatthew G. Knepley       } else if ((p >= fStart) && (p < fEnd)) {
2105*b5da9499SMatthew G. Knepley         /* Old faces add new faces and face edges */
2106*b5da9499SMatthew G. Knepley         numLeavesNew += 4 + 3;
2107*b5da9499SMatthew G. Knepley       } else if ((p >= cStart) && (p < cEnd)) {
2108*b5da9499SMatthew G. Knepley         /* Old cells add new cells and interior faces and edges */
2109*b5da9499SMatthew G. Knepley         numLeavesNew += 8 + 8 + 1;
2110*b5da9499SMatthew G. Knepley       }
2111*b5da9499SMatthew G. Knepley       break;
211275d3a19aSMatthew G. Knepley     default:
211375d3a19aSMatthew G. Knepley       SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
211475d3a19aSMatthew G. Knepley     }
211575d3a19aSMatthew G. Knepley   }
211675d3a19aSMatthew G. Knepley   /* Communicate depthSizes for each remote rank */
211775d3a19aSMatthew G. Knepley   ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr);
211875d3a19aSMatthew G. Knepley   ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr);
211975d3a19aSMatthew G. Knepley   ierr = PetscMalloc5((depth+1)*numNeighbors,PetscInt,&rdepthSize,numNeighbors,PetscInt,&rvStartNew,numNeighbors,PetscInt,&reStartNew,numNeighbors,PetscInt,&rfStartNew,numNeighbors,PetscInt,&rcStartNew);CHKERRQ(ierr);
212075d3a19aSMatthew 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);
212175d3a19aSMatthew G. Knepley   ierr = MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);CHKERRQ(ierr);
212275d3a19aSMatthew G. Knepley   ierr = MPI_Type_commit(&depthType);CHKERRQ(ierr);
212375d3a19aSMatthew G. Knepley   ierr = PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr);
212475d3a19aSMatthew G. Knepley   ierr = PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr);
212575d3a19aSMatthew G. Knepley   for (n = 0; n < numNeighbors; ++n) {
212675d3a19aSMatthew G. Knepley     ierr = GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);CHKERRQ(ierr);
212775d3a19aSMatthew G. Knepley   }
212875d3a19aSMatthew G. Knepley   depthSizeOld[depth]   = cMax;
212975d3a19aSMatthew G. Knepley   depthSizeOld[0]       = vMax;
213075d3a19aSMatthew G. Knepley   depthSizeOld[depth-1] = fMax;
213175d3a19aSMatthew G. Knepley   depthSizeOld[1]       = eMax;
213275d3a19aSMatthew G. Knepley 
213375d3a19aSMatthew G. Knepley   ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr);
213475d3a19aSMatthew G. Knepley   ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthMaxOld);CHKERRQ(ierr);
213575d3a19aSMatthew G. Knepley 
213675d3a19aSMatthew G. Knepley   depthSizeOld[depth]   = cEnd - cStart;
213775d3a19aSMatthew G. Knepley   depthSizeOld[0]       = vEnd - vStart;
213875d3a19aSMatthew G. Knepley   depthSizeOld[depth-1] = fEnd - fStart;
213975d3a19aSMatthew G. Knepley   depthSizeOld[1]       = eEnd - eStart;
214075d3a19aSMatthew G. Knepley 
214175d3a19aSMatthew G. Knepley   ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr);
214275d3a19aSMatthew G. Knepley   ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr);
214375d3a19aSMatthew G. Knepley   for (n = 0; n < numNeighbors; ++n) {
214475d3a19aSMatthew G. Knepley     ierr = GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);CHKERRQ(ierr);
214575d3a19aSMatthew G. Knepley   }
214675d3a19aSMatthew G. Knepley   ierr = MPI_Type_free(&depthType);CHKERRQ(ierr);
214775d3a19aSMatthew G. Knepley   ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr);
214875d3a19aSMatthew G. Knepley   /* Calculate new point SF */
214975d3a19aSMatthew G. Knepley   ierr = PetscMalloc(numLeavesNew * sizeof(PetscInt),    &localPointsNew);CHKERRQ(ierr);
215075d3a19aSMatthew G. Knepley   ierr = PetscMalloc(numLeavesNew * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr);
215175d3a19aSMatthew G. Knepley   ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr);
215275d3a19aSMatthew G. Knepley   for (l = 0, m = 0; l < numLeaves; ++l) {
215375d3a19aSMatthew G. Knepley     PetscInt    p     = localPoints[l];
215475d3a19aSMatthew G. Knepley     PetscInt    rp    = remotePoints[l].index, n;
215575d3a19aSMatthew G. Knepley     PetscMPIInt rrank = remotePoints[l].rank;
215675d3a19aSMatthew G. Knepley 
215775d3a19aSMatthew G. Knepley     ierr = PetscFindInt(rrank, numNeighbors, neighbors, &n);CHKERRQ(ierr);
215875d3a19aSMatthew G. Knepley     if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank);
215975d3a19aSMatthew G. Knepley     switch (refiner) {
216075d3a19aSMatthew G. Knepley     case 1:
216175d3a19aSMatthew G. Knepley       /* Simplicial 2D */
216275d3a19aSMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
216375d3a19aSMatthew G. Knepley         /* Old vertices stay the same */
216475d3a19aSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (p  - vStart);
216575d3a19aSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
216675d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
216775d3a19aSMatthew G. Knepley         ++m;
216875d3a19aSMatthew G. Knepley       } else if ((p >= fStart) && (p < fEnd)) {
216975d3a19aSMatthew G. Knepley         /* Old faces add new faces and vertex */
217075d3a19aSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - fStart);
217175d3a19aSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
217275d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
217375d3a19aSMatthew G. Knepley         ++m;
217475d3a19aSMatthew G. Knepley         for (r = 0; r < 2; ++r, ++m) {
217575d3a19aSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (p  - fStart)*2     + r;
217675d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
217775d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
217875d3a19aSMatthew G. Knepley         }
217975d3a19aSMatthew G. Knepley       } else if ((p >= cStart) && (p < cEnd)) {
218075d3a19aSMatthew G. Knepley         /* Old cells add new cells and interior faces */
218175d3a19aSMatthew G. Knepley         for (r = 0; r < 4; ++r, ++m) {
218275d3a19aSMatthew G. Knepley           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r;
218375d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
218475d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
218575d3a19aSMatthew G. Knepley         }
218675d3a19aSMatthew G. Knepley         for (r = 0; r < 3; ++r, ++m) {
218775d3a19aSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (fEnd - fStart)*2                    + (p  - cStart)*3     + r;
218875d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r;
218975d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
219075d3a19aSMatthew G. Knepley         }
219175d3a19aSMatthew G. Knepley       }
219275d3a19aSMatthew G. Knepley       break;
219375d3a19aSMatthew G. Knepley     case 2:
219475d3a19aSMatthew G. Knepley       /* Hex 2D */
219575d3a19aSMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
219675d3a19aSMatthew G. Knepley         /* Old vertices stay the same */
219775d3a19aSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (p  - vStart);
219875d3a19aSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
219975d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
220075d3a19aSMatthew G. Knepley         ++m;
220175d3a19aSMatthew G. Knepley       } else if ((p >= fStart) && (p < fEnd)) {
220275d3a19aSMatthew G. Knepley         /* Old faces add new faces and vertex */
220375d3a19aSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - fStart);
220475d3a19aSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
220575d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
220675d3a19aSMatthew G. Knepley         ++m;
220775d3a19aSMatthew G. Knepley         for (r = 0; r < 2; ++r, ++m) {
220875d3a19aSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (p  - fStart)*2     + r;
220975d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
221075d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
221175d3a19aSMatthew G. Knepley         }
221275d3a19aSMatthew G. Knepley       } else if ((p >= cStart) && (p < cEnd)) {
221375d3a19aSMatthew G. Knepley         /* Old cells add new cells and interior faces */
221475d3a19aSMatthew G. Knepley         for (r = 0; r < 4; ++r, ++m) {
221575d3a19aSMatthew G. Knepley           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r;
221675d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
221775d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
221875d3a19aSMatthew G. Knepley         }
221975d3a19aSMatthew G. Knepley         for (r = 0; r < 4; ++r, ++m) {
222075d3a19aSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (fEnd - fStart)*2                    + (p  - cStart)*4     + r;
222175d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*4 + r;
222275d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
222375d3a19aSMatthew G. Knepley         }
222475d3a19aSMatthew G. Knepley       }
222575d3a19aSMatthew G. Knepley       break;
222675d3a19aSMatthew G. Knepley     case 3:
222775d3a19aSMatthew G. Knepley       /* Hybrid simplicial 2D */
222875d3a19aSMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
222975d3a19aSMatthew G. Knepley         /* Old vertices stay the same */
223075d3a19aSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (p  - vStart);
223175d3a19aSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
223275d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
223375d3a19aSMatthew G. Knepley         ++m;
223475d3a19aSMatthew G. Knepley       } else if ((p >= fStart) && (p < fMax)) {
223575d3a19aSMatthew G. Knepley         /* Old interior faces add new faces and vertex */
223675d3a19aSMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - fStart);
223775d3a19aSMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
223875d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
223975d3a19aSMatthew G. Knepley         ++m;
224075d3a19aSMatthew G. Knepley         for (r = 0; r < 2; ++r, ++m) {
224175d3a19aSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (p  - fStart)*2     + r;
224275d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
224375d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
224475d3a19aSMatthew G. Knepley         }
224575d3a19aSMatthew G. Knepley       } else if ((p >= fMax) && (p < fEnd)) {
224675d3a19aSMatthew G. Knepley         /* Old hybrid faces stay the same */
224775d3a19aSMatthew G. Knepley         localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*2     + (p  - fMax);
224875d3a19aSMatthew G. Knepley         remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rdepthMaxOld[n*(depth+1)+depth-1]);
224975d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
225075d3a19aSMatthew G. Knepley         ++m;
225175d3a19aSMatthew G. Knepley       } else if ((p >= cStart) && (p < cMax)) {
225275d3a19aSMatthew G. Knepley         /* Old interior cells add new cells and interior faces */
225375d3a19aSMatthew G. Knepley         for (r = 0; r < 4; ++r, ++m) {
225475d3a19aSMatthew G. Knepley           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r;
225575d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
225675d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
225775d3a19aSMatthew G. Knepley         }
225875d3a19aSMatthew G. Knepley         for (r = 0; r < 3; ++r, ++m) {
225975d3a19aSMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*2     + (p  - cStart)*3     + r;
226075d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + (rdepthMaxOld[n*(depth+1)+depth-1] - rfStart[n])*2 + (rp - rcStart[n])*3 + r;
226175d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
226275d3a19aSMatthew G. Knepley         }
226375d3a19aSMatthew G. Knepley       } else if ((p >= cStart) && (p < cMax)) {
226475d3a19aSMatthew G. Knepley         /* Old hybrid cells add new cells and hybrid face */
226575d3a19aSMatthew G. Knepley         for (r = 0; r < 2; ++r, ++m) {
226675d3a19aSMatthew G. Knepley           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r;
226775d3a19aSMatthew G. Knepley           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
226875d3a19aSMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
226975d3a19aSMatthew G. Knepley         }
227075d3a19aSMatthew G. Knepley         localPointsNew[m]        = fStartNew     + (fMax                              - fStart)*2     + (cMax                            - cStart)*3     + (p  - cMax);
227175d3a19aSMatthew 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]);
227275d3a19aSMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
227375d3a19aSMatthew G. Knepley         ++m;
227475d3a19aSMatthew G. Knepley       }
227575d3a19aSMatthew G. Knepley       break;
2276*b5da9499SMatthew G. Knepley     case 5:
2277*b5da9499SMatthew G. Knepley       /* Simplicial 3D */
2278*b5da9499SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) {
2279*b5da9499SMatthew G. Knepley         /* Old vertices stay the same */
2280*b5da9499SMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (p  - vStart);
2281*b5da9499SMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
2282*b5da9499SMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
2283*b5da9499SMatthew G. Knepley         ++m;
2284*b5da9499SMatthew G. Knepley       } else if ((p >= fStart) && (p < fEnd)) {
2285*b5da9499SMatthew G. Knepley         /* Old edges add new edges and vertex */
2286*b5da9499SMatthew G. Knepley         for (r = 0; r < 2; ++r, ++m) {
2287*b5da9499SMatthew G. Knepley           localPointsNew[m]        = eStartNew     + (p  - eStart)*2     + r;
2288*b5da9499SMatthew G. Knepley           remotePointsNew[m].index = reStartNew[n] + (rp - reStart[n])*2 + r;
2289*b5da9499SMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
2290*b5da9499SMatthew G. Knepley         }
2291*b5da9499SMatthew G. Knepley         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - eStart);
2292*b5da9499SMatthew G. Knepley         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - reStart[n]);
2293*b5da9499SMatthew G. Knepley         remotePointsNew[m].rank  = rrank;
2294*b5da9499SMatthew G. Knepley         ++m;
2295*b5da9499SMatthew G. Knepley       } else if ((p >= fStart) && (p < fEnd)) {
2296*b5da9499SMatthew G. Knepley         /* Old faces add new faces and face edges */
2297*b5da9499SMatthew G. Knepley         for (r = 0; r < 4; ++r, ++m) {
2298*b5da9499SMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (p  - fStart)*4     + r;
2299*b5da9499SMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*4 + r;
2300*b5da9499SMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
2301*b5da9499SMatthew G. Knepley         }
2302*b5da9499SMatthew G. Knepley         for (r = 0; r < 3; ++r, ++m) {
2303*b5da9499SMatthew G. Knepley           localPointsNew[m]        = eStartNew     + (eEnd - eStart)*2              + (p  - fStart)*3     + r;
2304*b5da9499SMatthew G. Knepley           remotePointsNew[m].index = reStartNew[n] + rdepthSizeOld[n*(depth+1)+1]*2 + (rp - rfStart[n])*3 + r;
2305*b5da9499SMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
2306*b5da9499SMatthew G. Knepley         }
2307*b5da9499SMatthew G. Knepley       } else if ((p >= cStart) && (p < cEnd)) {
2308*b5da9499SMatthew G. Knepley         /* Old cells add new cells and interior faces and edges */
2309*b5da9499SMatthew G. Knepley         for (r = 0; r < 8; ++r, ++m) {
2310*b5da9499SMatthew G. Knepley           localPointsNew[m]        = cStartNew     + (p  - cStart)*8     + r;
2311*b5da9499SMatthew G. Knepley           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*8 + r;
2312*b5da9499SMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
2313*b5da9499SMatthew G. Knepley         }
2314*b5da9499SMatthew G. Knepley         for (r = 0; r < 8; ++r, ++m) {
2315*b5da9499SMatthew G. Knepley           localPointsNew[m]        = fStartNew     + (fEnd - fStart)*4                    + (p  - cStart)*8     + r;
2316*b5da9499SMatthew G. Knepley           remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*4 + (rp - rcStart[n])*8 + r;
2317*b5da9499SMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
2318*b5da9499SMatthew G. Knepley         }
2319*b5da9499SMatthew G. Knepley         for (r = 0; r < 1; ++r, ++m) {
2320*b5da9499SMatthew G. Knepley           localPointsNew[m]        = eStartNew     + (eEnd - eStart)*2              + (fEnd - fStart)*3                    + (p  - cStart)*1     + r;
2321*b5da9499SMatthew G. Knepley           remotePointsNew[m].index = reStartNew[n] + rdepthSizeOld[n*(depth+1)+1]*2 + rdepthSizeOld[n*(depth+1)+depth-1]*3 + (rp - rcStart[n])*1 + r;
2322*b5da9499SMatthew G. Knepley           remotePointsNew[m].rank  = rrank;
2323*b5da9499SMatthew G. Knepley         }
2324*b5da9499SMatthew G. Knepley       }
2325*b5da9499SMatthew G. Knepley       break;
232675d3a19aSMatthew G. Knepley     default:
232775d3a19aSMatthew G. Knepley       SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
232875d3a19aSMatthew G. Knepley     }
232975d3a19aSMatthew G. Knepley   }
233075d3a19aSMatthew G. Knepley   ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr);
233175d3a19aSMatthew G. Knepley   ierr = ISDestroy(&processRanks);CHKERRQ(ierr);
233275d3a19aSMatthew G. Knepley   ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr);
233375d3a19aSMatthew G. Knepley   ierr = PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);CHKERRQ(ierr);
233475d3a19aSMatthew G. Knepley   ierr = PetscFree6(depthSizeOld,rdepthSizeOld,rvStart,reStart,rfStart,rcStart);CHKERRQ(ierr);
233575d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
233675d3a19aSMatthew G. Knepley }
233775d3a19aSMatthew G. Knepley 
233875d3a19aSMatthew G. Knepley #undef __FUNCT__
233975d3a19aSMatthew G. Knepley #define __FUNCT__ "CellRefinerCreateLabels"
234075d3a19aSMatthew G. Knepley PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
234175d3a19aSMatthew G. Knepley {
234275d3a19aSMatthew G. Knepley   PetscInt       numLabels, l;
2343*b5da9499SMatthew G. Knepley   PetscInt       depth, newp, cStart, cStartNew, cEnd, cMax, vStart, vStartNew, vEnd, vMax, fStart, fStartNew, fEnd, fMax, eStart, eStartNew, eEnd, eMax, r;
234475d3a19aSMatthew G. Knepley   PetscErrorCode ierr;
234575d3a19aSMatthew G. Knepley 
234675d3a19aSMatthew G. Knepley   PetscFunctionBegin;
234775d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
234875d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
234975d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
235075d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
2351d963de37SMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
2352d963de37SMatthew G. Knepley   ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr);
235375d3a19aSMatthew G. Knepley   ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr);
235475d3a19aSMatthew G. Knepley   ierr = DMPlexGetHybridBounds(dm, &cMax, &fMax, &eMax, &vMax);CHKERRQ(ierr);
235575d3a19aSMatthew G. Knepley   switch (refiner) {
235675d3a19aSMatthew G. Knepley   case 3:
235775d3a19aSMatthew G. Knepley     if (cMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No cell maximum specified in hybrid mesh");
235875d3a19aSMatthew G. Knepley     cMax = PetscMin(cEnd, cMax);
235975d3a19aSMatthew G. Knepley     if (fMax < 0) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "No face maximum specified in hybrid mesh");
236075d3a19aSMatthew G. Knepley     fMax = PetscMin(fEnd, fMax);
236175d3a19aSMatthew G. Knepley   }
236275d3a19aSMatthew G. Knepley   for (l = 0; l < numLabels; ++l) {
236375d3a19aSMatthew G. Knepley     DMLabel         label, labelNew;
236475d3a19aSMatthew G. Knepley     const char     *lname;
236575d3a19aSMatthew G. Knepley     PetscBool       isDepth;
236675d3a19aSMatthew G. Knepley     IS              valueIS;
236775d3a19aSMatthew G. Knepley     const PetscInt *values;
236875d3a19aSMatthew G. Knepley     PetscInt        numValues, val;
236975d3a19aSMatthew G. Knepley 
237075d3a19aSMatthew G. Knepley     ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr);
237175d3a19aSMatthew G. Knepley     ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr);
237275d3a19aSMatthew G. Knepley     if (isDepth) continue;
237375d3a19aSMatthew G. Knepley     ierr = DMPlexCreateLabel(rdm, lname);CHKERRQ(ierr);
237475d3a19aSMatthew G. Knepley     ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr);
237575d3a19aSMatthew G. Knepley     ierr = DMPlexGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr);
237675d3a19aSMatthew G. Knepley     ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr);
237775d3a19aSMatthew G. Knepley     ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr);
237875d3a19aSMatthew G. Knepley     ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr);
237975d3a19aSMatthew G. Knepley     for (val = 0; val < numValues; ++val) {
238075d3a19aSMatthew G. Knepley       IS              pointIS;
238175d3a19aSMatthew G. Knepley       const PetscInt *points;
238275d3a19aSMatthew G. Knepley       PetscInt        numPoints, n;
238375d3a19aSMatthew G. Knepley 
238475d3a19aSMatthew G. Knepley       ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr);
238575d3a19aSMatthew G. Knepley       ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr);
238675d3a19aSMatthew G. Knepley       ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr);
238775d3a19aSMatthew G. Knepley       for (n = 0; n < numPoints; ++n) {
238875d3a19aSMatthew G. Knepley         const PetscInt p = points[n];
238975d3a19aSMatthew G. Knepley         switch (refiner) {
239075d3a19aSMatthew G. Knepley         case 1:
239175d3a19aSMatthew G. Knepley           /* Simplicial 2D */
239275d3a19aSMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) {
239375d3a19aSMatthew G. Knepley             /* Old vertices stay the same */
239475d3a19aSMatthew G. Knepley             newp = vStartNew + (p - vStart);
239575d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
239675d3a19aSMatthew G. Knepley           } else if ((p >= fStart) && (p < fEnd)) {
239775d3a19aSMatthew G. Knepley             /* Old faces add new faces and vertex */
239875d3a19aSMatthew G. Knepley             newp = vStartNew + (vEnd - vStart) + (p - fStart);
239975d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
240075d3a19aSMatthew G. Knepley             for (r = 0; r < 2; ++r) {
240175d3a19aSMatthew G. Knepley               newp = fStartNew + (p - fStart)*2 + r;
240275d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
240375d3a19aSMatthew G. Knepley             }
240475d3a19aSMatthew G. Knepley           } else if ((p >= cStart) && (p < cEnd)) {
240575d3a19aSMatthew G. Knepley             /* Old cells add new cells and interior faces */
240675d3a19aSMatthew G. Knepley             for (r = 0; r < 4; ++r) {
240775d3a19aSMatthew G. Knepley               newp = cStartNew + (p - cStart)*4 + r;
240875d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
240975d3a19aSMatthew G. Knepley             }
241075d3a19aSMatthew G. Knepley             for (r = 0; r < 3; ++r) {
241175d3a19aSMatthew G. Knepley               newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r;
241275d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
241375d3a19aSMatthew G. Knepley             }
241475d3a19aSMatthew G. Knepley           }
241575d3a19aSMatthew G. Knepley           break;
241675d3a19aSMatthew G. Knepley         case 2:
241775d3a19aSMatthew G. Knepley           /* Hex 2D */
241875d3a19aSMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) {
241975d3a19aSMatthew G. Knepley             /* Old vertices stay the same */
242075d3a19aSMatthew G. Knepley             newp = vStartNew + (p - vStart);
242175d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
242275d3a19aSMatthew G. Knepley           } else if ((p >= fStart) && (p < fEnd)) {
242375d3a19aSMatthew G. Knepley             /* Old faces add new faces and vertex */
242475d3a19aSMatthew G. Knepley             newp = vStartNew + (vEnd - vStart) + (p - fStart);
242575d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
242675d3a19aSMatthew G. Knepley             for (r = 0; r < 2; ++r) {
242775d3a19aSMatthew G. Knepley               newp = fStartNew + (p - fStart)*2 + r;
242875d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
242975d3a19aSMatthew G. Knepley             }
243075d3a19aSMatthew G. Knepley           } else if ((p >= cStart) && (p < cEnd)) {
243175d3a19aSMatthew G. Knepley             /* Old cells add new cells and interior faces and vertex */
243275d3a19aSMatthew G. Knepley             for (r = 0; r < 4; ++r) {
243375d3a19aSMatthew G. Knepley               newp = cStartNew + (p - cStart)*4 + r;
243475d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
243575d3a19aSMatthew G. Knepley             }
243675d3a19aSMatthew G. Knepley             for (r = 0; r < 4; ++r) {
243775d3a19aSMatthew G. Knepley               newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r;
243875d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
243975d3a19aSMatthew G. Knepley             }
244075d3a19aSMatthew G. Knepley             newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart);
244175d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
244275d3a19aSMatthew G. Knepley           }
244375d3a19aSMatthew G. Knepley           break;
244475d3a19aSMatthew G. Knepley         case 3:
244575d3a19aSMatthew G. Knepley           /* Hybrid simplicial 2D */
244675d3a19aSMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) {
244775d3a19aSMatthew G. Knepley             /* Old vertices stay the same */
244875d3a19aSMatthew G. Knepley             newp = vStartNew + (p - vStart);
244975d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
245075d3a19aSMatthew G. Knepley           } else if ((p >= fStart) && (p < fMax)) {
245175d3a19aSMatthew G. Knepley             /* Old interior faces add new faces and vertex */
245275d3a19aSMatthew G. Knepley             newp = vStartNew + (vEnd - vStart) + (p - fStart);
245375d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
245475d3a19aSMatthew G. Knepley             for (r = 0; r < 2; ++r) {
245575d3a19aSMatthew G. Knepley               newp = fStartNew + (p - fStart)*2 + r;
245675d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
245775d3a19aSMatthew G. Knepley             }
245875d3a19aSMatthew G. Knepley           } else if ((p >= fMax) && (p < fEnd)) {
245975d3a19aSMatthew G. Knepley             /* Old hybrid faces stay the same */
246075d3a19aSMatthew G. Knepley             newp = fStartNew + (fMax - fStart)*2 + (p - fMax);
246175d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
246275d3a19aSMatthew G. Knepley           } else if ((p >= cStart) && (p < cMax)) {
246375d3a19aSMatthew G. Knepley             /* Old interior cells add new cells and interior faces */
246475d3a19aSMatthew G. Knepley             for (r = 0; r < 4; ++r) {
246575d3a19aSMatthew G. Knepley               newp = cStartNew + (p - cStart)*4 + r;
246675d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
246775d3a19aSMatthew G. Knepley             }
246875d3a19aSMatthew G. Knepley             for (r = 0; r < 3; ++r) {
246975d3a19aSMatthew G. Knepley               newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r;
247075d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
247175d3a19aSMatthew G. Knepley             }
247275d3a19aSMatthew G. Knepley           } else if ((p >= cMax) && (p < cEnd)) {
247375d3a19aSMatthew G. Knepley             /* Old hybrid cells add new cells and hybrid face */
247475d3a19aSMatthew G. Knepley             for (r = 0; r < 2; ++r) {
247575d3a19aSMatthew G. Knepley               newp = cStartNew + (cMax - cStart)*4 + (p - cMax)*2 + r;
247675d3a19aSMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
247775d3a19aSMatthew G. Knepley             }
247875d3a19aSMatthew G. Knepley             newp = fStartNew + (fMax - fStart)*2 + (cMax - cStart)*3 + (p - cMax);
247975d3a19aSMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
248075d3a19aSMatthew G. Knepley           }
248175d3a19aSMatthew G. Knepley           break;
2482*b5da9499SMatthew G. Knepley         case 5:
2483*b5da9499SMatthew G. Knepley           /* Simplicial 3D */
2484*b5da9499SMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) {
2485*b5da9499SMatthew G. Knepley             /* Old vertices stay the same */
2486*b5da9499SMatthew G. Knepley             newp = vStartNew + (p - vStart);
2487*b5da9499SMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
2488*b5da9499SMatthew G. Knepley           } else if ((p >= eStart) && (p < eEnd)) {
2489*b5da9499SMatthew G. Knepley             /* Old edges add new edges and vertex */
2490*b5da9499SMatthew G. Knepley             for (r = 0; r < 2; ++r) {
2491*b5da9499SMatthew G. Knepley               newp = eStartNew + (p - eStart)*2 + r;
2492*b5da9499SMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
2493*b5da9499SMatthew G. Knepley             }
2494*b5da9499SMatthew G. Knepley             newp = vStartNew + (vEnd - vStart) + (p - eStart);
2495*b5da9499SMatthew G. Knepley             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
2496*b5da9499SMatthew G. Knepley           } else if ((p >= fStart) && (p < fEnd)) {
2497*b5da9499SMatthew G. Knepley             /* Old faces add new faces and edges */
2498*b5da9499SMatthew G. Knepley             for (r = 0; r < 4; ++r) {
2499*b5da9499SMatthew G. Knepley               newp = fStartNew + (p - fStart)*4 + r;
2500*b5da9499SMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
2501*b5da9499SMatthew G. Knepley             }
2502*b5da9499SMatthew G. Knepley             for (r = 0; r < 3; ++r) {
2503*b5da9499SMatthew G. Knepley               newp = eStartNew + (eEnd - eStart)*2 + (p - fStart)*3 + r;
2504*b5da9499SMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
2505*b5da9499SMatthew G. Knepley             }
2506*b5da9499SMatthew G. Knepley           } else if ((p >= cStart) && (p < cEnd)) {
2507*b5da9499SMatthew G. Knepley             /* Old cells add new cells and interior faces and edges */
2508*b5da9499SMatthew G. Knepley             for (r = 0; r < 8; ++r) {
2509*b5da9499SMatthew G. Knepley               newp = cStartNew + (p - cStart)*8 + r;
2510*b5da9499SMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
2511*b5da9499SMatthew G. Knepley             }
2512*b5da9499SMatthew G. Knepley             for (r = 0; r < 8; ++r) {
2513*b5da9499SMatthew G. Knepley               newp = fStartNew + (fEnd - fStart)*4 + (p - cStart)*8 + r;
2514*b5da9499SMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
2515*b5da9499SMatthew G. Knepley             }
2516*b5da9499SMatthew G. Knepley             for (r = 0; r < 1; ++r) {
2517*b5da9499SMatthew G. Knepley               newp = eStartNew + (eEnd - eStart)*2 + (fEnd - fStart)*3 + (p - cStart)*1 + r;
2518*b5da9499SMatthew G. Knepley               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
2519*b5da9499SMatthew G. Knepley             }
2520*b5da9499SMatthew G. Knepley           }
2521*b5da9499SMatthew G. Knepley           break;
252275d3a19aSMatthew G. Knepley         default:
252375d3a19aSMatthew G. Knepley           SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
252475d3a19aSMatthew G. Knepley         }
252575d3a19aSMatthew G. Knepley       }
252675d3a19aSMatthew G. Knepley       ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr);
252775d3a19aSMatthew G. Knepley       ierr = ISDestroy(&pointIS);CHKERRQ(ierr);
252875d3a19aSMatthew G. Knepley     }
252975d3a19aSMatthew G. Knepley     ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr);
253075d3a19aSMatthew G. Knepley     ierr = ISDestroy(&valueIS);CHKERRQ(ierr);
253175d3a19aSMatthew G. Knepley     if (0) {
253275d3a19aSMatthew G. Knepley       ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr);
253375d3a19aSMatthew G. Knepley       ierr = DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
253475d3a19aSMatthew G. Knepley       ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
253575d3a19aSMatthew G. Knepley     }
253675d3a19aSMatthew G. Knepley   }
253775d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
253875d3a19aSMatthew G. Knepley }
253975d3a19aSMatthew G. Knepley 
254075d3a19aSMatthew G. Knepley #undef __FUNCT__
2541509c9b89SMatthew G. Knepley #define __FUNCT__ "DMPlexRefineUniform_Internal"
254275d3a19aSMatthew G. Knepley /* This will only work for interpolated meshes */
2543509c9b89SMatthew G. Knepley PetscErrorCode DMPlexRefineUniform_Internal(DM dm, CellRefiner cellRefiner, DM *dmRefined)
254475d3a19aSMatthew G. Knepley {
254575d3a19aSMatthew G. Knepley   DM             rdm;
254675d3a19aSMatthew G. Knepley   PetscInt      *depthSize;
254775d3a19aSMatthew G. Knepley   PetscInt       dim, depth = 0, d, pStart = 0, pEnd = 0;
254875d3a19aSMatthew G. Knepley   PetscErrorCode ierr;
254975d3a19aSMatthew G. Knepley 
255075d3a19aSMatthew G. Knepley   PetscFunctionBegin;
255175d3a19aSMatthew G. Knepley   ierr = DMCreate(PetscObjectComm((PetscObject)dm), &rdm);CHKERRQ(ierr);
255275d3a19aSMatthew G. Knepley   ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr);
255375d3a19aSMatthew G. Knepley   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
255475d3a19aSMatthew G. Knepley   ierr = DMPlexSetDimension(rdm, dim);CHKERRQ(ierr);
255575d3a19aSMatthew G. Knepley   /* Calculate number of new points of each depth */
255675d3a19aSMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
255775d3a19aSMatthew G. Knepley   ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthSize);CHKERRQ(ierr);
255875d3a19aSMatthew G. Knepley   ierr = PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr);
255975d3a19aSMatthew G. Knepley   ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr);
256075d3a19aSMatthew G. Knepley   /* Step 1: Set chart */
256175d3a19aSMatthew G. Knepley   for (d = 0; d <= depth; ++d) pEnd += depthSize[d];
256275d3a19aSMatthew G. Knepley   ierr = DMPlexSetChart(rdm, pStart, pEnd);CHKERRQ(ierr);
256375d3a19aSMatthew G. Knepley   /* Step 2: Set cone/support sizes */
256475d3a19aSMatthew G. Knepley   ierr = CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
256575d3a19aSMatthew G. Knepley   /* Step 3: Setup refined DM */
256675d3a19aSMatthew G. Knepley   ierr = DMSetUp(rdm);CHKERRQ(ierr);
256775d3a19aSMatthew G. Knepley   /* Step 4: Set cones and supports */
256875d3a19aSMatthew G. Knepley   ierr = CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
256975d3a19aSMatthew G. Knepley   /* Step 5: Stratify */
257075d3a19aSMatthew G. Knepley   ierr = DMPlexStratify(rdm);CHKERRQ(ierr);
257175d3a19aSMatthew G. Knepley   /* Step 6: Set coordinates for vertices */
257275d3a19aSMatthew G. Knepley   ierr = CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
257375d3a19aSMatthew G. Knepley   /* Step 7: Create pointSF */
257475d3a19aSMatthew G. Knepley   ierr = CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
257575d3a19aSMatthew G. Knepley   /* Step 8: Create labels */
257675d3a19aSMatthew G. Knepley   ierr = CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
257775d3a19aSMatthew G. Knepley   ierr = PetscFree(depthSize);CHKERRQ(ierr);
257875d3a19aSMatthew G. Knepley 
257975d3a19aSMatthew G. Knepley   *dmRefined = rdm;
258075d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
258175d3a19aSMatthew G. Knepley }
258275d3a19aSMatthew G. Knepley 
258375d3a19aSMatthew G. Knepley #undef __FUNCT__
258475d3a19aSMatthew G. Knepley #define __FUNCT__ "DMPlexSetRefinementUniform"
258575d3a19aSMatthew G. Knepley PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform)
258675d3a19aSMatthew G. Knepley {
258775d3a19aSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
258875d3a19aSMatthew G. Knepley 
258975d3a19aSMatthew G. Knepley   PetscFunctionBegin;
259075d3a19aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
259175d3a19aSMatthew G. Knepley   mesh->refinementUniform = refinementUniform;
259275d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
259375d3a19aSMatthew G. Knepley }
259475d3a19aSMatthew G. Knepley 
259575d3a19aSMatthew G. Knepley #undef __FUNCT__
259675d3a19aSMatthew G. Knepley #define __FUNCT__ "DMPlexGetRefinementUniform"
259775d3a19aSMatthew G. Knepley PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform)
259875d3a19aSMatthew G. Knepley {
259975d3a19aSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
260075d3a19aSMatthew G. Knepley 
260175d3a19aSMatthew G. Knepley   PetscFunctionBegin;
260275d3a19aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
260375d3a19aSMatthew G. Knepley   PetscValidPointer(refinementUniform,  2);
260475d3a19aSMatthew G. Knepley   *refinementUniform = mesh->refinementUniform;
260575d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
260675d3a19aSMatthew G. Knepley }
260775d3a19aSMatthew G. Knepley 
260875d3a19aSMatthew G. Knepley #undef __FUNCT__
260975d3a19aSMatthew G. Knepley #define __FUNCT__ "DMPlexSetRefinementLimit"
261075d3a19aSMatthew G. Knepley PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit)
261175d3a19aSMatthew G. Knepley {
261275d3a19aSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
261375d3a19aSMatthew G. Knepley 
261475d3a19aSMatthew G. Knepley   PetscFunctionBegin;
261575d3a19aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
261675d3a19aSMatthew G. Knepley   mesh->refinementLimit = refinementLimit;
261775d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
261875d3a19aSMatthew G. Knepley }
261975d3a19aSMatthew G. Knepley 
262075d3a19aSMatthew G. Knepley #undef __FUNCT__
262175d3a19aSMatthew G. Knepley #define __FUNCT__ "DMPlexGetRefinementLimit"
262275d3a19aSMatthew G. Knepley PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit)
262375d3a19aSMatthew G. Knepley {
262475d3a19aSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
262575d3a19aSMatthew G. Knepley 
262675d3a19aSMatthew G. Knepley   PetscFunctionBegin;
262775d3a19aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
262875d3a19aSMatthew G. Knepley   PetscValidPointer(refinementLimit,  2);
262975d3a19aSMatthew G. Knepley   /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */
263075d3a19aSMatthew G. Knepley   *refinementLimit = mesh->refinementLimit;
263175d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
263275d3a19aSMatthew G. Knepley }
263375d3a19aSMatthew G. Knepley 
263475d3a19aSMatthew G. Knepley #undef __FUNCT__
2635509c9b89SMatthew G. Knepley #define __FUNCT__ "DMPlexGetCellRefiner_Internal"
2636509c9b89SMatthew G. Knepley PetscErrorCode DMPlexGetCellRefiner_Internal(DM dm, CellRefiner *cellRefiner)
263775d3a19aSMatthew G. Knepley {
263875d3a19aSMatthew G. Knepley   PetscInt       dim, cStart, coneSize, cMax;
263975d3a19aSMatthew G. Knepley   PetscErrorCode ierr;
264075d3a19aSMatthew G. Knepley 
264175d3a19aSMatthew G. Knepley   PetscFunctionBegin;
264275d3a19aSMatthew G. Knepley   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
264375d3a19aSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, NULL);CHKERRQ(ierr);
264475d3a19aSMatthew G. Knepley   ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr);
264575d3a19aSMatthew G. Knepley   ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr);
264675d3a19aSMatthew G. Knepley   switch (dim) {
264775d3a19aSMatthew G. Knepley   case 2:
264875d3a19aSMatthew G. Knepley     switch (coneSize) {
264975d3a19aSMatthew G. Knepley     case 3:
265075d3a19aSMatthew G. Knepley       if (cMax >= 0) *cellRefiner = 3; /* Hybrid */
265175d3a19aSMatthew G. Knepley       else *cellRefiner = 1; /* Triangular */
265275d3a19aSMatthew G. Knepley       break;
265375d3a19aSMatthew G. Knepley     case 4:
265475d3a19aSMatthew G. Knepley       if (cMax >= 0) *cellRefiner = 4; /* Hybrid */
265575d3a19aSMatthew G. Knepley       else *cellRefiner = 2; /* Quadrilateral */
265675d3a19aSMatthew G. Knepley       break;
265775d3a19aSMatthew G. Knepley     default:
265875d3a19aSMatthew G. Knepley       SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim);
265975d3a19aSMatthew G. Knepley     }
266075d3a19aSMatthew G. Knepley     break;
2661*b5da9499SMatthew G. Knepley   case 3:
2662*b5da9499SMatthew G. Knepley     switch (coneSize) {
2663*b5da9499SMatthew G. Knepley     case 4:
2664*b5da9499SMatthew G. Knepley       if (cMax >= 0) *cellRefiner = 7; /* Hybrid */
2665*b5da9499SMatthew G. Knepley       else *cellRefiner = 5; /* Tetrahedral */
2666*b5da9499SMatthew G. Knepley       break;
2667*b5da9499SMatthew G. Knepley     default:
2668*b5da9499SMatthew G. Knepley       SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim);
2669*b5da9499SMatthew G. Knepley     }
2670*b5da9499SMatthew G. Knepley     break;
267175d3a19aSMatthew G. Knepley   default:
267275d3a19aSMatthew G. Knepley     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim);
267375d3a19aSMatthew G. Knepley   }
267475d3a19aSMatthew G. Knepley   PetscFunctionReturn(0);
267575d3a19aSMatthew G. Knepley }
2676