xref: /petsc/src/dm/impls/plex/plex.c (revision 552f735842aa6127d09b62f740a903cdd0631614)
1*552f7358SJed Brown #include <petsc-private/pleximpl.h>   /*I      "petscdmplex.h"   I*/
2*552f7358SJed Brown #include <../src/sys/utils/hash.h>
3*552f7358SJed Brown 
4*552f7358SJed Brown /* Logging support */
5*552f7358SJed Brown PetscLogEvent DMPLEX_Distribute, DMPLEX_Stratify;
6*552f7358SJed Brown 
7*552f7358SJed Brown extern PetscErrorCode VecView_Seq(Vec, PetscViewer);
8*552f7358SJed Brown extern PetscErrorCode VecView_MPI(Vec, PetscViewer);
9*552f7358SJed Brown 
10*552f7358SJed Brown #undef __FUNCT__
11*552f7358SJed Brown #define __FUNCT__ "VecView_Plex_Local"
12*552f7358SJed Brown PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer)
13*552f7358SJed Brown {
14*552f7358SJed Brown   DM             dm;
15*552f7358SJed Brown   PetscBool      isvtk;
16*552f7358SJed Brown   PetscErrorCode ierr;
17*552f7358SJed Brown 
18*552f7358SJed Brown   PetscFunctionBegin;
19*552f7358SJed Brown   ierr = VecGetDM(v, &dm);CHKERRQ(ierr);
20*552f7358SJed Brown   if (!dm) SETERRQ(((PetscObject) v)->comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
21*552f7358SJed Brown   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr);
22*552f7358SJed Brown   if (isvtk) {
23*552f7358SJed Brown     PetscViewerVTKFieldType ft = PETSC_VTK_POINT_FIELD;
24*552f7358SJed Brown     PetscSection            section;
25*552f7358SJed Brown     PetscInt                dim, pStart, pEnd, cStart, fStart, vStart, cdof = 0, fdof = 0, vdof = 0;
26*552f7358SJed Brown 
27*552f7358SJed Brown     ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
28*552f7358SJed Brown     ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
29*552f7358SJed Brown     ierr = DMPlexGetHeightStratum(dm, 0, &cStart, PETSC_NULL);CHKERRQ(ierr);
30*552f7358SJed Brown     ierr = DMPlexGetHeightStratum(dm, 1, &fStart, PETSC_NULL);CHKERRQ(ierr);
31*552f7358SJed Brown     ierr = DMPlexGetDepthStratum(dm, 0, &vStart, PETSC_NULL);CHKERRQ(ierr);
32*552f7358SJed Brown     ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr);
33*552f7358SJed Brown     /* Assumes that numer of dofs per point of each stratum is constant, natural for VTK */
34*552f7358SJed Brown     if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetDof(section, cStart, &cdof);CHKERRQ(ierr);}
35*552f7358SJed Brown     if ((fStart >= pStart) && (fStart < pEnd)) {ierr = PetscSectionGetDof(section, fStart, &fdof);CHKERRQ(ierr);}
36*552f7358SJed Brown     if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetDof(section, vStart, &vdof);CHKERRQ(ierr);}
37*552f7358SJed Brown     if (cdof && fdof && vdof) { /* Actually Q2 or some such, but visualize as Q1 */
38*552f7358SJed Brown       ft = (cdof == dim) ? PETSC_VTK_POINT_VECTOR_FIELD : PETSC_VTK_POINT_FIELD;
39*552f7358SJed Brown     } else if (cdof && vdof) {
40*552f7358SJed Brown       SETERRQ(((PetscObject)viewer)->comm,PETSC_ERR_SUP,"No support for viewing mixed space with dofs at both vertices and cells");
41*552f7358SJed Brown     } else if (cdof) {
42*552f7358SJed Brown       /* TODO: This assumption should be removed when there is a way of identifying whether a space is conceptually a
43*552f7358SJed Brown        * vector or just happens to have the same number of dofs as the dimension. */
44*552f7358SJed Brown       if (cdof == dim) {
45*552f7358SJed Brown         ft = PETSC_VTK_CELL_VECTOR_FIELD;
46*552f7358SJed Brown       } else {
47*552f7358SJed Brown         ft = PETSC_VTK_CELL_FIELD;
48*552f7358SJed Brown       }
49*552f7358SJed Brown     } else if (vdof) {
50*552f7358SJed Brown       if (vdof == dim) {
51*552f7358SJed Brown         ft = PETSC_VTK_POINT_VECTOR_FIELD;
52*552f7358SJed Brown       } else {
53*552f7358SJed Brown         ft = PETSC_VTK_POINT_FIELD;
54*552f7358SJed Brown       }
55*552f7358SJed Brown     } else SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Could not classify input Vec for VTK");
56*552f7358SJed Brown 
57*552f7358SJed Brown     ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); /* viewer drops reference */
58*552f7358SJed Brown     ierr = PetscObjectReference((PetscObject) v);CHKERRQ(ierr);  /* viewer drops reference */
59*552f7358SJed Brown     ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, ft, (PetscObject) v);CHKERRQ(ierr);
60*552f7358SJed Brown   } else {
61*552f7358SJed Brown     PetscBool isseq;
62*552f7358SJed Brown 
63*552f7358SJed Brown     ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr);
64*552f7358SJed Brown     if (isseq) {
65*552f7358SJed Brown       ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);
66*552f7358SJed Brown     } else {
67*552f7358SJed Brown       ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);
68*552f7358SJed Brown     }
69*552f7358SJed Brown   }
70*552f7358SJed Brown   PetscFunctionReturn(0);
71*552f7358SJed Brown }
72*552f7358SJed Brown 
73*552f7358SJed Brown #undef __FUNCT__
74*552f7358SJed Brown #define __FUNCT__ "VecView_Plex"
75*552f7358SJed Brown PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer)
76*552f7358SJed Brown {
77*552f7358SJed Brown   DM             dm;
78*552f7358SJed Brown   PetscBool      isvtk;
79*552f7358SJed Brown   PetscErrorCode ierr;
80*552f7358SJed Brown 
81*552f7358SJed Brown   PetscFunctionBegin;
82*552f7358SJed Brown   ierr = VecGetDM(v, &dm);CHKERRQ(ierr);
83*552f7358SJed Brown   if (!dm) SETERRQ(((PetscObject) v)->comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
84*552f7358SJed Brown   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr);
85*552f7358SJed Brown   if (isvtk) {
86*552f7358SJed Brown     Vec         locv;
87*552f7358SJed Brown     const char *name;
88*552f7358SJed Brown 
89*552f7358SJed Brown     ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr);
90*552f7358SJed Brown     ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr);
91*552f7358SJed Brown     ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr);
92*552f7358SJed Brown     ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr);
93*552f7358SJed Brown     ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr);
94*552f7358SJed Brown     ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr);
95*552f7358SJed Brown     ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr);
96*552f7358SJed Brown   } else {
97*552f7358SJed Brown     PetscBool isseq;
98*552f7358SJed Brown 
99*552f7358SJed Brown     ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr);
100*552f7358SJed Brown     if (isseq) {
101*552f7358SJed Brown       ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);
102*552f7358SJed Brown     } else {
103*552f7358SJed Brown       ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);
104*552f7358SJed Brown     }
105*552f7358SJed Brown   }
106*552f7358SJed Brown   PetscFunctionReturn(0);
107*552f7358SJed Brown }
108*552f7358SJed Brown 
109*552f7358SJed Brown #undef __FUNCT__
110*552f7358SJed Brown #define __FUNCT__ "DMPlexView_Ascii"
111*552f7358SJed Brown PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer)
112*552f7358SJed Brown {
113*552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex *) dm->data;
114*552f7358SJed Brown   DM                cdm;
115*552f7358SJed Brown   DMLabel           markers;
116*552f7358SJed Brown   PetscSection      coordSection;
117*552f7358SJed Brown   Vec               coordinates;
118*552f7358SJed Brown   PetscViewerFormat format;
119*552f7358SJed Brown   PetscErrorCode    ierr;
120*552f7358SJed Brown 
121*552f7358SJed Brown   PetscFunctionBegin;
122*552f7358SJed Brown   ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
123*552f7358SJed Brown   ierr = DMGetDefaultSection(cdm, &coordSection);CHKERRQ(ierr);
124*552f7358SJed Brown   ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
125*552f7358SJed Brown   ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr);
126*552f7358SJed Brown   if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
127*552f7358SJed Brown     const char *name;
128*552f7358SJed Brown     PetscInt    maxConeSize, maxSupportSize;
129*552f7358SJed Brown     PetscInt    pStart, pEnd, p;
130*552f7358SJed Brown     PetscMPIInt rank, size;
131*552f7358SJed Brown 
132*552f7358SJed Brown     ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr);
133*552f7358SJed Brown     ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr);
134*552f7358SJed Brown     ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr);
135*552f7358SJed Brown     ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
136*552f7358SJed Brown     ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr);
137*552f7358SJed Brown     ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr);
138*552f7358SJed Brown     ierr = PetscViewerASCIIPrintf(viewer, "Mesh '%s':\n", name);CHKERRQ(ierr);
139*552f7358SJed Brown     ierr = PetscViewerASCIISynchronizedPrintf(viewer, "Max sizes cone: %D support: %D\n", maxConeSize, maxSupportSize);CHKERRQ(ierr);
140*552f7358SJed Brown     ierr = PetscViewerASCIIPrintf(viewer, "orientation is missing\n", name);CHKERRQ(ierr);
141*552f7358SJed Brown     ierr = PetscViewerASCIIPrintf(viewer, "cap --> base:\n", name);CHKERRQ(ierr);
142*552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
143*552f7358SJed Brown       PetscInt dof, off, s;
144*552f7358SJed Brown 
145*552f7358SJed Brown       ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr);
146*552f7358SJed Brown       ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr);
147*552f7358SJed Brown       for (s = off; s < off+dof; ++s) {
148*552f7358SJed Brown         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr);
149*552f7358SJed Brown       }
150*552f7358SJed Brown     }
151*552f7358SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
152*552f7358SJed Brown     ierr = PetscViewerASCIIPrintf(viewer, "base <-- cap:\n", name);CHKERRQ(ierr);
153*552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
154*552f7358SJed Brown       PetscInt dof, off, c;
155*552f7358SJed Brown 
156*552f7358SJed Brown       ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr);
157*552f7358SJed Brown       ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr);
158*552f7358SJed Brown       for (c = off; c < off+dof; ++c) {
159*552f7358SJed Brown         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr);
160*552f7358SJed Brown       }
161*552f7358SJed Brown     }
162*552f7358SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
163*552f7358SJed Brown     ierr = PetscSectionGetChart(coordSection, &pStart, PETSC_NULL);CHKERRQ(ierr);
164*552f7358SJed Brown     if (pStart >= 0) {ierr = PetscSectionVecView(coordSection, coordinates, viewer);CHKERRQ(ierr);}
165*552f7358SJed Brown     ierr = DMPlexGetLabel(dm, "marker", &markers);CHKERRQ(ierr);
166*552f7358SJed Brown     if (markers) {
167*552f7358SJed Brown       ierr = DMLabelView(markers,viewer);CHKERRQ(ierr);
168*552f7358SJed Brown     }
169*552f7358SJed Brown     if (size > 1) {
170*552f7358SJed Brown       PetscSF sf;
171*552f7358SJed Brown 
172*552f7358SJed Brown       ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr);
173*552f7358SJed Brown       ierr = PetscSFView(sf, viewer);CHKERRQ(ierr);
174*552f7358SJed Brown     }
175*552f7358SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
176*552f7358SJed Brown   } else if (format == PETSC_VIEWER_ASCII_LATEX) {
177*552f7358SJed Brown     const char  *name;
178*552f7358SJed Brown     const char  *colors[3] = {"red", "blue", "green"};
179*552f7358SJed Brown     const int    numColors = 3;
180*552f7358SJed Brown     PetscReal    scale = 2.0;
181*552f7358SJed Brown     PetscScalar *coords;
182*552f7358SJed Brown     PetscInt     depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p;
183*552f7358SJed Brown     PetscMPIInt  rank, size;
184*552f7358SJed Brown 
185*552f7358SJed Brown     ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
186*552f7358SJed Brown     ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr);
187*552f7358SJed Brown     ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr);
188*552f7358SJed Brown     ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr);
189*552f7358SJed Brown     ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr);
190*552f7358SJed Brown     ierr = PetscViewerASCIIPrintf(viewer, "\\documentclass{article}\n\n\
191*552f7358SJed Brown \\usepackage{tikz}\n\
192*552f7358SJed Brown \\usepackage{pgflibraryshapes}\n\
193*552f7358SJed Brown \\usetikzlibrary{backgrounds}\n\
194*552f7358SJed Brown \\usetikzlibrary{arrows}\n\
195*552f7358SJed Brown \\newenvironment{changemargin}[2]{%%\n\
196*552f7358SJed Brown   \\begin{list}{}{%%\n\
197*552f7358SJed Brown     \\setlength{\\topsep}{0pt}%%\n\
198*552f7358SJed Brown     \\setlength{\\leftmargin}{#1}%%\n\
199*552f7358SJed Brown     \\setlength{\\rightmargin}{#2}%%\n\
200*552f7358SJed Brown     \\setlength{\\listparindent}{\\parindent}%%\n\
201*552f7358SJed Brown     \\setlength{\\itemindent}{\\parindent}%%\n\
202*552f7358SJed Brown     \\setlength{\\parsep}{\\parskip}%%\n\
203*552f7358SJed Brown   }%%\n\
204*552f7358SJed Brown   \\item[]}{\\end{list}}\n\n\
205*552f7358SJed Brown \\begin{document}\n\
206*552f7358SJed Brown \\section{%s}\n\
207*552f7358SJed Brown \\begin{changemargin}{-1cm}{0cm}\n\
208*552f7358SJed Brown \\begin{center}\n\
209*552f7358SJed Brown \\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", name, 8.0/scale);CHKERRQ(ierr);
210*552f7358SJed Brown     /* Plot vertices */
211*552f7358SJed Brown     ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
212*552f7358SJed Brown     ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr);
213*552f7358SJed Brown     ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr);
214*552f7358SJed Brown     for(v = vStart; v < vEnd; ++v) {
215*552f7358SJed Brown       PetscInt off, dof, d;
216*552f7358SJed Brown 
217*552f7358SJed Brown       ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr);
218*552f7358SJed Brown       ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr);
219*552f7358SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr);
220*552f7358SJed Brown       for (d = 0; d < dof; ++d) {
221*552f7358SJed Brown         if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);}
222*552f7358SJed Brown         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%G", scale*PetscRealPart(coords[off+d]));CHKERRQ(ierr);
223*552f7358SJed Brown       }
224*552f7358SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", v, rank, colors[rank%numColors], v);CHKERRQ(ierr);
225*552f7358SJed Brown     }
226*552f7358SJed Brown     ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr);
227*552f7358SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
228*552f7358SJed Brown     ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr);
229*552f7358SJed Brown     /* Plot edges */
230*552f7358SJed Brown     ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr);
231*552f7358SJed Brown     ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr);
232*552f7358SJed Brown     if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);}
233*552f7358SJed Brown     for(e = eStart; e < eEnd; ++e) {
234*552f7358SJed Brown       const PetscInt *cone;
235*552f7358SJed Brown       PetscInt        coneSize, offA, offB, dof, d;
236*552f7358SJed Brown 
237*552f7358SJed Brown       ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr);
238*552f7358SJed Brown       if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Edge %d cone should have two vertices, not %d", e, coneSize);
239*552f7358SJed Brown       ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr);
240*552f7358SJed Brown       ierr = PetscSectionGetDof(coordSection, cone[0], &dof);CHKERRQ(ierr);
241*552f7358SJed Brown       ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr);
242*552f7358SJed Brown       ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr);
243*552f7358SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr);
244*552f7358SJed Brown       for (d = 0; d < dof; ++d) {
245*552f7358SJed Brown         if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);}
246*552f7358SJed Brown         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%G", scale*0.5*PetscRealPart(coords[offA+d]+coords[offB+d]));CHKERRQ(ierr);
247*552f7358SJed Brown       }
248*552f7358SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", e, rank, colors[rank%numColors], e);CHKERRQ(ierr);
249*552f7358SJed Brown     }
250*552f7358SJed Brown     ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr);
251*552f7358SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
252*552f7358SJed Brown     ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr);
253*552f7358SJed Brown     /* Plot cells */
254*552f7358SJed Brown     ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
255*552f7358SJed Brown     for(c = cStart; c < cEnd; ++c) {
256*552f7358SJed Brown       PetscInt *closure = PETSC_NULL;
257*552f7358SJed Brown       PetscInt  closureSize, firstPoint = -1;
258*552f7358SJed Brown 
259*552f7358SJed Brown       ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
260*552f7358SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]);CHKERRQ(ierr);
261*552f7358SJed Brown       for (p = 0; p < closureSize*2; p += 2) {
262*552f7358SJed Brown         const PetscInt point = closure[p];
263*552f7358SJed Brown 
264*552f7358SJed Brown         if ((point < vStart) || (point >= vEnd)) continue;
265*552f7358SJed Brown         if (firstPoint >= 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- ");CHKERRQ(ierr);}
266*552f7358SJed Brown         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%D)", point, rank);CHKERRQ(ierr);
267*552f7358SJed Brown         if (firstPoint < 0) firstPoint = point;
268*552f7358SJed Brown       }
269*552f7358SJed Brown       /* Why doesn't this work? ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- cycle;\n");CHKERRQ(ierr); */
270*552f7358SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%D);\n", firstPoint, rank);CHKERRQ(ierr);
271*552f7358SJed Brown       ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
272*552f7358SJed Brown     }
273*552f7358SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
274*552f7358SJed Brown     ierr = PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n\\end{center}\n");CHKERRQ(ierr);
275*552f7358SJed Brown     ierr = PetscViewerASCIIPrintf(viewer, "Mesh for process ");CHKERRQ(ierr);
276*552f7358SJed Brown     for(p = 0; p < size; ++p) {
277*552f7358SJed Brown       if (p > 0 && p == size-1) {
278*552f7358SJed Brown         ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr);
279*552f7358SJed Brown       } else if (p > 0) {
280*552f7358SJed Brown         ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr);
281*552f7358SJed Brown       }
282*552f7358SJed Brown       ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr);
283*552f7358SJed Brown     }
284*552f7358SJed Brown     ierr = PetscViewerASCIIPrintf(viewer, ".\n");CHKERRQ(ierr);
285*552f7358SJed Brown     ierr = PetscViewerASCIIPrintf(viewer, "\\end{changemargin}\n\
286*552f7358SJed Brown \\end{document}\n", name);CHKERRQ(ierr);
287*552f7358SJed Brown   } else {
288*552f7358SJed Brown     MPI_Comm    comm = ((PetscObject) dm)->comm;
289*552f7358SJed Brown     PetscInt   *sizes;
290*552f7358SJed Brown     PetscInt    locDepth, depth, dim, d;
291*552f7358SJed Brown     PetscInt    pStart, pEnd, p;
292*552f7358SJed Brown     PetscMPIInt size;
293*552f7358SJed Brown 
294*552f7358SJed Brown     ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
295*552f7358SJed Brown     ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
296*552f7358SJed Brown     ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimensions:\n", dim);CHKERRQ(ierr);
297*552f7358SJed Brown     ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr);
298*552f7358SJed Brown     ierr = MPI_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr);
299*552f7358SJed Brown     ierr = PetscMalloc(size * sizeof(PetscInt), &sizes);CHKERRQ(ierr);
300*552f7358SJed Brown     if (depth == 1) {
301*552f7358SJed Brown       ierr = DMPlexGetDepthStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr);
302*552f7358SJed Brown       pEnd = pEnd - pStart;
303*552f7358SJed Brown       ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr);
304*552f7358SJed Brown       ierr = PetscViewerASCIIPrintf(viewer, "  %D-cells:", 0);CHKERRQ(ierr);
305*552f7358SJed Brown       for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);}
306*552f7358SJed Brown       ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr);
307*552f7358SJed Brown       ierr = DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr);
308*552f7358SJed Brown       pEnd = pEnd - pStart;
309*552f7358SJed Brown       ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr);
310*552f7358SJed Brown       ierr = PetscViewerASCIIPrintf(viewer, "  %D-cells:", dim);CHKERRQ(ierr);
311*552f7358SJed Brown       for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);}
312*552f7358SJed Brown       ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr);
313*552f7358SJed Brown     } else {
314*552f7358SJed Brown       for (d = 0; d <= dim; d++) {
315*552f7358SJed Brown         ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr);
316*552f7358SJed Brown         pEnd = pEnd - pStart;
317*552f7358SJed Brown         ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr);
318*552f7358SJed Brown         ierr = PetscViewerASCIIPrintf(viewer, "  %D-cells:", d);CHKERRQ(ierr);
319*552f7358SJed Brown         for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);}
320*552f7358SJed Brown         ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr);
321*552f7358SJed Brown       }
322*552f7358SJed Brown     }
323*552f7358SJed Brown     ierr = PetscFree(sizes);CHKERRQ(ierr);
324*552f7358SJed Brown   }
325*552f7358SJed Brown   PetscFunctionReturn(0);
326*552f7358SJed Brown }
327*552f7358SJed Brown 
328*552f7358SJed Brown #undef __FUNCT__
329*552f7358SJed Brown #define __FUNCT__ "DMView_Plex"
330*552f7358SJed Brown PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer)
331*552f7358SJed Brown {
332*552f7358SJed Brown   PetscBool      iascii, isbinary;
333*552f7358SJed Brown   PetscErrorCode ierr;
334*552f7358SJed Brown 
335*552f7358SJed Brown   PetscFunctionBegin;
336*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
337*552f7358SJed Brown   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
338*552f7358SJed Brown   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
339*552f7358SJed Brown   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERBINARY, &isbinary);CHKERRQ(ierr);
340*552f7358SJed Brown   if (iascii) {
341*552f7358SJed Brown     ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr);
342*552f7358SJed Brown #if 0
343*552f7358SJed Brown   } else if (isbinary) {
344*552f7358SJed Brown     ierr = DMPlexView_Binary(dm, viewer);CHKERRQ(ierr);
345*552f7358SJed Brown #endif
346*552f7358SJed Brown   } else SETERRQ1(((PetscObject)viewer)->comm,PETSC_ERR_SUP,"Viewer type %s not supported by this mesh object", ((PetscObject)viewer)->type_name);
347*552f7358SJed Brown   PetscFunctionReturn(0);
348*552f7358SJed Brown }
349*552f7358SJed Brown 
350*552f7358SJed Brown #undef __FUNCT__
351*552f7358SJed Brown #define __FUNCT__ "DMDestroy_Plex"
352*552f7358SJed Brown PetscErrorCode DMDestroy_Plex(DM dm)
353*552f7358SJed Brown {
354*552f7358SJed Brown   DM_Plex    *mesh = (DM_Plex *) dm->data;
355*552f7358SJed Brown   DMLabel        next = mesh->labels;
356*552f7358SJed Brown   PetscErrorCode ierr;
357*552f7358SJed Brown 
358*552f7358SJed Brown   PetscFunctionBegin;
359*552f7358SJed Brown   if (--mesh->refct > 0) {PetscFunctionReturn(0);}
360*552f7358SJed Brown   ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr);
361*552f7358SJed Brown   ierr = PetscFree(mesh->cones);CHKERRQ(ierr);
362*552f7358SJed Brown   ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr);
363*552f7358SJed Brown   ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr);
364*552f7358SJed Brown   ierr = PetscFree(mesh->supports);CHKERRQ(ierr);
365*552f7358SJed Brown   ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr);
366*552f7358SJed Brown   while(next) {
367*552f7358SJed Brown     DMLabel tmp = next->next;
368*552f7358SJed Brown 
369*552f7358SJed Brown     ierr = DMLabelDestroy(&next);CHKERRQ(ierr);
370*552f7358SJed Brown     next = tmp;
371*552f7358SJed Brown   }
372*552f7358SJed Brown   ierr = ISDestroy(&mesh->subpointMap);CHKERRQ(ierr);
373*552f7358SJed Brown   ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr);
374*552f7358SJed Brown   ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr);
375*552f7358SJed Brown   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
376*552f7358SJed Brown   ierr = PetscFree(mesh);CHKERRQ(ierr);
377*552f7358SJed Brown   PetscFunctionReturn(0);
378*552f7358SJed Brown }
379*552f7358SJed Brown 
380*552f7358SJed Brown #undef __FUNCT__
381*552f7358SJed Brown #define __FUNCT__ "DMPlexGetAdjacencySingleLevel_Private"
382*552f7358SJed Brown PetscErrorCode DMPlexGetAdjacencySingleLevel_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[])
383*552f7358SJed Brown {
384*552f7358SJed Brown   const PetscInt *support = PETSC_NULL;
385*552f7358SJed Brown   PetscInt        numAdj  = 0, maxAdjSize = *adjSize, supportSize, s;
386*552f7358SJed Brown   PetscErrorCode  ierr;
387*552f7358SJed Brown 
388*552f7358SJed Brown   PetscFunctionBegin;
389*552f7358SJed Brown   if (useClosure) {
390*552f7358SJed Brown     ierr = DMPlexGetConeSize(dm, p, &supportSize);CHKERRQ(ierr);
391*552f7358SJed Brown     ierr = DMPlexGetCone(dm, p, &support);CHKERRQ(ierr);
392*552f7358SJed Brown     for (s = 0; s < supportSize; ++s) {
393*552f7358SJed Brown       const PetscInt *cone = PETSC_NULL;
394*552f7358SJed Brown       PetscInt        coneSize, c, q;
395*552f7358SJed Brown 
396*552f7358SJed Brown       ierr = DMPlexGetSupportSize(dm, support[s], &coneSize);CHKERRQ(ierr);
397*552f7358SJed Brown       ierr = DMPlexGetSupport(dm, support[s], &cone);CHKERRQ(ierr);
398*552f7358SJed Brown       for (c = 0; c < coneSize; ++c) {
399*552f7358SJed Brown         for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) {
400*552f7358SJed Brown           if (cone[c] == adj[q]) break;
401*552f7358SJed Brown         }
402*552f7358SJed Brown         if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize);
403*552f7358SJed Brown       }
404*552f7358SJed Brown     }
405*552f7358SJed Brown   } else {
406*552f7358SJed Brown     ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr);
407*552f7358SJed Brown     ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr);
408*552f7358SJed Brown     for (s = 0; s < supportSize; ++s) {
409*552f7358SJed Brown       const PetscInt *cone = PETSC_NULL;
410*552f7358SJed Brown       PetscInt        coneSize, c, q;
411*552f7358SJed Brown 
412*552f7358SJed Brown       ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
413*552f7358SJed Brown       ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
414*552f7358SJed Brown       for (c = 0; c < coneSize; ++c) {
415*552f7358SJed Brown         for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) {
416*552f7358SJed Brown           if (cone[c] == adj[q]) break;
417*552f7358SJed Brown         }
418*552f7358SJed Brown         if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize);
419*552f7358SJed Brown       }
420*552f7358SJed Brown     }
421*552f7358SJed Brown   }
422*552f7358SJed Brown   *adjSize = numAdj;
423*552f7358SJed Brown   PetscFunctionReturn(0);
424*552f7358SJed Brown }
425*552f7358SJed Brown 
426*552f7358SJed Brown #undef __FUNCT__
427*552f7358SJed Brown #define __FUNCT__ "DMPlexGetAdjacency_Private"
428*552f7358SJed Brown PetscErrorCode DMPlexGetAdjacency_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[])
429*552f7358SJed Brown {
430*552f7358SJed Brown   const PetscInt *star   = tmpClosure;
431*552f7358SJed Brown   PetscInt        numAdj = 0, maxAdjSize = *adjSize, starSize, s;
432*552f7358SJed Brown   PetscErrorCode  ierr;
433*552f7358SJed Brown 
434*552f7358SJed Brown   PetscFunctionBegin;
435*552f7358SJed Brown   ierr = DMPlexGetTransitiveClosure(dm, p, useClosure, &starSize, (PetscInt **) &star);CHKERRQ(ierr);
436*552f7358SJed Brown   for (s = 2; s < starSize*2; s += 2) {
437*552f7358SJed Brown     const PetscInt *closure = PETSC_NULL;
438*552f7358SJed Brown     PetscInt        closureSize, c, q;
439*552f7358SJed Brown 
440*552f7358SJed Brown     ierr = DMPlexGetTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt **) &closure);CHKERRQ(ierr);
441*552f7358SJed Brown     for (c = 0; c < closureSize*2; c += 2) {
442*552f7358SJed Brown       for (q = 0; q < numAdj || (adj[numAdj++] = closure[c],0); ++q) {
443*552f7358SJed Brown         if (closure[c] == adj[q]) break;
444*552f7358SJed Brown       }
445*552f7358SJed Brown       if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize);
446*552f7358SJed Brown     }
447*552f7358SJed Brown     ierr = DMPlexRestoreTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt **) &closure);CHKERRQ(ierr);
448*552f7358SJed Brown   }
449*552f7358SJed Brown   *adjSize = numAdj;
450*552f7358SJed Brown   PetscFunctionReturn(0);
451*552f7358SJed Brown }
452*552f7358SJed Brown 
453*552f7358SJed Brown #undef __FUNCT__
454*552f7358SJed Brown #define __FUNCT__ "DMPlexSetPreallocationCenterDimension"
455*552f7358SJed Brown PetscErrorCode DMPlexSetPreallocationCenterDimension(DM dm, PetscInt preallocCenterDim)
456*552f7358SJed Brown {
457*552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *) dm->data;
458*552f7358SJed Brown 
459*552f7358SJed Brown   PetscFunctionBegin;
460*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
461*552f7358SJed Brown   mesh->preallocCenterDim = preallocCenterDim;
462*552f7358SJed Brown   PetscFunctionReturn(0);
463*552f7358SJed Brown }
464*552f7358SJed Brown 
465*552f7358SJed Brown #undef __FUNCT__
466*552f7358SJed Brown #define __FUNCT__ "DMPlexPreallocateOperator"
467*552f7358SJed Brown PetscErrorCode DMPlexPreallocateOperator(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix)
468*552f7358SJed Brown {
469*552f7358SJed Brown   DM_Plex        *mesh = (DM_Plex *) dm->data;
470*552f7358SJed Brown   MPI_Comm           comm = ((PetscObject) dm)->comm;
471*552f7358SJed Brown   PetscSF            sf, sfDof, sfAdj;
472*552f7358SJed Brown   PetscSection       leafSectionAdj, rootSectionAdj, sectionAdj;
473*552f7358SJed Brown   PetscInt           nleaves, l, p;
474*552f7358SJed Brown   const PetscInt    *leaves;
475*552f7358SJed Brown   const PetscSFNode *remotes;
476*552f7358SJed Brown   PetscInt           dim, pStart, pEnd, numDof, globalOffStart, globalOffEnd, numCols;
477*552f7358SJed Brown   PetscInt          *tmpClosure, *tmpAdj, *adj, *rootAdj, *cols, *remoteOffsets;
478*552f7358SJed Brown   PetscInt           depth, maxConeSize, maxSupportSize, maxClosureSize, maxAdjSize, adjSize;
479*552f7358SJed Brown   PetscLayout        rLayout;
480*552f7358SJed Brown   PetscInt           locRows, rStart, rEnd, r;
481*552f7358SJed Brown   PetscMPIInt        size;
482*552f7358SJed Brown   PetscBool          useClosure, debug = PETSC_FALSE;
483*552f7358SJed Brown   PetscErrorCode     ierr;
484*552f7358SJed Brown 
485*552f7358SJed Brown   PetscFunctionBegin;
486*552f7358SJed Brown   ierr = PetscOptionsGetBool(PETSC_NULL, "-dm_view_preallocation", &debug, PETSC_NULL);CHKERRQ(ierr);
487*552f7358SJed Brown   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
488*552f7358SJed Brown   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
489*552f7358SJed Brown   ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr);
490*552f7358SJed Brown   /* Create dof SF based on point SF */
491*552f7358SJed Brown   if (debug) {
492*552f7358SJed Brown     ierr = PetscPrintf(comm, "Input Section for Preallocation:\n");CHKERRQ(ierr);
493*552f7358SJed Brown     ierr = PetscSectionView(section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
494*552f7358SJed Brown     ierr = PetscPrintf(comm, "Input Global Section for Preallocation:\n");CHKERRQ(ierr);
495*552f7358SJed Brown     ierr = PetscSectionView(sectionGlobal, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
496*552f7358SJed Brown     ierr = PetscPrintf(comm, "Input SF for Preallocation:\n");CHKERRQ(ierr);
497*552f7358SJed Brown     ierr = PetscSFView(sf, PETSC_NULL);CHKERRQ(ierr);
498*552f7358SJed Brown   }
499*552f7358SJed Brown   ierr = PetscSFCreateRemoteOffsets(sf, section, section, &remoteOffsets);CHKERRQ(ierr);
500*552f7358SJed Brown   ierr = PetscSFCreateSectionSF(sf, section, remoteOffsets, section, &sfDof);CHKERRQ(ierr);
501*552f7358SJed Brown   if (debug) {
502*552f7358SJed Brown     ierr = PetscPrintf(comm, "Dof SF for Preallocation:\n");CHKERRQ(ierr);
503*552f7358SJed Brown     ierr = PetscSFView(sfDof, PETSC_NULL);CHKERRQ(ierr);
504*552f7358SJed Brown   }
505*552f7358SJed Brown   /* Create section for dof adjacency (dof ==> # adj dof) */
506*552f7358SJed Brown   /*   FEM:   Two points p and q are adjacent if q \in closure(star(p)), preallocCenterDim = dim   */
507*552f7358SJed Brown   /*   FVM:   Two points p and q are adjacent if q \in star(cone(p)),    preallocCenterDim = dim-1 */
508*552f7358SJed Brown   /*   FVM++: Two points p and q are adjacent if q \in star(closure(p)), preallocCenterDim = 0     */
509*552f7358SJed Brown   if (mesh->preallocCenterDim == dim) {
510*552f7358SJed Brown     useClosure = PETSC_FALSE;
511*552f7358SJed Brown   } else if (mesh->preallocCenterDim == 0) {
512*552f7358SJed Brown     useClosure = PETSC_TRUE;
513*552f7358SJed Brown   } else SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Do not support preallocation with center points of dimension %d", mesh->preallocCenterDim);
514*552f7358SJed Brown 
515*552f7358SJed Brown   ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr);
516*552f7358SJed Brown   ierr = PetscSectionGetStorageSize(section, &numDof);CHKERRQ(ierr);
517*552f7358SJed Brown   ierr = PetscSectionCreate(comm, &leafSectionAdj);CHKERRQ(ierr);
518*552f7358SJed Brown   ierr = PetscSectionSetChart(leafSectionAdj, 0, numDof);CHKERRQ(ierr);
519*552f7358SJed Brown   ierr = PetscSectionCreate(comm, &rootSectionAdj);CHKERRQ(ierr);
520*552f7358SJed Brown   ierr = PetscSectionSetChart(rootSectionAdj, 0, numDof);CHKERRQ(ierr);
521*552f7358SJed Brown   /*   Fill in the ghost dofs on the interface */
522*552f7358SJed Brown   ierr = PetscSFGetGraph(sf, PETSC_NULL, &nleaves, &leaves, &remotes);CHKERRQ(ierr);
523*552f7358SJed Brown   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
524*552f7358SJed Brown   ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr);
525*552f7358SJed Brown   maxClosureSize = (PetscInt) (2*PetscMax(pow((PetscReal) mesh->maxConeSize, depth)+1, pow((PetscReal) mesh->maxSupportSize, depth)+1));
526*552f7358SJed Brown   maxAdjSize     = (PetscInt) (pow((PetscReal) mesh->maxConeSize, depth)*pow((PetscReal) mesh->maxSupportSize, depth)+1);
527*552f7358SJed Brown   ierr = PetscMalloc2(maxClosureSize,PetscInt,&tmpClosure,maxAdjSize,PetscInt,&tmpAdj);CHKERRQ(ierr);
528*552f7358SJed Brown 
529*552f7358SJed Brown   /*
530*552f7358SJed Brown    ** The bootstrapping process involves six rounds with similar structure of visiting neighbors of each point.
531*552f7358SJed Brown     1. Visit unowned points on interface, count adjacencies placing in leafSectionAdj
532*552f7358SJed Brown        Reduce those counts to rootSectionAdj (now redundantly counting some interface points)
533*552f7358SJed Brown     2. Visit owned points on interface, count adjacencies placing in rootSectionAdj
534*552f7358SJed Brown        Create sfAdj connecting rootSectionAdj and leafSectionAdj
535*552f7358SJed Brown     3. Visit unowned points on interface, write adjacencies to adj
536*552f7358SJed Brown        Gather adj to rootAdj (note that there is redundancy in rootAdj when multiple procs find the same adjacencies)
537*552f7358SJed Brown     4. Visit owned points on interface, write adjacencies to rootAdj
538*552f7358SJed Brown        Remove redundancy in rootAdj
539*552f7358SJed Brown    ** The last two traversals use transitive closure
540*552f7358SJed Brown     5. Visit all owned points in the subdomain, count dofs for each point (sectionAdj)
541*552f7358SJed Brown        Allocate memory addressed by sectionAdj (cols)
542*552f7358SJed Brown     6. Visit all owned points in the subdomain, insert dof adjacencies into cols
543*552f7358SJed Brown    ** Knowing all the column adjacencies, check ownership and sum into dnz and onz
544*552f7358SJed Brown   */
545*552f7358SJed Brown 
546*552f7358SJed Brown   for (l = 0; l < nleaves; ++l) {
547*552f7358SJed Brown     PetscInt dof, off, d, q;
548*552f7358SJed Brown     PetscInt p = leaves[l], numAdj = maxAdjSize;
549*552f7358SJed Brown 
550*552f7358SJed Brown     ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr);
551*552f7358SJed Brown     ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr);
552*552f7358SJed Brown     ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr);
553*552f7358SJed Brown     for (q = 0; q < numAdj; ++q) {
554*552f7358SJed Brown       PetscInt ndof, ncdof;
555*552f7358SJed Brown 
556*552f7358SJed Brown       ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr);
557*552f7358SJed Brown       ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr);
558*552f7358SJed Brown       for (d = off; d < off+dof; ++d) {
559*552f7358SJed Brown         ierr = PetscSectionAddDof(leafSectionAdj, d, ndof-ncdof);CHKERRQ(ierr);
560*552f7358SJed Brown       }
561*552f7358SJed Brown     }
562*552f7358SJed Brown   }
563*552f7358SJed Brown   ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr);
564*552f7358SJed Brown   if (debug) {
565*552f7358SJed Brown     ierr = PetscPrintf(comm, "Adjacency Section for Preallocation on Leaves:\n");CHKERRQ(ierr);
566*552f7358SJed Brown     ierr = PetscSectionView(leafSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
567*552f7358SJed Brown   }
568*552f7358SJed Brown   /* Get maximum remote adjacency sizes for owned dofs on interface (roots) */
569*552f7358SJed Brown   if (size > 1) {
570*552f7358SJed Brown     ierr = PetscSFReduceBegin(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr);
571*552f7358SJed Brown     ierr = PetscSFReduceEnd(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr);
572*552f7358SJed Brown   }
573*552f7358SJed Brown   if (debug) {
574*552f7358SJed Brown     ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots:\n");CHKERRQ(ierr);
575*552f7358SJed Brown     ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
576*552f7358SJed Brown   }
577*552f7358SJed Brown   /* Add in local adjacency sizes for owned dofs on interface (roots) */
578*552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
579*552f7358SJed Brown     PetscInt numAdj = maxAdjSize, adof, dof, off, d, q;
580*552f7358SJed Brown 
581*552f7358SJed Brown     ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr);
582*552f7358SJed Brown     ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr);
583*552f7358SJed Brown     if (!dof) continue;
584*552f7358SJed Brown     ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr);
585*552f7358SJed Brown     if (adof <= 0) continue;
586*552f7358SJed Brown     ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr);
587*552f7358SJed Brown     for (q = 0; q < numAdj; ++q) {
588*552f7358SJed Brown       PetscInt ndof, ncdof;
589*552f7358SJed Brown 
590*552f7358SJed Brown       ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr);
591*552f7358SJed Brown       ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr);
592*552f7358SJed Brown       for (d = off; d < off+dof; ++d) {
593*552f7358SJed Brown         ierr = PetscSectionAddDof(rootSectionAdj, d, ndof-ncdof);CHKERRQ(ierr);
594*552f7358SJed Brown       }
595*552f7358SJed Brown     }
596*552f7358SJed Brown   }
597*552f7358SJed Brown   ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr);
598*552f7358SJed Brown   if (debug) {
599*552f7358SJed Brown     ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after local additions:\n");CHKERRQ(ierr);
600*552f7358SJed Brown     ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
601*552f7358SJed Brown   }
602*552f7358SJed Brown   /* Create adj SF based on dof SF */
603*552f7358SJed Brown   ierr = PetscSFCreateRemoteOffsets(sfDof, rootSectionAdj, leafSectionAdj, &remoteOffsets);CHKERRQ(ierr);
604*552f7358SJed Brown   ierr = PetscSFCreateSectionSF(sfDof, rootSectionAdj, remoteOffsets, leafSectionAdj, &sfAdj);CHKERRQ(ierr);
605*552f7358SJed Brown   if (debug) {
606*552f7358SJed Brown     ierr = PetscPrintf(comm, "Adjacency SF for Preallocation:\n");CHKERRQ(ierr);
607*552f7358SJed Brown     ierr = PetscSFView(sfAdj, PETSC_NULL);CHKERRQ(ierr);
608*552f7358SJed Brown   }
609*552f7358SJed Brown   ierr = PetscSFDestroy(&sfDof);CHKERRQ(ierr);
610*552f7358SJed Brown   /* Create leaf adjacency */
611*552f7358SJed Brown   ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr);
612*552f7358SJed Brown   ierr = PetscSectionGetStorageSize(leafSectionAdj, &adjSize);CHKERRQ(ierr);
613*552f7358SJed Brown   ierr = PetscMalloc(adjSize * sizeof(PetscInt), &adj);CHKERRQ(ierr);
614*552f7358SJed Brown   ierr = PetscMemzero(adj, adjSize * sizeof(PetscInt));CHKERRQ(ierr);
615*552f7358SJed Brown   for (l = 0; l < nleaves; ++l) {
616*552f7358SJed Brown     PetscInt dof, off, d, q;
617*552f7358SJed Brown     PetscInt p = leaves[l], numAdj = maxAdjSize;
618*552f7358SJed Brown 
619*552f7358SJed Brown     ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr);
620*552f7358SJed Brown     ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr);
621*552f7358SJed Brown     ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr);
622*552f7358SJed Brown     for (d = off; d < off+dof; ++d) {
623*552f7358SJed Brown       PetscInt aoff, i = 0;
624*552f7358SJed Brown 
625*552f7358SJed Brown       ierr = PetscSectionGetOffset(leafSectionAdj, d, &aoff);CHKERRQ(ierr);
626*552f7358SJed Brown       for (q = 0; q < numAdj; ++q) {
627*552f7358SJed Brown         PetscInt  ndof, ncdof, ngoff, nd;
628*552f7358SJed Brown 
629*552f7358SJed Brown         ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr);
630*552f7358SJed Brown         ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr);
631*552f7358SJed Brown         ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr);
632*552f7358SJed Brown         for (nd = 0; nd < ndof-ncdof; ++nd) {
633*552f7358SJed Brown           adj[aoff+i] = (ngoff < 0 ? -(ngoff+1) : ngoff) + nd;
634*552f7358SJed Brown           ++i;
635*552f7358SJed Brown         }
636*552f7358SJed Brown       }
637*552f7358SJed Brown     }
638*552f7358SJed Brown   }
639*552f7358SJed Brown   /* Debugging */
640*552f7358SJed Brown   if (debug) {
641*552f7358SJed Brown     IS tmp;
642*552f7358SJed Brown     ierr = PetscPrintf(comm, "Leaf adjacency indices\n");CHKERRQ(ierr);
643*552f7358SJed Brown     ierr = ISCreateGeneral(comm, adjSize, adj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr);
644*552f7358SJed Brown     ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr);
645*552f7358SJed Brown   }
646*552f7358SJed Brown   /* Gather adjacenct indices to root */
647*552f7358SJed Brown   ierr = PetscSectionGetStorageSize(rootSectionAdj, &adjSize);CHKERRQ(ierr);
648*552f7358SJed Brown   ierr = PetscMalloc(adjSize * sizeof(PetscInt), &rootAdj);CHKERRQ(ierr);
649*552f7358SJed Brown   for (r = 0; r < adjSize; ++r) {
650*552f7358SJed Brown     rootAdj[r] = -1;
651*552f7358SJed Brown   }
652*552f7358SJed Brown   if (size > 1) {
653*552f7358SJed Brown     ierr = PetscSFGatherBegin(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr);
654*552f7358SJed Brown     ierr = PetscSFGatherEnd(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr);
655*552f7358SJed Brown   }
656*552f7358SJed Brown   ierr = PetscSFDestroy(&sfAdj);CHKERRQ(ierr);
657*552f7358SJed Brown   ierr = PetscFree(adj);CHKERRQ(ierr);
658*552f7358SJed Brown   /* Debugging */
659*552f7358SJed Brown   if (debug) {
660*552f7358SJed Brown     IS tmp;
661*552f7358SJed Brown     ierr = PetscPrintf(comm, "Root adjacency indices after gather\n");CHKERRQ(ierr);
662*552f7358SJed Brown     ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr);
663*552f7358SJed Brown     ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr);
664*552f7358SJed Brown   }
665*552f7358SJed Brown   /* Add in local adjacency indices for owned dofs on interface (roots) */
666*552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
667*552f7358SJed Brown     PetscInt numAdj = maxAdjSize, adof, dof, off, d, q;
668*552f7358SJed Brown 
669*552f7358SJed Brown     ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr);
670*552f7358SJed Brown     ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr);
671*552f7358SJed Brown     if (!dof) continue;
672*552f7358SJed Brown     ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr);
673*552f7358SJed Brown     if (adof <= 0) continue;
674*552f7358SJed Brown     ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr);
675*552f7358SJed Brown     for (d = off; d < off+dof; ++d) {
676*552f7358SJed Brown       PetscInt adof, aoff, i;
677*552f7358SJed Brown 
678*552f7358SJed Brown       ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr);
679*552f7358SJed Brown       ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr);
680*552f7358SJed Brown       i    = adof-1;
681*552f7358SJed Brown       for (q = 0; q < numAdj; ++q) {
682*552f7358SJed Brown         PetscInt ndof, ncdof, ngoff, nd;
683*552f7358SJed Brown 
684*552f7358SJed Brown         ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr);
685*552f7358SJed Brown         ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr);
686*552f7358SJed Brown         ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr);
687*552f7358SJed Brown         for (nd = 0; nd < ndof-ncdof; ++nd) {
688*552f7358SJed Brown           rootAdj[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd: ngoff+nd;
689*552f7358SJed Brown           --i;
690*552f7358SJed Brown         }
691*552f7358SJed Brown       }
692*552f7358SJed Brown     }
693*552f7358SJed Brown   }
694*552f7358SJed Brown   /* Debugging */
695*552f7358SJed Brown   if (debug) {
696*552f7358SJed Brown     IS tmp;
697*552f7358SJed Brown     ierr = PetscPrintf(comm, "Root adjacency indices\n");CHKERRQ(ierr);
698*552f7358SJed Brown     ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr);
699*552f7358SJed Brown     ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr);
700*552f7358SJed Brown   }
701*552f7358SJed Brown   /* Compress indices */
702*552f7358SJed Brown   ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr);
703*552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
704*552f7358SJed Brown     PetscInt dof, cdof, off, d;
705*552f7358SJed Brown     PetscInt adof, aoff;
706*552f7358SJed Brown 
707*552f7358SJed Brown     ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr);
708*552f7358SJed Brown     ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr);
709*552f7358SJed Brown     ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr);
710*552f7358SJed Brown     if (!dof) continue;
711*552f7358SJed Brown     ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr);
712*552f7358SJed Brown     if (adof <= 0) continue;
713*552f7358SJed Brown     for (d = off; d < off+dof-cdof; ++d) {
714*552f7358SJed Brown       ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr);
715*552f7358SJed Brown       ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr);
716*552f7358SJed Brown       ierr = PetscSortRemoveDupsInt(&adof, &rootAdj[aoff]);CHKERRQ(ierr);
717*552f7358SJed Brown       ierr = PetscSectionSetDof(rootSectionAdj, d, adof);CHKERRQ(ierr);
718*552f7358SJed Brown     }
719*552f7358SJed Brown   }
720*552f7358SJed Brown   /* Debugging */
721*552f7358SJed Brown   if (debug) {
722*552f7358SJed Brown     IS tmp;
723*552f7358SJed Brown     ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after compression:\n");CHKERRQ(ierr);
724*552f7358SJed Brown     ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
725*552f7358SJed Brown     ierr = PetscPrintf(comm, "Root adjacency indices after compression\n");CHKERRQ(ierr);
726*552f7358SJed Brown     ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr);
727*552f7358SJed Brown     ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr);
728*552f7358SJed Brown   }
729*552f7358SJed Brown   /* Build adjacency section: Maps global indices to sets of adjacent global indices */
730*552f7358SJed Brown   ierr = PetscSectionGetOffsetRange(sectionGlobal, &globalOffStart, &globalOffEnd);CHKERRQ(ierr);
731*552f7358SJed Brown   ierr = PetscSectionCreate(comm, &sectionAdj);CHKERRQ(ierr);
732*552f7358SJed Brown   ierr = PetscSectionSetChart(sectionAdj, globalOffStart, globalOffEnd);CHKERRQ(ierr);
733*552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
734*552f7358SJed Brown     PetscInt  numAdj = maxAdjSize, dof, cdof, off, goff, d, q;
735*552f7358SJed Brown     PetscBool found  = PETSC_TRUE;
736*552f7358SJed Brown 
737*552f7358SJed Brown     ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr);
738*552f7358SJed Brown     ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr);
739*552f7358SJed Brown     ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr);
740*552f7358SJed Brown     ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr);
741*552f7358SJed Brown     for (d = 0; d < dof-cdof; ++d) {
742*552f7358SJed Brown       PetscInt ldof, rdof;
743*552f7358SJed Brown 
744*552f7358SJed Brown       ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr);
745*552f7358SJed Brown       ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr);
746*552f7358SJed Brown       if (ldof > 0) {
747*552f7358SJed Brown         /* We do not own this point */
748*552f7358SJed Brown       } else if (rdof > 0) {
749*552f7358SJed Brown         ierr = PetscSectionSetDof(sectionAdj, goff+d, rdof);CHKERRQ(ierr);
750*552f7358SJed Brown       } else {
751*552f7358SJed Brown         found = PETSC_FALSE;
752*552f7358SJed Brown       }
753*552f7358SJed Brown     }
754*552f7358SJed Brown     if (found) continue;
755*552f7358SJed Brown     ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr);
756*552f7358SJed Brown     ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr);
757*552f7358SJed Brown     ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr);
758*552f7358SJed Brown     for (q = 0; q < numAdj; ++q) {
759*552f7358SJed Brown       PetscInt ndof, ncdof, noff;
760*552f7358SJed Brown 
761*552f7358SJed Brown       /* Adjacent points may not be in the section chart */
762*552f7358SJed Brown       if ((tmpAdj[q] < pStart) || (tmpAdj[q] >= pEnd)) continue;
763*552f7358SJed Brown       ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr);
764*552f7358SJed Brown       ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr);
765*552f7358SJed Brown       ierr = PetscSectionGetOffset(section, tmpAdj[q], &noff);CHKERRQ(ierr);
766*552f7358SJed Brown       for (d = goff; d < goff+dof-cdof; ++d) {
767*552f7358SJed Brown         ierr = PetscSectionAddDof(sectionAdj, d, ndof-ncdof);CHKERRQ(ierr);
768*552f7358SJed Brown       }
769*552f7358SJed Brown     }
770*552f7358SJed Brown   }
771*552f7358SJed Brown   ierr = PetscSectionSetUp(sectionAdj);CHKERRQ(ierr);
772*552f7358SJed Brown   if (debug) {
773*552f7358SJed Brown     ierr = PetscPrintf(comm, "Adjacency Section for Preallocation:\n");CHKERRQ(ierr);
774*552f7358SJed Brown     ierr = PetscSectionView(sectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
775*552f7358SJed Brown   }
776*552f7358SJed Brown   /* Get adjacent indices */
777*552f7358SJed Brown   ierr = PetscSectionGetStorageSize(sectionAdj, &numCols);CHKERRQ(ierr);
778*552f7358SJed Brown   ierr = PetscMalloc(numCols * sizeof(PetscInt), &cols);CHKERRQ(ierr);
779*552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
780*552f7358SJed Brown     PetscInt  numAdj = maxAdjSize, dof, cdof, off, goff, d, q;
781*552f7358SJed Brown     PetscBool found  = PETSC_TRUE;
782*552f7358SJed Brown 
783*552f7358SJed Brown     ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr);
784*552f7358SJed Brown     ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr);
785*552f7358SJed Brown     ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr);
786*552f7358SJed Brown     ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr);
787*552f7358SJed Brown     for (d = 0; d < dof-cdof; ++d) {
788*552f7358SJed Brown       PetscInt ldof, rdof;
789*552f7358SJed Brown 
790*552f7358SJed Brown       ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr);
791*552f7358SJed Brown       ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr);
792*552f7358SJed Brown       if (ldof > 0) {
793*552f7358SJed Brown         /* We do not own this point */
794*552f7358SJed Brown       } else if (rdof > 0) {
795*552f7358SJed Brown         PetscInt aoff, roff;
796*552f7358SJed Brown 
797*552f7358SJed Brown         ierr = PetscSectionGetOffset(sectionAdj, goff+d, &aoff);CHKERRQ(ierr);
798*552f7358SJed Brown         ierr = PetscSectionGetOffset(rootSectionAdj, off+d, &roff);CHKERRQ(ierr);
799*552f7358SJed Brown         ierr = PetscMemcpy(&cols[aoff], &rootAdj[roff], rdof * sizeof(PetscInt));CHKERRQ(ierr);
800*552f7358SJed Brown       } else {
801*552f7358SJed Brown         found = PETSC_FALSE;
802*552f7358SJed Brown       }
803*552f7358SJed Brown     }
804*552f7358SJed Brown     if (found) continue;
805*552f7358SJed Brown     ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr);
806*552f7358SJed Brown     for (d = goff; d < goff+dof-cdof; ++d) {
807*552f7358SJed Brown       PetscInt adof, aoff, i = 0;
808*552f7358SJed Brown 
809*552f7358SJed Brown       ierr = PetscSectionGetDof(sectionAdj, d, &adof);CHKERRQ(ierr);
810*552f7358SJed Brown       ierr = PetscSectionGetOffset(sectionAdj, d, &aoff);CHKERRQ(ierr);
811*552f7358SJed Brown       for (q = 0; q < numAdj; ++q) {
812*552f7358SJed Brown         PetscInt        ndof, ncdof, ngoff, nd;
813*552f7358SJed Brown         const PetscInt *ncind;
814*552f7358SJed Brown 
815*552f7358SJed Brown         /* Adjacent points may not be in the section chart */
816*552f7358SJed Brown         if ((tmpAdj[q] < pStart) || (tmpAdj[q] >= pEnd)) continue;
817*552f7358SJed Brown         ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr);
818*552f7358SJed Brown         ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr);
819*552f7358SJed Brown         ierr = PetscSectionGetConstraintIndices(section, tmpAdj[q], &ncind);CHKERRQ(ierr);
820*552f7358SJed Brown         ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr);
821*552f7358SJed Brown         for (nd = 0; nd < ndof-ncdof; ++nd, ++i) {
822*552f7358SJed Brown           cols[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd: ngoff+nd;
823*552f7358SJed Brown         }
824*552f7358SJed Brown       }
825*552f7358SJed Brown       if (i != adof) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of entries %D != %D for dof %D (point %D)", i, adof, d, p);
826*552f7358SJed Brown     }
827*552f7358SJed Brown   }
828*552f7358SJed Brown   ierr = PetscSectionDestroy(&leafSectionAdj);CHKERRQ(ierr);
829*552f7358SJed Brown   ierr = PetscSectionDestroy(&rootSectionAdj);CHKERRQ(ierr);
830*552f7358SJed Brown   ierr = PetscFree(rootAdj);CHKERRQ(ierr);
831*552f7358SJed Brown   ierr = PetscFree2(tmpClosure, tmpAdj);CHKERRQ(ierr);
832*552f7358SJed Brown   /* Debugging */
833*552f7358SJed Brown   if (debug) {
834*552f7358SJed Brown     IS tmp;
835*552f7358SJed Brown     ierr = PetscPrintf(comm, "Column indices\n");CHKERRQ(ierr);
836*552f7358SJed Brown     ierr = ISCreateGeneral(comm, numCols, cols, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr);
837*552f7358SJed Brown     ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr);
838*552f7358SJed Brown   }
839*552f7358SJed Brown   /* Create allocation vectors from adjacency graph */
840*552f7358SJed Brown   ierr = MatGetLocalSize(A, &locRows, PETSC_NULL);CHKERRQ(ierr);
841*552f7358SJed Brown   ierr = PetscLayoutCreate(((PetscObject) A)->comm, &rLayout);CHKERRQ(ierr);
842*552f7358SJed Brown   ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr);
843*552f7358SJed Brown   ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr);
844*552f7358SJed Brown   ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr);
845*552f7358SJed Brown   ierr = PetscLayoutGetRange(rLayout, &rStart, &rEnd);CHKERRQ(ierr);
846*552f7358SJed Brown   ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr);
847*552f7358SJed Brown   /* Only loop over blocks of rows */
848*552f7358SJed Brown   if (rStart%bs || rEnd%bs) SETERRQ3(((PetscObject) A)->comm, PETSC_ERR_ARG_WRONG, "Invalid layout [%d, %d) for matrix, must be divisible by block size %d", rStart, rEnd, bs);
849*552f7358SJed Brown   for (r = rStart/bs; r < rEnd/bs; ++r) {
850*552f7358SJed Brown     const PetscInt row = r*bs;
851*552f7358SJed Brown     PetscInt numCols, cStart, c;
852*552f7358SJed Brown 
853*552f7358SJed Brown     ierr = PetscSectionGetDof(sectionAdj, row, &numCols);CHKERRQ(ierr);
854*552f7358SJed Brown     ierr = PetscSectionGetOffset(sectionAdj, row, &cStart);CHKERRQ(ierr);
855*552f7358SJed Brown     for (c = cStart; c < cStart+numCols; ++c) {
856*552f7358SJed Brown       if ((cols[c] >= rStart*bs) && (cols[c] < rEnd*bs)) {
857*552f7358SJed Brown         ++dnz[r-rStart];
858*552f7358SJed Brown         if (cols[c] >= row) {++dnzu[r-rStart];}
859*552f7358SJed Brown       } else {
860*552f7358SJed Brown         ++onz[r-rStart];
861*552f7358SJed Brown         if (cols[c] >= row) {++onzu[r-rStart];}
862*552f7358SJed Brown       }
863*552f7358SJed Brown     }
864*552f7358SJed Brown   }
865*552f7358SJed Brown   if (bs > 1) {
866*552f7358SJed Brown     for (r = 0; r < locRows/bs; ++r) {
867*552f7358SJed Brown       dnz[r]  /= bs;
868*552f7358SJed Brown       onz[r]  /= bs;
869*552f7358SJed Brown       dnzu[r] /= bs;
870*552f7358SJed Brown       onzu[r] /= bs;
871*552f7358SJed Brown     }
872*552f7358SJed Brown   }
873*552f7358SJed Brown   /* Set matrix pattern */
874*552f7358SJed Brown   ierr = MatXAIJSetPreallocation(A, bs, dnz, onz, dnzu, onzu);CHKERRQ(ierr);
875*552f7358SJed Brown   ierr = MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
876*552f7358SJed Brown   /* Fill matrix with zeros */
877*552f7358SJed Brown   if (fillMatrix) {
878*552f7358SJed Brown     PetscScalar *values;
879*552f7358SJed Brown     PetscInt     maxRowLen = 0;
880*552f7358SJed Brown 
881*552f7358SJed Brown     for (r = rStart; r < rEnd; ++r) {
882*552f7358SJed Brown       PetscInt len;
883*552f7358SJed Brown 
884*552f7358SJed Brown       ierr = PetscSectionGetDof(sectionAdj, r, &len);CHKERRQ(ierr);
885*552f7358SJed Brown       maxRowLen = PetscMax(maxRowLen, len);
886*552f7358SJed Brown     }
887*552f7358SJed Brown     ierr = PetscMalloc(maxRowLen * sizeof(PetscScalar), &values);CHKERRQ(ierr);
888*552f7358SJed Brown     ierr = PetscMemzero(values, maxRowLen * sizeof(PetscScalar));CHKERRQ(ierr);
889*552f7358SJed Brown     for (r = rStart; r < rEnd; ++r) {
890*552f7358SJed Brown       PetscInt numCols, cStart;
891*552f7358SJed Brown 
892*552f7358SJed Brown       ierr = PetscSectionGetDof(sectionAdj, r, &numCols);CHKERRQ(ierr);
893*552f7358SJed Brown       ierr = PetscSectionGetOffset(sectionAdj, r, &cStart);CHKERRQ(ierr);
894*552f7358SJed Brown       ierr = MatSetValues(A, 1, &r, numCols, &cols[cStart], values, INSERT_VALUES);CHKERRQ(ierr);
895*552f7358SJed Brown     }
896*552f7358SJed Brown     ierr = PetscFree(values);CHKERRQ(ierr);
897*552f7358SJed Brown     ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
898*552f7358SJed Brown     ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
899*552f7358SJed Brown   }
900*552f7358SJed Brown   ierr = PetscSectionDestroy(&sectionAdj);CHKERRQ(ierr);
901*552f7358SJed Brown   ierr = PetscFree(cols);CHKERRQ(ierr);
902*552f7358SJed Brown   PetscFunctionReturn(0);
903*552f7358SJed Brown }
904*552f7358SJed Brown 
905*552f7358SJed Brown #if 0
906*552f7358SJed Brown #undef __FUNCT__
907*552f7358SJed Brown #define __FUNCT__ "DMPlexPreallocateOperator_2"
908*552f7358SJed Brown PetscErrorCode DMPlexPreallocateOperator_2(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix)
909*552f7358SJed Brown {
910*552f7358SJed Brown   PetscErrorCode ierr;
911*552f7358SJed Brown   PetscInt c,cStart,cEnd,pStart,pEnd;
912*552f7358SJed Brown   PetscInt *tmpClosure,*tmpAdj,*visits;
913*552f7358SJed Brown 
914*552f7358SJed Brown   PetscFunctionBegin;
915*552f7358SJed Brown   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
916*552f7358SJed Brown   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
917*552f7358SJed Brown   ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr);
918*552f7358SJed Brown   maxClosureSize = 2*PetscMax(pow(mesh->maxConeSize, depth)+1, pow(mesh->maxSupportSize, depth)+1);
919*552f7358SJed Brown   ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr);
920*552f7358SJed Brown   npoints = pEnd - pStart;
921*552f7358SJed Brown   ierr = PetscMalloc3(maxClosureSize,PetscInt,&tmpClosure,npoints,PetscInt,&lvisits,npoints,PetscInt,&visits);CHKERRQ(ierr);
922*552f7358SJed Brown   ierr = PetscMemzero(lvisits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr);
923*552f7358SJed Brown   ierr = PetscMemzero(visits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr);
924*552f7358SJed Brown   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
925*552f7358SJed Brown   for (c=cStart; c<cEnd; c++) {
926*552f7358SJed Brown     PetscInt *support = tmpClosure;
927*552f7358SJed Brown     ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_FALSE, &supportSize, (PetscInt**)&support);CHKERRQ(ierr);
928*552f7358SJed Brown     for (p=0; p<supportSize; p++) {
929*552f7358SJed Brown       lvisits[support[p]]++;
930*552f7358SJed Brown     }
931*552f7358SJed Brown   }
932*552f7358SJed Brown   ierr = PetscSFReduceBegin(sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr);
933*552f7358SJed Brown   ierr = PetscSFReduceEnd  (sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr);
934*552f7358SJed Brown   ierr = PetscSFBcastBegin(sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr);
935*552f7358SJed Brown   ierr = PetscSFBcastEnd  (sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr);
936*552f7358SJed Brown 
937*552f7358SJed Brown   ierr = PetscSFGetRanks();CHKERRQ(ierr);
938*552f7358SJed Brown 
939*552f7358SJed Brown 
940*552f7358SJed Brown   ierr = PetscMalloc2(maxClosureSize*maxClosureSize,PetscInt,&cellmat,npoints,PetscInt,&owner);CHKERRQ(ierr);
941*552f7358SJed Brown   for (c=cStart; c<cEnd; c++) {
942*552f7358SJed Brown     ierr = PetscMemzero(cellmat,maxClosureSize*maxClosureSize*sizeof(PetscInt));CHKERRQ(ierr);
943*552f7358SJed Brown     /*
944*552f7358SJed Brown      Depth-first walk of transitive closure.
945*552f7358SJed Brown      At each leaf frame f of transitive closure that we see, add 1/visits[f] to each pair (p,q) not marked as done in cellmat.
946*552f7358SJed Brown      This contribution is added to dnz if owning ranks of p and q match, to onz otherwise.
947*552f7358SJed Brown      */
948*552f7358SJed Brown   }
949*552f7358SJed Brown 
950*552f7358SJed Brown   ierr = PetscSFReduceBegin(sf,MPIU_INT,ldnz,dnz,MPI_SUM);CHKERRQ(ierr);
951*552f7358SJed Brown   ierr = PetscSFReduceEnd  (sf,MPIU_INT,lonz,onz,MPI_SUM);CHKERRQ(ierr);
952*552f7358SJed Brown   PetscFunctionReturn(0);
953*552f7358SJed Brown }
954*552f7358SJed Brown #endif
955*552f7358SJed Brown 
956*552f7358SJed Brown #undef __FUNCT__
957*552f7358SJed Brown #define __FUNCT__ "DMCreateMatrix_Plex"
958*552f7358SJed Brown PetscErrorCode DMCreateMatrix_Plex(DM dm, MatType mtype, Mat *J)
959*552f7358SJed Brown {
960*552f7358SJed Brown   PetscSection   section, sectionGlobal;
961*552f7358SJed Brown   PetscInt       bs = -1;
962*552f7358SJed Brown   PetscInt       localSize;
963*552f7358SJed Brown   PetscBool      isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isSymmetric;
964*552f7358SJed Brown   PetscErrorCode ierr;
965*552f7358SJed Brown 
966*552f7358SJed Brown   PetscFunctionBegin;
967*552f7358SJed Brown #ifndef PETSC_USE_DYNAMIC_LIBRARIES
968*552f7358SJed Brown   ierr = MatInitializePackage(PETSC_NULL);CHKERRQ(ierr);
969*552f7358SJed Brown #endif
970*552f7358SJed Brown   if (!mtype) mtype = MATAIJ;
971*552f7358SJed Brown   ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
972*552f7358SJed Brown   ierr = DMGetDefaultGlobalSection(dm, &sectionGlobal);CHKERRQ(ierr);
973*552f7358SJed Brown   /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */
974*552f7358SJed Brown   ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr);
975*552f7358SJed Brown   ierr = MatCreate(((PetscObject) dm)->comm, J);CHKERRQ(ierr);
976*552f7358SJed Brown   ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
977*552f7358SJed Brown   ierr = MatSetType(*J, mtype);CHKERRQ(ierr);
978*552f7358SJed Brown   ierr = MatSetFromOptions(*J);CHKERRQ(ierr);
979*552f7358SJed Brown   ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr);
980*552f7358SJed Brown   ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr);
981*552f7358SJed Brown   ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr);
982*552f7358SJed Brown   ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr);
983*552f7358SJed Brown   ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr);
984*552f7358SJed Brown   ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr);
985*552f7358SJed Brown   ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr);
986*552f7358SJed Brown   /* Check for symmetric storage */
987*552f7358SJed Brown   isSymmetric = (PetscBool) (isSymBlock || isSymSeqBlock || isSymMPIBlock);
988*552f7358SJed Brown   if (isSymmetric) {
989*552f7358SJed Brown     ierr = MatSetOption(*J, MAT_IGNORE_LOWER_TRIANGULAR, PETSC_TRUE);CHKERRQ(ierr);
990*552f7358SJed Brown   }
991*552f7358SJed Brown   if (!isShell) {
992*552f7358SJed Brown     PetscBool fillMatrix = (PetscBool) !dm->prealloc_only;
993*552f7358SJed Brown     PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal;
994*552f7358SJed Brown 
995*552f7358SJed Brown     if (bs < 0) {
996*552f7358SJed Brown       if (isBlock || isSeqBlock || isMPIBlock || isSymBlock || isSymSeqBlock || isSymMPIBlock) {
997*552f7358SJed Brown         PetscInt pStart, pEnd, p, dof;
998*552f7358SJed Brown 
999*552f7358SJed Brown         ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr);
1000*552f7358SJed Brown         for (p = pStart; p < pEnd; ++p) {
1001*552f7358SJed Brown           ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr);
1002*552f7358SJed Brown           if (dof) {
1003*552f7358SJed Brown             bs = dof;
1004*552f7358SJed Brown             break;
1005*552f7358SJed Brown           }
1006*552f7358SJed Brown         }
1007*552f7358SJed Brown       } else {
1008*552f7358SJed Brown         bs = 1;
1009*552f7358SJed Brown       }
1010*552f7358SJed Brown       /* Must have same blocksize on all procs (some might have no points) */
1011*552f7358SJed Brown       bsLocal = bs;
1012*552f7358SJed Brown       ierr = MPI_Allreduce(&bsLocal, &bs, 1, MPIU_INT, MPI_MAX, ((PetscObject) dm)->comm);CHKERRQ(ierr);
1013*552f7358SJed Brown     }
1014*552f7358SJed Brown     ierr = PetscMalloc4(localSize/bs, PetscInt, &dnz, localSize/bs, PetscInt, &onz, localSize/bs, PetscInt, &dnzu, localSize/bs, PetscInt, &onzu);CHKERRQ(ierr);
1015*552f7358SJed Brown     ierr = PetscMemzero(dnz,  localSize/bs * sizeof(PetscInt));CHKERRQ(ierr);
1016*552f7358SJed Brown     ierr = PetscMemzero(onz,  localSize/bs * sizeof(PetscInt));CHKERRQ(ierr);
1017*552f7358SJed Brown     ierr = PetscMemzero(dnzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr);
1018*552f7358SJed Brown     ierr = PetscMemzero(onzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr);
1019*552f7358SJed Brown     ierr = DMPlexPreallocateOperator(dm, bs, section, sectionGlobal, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr);
1020*552f7358SJed Brown     ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr);
1021*552f7358SJed Brown   }
1022*552f7358SJed Brown   PetscFunctionReturn(0);
1023*552f7358SJed Brown }
1024*552f7358SJed Brown 
1025*552f7358SJed Brown #undef __FUNCT__
1026*552f7358SJed Brown #define __FUNCT__ "DMPlexGetDimension"
1027*552f7358SJed Brown /*@
1028*552f7358SJed Brown   DMPlexGetDimension - Return the topological mesh dimension
1029*552f7358SJed Brown 
1030*552f7358SJed Brown   Not collective
1031*552f7358SJed Brown 
1032*552f7358SJed Brown   Input Parameter:
1033*552f7358SJed Brown . mesh - The DMPlex
1034*552f7358SJed Brown 
1035*552f7358SJed Brown   Output Parameter:
1036*552f7358SJed Brown . dim - The topological mesh dimension
1037*552f7358SJed Brown 
1038*552f7358SJed Brown   Level: beginner
1039*552f7358SJed Brown 
1040*552f7358SJed Brown .seealso: DMPlexCreate()
1041*552f7358SJed Brown @*/
1042*552f7358SJed Brown PetscErrorCode DMPlexGetDimension(DM dm, PetscInt *dim)
1043*552f7358SJed Brown {
1044*552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *) dm->data;
1045*552f7358SJed Brown 
1046*552f7358SJed Brown   PetscFunctionBegin;
1047*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1048*552f7358SJed Brown   PetscValidPointer(dim, 2);
1049*552f7358SJed Brown   *dim = mesh->dim;
1050*552f7358SJed Brown   PetscFunctionReturn(0);
1051*552f7358SJed Brown }
1052*552f7358SJed Brown 
1053*552f7358SJed Brown #undef __FUNCT__
1054*552f7358SJed Brown #define __FUNCT__ "DMPlexSetDimension"
1055*552f7358SJed Brown /*@
1056*552f7358SJed Brown   DMPlexSetDimension - Set the topological mesh dimension
1057*552f7358SJed Brown 
1058*552f7358SJed Brown   Collective on mesh
1059*552f7358SJed Brown 
1060*552f7358SJed Brown   Input Parameters:
1061*552f7358SJed Brown + mesh - The DMPlex
1062*552f7358SJed Brown - dim - The topological mesh dimension
1063*552f7358SJed Brown 
1064*552f7358SJed Brown   Level: beginner
1065*552f7358SJed Brown 
1066*552f7358SJed Brown .seealso: DMPlexCreate()
1067*552f7358SJed Brown @*/
1068*552f7358SJed Brown PetscErrorCode DMPlexSetDimension(DM dm, PetscInt dim)
1069*552f7358SJed Brown {
1070*552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *) dm->data;
1071*552f7358SJed Brown 
1072*552f7358SJed Brown   PetscFunctionBegin;
1073*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1074*552f7358SJed Brown   PetscValidLogicalCollectiveInt(dm, dim, 2);
1075*552f7358SJed Brown   mesh->dim = dim;
1076*552f7358SJed Brown   mesh->preallocCenterDim = dim;
1077*552f7358SJed Brown   PetscFunctionReturn(0);
1078*552f7358SJed Brown }
1079*552f7358SJed Brown 
1080*552f7358SJed Brown #undef __FUNCT__
1081*552f7358SJed Brown #define __FUNCT__ "DMPlexGetChart"
1082*552f7358SJed Brown /*@
1083*552f7358SJed Brown   DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd)
1084*552f7358SJed Brown 
1085*552f7358SJed Brown   Not collective
1086*552f7358SJed Brown 
1087*552f7358SJed Brown   Input Parameter:
1088*552f7358SJed Brown . mesh - The DMPlex
1089*552f7358SJed Brown 
1090*552f7358SJed Brown   Output Parameters:
1091*552f7358SJed Brown + pStart - The first mesh point
1092*552f7358SJed Brown - pEnd   - The upper bound for mesh points
1093*552f7358SJed Brown 
1094*552f7358SJed Brown   Level: beginner
1095*552f7358SJed Brown 
1096*552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetChart()
1097*552f7358SJed Brown @*/
1098*552f7358SJed Brown PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd)
1099*552f7358SJed Brown {
1100*552f7358SJed Brown   DM_Plex    *mesh = (DM_Plex *) dm->data;
1101*552f7358SJed Brown   PetscErrorCode ierr;
1102*552f7358SJed Brown 
1103*552f7358SJed Brown   PetscFunctionBegin;
1104*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1105*552f7358SJed Brown   ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr);
1106*552f7358SJed Brown   PetscFunctionReturn(0);
1107*552f7358SJed Brown }
1108*552f7358SJed Brown 
1109*552f7358SJed Brown #undef __FUNCT__
1110*552f7358SJed Brown #define __FUNCT__ "DMPlexSetChart"
1111*552f7358SJed Brown /*@
1112*552f7358SJed Brown   DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd)
1113*552f7358SJed Brown 
1114*552f7358SJed Brown   Not collective
1115*552f7358SJed Brown 
1116*552f7358SJed Brown   Input Parameters:
1117*552f7358SJed Brown + mesh - The DMPlex
1118*552f7358SJed Brown . pStart - The first mesh point
1119*552f7358SJed Brown - pEnd   - The upper bound for mesh points
1120*552f7358SJed Brown 
1121*552f7358SJed Brown   Output Parameters:
1122*552f7358SJed Brown 
1123*552f7358SJed Brown   Level: beginner
1124*552f7358SJed Brown 
1125*552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetChart()
1126*552f7358SJed Brown @*/
1127*552f7358SJed Brown PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd)
1128*552f7358SJed Brown {
1129*552f7358SJed Brown   DM_Plex    *mesh = (DM_Plex *) dm->data;
1130*552f7358SJed Brown   PetscErrorCode ierr;
1131*552f7358SJed Brown 
1132*552f7358SJed Brown   PetscFunctionBegin;
1133*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1134*552f7358SJed Brown   ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr);
1135*552f7358SJed Brown   ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr);
1136*552f7358SJed Brown   PetscFunctionReturn(0);
1137*552f7358SJed Brown }
1138*552f7358SJed Brown 
1139*552f7358SJed Brown #undef __FUNCT__
1140*552f7358SJed Brown #define __FUNCT__ "DMPlexGetConeSize"
1141*552f7358SJed Brown /*@
1142*552f7358SJed Brown   DMPlexGetConeSize - Return the number of in-edges for this point in the Sieve DAG
1143*552f7358SJed Brown 
1144*552f7358SJed Brown   Not collective
1145*552f7358SJed Brown 
1146*552f7358SJed Brown   Input Parameters:
1147*552f7358SJed Brown + mesh - The DMPlex
1148*552f7358SJed Brown - p - The Sieve point, which must lie in the chart set with DMPlexSetChart()
1149*552f7358SJed Brown 
1150*552f7358SJed Brown   Output Parameter:
1151*552f7358SJed Brown . size - The cone size for point p
1152*552f7358SJed Brown 
1153*552f7358SJed Brown   Level: beginner
1154*552f7358SJed Brown 
1155*552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart()
1156*552f7358SJed Brown @*/
1157*552f7358SJed Brown PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size)
1158*552f7358SJed Brown {
1159*552f7358SJed Brown   DM_Plex    *mesh = (DM_Plex *) dm->data;
1160*552f7358SJed Brown   PetscErrorCode ierr;
1161*552f7358SJed Brown 
1162*552f7358SJed Brown   PetscFunctionBegin;
1163*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1164*552f7358SJed Brown   PetscValidPointer(size, 3);
1165*552f7358SJed Brown   ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr);
1166*552f7358SJed Brown   PetscFunctionReturn(0);
1167*552f7358SJed Brown }
1168*552f7358SJed Brown 
1169*552f7358SJed Brown #undef __FUNCT__
1170*552f7358SJed Brown #define __FUNCT__ "DMPlexSetConeSize"
1171*552f7358SJed Brown /*@
1172*552f7358SJed Brown   DMPlexSetConeSize - Set the number of in-edges for this point in the Sieve DAG
1173*552f7358SJed Brown 
1174*552f7358SJed Brown   Not collective
1175*552f7358SJed Brown 
1176*552f7358SJed Brown   Input Parameters:
1177*552f7358SJed Brown + mesh - The DMPlex
1178*552f7358SJed Brown . p - The Sieve point, which must lie in the chart set with DMPlexSetChart()
1179*552f7358SJed Brown - size - The cone size for point p
1180*552f7358SJed Brown 
1181*552f7358SJed Brown   Output Parameter:
1182*552f7358SJed Brown 
1183*552f7358SJed Brown   Note:
1184*552f7358SJed Brown   This should be called after DMPlexSetChart().
1185*552f7358SJed Brown 
1186*552f7358SJed Brown   Level: beginner
1187*552f7358SJed Brown 
1188*552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart()
1189*552f7358SJed Brown @*/
1190*552f7358SJed Brown PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size)
1191*552f7358SJed Brown {
1192*552f7358SJed Brown   DM_Plex    *mesh = (DM_Plex *) dm->data;
1193*552f7358SJed Brown   PetscErrorCode ierr;
1194*552f7358SJed Brown 
1195*552f7358SJed Brown   PetscFunctionBegin;
1196*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1197*552f7358SJed Brown   ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr);
1198*552f7358SJed Brown   mesh->maxConeSize = PetscMax(mesh->maxConeSize, size);
1199*552f7358SJed Brown   PetscFunctionReturn(0);
1200*552f7358SJed Brown }
1201*552f7358SJed Brown 
1202*552f7358SJed Brown #undef __FUNCT__
1203*552f7358SJed Brown #define __FUNCT__ "DMPlexGetCone"
1204*552f7358SJed Brown /*@C
1205*552f7358SJed Brown   DMPlexGetCone - Return the points on the in-edges for this point in the Sieve DAG
1206*552f7358SJed Brown 
1207*552f7358SJed Brown   Not collective
1208*552f7358SJed Brown 
1209*552f7358SJed Brown   Input Parameters:
1210*552f7358SJed Brown + mesh - The DMPlex
1211*552f7358SJed Brown - p - The Sieve point, which must lie in the chart set with DMPlexSetChart()
1212*552f7358SJed Brown 
1213*552f7358SJed Brown   Output Parameter:
1214*552f7358SJed Brown . cone - An array of points which are on the in-edges for point p
1215*552f7358SJed Brown 
1216*552f7358SJed Brown   Level: beginner
1217*552f7358SJed Brown 
1218*552f7358SJed Brown   Note:
1219*552f7358SJed Brown   This routine is not available in Fortran.
1220*552f7358SJed Brown 
1221*552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart()
1222*552f7358SJed Brown @*/
1223*552f7358SJed Brown PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[])
1224*552f7358SJed Brown {
1225*552f7358SJed Brown   DM_Plex    *mesh = (DM_Plex *) dm->data;
1226*552f7358SJed Brown   PetscInt       off;
1227*552f7358SJed Brown   PetscErrorCode ierr;
1228*552f7358SJed Brown 
1229*552f7358SJed Brown   PetscFunctionBegin;
1230*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1231*552f7358SJed Brown   PetscValidPointer(cone, 3);
1232*552f7358SJed Brown   ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr);
1233*552f7358SJed Brown   *cone = &mesh->cones[off];
1234*552f7358SJed Brown   PetscFunctionReturn(0);
1235*552f7358SJed Brown }
1236*552f7358SJed Brown 
1237*552f7358SJed Brown #undef __FUNCT__
1238*552f7358SJed Brown #define __FUNCT__ "DMPlexSetCone"
1239*552f7358SJed Brown /*@
1240*552f7358SJed Brown   DMPlexSetCone - Set the points on the in-edges for this point in the Sieve DAG
1241*552f7358SJed Brown 
1242*552f7358SJed Brown   Not collective
1243*552f7358SJed Brown 
1244*552f7358SJed Brown   Input Parameters:
1245*552f7358SJed Brown + mesh - The DMPlex
1246*552f7358SJed Brown . p - The Sieve point, which must lie in the chart set with DMPlexSetChart()
1247*552f7358SJed Brown - cone - An array of points which are on the in-edges for point p
1248*552f7358SJed Brown 
1249*552f7358SJed Brown   Output Parameter:
1250*552f7358SJed Brown 
1251*552f7358SJed Brown   Note:
1252*552f7358SJed Brown   This should be called after all calls to DMPlexSetConeSize() and DMSetUp().
1253*552f7358SJed Brown 
1254*552f7358SJed Brown   Level: beginner
1255*552f7358SJed Brown 
1256*552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp()
1257*552f7358SJed Brown @*/
1258*552f7358SJed Brown PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[])
1259*552f7358SJed Brown {
1260*552f7358SJed Brown   DM_Plex    *mesh = (DM_Plex *) dm->data;
1261*552f7358SJed Brown   PetscInt       pStart, pEnd;
1262*552f7358SJed Brown   PetscInt       dof, off, c;
1263*552f7358SJed Brown   PetscErrorCode ierr;
1264*552f7358SJed Brown 
1265*552f7358SJed Brown   PetscFunctionBegin;
1266*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1267*552f7358SJed Brown   ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr);
1268*552f7358SJed Brown   ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr);
1269*552f7358SJed Brown   if (dof) PetscValidPointer(cone, 3);
1270*552f7358SJed Brown   ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr);
1271*552f7358SJed Brown   if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd);
1272*552f7358SJed Brown   for (c = 0; c < dof; ++c) {
1273*552f7358SJed Brown     if ((cone[c] < pStart) || (cone[c] >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", cone[c], pStart, pEnd);
1274*552f7358SJed Brown     mesh->cones[off+c] = cone[c];
1275*552f7358SJed Brown   }
1276*552f7358SJed Brown   PetscFunctionReturn(0);
1277*552f7358SJed Brown }
1278*552f7358SJed Brown 
1279*552f7358SJed Brown #undef __FUNCT__
1280*552f7358SJed Brown #define __FUNCT__ "DMPlexGetConeOrientation"
1281*552f7358SJed Brown /*@C
1282*552f7358SJed Brown   DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the Sieve DAG
1283*552f7358SJed Brown 
1284*552f7358SJed Brown   Not collective
1285*552f7358SJed Brown 
1286*552f7358SJed Brown   Input Parameters:
1287*552f7358SJed Brown + mesh - The DMPlex
1288*552f7358SJed Brown - p - The Sieve point, which must lie in the chart set with DMPlexSetChart()
1289*552f7358SJed Brown 
1290*552f7358SJed Brown   Output Parameter:
1291*552f7358SJed Brown . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an
1292*552f7358SJed Brown                     integer giving the prescription for cone traversal. If it is negative, the cone is
1293*552f7358SJed Brown                     traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives
1294*552f7358SJed Brown                     the index of the cone point on which to start.
1295*552f7358SJed Brown 
1296*552f7358SJed Brown   Level: beginner
1297*552f7358SJed Brown 
1298*552f7358SJed Brown   Note:
1299*552f7358SJed Brown   This routine is not available in Fortran.
1300*552f7358SJed Brown 
1301*552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart()
1302*552f7358SJed Brown @*/
1303*552f7358SJed Brown PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[])
1304*552f7358SJed Brown {
1305*552f7358SJed Brown   DM_Plex    *mesh = (DM_Plex *) dm->data;
1306*552f7358SJed Brown   PetscInt       off;
1307*552f7358SJed Brown   PetscErrorCode ierr;
1308*552f7358SJed Brown 
1309*552f7358SJed Brown   PetscFunctionBegin;
1310*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1311*552f7358SJed Brown #if defined(PETSC_USE_DEBUG)
1312*552f7358SJed Brown   {
1313*552f7358SJed Brown     PetscInt dof;
1314*552f7358SJed Brown     ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr);
1315*552f7358SJed Brown     if (dof) PetscValidPointer(coneOrientation, 3);
1316*552f7358SJed Brown   }
1317*552f7358SJed Brown #endif
1318*552f7358SJed Brown   ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr);
1319*552f7358SJed Brown   *coneOrientation = &mesh->coneOrientations[off];
1320*552f7358SJed Brown   PetscFunctionReturn(0);
1321*552f7358SJed Brown }
1322*552f7358SJed Brown 
1323*552f7358SJed Brown #undef __FUNCT__
1324*552f7358SJed Brown #define __FUNCT__ "DMPlexSetConeOrientation"
1325*552f7358SJed Brown /*@
1326*552f7358SJed Brown   DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the Sieve DAG
1327*552f7358SJed Brown 
1328*552f7358SJed Brown   Not collective
1329*552f7358SJed Brown 
1330*552f7358SJed Brown   Input Parameters:
1331*552f7358SJed Brown + mesh - The DMPlex
1332*552f7358SJed Brown . p - The Sieve point, which must lie in the chart set with DMPlexSetChart()
1333*552f7358SJed Brown - coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an
1334*552f7358SJed Brown                     integer giving the prescription for cone traversal. If it is negative, the cone is
1335*552f7358SJed Brown                     traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives
1336*552f7358SJed Brown                     the index of the cone point on which to start.
1337*552f7358SJed Brown 
1338*552f7358SJed Brown   Output Parameter:
1339*552f7358SJed Brown 
1340*552f7358SJed Brown   Note:
1341*552f7358SJed Brown   This should be called after all calls to DMPlexSetConeSize() and DMSetUp().
1342*552f7358SJed Brown 
1343*552f7358SJed Brown   Level: beginner
1344*552f7358SJed Brown 
1345*552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp()
1346*552f7358SJed Brown @*/
1347*552f7358SJed Brown PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[])
1348*552f7358SJed Brown {
1349*552f7358SJed Brown   DM_Plex    *mesh = (DM_Plex *) dm->data;
1350*552f7358SJed Brown   PetscInt       pStart, pEnd;
1351*552f7358SJed Brown   PetscInt       dof, off, c;
1352*552f7358SJed Brown   PetscErrorCode ierr;
1353*552f7358SJed Brown 
1354*552f7358SJed Brown   PetscFunctionBegin;
1355*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1356*552f7358SJed Brown   ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr);
1357*552f7358SJed Brown   ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr);
1358*552f7358SJed Brown   if (dof) PetscValidPointer(coneOrientation, 3);
1359*552f7358SJed Brown   ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr);
1360*552f7358SJed Brown   if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd);
1361*552f7358SJed Brown   for (c = 0; c < dof; ++c) {
1362*552f7358SJed Brown     PetscInt cdof, o = coneOrientation[c];
1363*552f7358SJed Brown 
1364*552f7358SJed Brown     ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr);
1365*552f7358SJed Brown     if (o && ((o < -(cdof+1)) || (o >= cdof))) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone orientation %D is not in the valid range [%D. %D)", o, -(cdof+1), cdof);
1366*552f7358SJed Brown     mesh->coneOrientations[off+c] = o;
1367*552f7358SJed Brown   }
1368*552f7358SJed Brown   PetscFunctionReturn(0);
1369*552f7358SJed Brown }
1370*552f7358SJed Brown 
1371*552f7358SJed Brown #undef __FUNCT__
1372*552f7358SJed Brown #define __FUNCT__ "DMPlexInsertCone"
1373*552f7358SJed Brown PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint)
1374*552f7358SJed Brown {
1375*552f7358SJed Brown   DM_Plex    *mesh = (DM_Plex *) dm->data;
1376*552f7358SJed Brown   PetscInt       pStart, pEnd;
1377*552f7358SJed Brown   PetscInt       dof, off;
1378*552f7358SJed Brown   PetscErrorCode ierr;
1379*552f7358SJed Brown 
1380*552f7358SJed Brown   PetscFunctionBegin;
1381*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1382*552f7358SJed Brown   ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr);
1383*552f7358SJed Brown   ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr);
1384*552f7358SJed Brown   ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr);
1385*552f7358SJed Brown   if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd);
1386*552f7358SJed Brown   if ((conePoint < pStart) || (conePoint >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", conePoint, pStart, pEnd);
1387*552f7358SJed Brown   if (conePos >= dof) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone position %D of point %D is not in the valid range [0, %D)", conePos, p, dof);
1388*552f7358SJed Brown   mesh->cones[off+conePos] = conePoint;
1389*552f7358SJed Brown   PetscFunctionReturn(0);
1390*552f7358SJed Brown }
1391*552f7358SJed Brown 
1392*552f7358SJed Brown #undef __FUNCT__
1393*552f7358SJed Brown #define __FUNCT__ "DMPlexGetSupportSize"
1394*552f7358SJed Brown /*@
1395*552f7358SJed Brown   DMPlexGetSupportSize - Return the number of out-edges for this point in the Sieve DAG
1396*552f7358SJed Brown 
1397*552f7358SJed Brown   Not collective
1398*552f7358SJed Brown 
1399*552f7358SJed Brown   Input Parameters:
1400*552f7358SJed Brown + mesh - The DMPlex
1401*552f7358SJed Brown - p - The Sieve point, which must lie in the chart set with DMPlexSetChart()
1402*552f7358SJed Brown 
1403*552f7358SJed Brown   Output Parameter:
1404*552f7358SJed Brown . size - The support size for point p
1405*552f7358SJed Brown 
1406*552f7358SJed Brown   Level: beginner
1407*552f7358SJed Brown 
1408*552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize()
1409*552f7358SJed Brown @*/
1410*552f7358SJed Brown PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size)
1411*552f7358SJed Brown {
1412*552f7358SJed Brown   DM_Plex    *mesh = (DM_Plex *) dm->data;
1413*552f7358SJed Brown   PetscErrorCode ierr;
1414*552f7358SJed Brown 
1415*552f7358SJed Brown   PetscFunctionBegin;
1416*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1417*552f7358SJed Brown   PetscValidPointer(size, 3);
1418*552f7358SJed Brown   ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr);
1419*552f7358SJed Brown   PetscFunctionReturn(0);
1420*552f7358SJed Brown }
1421*552f7358SJed Brown 
1422*552f7358SJed Brown #undef __FUNCT__
1423*552f7358SJed Brown #define __FUNCT__ "DMPlexSetSupportSize"
1424*552f7358SJed Brown /*@
1425*552f7358SJed Brown   DMPlexSetSupportSize - Set the number of out-edges for this point in the Sieve DAG
1426*552f7358SJed Brown 
1427*552f7358SJed Brown   Not collective
1428*552f7358SJed Brown 
1429*552f7358SJed Brown   Input Parameters:
1430*552f7358SJed Brown + mesh - The DMPlex
1431*552f7358SJed Brown . p - The Sieve point, which must lie in the chart set with DMPlexSetChart()
1432*552f7358SJed Brown - size - The support size for point p
1433*552f7358SJed Brown 
1434*552f7358SJed Brown   Output Parameter:
1435*552f7358SJed Brown 
1436*552f7358SJed Brown   Note:
1437*552f7358SJed Brown   This should be called after DMPlexSetChart().
1438*552f7358SJed Brown 
1439*552f7358SJed Brown   Level: beginner
1440*552f7358SJed Brown 
1441*552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart()
1442*552f7358SJed Brown @*/
1443*552f7358SJed Brown PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size)
1444*552f7358SJed Brown {
1445*552f7358SJed Brown   DM_Plex    *mesh = (DM_Plex *) dm->data;
1446*552f7358SJed Brown   PetscErrorCode ierr;
1447*552f7358SJed Brown 
1448*552f7358SJed Brown   PetscFunctionBegin;
1449*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1450*552f7358SJed Brown   ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr);
1451*552f7358SJed Brown   mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size);
1452*552f7358SJed Brown   PetscFunctionReturn(0);
1453*552f7358SJed Brown }
1454*552f7358SJed Brown 
1455*552f7358SJed Brown #undef __FUNCT__
1456*552f7358SJed Brown #define __FUNCT__ "DMPlexGetSupport"
1457*552f7358SJed Brown /*@C
1458*552f7358SJed Brown   DMPlexGetSupport - Return the points on the out-edges for this point in the Sieve DAG
1459*552f7358SJed Brown 
1460*552f7358SJed Brown   Not collective
1461*552f7358SJed Brown 
1462*552f7358SJed Brown   Input Parameters:
1463*552f7358SJed Brown + mesh - The DMPlex
1464*552f7358SJed Brown - p - The Sieve point, which must lie in the chart set with DMPlexSetChart()
1465*552f7358SJed Brown 
1466*552f7358SJed Brown   Output Parameter:
1467*552f7358SJed Brown . support - An array of points which are on the out-edges for point p
1468*552f7358SJed Brown 
1469*552f7358SJed Brown   Level: beginner
1470*552f7358SJed Brown 
1471*552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone()
1472*552f7358SJed Brown @*/
1473*552f7358SJed Brown PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[])
1474*552f7358SJed Brown {
1475*552f7358SJed Brown   DM_Plex    *mesh = (DM_Plex *) dm->data;
1476*552f7358SJed Brown   PetscInt       off;
1477*552f7358SJed Brown   PetscErrorCode ierr;
1478*552f7358SJed Brown 
1479*552f7358SJed Brown   PetscFunctionBegin;
1480*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1481*552f7358SJed Brown   PetscValidPointer(support, 3);
1482*552f7358SJed Brown   ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr);
1483*552f7358SJed Brown   *support = &mesh->supports[off];
1484*552f7358SJed Brown   PetscFunctionReturn(0);
1485*552f7358SJed Brown }
1486*552f7358SJed Brown 
1487*552f7358SJed Brown #undef __FUNCT__
1488*552f7358SJed Brown #define __FUNCT__ "DMPlexSetSupport"
1489*552f7358SJed Brown /*@
1490*552f7358SJed Brown   DMPlexSetSupport - Set the points on the out-edges for this point in the Sieve DAG
1491*552f7358SJed Brown 
1492*552f7358SJed Brown   Not collective
1493*552f7358SJed Brown 
1494*552f7358SJed Brown   Input Parameters:
1495*552f7358SJed Brown + mesh - The DMPlex
1496*552f7358SJed Brown . p - The Sieve point, which must lie in the chart set with DMPlexSetChart()
1497*552f7358SJed Brown - support - An array of points which are on the in-edges for point p
1498*552f7358SJed Brown 
1499*552f7358SJed Brown   Output Parameter:
1500*552f7358SJed Brown 
1501*552f7358SJed Brown   Note:
1502*552f7358SJed Brown   This should be called after all calls to DMPlexSetSupportSize() and DMSetUp().
1503*552f7358SJed Brown 
1504*552f7358SJed Brown   Level: beginner
1505*552f7358SJed Brown 
1506*552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp()
1507*552f7358SJed Brown @*/
1508*552f7358SJed Brown PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[])
1509*552f7358SJed Brown {
1510*552f7358SJed Brown   DM_Plex    *mesh = (DM_Plex *) dm->data;
1511*552f7358SJed Brown   PetscInt       pStart, pEnd;
1512*552f7358SJed Brown   PetscInt       dof, off, c;
1513*552f7358SJed Brown   PetscErrorCode ierr;
1514*552f7358SJed Brown 
1515*552f7358SJed Brown   PetscFunctionBegin;
1516*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1517*552f7358SJed Brown   ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr);
1518*552f7358SJed Brown   ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr);
1519*552f7358SJed Brown   if (dof) PetscValidPointer(support, 3);
1520*552f7358SJed Brown   ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr);
1521*552f7358SJed Brown   if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd);
1522*552f7358SJed Brown   for (c = 0; c < dof; ++c) {
1523*552f7358SJed Brown     if ((support[c] < pStart) || (support[c] >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", support[c], pStart, pEnd);
1524*552f7358SJed Brown     mesh->supports[off+c] = support[c];
1525*552f7358SJed Brown   }
1526*552f7358SJed Brown   PetscFunctionReturn(0);
1527*552f7358SJed Brown }
1528*552f7358SJed Brown 
1529*552f7358SJed Brown #undef __FUNCT__
1530*552f7358SJed Brown #define __FUNCT__ "DMPlexInsertSupport"
1531*552f7358SJed Brown PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint)
1532*552f7358SJed Brown {
1533*552f7358SJed Brown   DM_Plex    *mesh = (DM_Plex *) dm->data;
1534*552f7358SJed Brown   PetscInt       pStart, pEnd;
1535*552f7358SJed Brown   PetscInt       dof, off;
1536*552f7358SJed Brown   PetscErrorCode ierr;
1537*552f7358SJed Brown 
1538*552f7358SJed Brown   PetscFunctionBegin;
1539*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1540*552f7358SJed Brown   ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr);
1541*552f7358SJed Brown   ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr);
1542*552f7358SJed Brown   ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr);
1543*552f7358SJed Brown   if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd);
1544*552f7358SJed Brown   if ((supportPoint < pStart) || (supportPoint >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", supportPoint, pStart, pEnd);
1545*552f7358SJed Brown   if (supportPos >= dof) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Support position %D of point %D is not in the valid range [0, %D)", supportPos, p, dof);
1546*552f7358SJed Brown   mesh->supports[off+supportPos] = supportPoint;
1547*552f7358SJed Brown   PetscFunctionReturn(0);
1548*552f7358SJed Brown }
1549*552f7358SJed Brown 
1550*552f7358SJed Brown #undef __FUNCT__
1551*552f7358SJed Brown #define __FUNCT__ "DMPlexGetTransitiveClosure"
1552*552f7358SJed Brown /*@C
1553*552f7358SJed Brown   DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG
1554*552f7358SJed Brown 
1555*552f7358SJed Brown   Not collective
1556*552f7358SJed Brown 
1557*552f7358SJed Brown   Input Parameters:
1558*552f7358SJed Brown + mesh - The DMPlex
1559*552f7358SJed Brown . p - The Sieve point, which must lie in the chart set with DMPlexSetChart()
1560*552f7358SJed Brown . useCone - PETSC_TRUE for in-edges,  otherwise use out-edges
1561*552f7358SJed Brown - points - If points is PETSC_NULL on input, internal storage will be returned, otherwise the provided array is used
1562*552f7358SJed Brown 
1563*552f7358SJed Brown   Output Parameters:
1564*552f7358SJed Brown + numPoints - The number of points in the closure, so points[] is of size 2*numPoints
1565*552f7358SJed Brown - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]
1566*552f7358SJed Brown 
1567*552f7358SJed Brown   Note:
1568*552f7358SJed Brown   If using internal storage (points is PETSC_NULL on input), each call overwrites the last output.
1569*552f7358SJed Brown 
1570*552f7358SJed Brown   Level: beginner
1571*552f7358SJed Brown 
1572*552f7358SJed Brown .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone()
1573*552f7358SJed Brown @*/
1574*552f7358SJed Brown PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
1575*552f7358SJed Brown {
1576*552f7358SJed Brown   DM_Plex     *mesh = (DM_Plex *) dm->data;
1577*552f7358SJed Brown   PetscInt       *closure, *fifo;
1578*552f7358SJed Brown   const PetscInt *tmp = PETSC_NULL, *tmpO = PETSC_NULL;
1579*552f7358SJed Brown   PetscInt        tmpSize, t;
1580*552f7358SJed Brown   PetscInt        depth = 0, maxSize;
1581*552f7358SJed Brown   PetscInt        closureSize = 2, fifoSize = 0, fifoStart = 0;
1582*552f7358SJed Brown   PetscErrorCode  ierr;
1583*552f7358SJed Brown 
1584*552f7358SJed Brown   PetscFunctionBegin;
1585*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1586*552f7358SJed Brown   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
1587*552f7358SJed Brown   maxSize = (PetscInt) (2*PetscMax(PetscMax(pow((PetscReal) mesh->maxConeSize, depth)+1, pow((PetscReal) mesh->maxSupportSize, depth)+1), depth+1));
1588*552f7358SJed Brown   ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr);
1589*552f7358SJed Brown   if (*points) {
1590*552f7358SJed Brown     closure = *points;
1591*552f7358SJed Brown   } else {
1592*552f7358SJed Brown     ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &closure);CHKERRQ(ierr);
1593*552f7358SJed Brown   }
1594*552f7358SJed Brown   closure[0] = p; closure[1] = 0;
1595*552f7358SJed Brown   /* This is only 1-level */
1596*552f7358SJed Brown   if (useCone) {
1597*552f7358SJed Brown     ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr);
1598*552f7358SJed Brown     ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr);
1599*552f7358SJed Brown     ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr);
1600*552f7358SJed Brown   } else {
1601*552f7358SJed Brown     ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr);
1602*552f7358SJed Brown     ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr);
1603*552f7358SJed Brown   }
1604*552f7358SJed Brown   for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) {
1605*552f7358SJed Brown     const PetscInt cp = tmp[t];
1606*552f7358SJed Brown     const PetscInt co = tmpO ? tmpO[t] : 0;
1607*552f7358SJed Brown 
1608*552f7358SJed Brown     closure[closureSize]   = cp;
1609*552f7358SJed Brown     closure[closureSize+1] = co;
1610*552f7358SJed Brown     fifo[fifoSize]         = cp;
1611*552f7358SJed Brown     fifo[fifoSize+1]       = co;
1612*552f7358SJed Brown   }
1613*552f7358SJed Brown   while(fifoSize - fifoStart) {
1614*552f7358SJed Brown     const PetscInt q   = fifo[fifoStart];
1615*552f7358SJed Brown     const PetscInt o   = fifo[fifoStart+1];
1616*552f7358SJed Brown     const PetscInt rev = o >= 0 ? 0 : 1;
1617*552f7358SJed Brown     const PetscInt off = rev ? -(o+1) : o;
1618*552f7358SJed Brown 
1619*552f7358SJed Brown     if (useCone) {
1620*552f7358SJed Brown       ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr);
1621*552f7358SJed Brown       ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr);
1622*552f7358SJed Brown       ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr);
1623*552f7358SJed Brown     } else {
1624*552f7358SJed Brown       ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr);
1625*552f7358SJed Brown       ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr);
1626*552f7358SJed Brown       tmpO = PETSC_NULL;
1627*552f7358SJed Brown     }
1628*552f7358SJed Brown     for (t = 0; t < tmpSize; ++t) {
1629*552f7358SJed Brown       const PetscInt i  = ((rev ? tmpSize-t : t) + off)%tmpSize;
1630*552f7358SJed Brown       const PetscInt cp = tmp[i];
1631*552f7358SJed Brown       /* Must propogate orientation */
1632*552f7358SJed Brown       const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0;
1633*552f7358SJed Brown       PetscInt       c;
1634*552f7358SJed Brown 
1635*552f7358SJed Brown       /* Check for duplicate */
1636*552f7358SJed Brown       for (c = 0; c < closureSize; c += 2) {
1637*552f7358SJed Brown         if (closure[c] == cp) break;
1638*552f7358SJed Brown       }
1639*552f7358SJed Brown       if (c == closureSize) {
1640*552f7358SJed Brown         closure[closureSize]   = cp;
1641*552f7358SJed Brown         closure[closureSize+1] = co;
1642*552f7358SJed Brown         fifo[fifoSize]         = cp;
1643*552f7358SJed Brown         fifo[fifoSize+1]       = co;
1644*552f7358SJed Brown         closureSize += 2;
1645*552f7358SJed Brown         fifoSize    += 2;
1646*552f7358SJed Brown       }
1647*552f7358SJed Brown     }
1648*552f7358SJed Brown     fifoStart += 2;
1649*552f7358SJed Brown   }
1650*552f7358SJed Brown   if (numPoints) *numPoints = closureSize/2;
1651*552f7358SJed Brown   if (points)    *points    = closure;
1652*552f7358SJed Brown   ierr = DMRestoreWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr);
1653*552f7358SJed Brown   PetscFunctionReturn(0);
1654*552f7358SJed Brown }
1655*552f7358SJed Brown 
1656*552f7358SJed Brown #undef __FUNCT__
1657*552f7358SJed Brown #define __FUNCT__ "DMPlexRestoreTransitiveClosure"
1658*552f7358SJed Brown /*@C
1659*552f7358SJed Brown   DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG
1660*552f7358SJed Brown 
1661*552f7358SJed Brown   Not collective
1662*552f7358SJed Brown 
1663*552f7358SJed Brown   Input Parameters:
1664*552f7358SJed Brown + mesh - The DMPlex
1665*552f7358SJed Brown . p - The Sieve point, which must lie in the chart set with DMPlexSetChart()
1666*552f7358SJed Brown . useCone - PETSC_TRUE for in-edges,  otherwise use out-edges
1667*552f7358SJed Brown - points - If points is PETSC_NULL on input, internal storage will be returned, otherwise the provided array is used
1668*552f7358SJed Brown 
1669*552f7358SJed Brown   Output Parameters:
1670*552f7358SJed Brown + numPoints - The number of points in the closure, so points[] is of size 2*numPoints
1671*552f7358SJed Brown - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]
1672*552f7358SJed Brown 
1673*552f7358SJed Brown   Note:
1674*552f7358SJed Brown   If not using internal storage (points is not PETSC_NULL on input), this call is unnecessary
1675*552f7358SJed Brown 
1676*552f7358SJed Brown   Level: beginner
1677*552f7358SJed Brown 
1678*552f7358SJed Brown .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone()
1679*552f7358SJed Brown @*/
1680*552f7358SJed Brown PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
1681*552f7358SJed Brown {
1682*552f7358SJed Brown   PetscErrorCode  ierr;
1683*552f7358SJed Brown 
1684*552f7358SJed Brown   PetscFunctionBegin;
1685*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1686*552f7358SJed Brown   ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, points);CHKERRQ(ierr);
1687*552f7358SJed Brown   PetscFunctionReturn(0);
1688*552f7358SJed Brown }
1689*552f7358SJed Brown 
1690*552f7358SJed Brown #undef __FUNCT__
1691*552f7358SJed Brown #define __FUNCT__ "DMPlexGetFaces"
1692*552f7358SJed Brown /*
1693*552f7358SJed Brown   DMPlexGetFaces -
1694*552f7358SJed Brown 
1695*552f7358SJed Brown   Note: This will only work for cell-vertex meshes.
1696*552f7358SJed Brown */
1697*552f7358SJed Brown PetscErrorCode DMPlexGetFaces(DM dm, PetscInt p, PetscInt *numFaces, PetscInt *faceSize, const PetscInt *faces[])
1698*552f7358SJed Brown {
1699*552f7358SJed Brown   DM_Plex     *mesh  = (DM_Plex *) dm->data;
1700*552f7358SJed Brown   const PetscInt *cone  = PETSC_NULL;
1701*552f7358SJed Brown   PetscInt        depth = 0, dim, coneSize;
1702*552f7358SJed Brown   PetscErrorCode  ierr;
1703*552f7358SJed Brown 
1704*552f7358SJed Brown   PetscFunctionBegin;
1705*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1706*552f7358SJed Brown   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
1707*552f7358SJed Brown   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
1708*552f7358SJed Brown   if (depth > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Faces can only be returned for cell-vertex meshes.");
1709*552f7358SJed Brown   if (!mesh->facesTmp) {ierr = PetscMalloc(PetscSqr(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)) * sizeof(PetscInt), &mesh->facesTmp);CHKERRQ(ierr);}
1710*552f7358SJed Brown   ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
1711*552f7358SJed Brown   ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr);
1712*552f7358SJed Brown   switch(dim) {
1713*552f7358SJed Brown   case 2:
1714*552f7358SJed Brown     switch(coneSize) {
1715*552f7358SJed Brown     case 3:
1716*552f7358SJed Brown       mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1];
1717*552f7358SJed Brown       mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2];
1718*552f7358SJed Brown       mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[0];
1719*552f7358SJed Brown       *numFaces = 3;
1720*552f7358SJed Brown       *faceSize = 2;
1721*552f7358SJed Brown       *faces    = mesh->facesTmp;
1722*552f7358SJed Brown       break;
1723*552f7358SJed Brown     case 4:
1724*552f7358SJed Brown       mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1];
1725*552f7358SJed Brown       mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2];
1726*552f7358SJed Brown       mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[3];
1727*552f7358SJed Brown       mesh->facesTmp[6] = cone[3]; mesh->facesTmp[7] = cone[0];
1728*552f7358SJed Brown       *numFaces = 4;
1729*552f7358SJed Brown       *faceSize = 2;
1730*552f7358SJed Brown       *faces    = mesh->facesTmp;
1731*552f7358SJed Brown       break;
1732*552f7358SJed Brown     default:
1733*552f7358SJed Brown       SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim);
1734*552f7358SJed Brown     }
1735*552f7358SJed Brown     break;
1736*552f7358SJed Brown   case 3:
1737*552f7358SJed Brown     switch(coneSize) {
1738*552f7358SJed Brown     case 3:
1739*552f7358SJed Brown       mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1];
1740*552f7358SJed Brown       mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2];
1741*552f7358SJed Brown       mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[0];
1742*552f7358SJed Brown       *numFaces = 3;
1743*552f7358SJed Brown       *faceSize = 2;
1744*552f7358SJed Brown       *faces    = mesh->facesTmp;
1745*552f7358SJed Brown       break;
1746*552f7358SJed Brown     case 4:
1747*552f7358SJed Brown       mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1]  = cone[1]; mesh->facesTmp[2]  = cone[2];
1748*552f7358SJed Brown       mesh->facesTmp[3] = cone[0]; mesh->facesTmp[4]  = cone[2]; mesh->facesTmp[5]  = cone[3];
1749*552f7358SJed Brown       mesh->facesTmp[6] = cone[0]; mesh->facesTmp[7]  = cone[3]; mesh->facesTmp[8]  = cone[1];
1750*552f7358SJed Brown       mesh->facesTmp[9] = cone[1]; mesh->facesTmp[10] = cone[3]; mesh->facesTmp[11] = cone[2];
1751*552f7358SJed Brown       *numFaces = 4;
1752*552f7358SJed Brown       *faceSize = 3;
1753*552f7358SJed Brown       *faces    = mesh->facesTmp;
1754*552f7358SJed Brown       break;
1755*552f7358SJed Brown     default:
1756*552f7358SJed Brown       SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim);
1757*552f7358SJed Brown     }
1758*552f7358SJed Brown     break;
1759*552f7358SJed Brown   default:
1760*552f7358SJed Brown     SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %D not supported", dim);
1761*552f7358SJed Brown   }
1762*552f7358SJed Brown   PetscFunctionReturn(0);
1763*552f7358SJed Brown }
1764*552f7358SJed Brown 
1765*552f7358SJed Brown #undef __FUNCT__
1766*552f7358SJed Brown #define __FUNCT__ "DMPlexGetMaxSizes"
1767*552f7358SJed Brown /*@
1768*552f7358SJed Brown   DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the Sieve DAG
1769*552f7358SJed Brown 
1770*552f7358SJed Brown   Not collective
1771*552f7358SJed Brown 
1772*552f7358SJed Brown   Input Parameter:
1773*552f7358SJed Brown . mesh - The DMPlex
1774*552f7358SJed Brown 
1775*552f7358SJed Brown   Output Parameters:
1776*552f7358SJed Brown + maxConeSize - The maximum number of in-edges
1777*552f7358SJed Brown - maxSupportSize - The maximum number of out-edges
1778*552f7358SJed Brown 
1779*552f7358SJed Brown   Level: beginner
1780*552f7358SJed Brown 
1781*552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart()
1782*552f7358SJed Brown @*/
1783*552f7358SJed Brown PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize)
1784*552f7358SJed Brown {
1785*552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *) dm->data;
1786*552f7358SJed Brown 
1787*552f7358SJed Brown   PetscFunctionBegin;
1788*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1789*552f7358SJed Brown   if (maxConeSize)    *maxConeSize    = mesh->maxConeSize;
1790*552f7358SJed Brown   if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize;
1791*552f7358SJed Brown   PetscFunctionReturn(0);
1792*552f7358SJed Brown }
1793*552f7358SJed Brown 
1794*552f7358SJed Brown #undef __FUNCT__
1795*552f7358SJed Brown #define __FUNCT__ "DMSetUp_Plex"
1796*552f7358SJed Brown PetscErrorCode DMSetUp_Plex(DM dm)
1797*552f7358SJed Brown {
1798*552f7358SJed Brown   DM_Plex    *mesh = (DM_Plex *) dm->data;
1799*552f7358SJed Brown   PetscInt       size;
1800*552f7358SJed Brown   PetscErrorCode ierr;
1801*552f7358SJed Brown 
1802*552f7358SJed Brown   PetscFunctionBegin;
1803*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1804*552f7358SJed Brown   ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr);
1805*552f7358SJed Brown   ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr);
1806*552f7358SJed Brown   ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->cones);CHKERRQ(ierr);
1807*552f7358SJed Brown   ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->coneOrientations);CHKERRQ(ierr);
1808*552f7358SJed Brown   ierr = PetscMemzero(mesh->coneOrientations, size * sizeof(PetscInt));CHKERRQ(ierr);
1809*552f7358SJed Brown   if (mesh->maxSupportSize) {
1810*552f7358SJed Brown     ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr);
1811*552f7358SJed Brown     ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr);
1812*552f7358SJed Brown     ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr);
1813*552f7358SJed Brown   }
1814*552f7358SJed Brown   PetscFunctionReturn(0);
1815*552f7358SJed Brown }
1816*552f7358SJed Brown 
1817*552f7358SJed Brown #undef __FUNCT__
1818*552f7358SJed Brown #define __FUNCT__ "DMCreateSubDM_Plex"
1819*552f7358SJed Brown PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm)
1820*552f7358SJed Brown {
1821*552f7358SJed Brown   PetscSection   section, sectionGlobal;
1822*552f7358SJed Brown   PetscInt      *subIndices;
1823*552f7358SJed Brown   PetscInt       subSize = 0, subOff = 0, nF, f, pStart, pEnd, p;
1824*552f7358SJed Brown   PetscErrorCode ierr;
1825*552f7358SJed Brown 
1826*552f7358SJed Brown   PetscFunctionBegin;
1827*552f7358SJed Brown   if (!numFields) PetscFunctionReturn(0);
1828*552f7358SJed Brown   ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
1829*552f7358SJed Brown   ierr = DMGetDefaultGlobalSection(dm, &sectionGlobal);CHKERRQ(ierr);
1830*552f7358SJed Brown   if (!section) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Must set default section for DMPlex before splitting fields");
1831*552f7358SJed Brown   if (!sectionGlobal) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Must set default global section for DMPlex before splitting fields");
1832*552f7358SJed Brown   ierr = PetscSectionGetNumFields(section, &nF);CHKERRQ(ierr);
1833*552f7358SJed Brown   if (numFields > nF) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Number of requested fields %d greater than number of DM fields %d", numFields, nF);
1834*552f7358SJed Brown   ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr);
1835*552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
1836*552f7358SJed Brown     PetscInt gdof;
1837*552f7358SJed Brown 
1838*552f7358SJed Brown     ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr);
1839*552f7358SJed Brown     if (gdof > 0) {
1840*552f7358SJed Brown       for (f = 0; f < numFields; ++f) {
1841*552f7358SJed Brown         PetscInt fdof, fcdof;
1842*552f7358SJed Brown 
1843*552f7358SJed Brown         ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr);
1844*552f7358SJed Brown         ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr);
1845*552f7358SJed Brown         subSize += fdof-fcdof;
1846*552f7358SJed Brown       }
1847*552f7358SJed Brown     }
1848*552f7358SJed Brown   }
1849*552f7358SJed Brown   ierr = PetscMalloc(subSize * sizeof(PetscInt), &subIndices);CHKERRQ(ierr);
1850*552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
1851*552f7358SJed Brown     PetscInt gdof, goff;
1852*552f7358SJed Brown 
1853*552f7358SJed Brown     ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr);
1854*552f7358SJed Brown     if (gdof > 0) {
1855*552f7358SJed Brown       ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr);
1856*552f7358SJed Brown       for (f = 0; f < numFields; ++f) {
1857*552f7358SJed Brown         PetscInt fdof, fcdof, fc, f2, poff = 0;
1858*552f7358SJed Brown 
1859*552f7358SJed Brown         /* Can get rid of this loop by storing field information in the global section */
1860*552f7358SJed Brown         for (f2 = 0; f2 < fields[f]; ++f2) {
1861*552f7358SJed Brown           ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr);
1862*552f7358SJed Brown           ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr);
1863*552f7358SJed Brown           poff += fdof-fcdof;
1864*552f7358SJed Brown         }
1865*552f7358SJed Brown         ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr);
1866*552f7358SJed Brown         ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr);
1867*552f7358SJed Brown         for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) {
1868*552f7358SJed Brown           subIndices[subOff] = goff+poff+fc;
1869*552f7358SJed Brown         }
1870*552f7358SJed Brown       }
1871*552f7358SJed Brown     }
1872*552f7358SJed Brown   }
1873*552f7358SJed Brown   if (is) {ierr = ISCreateGeneral(((PetscObject) dm)->comm, subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr);}
1874*552f7358SJed Brown   if (subdm) {
1875*552f7358SJed Brown     PetscSection subsection;
1876*552f7358SJed Brown     PetscBool    haveNull = PETSC_FALSE;
1877*552f7358SJed Brown     PetscInt     f, nf = 0;
1878*552f7358SJed Brown 
1879*552f7358SJed Brown     ierr = DMPlexClone(dm, subdm);CHKERRQ(ierr);
1880*552f7358SJed Brown     ierr = PetscSectionCreateSubsection(section, numFields, fields, &subsection);CHKERRQ(ierr);
1881*552f7358SJed Brown     ierr = DMSetDefaultSection(*subdm, subsection);CHKERRQ(ierr);
1882*552f7358SJed Brown     for (f = 0; f < numFields; ++f) {
1883*552f7358SJed Brown       (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[fields[f]];
1884*552f7358SJed Brown       if ((*subdm)->nullspaceConstructors[f]) {
1885*552f7358SJed Brown         haveNull = PETSC_TRUE;
1886*552f7358SJed Brown         nf       = f;
1887*552f7358SJed Brown       }
1888*552f7358SJed Brown     }
1889*552f7358SJed Brown     if (haveNull) {
1890*552f7358SJed Brown       MatNullSpace nullSpace;
1891*552f7358SJed Brown 
1892*552f7358SJed Brown       ierr = (*(*subdm)->nullspaceConstructors[nf])(*subdm, nf, &nullSpace);CHKERRQ(ierr);
1893*552f7358SJed Brown       ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr);
1894*552f7358SJed Brown       ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr);
1895*552f7358SJed Brown     }
1896*552f7358SJed Brown     if (dm->fields) {
1897*552f7358SJed Brown       if (nF != dm->numFields) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "The number of DM fields %d does not match the number of Section fields %d", dm->numFields, nF);
1898*552f7358SJed Brown       ierr = DMSetNumFields(*subdm, numFields);CHKERRQ(ierr);
1899*552f7358SJed Brown       for (f = 0; f < numFields; ++f) {
1900*552f7358SJed Brown         ierr = PetscOListDuplicate(dm->fields[fields[f]]->olist, &(*subdm)->fields[f]->olist);
1901*552f7358SJed Brown       }
1902*552f7358SJed Brown       if (numFields == 1) {
1903*552f7358SJed Brown         MatNullSpace space;
1904*552f7358SJed Brown         Mat          pmat;
1905*552f7358SJed Brown 
1906*552f7358SJed Brown         ierr = PetscObjectQuery((*subdm)->fields[0], "nullspace", (PetscObject *) &space);CHKERRQ(ierr);
1907*552f7358SJed Brown         if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) space);CHKERRQ(ierr);}
1908*552f7358SJed Brown         ierr = PetscObjectQuery((*subdm)->fields[0], "nearnullspace", (PetscObject *) &space);CHKERRQ(ierr);
1909*552f7358SJed Brown         if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nearnullspace", (PetscObject) space);CHKERRQ(ierr);}
1910*552f7358SJed Brown         ierr = PetscObjectQuery((*subdm)->fields[0], "pmat", (PetscObject *) &pmat);CHKERRQ(ierr);
1911*552f7358SJed Brown         if (pmat) {ierr = PetscObjectCompose((PetscObject) *is, "pmat", (PetscObject) pmat);CHKERRQ(ierr);}
1912*552f7358SJed Brown       }
1913*552f7358SJed Brown     }
1914*552f7358SJed Brown   }
1915*552f7358SJed Brown   PetscFunctionReturn(0);
1916*552f7358SJed Brown }
1917*552f7358SJed Brown 
1918*552f7358SJed Brown #undef __FUNCT__
1919*552f7358SJed Brown #define __FUNCT__ "DMPlexSymmetrize"
1920*552f7358SJed Brown /*@
1921*552f7358SJed Brown   DMPlexSymmetrize - Creates support (out-edge) information from cone (in-edge) inoformation
1922*552f7358SJed Brown 
1923*552f7358SJed Brown   Not collective
1924*552f7358SJed Brown 
1925*552f7358SJed Brown   Input Parameter:
1926*552f7358SJed Brown . mesh - The DMPlex
1927*552f7358SJed Brown 
1928*552f7358SJed Brown   Output Parameter:
1929*552f7358SJed Brown 
1930*552f7358SJed Brown   Note:
1931*552f7358SJed Brown   This should be called after all calls to DMPlexSetCone()
1932*552f7358SJed Brown 
1933*552f7358SJed Brown   Level: beginner
1934*552f7358SJed Brown 
1935*552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone()
1936*552f7358SJed Brown @*/
1937*552f7358SJed Brown PetscErrorCode DMPlexSymmetrize(DM dm)
1938*552f7358SJed Brown {
1939*552f7358SJed Brown   DM_Plex    *mesh = (DM_Plex *) dm->data;
1940*552f7358SJed Brown   PetscInt      *offsets;
1941*552f7358SJed Brown   PetscInt       supportSize;
1942*552f7358SJed Brown   PetscInt       pStart, pEnd, p;
1943*552f7358SJed Brown   PetscErrorCode ierr;
1944*552f7358SJed Brown 
1945*552f7358SJed Brown   PetscFunctionBegin;
1946*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1947*552f7358SJed Brown   if (mesh->supports) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex");
1948*552f7358SJed Brown   /* Calculate support sizes */
1949*552f7358SJed Brown   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
1950*552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
1951*552f7358SJed Brown     PetscInt dof, off, c;
1952*552f7358SJed Brown 
1953*552f7358SJed Brown     ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr);
1954*552f7358SJed Brown     ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr);
1955*552f7358SJed Brown     for (c = off; c < off+dof; ++c) {
1956*552f7358SJed Brown       ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr);
1957*552f7358SJed Brown     }
1958*552f7358SJed Brown   }
1959*552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
1960*552f7358SJed Brown     PetscInt dof;
1961*552f7358SJed Brown 
1962*552f7358SJed Brown     ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr);
1963*552f7358SJed Brown     mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof);
1964*552f7358SJed Brown   }
1965*552f7358SJed Brown   ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr);
1966*552f7358SJed Brown   /* Calculate supports */
1967*552f7358SJed Brown   ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr);
1968*552f7358SJed Brown   ierr = PetscMalloc(supportSize * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr);
1969*552f7358SJed Brown   ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &offsets);CHKERRQ(ierr);
1970*552f7358SJed Brown   ierr = PetscMemzero(offsets, (pEnd - pStart) * sizeof(PetscInt));CHKERRQ(ierr);
1971*552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
1972*552f7358SJed Brown     PetscInt dof, off, c;
1973*552f7358SJed Brown 
1974*552f7358SJed Brown     ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr);
1975*552f7358SJed Brown     ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr);
1976*552f7358SJed Brown     for (c = off; c < off+dof; ++c) {
1977*552f7358SJed Brown       const PetscInt q = mesh->cones[c];
1978*552f7358SJed Brown       PetscInt       offS;
1979*552f7358SJed Brown 
1980*552f7358SJed Brown       ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr);
1981*552f7358SJed Brown       mesh->supports[offS+offsets[q]] = p;
1982*552f7358SJed Brown       ++offsets[q];
1983*552f7358SJed Brown     }
1984*552f7358SJed Brown   }
1985*552f7358SJed Brown   ierr = PetscFree(offsets);CHKERRQ(ierr);
1986*552f7358SJed Brown   PetscFunctionReturn(0);
1987*552f7358SJed Brown }
1988*552f7358SJed Brown 
1989*552f7358SJed Brown #undef __FUNCT__
1990*552f7358SJed Brown #define __FUNCT__ "DMPlexSetDepth_Private"
1991*552f7358SJed Brown PetscErrorCode DMPlexSetDepth_Private(DM dm, PetscInt p, PetscInt *depth)
1992*552f7358SJed Brown {
1993*552f7358SJed Brown   PetscInt       d;
1994*552f7358SJed Brown   PetscErrorCode ierr;
1995*552f7358SJed Brown 
1996*552f7358SJed Brown   PetscFunctionBegin;
1997*552f7358SJed Brown   ierr = DMPlexGetLabelValue(dm, "depth", p, &d);CHKERRQ(ierr);
1998*552f7358SJed Brown   if (d < 0) {
1999*552f7358SJed Brown     /* We are guaranteed that the point has a cone since the depth was not yet set */
2000*552f7358SJed Brown     const PetscInt *cone = PETSC_NULL;
2001*552f7358SJed Brown     PetscInt        dCone;
2002*552f7358SJed Brown 
2003*552f7358SJed Brown     ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr);
2004*552f7358SJed Brown     ierr = DMPlexSetDepth_Private(dm, cone[0], &dCone);CHKERRQ(ierr);
2005*552f7358SJed Brown     d    = dCone+1;
2006*552f7358SJed Brown     ierr = DMPlexSetLabelValue(dm, "depth", p, d);CHKERRQ(ierr);
2007*552f7358SJed Brown   }
2008*552f7358SJed Brown   *depth = d;
2009*552f7358SJed Brown   PetscFunctionReturn(0);
2010*552f7358SJed Brown }
2011*552f7358SJed Brown 
2012*552f7358SJed Brown #undef __FUNCT__
2013*552f7358SJed Brown #define __FUNCT__ "DMPlexStratify"
2014*552f7358SJed Brown /*@
2015*552f7358SJed Brown   DMPlexStratify - The Sieve DAG for most topologies is a graded poset (http://en.wikipedia.org/wiki/Graded_poset), and
2016*552f7358SJed Brown   can be illustrated by Hasse Diagram (a http://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the
2017*552f7358SJed Brown   same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in
2018*552f7358SJed Brown   the DAG.
2019*552f7358SJed Brown 
2020*552f7358SJed Brown   Not collective
2021*552f7358SJed Brown 
2022*552f7358SJed Brown   Input Parameter:
2023*552f7358SJed Brown . mesh - The DMPlex
2024*552f7358SJed Brown 
2025*552f7358SJed Brown   Output Parameter:
2026*552f7358SJed Brown 
2027*552f7358SJed Brown   Notes:
2028*552f7358SJed Brown   The normal association for the point grade is element dimension (or co-dimension). For instance, all vertices would
2029*552f7358SJed Brown   have depth 0, and all edges depth 1. Likewise, all cells heights would have height 0, and all faces height 1.
2030*552f7358SJed Brown 
2031*552f7358SJed Brown   This should be called after all calls to DMPlexSymmetrize()
2032*552f7358SJed Brown 
2033*552f7358SJed Brown   Level: beginner
2034*552f7358SJed Brown 
2035*552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSymmetrize()
2036*552f7358SJed Brown @*/
2037*552f7358SJed Brown PetscErrorCode DMPlexStratify(DM dm)
2038*552f7358SJed Brown {
2039*552f7358SJed Brown   DM_Plex    *mesh = (DM_Plex *) dm->data;
2040*552f7358SJed Brown   PetscInt       pStart, pEnd, p;
2041*552f7358SJed Brown   PetscInt       numRoots = 0, numLeaves = 0;
2042*552f7358SJed Brown   PetscErrorCode ierr;
2043*552f7358SJed Brown 
2044*552f7358SJed Brown   PetscFunctionBegin;
2045*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2046*552f7358SJed Brown   ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr);
2047*552f7358SJed Brown   /* Calculate depth */
2048*552f7358SJed Brown   ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr);
2049*552f7358SJed Brown   /* Initialize roots and count leaves */
2050*552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
2051*552f7358SJed Brown     PetscInt coneSize, supportSize;
2052*552f7358SJed Brown 
2053*552f7358SJed Brown     ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
2054*552f7358SJed Brown     ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr);
2055*552f7358SJed Brown     if (!coneSize && supportSize) {
2056*552f7358SJed Brown       ++numRoots;
2057*552f7358SJed Brown       ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr);
2058*552f7358SJed Brown     } else if (!supportSize && coneSize) {
2059*552f7358SJed Brown       ++numLeaves;
2060*552f7358SJed Brown     } else if (!supportSize && !coneSize) {
2061*552f7358SJed Brown       /* Isolated points */
2062*552f7358SJed Brown       ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr);
2063*552f7358SJed Brown     }
2064*552f7358SJed Brown   }
2065*552f7358SJed Brown   if (numRoots + numLeaves == (pEnd - pStart)) {
2066*552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
2067*552f7358SJed Brown       PetscInt coneSize, supportSize;
2068*552f7358SJed Brown 
2069*552f7358SJed Brown       ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
2070*552f7358SJed Brown       ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr);
2071*552f7358SJed Brown       if (!supportSize && coneSize) {
2072*552f7358SJed Brown         ierr = DMPlexSetLabelValue(dm, "depth", p, 1);CHKERRQ(ierr);
2073*552f7358SJed Brown       }
2074*552f7358SJed Brown     }
2075*552f7358SJed Brown   } else {
2076*552f7358SJed Brown     /* This might be slow since lookup is not fast */
2077*552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
2078*552f7358SJed Brown       PetscInt depth;
2079*552f7358SJed Brown 
2080*552f7358SJed Brown       ierr = DMPlexSetDepth_Private(dm, p, &depth);CHKERRQ(ierr);
2081*552f7358SJed Brown     }
2082*552f7358SJed Brown   }
2083*552f7358SJed Brown   ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr);
2084*552f7358SJed Brown   PetscFunctionReturn(0);
2085*552f7358SJed Brown }
2086*552f7358SJed Brown 
2087*552f7358SJed Brown #undef __FUNCT__
2088*552f7358SJed Brown #define __FUNCT__ "DMPlexGetJoin"
2089*552f7358SJed Brown /*@C
2090*552f7358SJed Brown   DMPlexGetJoin - Get an array for the join of the set of points
2091*552f7358SJed Brown 
2092*552f7358SJed Brown   Not Collective
2093*552f7358SJed Brown 
2094*552f7358SJed Brown   Input Parameters:
2095*552f7358SJed Brown + dm - The DMPlex object
2096*552f7358SJed Brown . numPoints - The number of input points for the join
2097*552f7358SJed Brown - points - The input points
2098*552f7358SJed Brown 
2099*552f7358SJed Brown   Output Parameters:
2100*552f7358SJed Brown + numCoveredPoints - The number of points in the join
2101*552f7358SJed Brown - coveredPoints - The points in the join
2102*552f7358SJed Brown 
2103*552f7358SJed Brown   Level: intermediate
2104*552f7358SJed Brown 
2105*552f7358SJed Brown   Note: Currently, this is restricted to a single level join
2106*552f7358SJed Brown 
2107*552f7358SJed Brown .keywords: mesh
2108*552f7358SJed Brown .seealso: DMPlexRestoreJoin(), DMPlexGetMeet()
2109*552f7358SJed Brown @*/
2110*552f7358SJed Brown PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
2111*552f7358SJed Brown {
2112*552f7358SJed Brown   DM_Plex    *mesh = (DM_Plex *) dm->data;
2113*552f7358SJed Brown   PetscInt      *join[2];
2114*552f7358SJed Brown   PetscInt       joinSize, i = 0;
2115*552f7358SJed Brown   PetscInt       dof, off, p, c, m;
2116*552f7358SJed Brown   PetscErrorCode ierr;
2117*552f7358SJed Brown 
2118*552f7358SJed Brown   PetscFunctionBegin;
2119*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2120*552f7358SJed Brown   PetscValidPointer(points, 2);
2121*552f7358SJed Brown   PetscValidPointer(numCoveredPoints, 3);
2122*552f7358SJed Brown   PetscValidPointer(coveredPoints, 4);
2123*552f7358SJed Brown   ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[0]);CHKERRQ(ierr);
2124*552f7358SJed Brown   ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1]);CHKERRQ(ierr);
2125*552f7358SJed Brown   /* Copy in support of first point */
2126*552f7358SJed Brown   ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr);
2127*552f7358SJed Brown   ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr);
2128*552f7358SJed Brown   for (joinSize = 0; joinSize < dof; ++joinSize) {
2129*552f7358SJed Brown     join[i][joinSize] = mesh->supports[off+joinSize];
2130*552f7358SJed Brown   }
2131*552f7358SJed Brown   /* Check each successive support */
2132*552f7358SJed Brown   for (p = 1; p < numPoints; ++p) {
2133*552f7358SJed Brown     PetscInt newJoinSize = 0;
2134*552f7358SJed Brown 
2135*552f7358SJed Brown     ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr);
2136*552f7358SJed Brown     ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr);
2137*552f7358SJed Brown     for (c = 0; c < dof; ++c) {
2138*552f7358SJed Brown       const PetscInt point = mesh->supports[off+c];
2139*552f7358SJed Brown 
2140*552f7358SJed Brown       for (m = 0; m < joinSize; ++m) {
2141*552f7358SJed Brown         if (point == join[i][m]) {
2142*552f7358SJed Brown           join[1-i][newJoinSize++] = point;
2143*552f7358SJed Brown           break;
2144*552f7358SJed Brown         }
2145*552f7358SJed Brown       }
2146*552f7358SJed Brown     }
2147*552f7358SJed Brown     joinSize = newJoinSize;
2148*552f7358SJed Brown     i = 1-i;
2149*552f7358SJed Brown   }
2150*552f7358SJed Brown   *numCoveredPoints = joinSize;
2151*552f7358SJed Brown   *coveredPoints    = join[i];
2152*552f7358SJed Brown   ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr);
2153*552f7358SJed Brown   PetscFunctionReturn(0);
2154*552f7358SJed Brown }
2155*552f7358SJed Brown 
2156*552f7358SJed Brown #undef __FUNCT__
2157*552f7358SJed Brown #define __FUNCT__ "DMPlexRestoreJoin"
2158*552f7358SJed Brown /*@C
2159*552f7358SJed Brown   DMPlexRestoreJoin - Restore an array for the join of the set of points
2160*552f7358SJed Brown 
2161*552f7358SJed Brown   Not Collective
2162*552f7358SJed Brown 
2163*552f7358SJed Brown   Input Parameters:
2164*552f7358SJed Brown + dm - The DMPlex object
2165*552f7358SJed Brown . numPoints - The number of input points for the join
2166*552f7358SJed Brown - points - The input points
2167*552f7358SJed Brown 
2168*552f7358SJed Brown   Output Parameters:
2169*552f7358SJed Brown + numCoveredPoints - The number of points in the join
2170*552f7358SJed Brown - coveredPoints - The points in the join
2171*552f7358SJed Brown 
2172*552f7358SJed Brown   Level: intermediate
2173*552f7358SJed Brown 
2174*552f7358SJed Brown .keywords: mesh
2175*552f7358SJed Brown .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet()
2176*552f7358SJed Brown @*/
2177*552f7358SJed Brown PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
2178*552f7358SJed Brown {
2179*552f7358SJed Brown   PetscErrorCode ierr;
2180*552f7358SJed Brown 
2181*552f7358SJed Brown   PetscFunctionBegin;
2182*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2183*552f7358SJed Brown   PetscValidPointer(coveredPoints, 4);
2184*552f7358SJed Brown   ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void *) coveredPoints);CHKERRQ(ierr);
2185*552f7358SJed Brown   PetscFunctionReturn(0);
2186*552f7358SJed Brown }
2187*552f7358SJed Brown 
2188*552f7358SJed Brown #undef __FUNCT__
2189*552f7358SJed Brown #define __FUNCT__ "DMPlexGetFullJoin"
2190*552f7358SJed Brown /*@C
2191*552f7358SJed Brown   DMPlexGetFullJoin - Get an array for the join of the set of points
2192*552f7358SJed Brown 
2193*552f7358SJed Brown   Not Collective
2194*552f7358SJed Brown 
2195*552f7358SJed Brown   Input Parameters:
2196*552f7358SJed Brown + dm - The DMPlex object
2197*552f7358SJed Brown . numPoints - The number of input points for the join
2198*552f7358SJed Brown - points - The input points
2199*552f7358SJed Brown 
2200*552f7358SJed Brown   Output Parameters:
2201*552f7358SJed Brown + numCoveredPoints - The number of points in the join
2202*552f7358SJed Brown - coveredPoints - The points in the join
2203*552f7358SJed Brown 
2204*552f7358SJed Brown   Level: intermediate
2205*552f7358SJed Brown 
2206*552f7358SJed Brown .keywords: mesh
2207*552f7358SJed Brown .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet()
2208*552f7358SJed Brown @*/
2209*552f7358SJed Brown PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
2210*552f7358SJed Brown {
2211*552f7358SJed Brown   DM_Plex    *mesh = (DM_Plex *) dm->data;
2212*552f7358SJed Brown   PetscInt      *offsets, **closures;
2213*552f7358SJed Brown   PetscInt      *join[2];
2214*552f7358SJed Brown   PetscInt       depth = 0, maxSize, joinSize = 0, i = 0;
2215*552f7358SJed Brown   PetscInt       p, d, c, m;
2216*552f7358SJed Brown   PetscErrorCode ierr;
2217*552f7358SJed Brown 
2218*552f7358SJed Brown   PetscFunctionBegin;
2219*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2220*552f7358SJed Brown   PetscValidPointer(points, 2);
2221*552f7358SJed Brown   PetscValidPointer(numCoveredPoints, 3);
2222*552f7358SJed Brown   PetscValidPointer(coveredPoints, 4);
2223*552f7358SJed Brown 
2224*552f7358SJed Brown   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
2225*552f7358SJed Brown   ierr = PetscMalloc(numPoints * sizeof(PetscInt *), &closures);CHKERRQ(ierr);
2226*552f7358SJed Brown   ierr = PetscMemzero(closures,numPoints*sizeof(PetscInt*));CHKERRQ(ierr);
2227*552f7358SJed Brown   ierr = DMGetWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr);
2228*552f7358SJed Brown   maxSize = (PetscInt) (pow((PetscReal) mesh->maxSupportSize, depth)+1);
2229*552f7358SJed Brown   ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[0]);CHKERRQ(ierr);
2230*552f7358SJed Brown   ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[1]);CHKERRQ(ierr);
2231*552f7358SJed Brown 
2232*552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
2233*552f7358SJed Brown     PetscInt closureSize;
2234*552f7358SJed Brown 
2235*552f7358SJed Brown     ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr);
2236*552f7358SJed Brown     offsets[p*(depth+2)+0] = 0;
2237*552f7358SJed Brown     for (d = 0; d < depth+1; ++d) {
2238*552f7358SJed Brown       PetscInt pStart, pEnd, i;
2239*552f7358SJed Brown 
2240*552f7358SJed Brown       ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr);
2241*552f7358SJed Brown       for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) {
2242*552f7358SJed Brown         if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) {
2243*552f7358SJed Brown           offsets[p*(depth+2)+d+1] = i;
2244*552f7358SJed Brown           break;
2245*552f7358SJed Brown         }
2246*552f7358SJed Brown       }
2247*552f7358SJed Brown       if (i == closureSize) offsets[p*(depth+2)+d+1] = i;
2248*552f7358SJed Brown     }
2249*552f7358SJed Brown     if (offsets[p*(depth+2)+depth+1] != closureSize) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(depth+2)+depth+1], closureSize);
2250*552f7358SJed Brown   }
2251*552f7358SJed Brown   for (d = 0; d < depth+1; ++d) {
2252*552f7358SJed Brown     PetscInt dof;
2253*552f7358SJed Brown 
2254*552f7358SJed Brown     /* Copy in support of first point */
2255*552f7358SJed Brown     dof = offsets[d+1] - offsets[d];
2256*552f7358SJed Brown     for (joinSize = 0; joinSize < dof; ++joinSize) {
2257*552f7358SJed Brown       join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2];
2258*552f7358SJed Brown     }
2259*552f7358SJed Brown     /* Check each successive cone */
2260*552f7358SJed Brown     for (p = 1; p < numPoints && joinSize; ++p) {
2261*552f7358SJed Brown       PetscInt newJoinSize = 0;
2262*552f7358SJed Brown 
2263*552f7358SJed Brown       dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d];
2264*552f7358SJed Brown       for (c = 0; c < dof; ++c) {
2265*552f7358SJed Brown         const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2];
2266*552f7358SJed Brown 
2267*552f7358SJed Brown         for (m = 0; m < joinSize; ++m) {
2268*552f7358SJed Brown           if (point == join[i][m]) {
2269*552f7358SJed Brown             join[1-i][newJoinSize++] = point;
2270*552f7358SJed Brown             break;
2271*552f7358SJed Brown           }
2272*552f7358SJed Brown         }
2273*552f7358SJed Brown       }
2274*552f7358SJed Brown       joinSize = newJoinSize;
2275*552f7358SJed Brown       i = 1-i;
2276*552f7358SJed Brown     }
2277*552f7358SJed Brown     if (joinSize) break;
2278*552f7358SJed Brown   }
2279*552f7358SJed Brown   *numCoveredPoints = joinSize;
2280*552f7358SJed Brown   *coveredPoints    = join[i];
2281*552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
2282*552f7358SJed Brown     ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, PETSC_NULL, &closures[p]);CHKERRQ(ierr);
2283*552f7358SJed Brown   }
2284*552f7358SJed Brown   ierr = PetscFree(closures);CHKERRQ(ierr);
2285*552f7358SJed Brown   ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr);
2286*552f7358SJed Brown   ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr);
2287*552f7358SJed Brown   PetscFunctionReturn(0);
2288*552f7358SJed Brown }
2289*552f7358SJed Brown 
2290*552f7358SJed Brown #undef __FUNCT__
2291*552f7358SJed Brown #define __FUNCT__ "DMPlexGetMeet"
2292*552f7358SJed Brown /*@C
2293*552f7358SJed Brown   DMPlexGetMeet - Get an array for the meet of the set of points
2294*552f7358SJed Brown 
2295*552f7358SJed Brown   Not Collective
2296*552f7358SJed Brown 
2297*552f7358SJed Brown   Input Parameters:
2298*552f7358SJed Brown + dm - The DMPlex object
2299*552f7358SJed Brown . numPoints - The number of input points for the meet
2300*552f7358SJed Brown - points - The input points
2301*552f7358SJed Brown 
2302*552f7358SJed Brown   Output Parameters:
2303*552f7358SJed Brown + numCoveredPoints - The number of points in the meet
2304*552f7358SJed Brown - coveredPoints - The points in the meet
2305*552f7358SJed Brown 
2306*552f7358SJed Brown   Level: intermediate
2307*552f7358SJed Brown 
2308*552f7358SJed Brown   Note: Currently, this is restricted to a single level meet
2309*552f7358SJed Brown 
2310*552f7358SJed Brown .keywords: mesh
2311*552f7358SJed Brown .seealso: DMPlexRestoreMeet(), DMPlexGetJoin()
2312*552f7358SJed Brown @*/
2313*552f7358SJed Brown PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints)
2314*552f7358SJed Brown {
2315*552f7358SJed Brown   DM_Plex    *mesh = (DM_Plex *) dm->data;
2316*552f7358SJed Brown   PetscInt      *meet[2];
2317*552f7358SJed Brown   PetscInt       meetSize, i = 0;
2318*552f7358SJed Brown   PetscInt       dof, off, p, c, m;
2319*552f7358SJed Brown   PetscErrorCode ierr;
2320*552f7358SJed Brown 
2321*552f7358SJed Brown   PetscFunctionBegin;
2322*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2323*552f7358SJed Brown   PetscValidPointer(points, 2);
2324*552f7358SJed Brown   PetscValidPointer(numCoveringPoints, 3);
2325*552f7358SJed Brown   PetscValidPointer(coveringPoints, 4);
2326*552f7358SJed Brown   ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[0]);CHKERRQ(ierr);
2327*552f7358SJed Brown   ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1]);CHKERRQ(ierr);
2328*552f7358SJed Brown   /* Copy in cone of first point */
2329*552f7358SJed Brown   ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr);
2330*552f7358SJed Brown   ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr);
2331*552f7358SJed Brown   for (meetSize = 0; meetSize < dof; ++meetSize) {
2332*552f7358SJed Brown     meet[i][meetSize] = mesh->cones[off+meetSize];
2333*552f7358SJed Brown   }
2334*552f7358SJed Brown   /* Check each successive cone */
2335*552f7358SJed Brown   for (p = 1; p < numPoints; ++p) {
2336*552f7358SJed Brown     PetscInt newMeetSize = 0;
2337*552f7358SJed Brown 
2338*552f7358SJed Brown     ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr);
2339*552f7358SJed Brown     ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr);
2340*552f7358SJed Brown     for (c = 0; c < dof; ++c) {
2341*552f7358SJed Brown       const PetscInt point = mesh->cones[off+c];
2342*552f7358SJed Brown 
2343*552f7358SJed Brown       for (m = 0; m < meetSize; ++m) {
2344*552f7358SJed Brown         if (point == meet[i][m]) {
2345*552f7358SJed Brown           meet[1-i][newMeetSize++] = point;
2346*552f7358SJed Brown           break;
2347*552f7358SJed Brown         }
2348*552f7358SJed Brown       }
2349*552f7358SJed Brown     }
2350*552f7358SJed Brown     meetSize = newMeetSize;
2351*552f7358SJed Brown     i = 1-i;
2352*552f7358SJed Brown   }
2353*552f7358SJed Brown   *numCoveringPoints = meetSize;
2354*552f7358SJed Brown   *coveringPoints    = meet[i];
2355*552f7358SJed Brown   ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr);
2356*552f7358SJed Brown   PetscFunctionReturn(0);
2357*552f7358SJed Brown }
2358*552f7358SJed Brown 
2359*552f7358SJed Brown #undef __FUNCT__
2360*552f7358SJed Brown #define __FUNCT__ "DMPlexRestoreMeet"
2361*552f7358SJed Brown /*@C
2362*552f7358SJed Brown   DMPlexRestoreMeet - Restore an array for the meet of the set of points
2363*552f7358SJed Brown 
2364*552f7358SJed Brown   Not Collective
2365*552f7358SJed Brown 
2366*552f7358SJed Brown   Input Parameters:
2367*552f7358SJed Brown + dm - The DMPlex object
2368*552f7358SJed Brown . numPoints - The number of input points for the meet
2369*552f7358SJed Brown - points - The input points
2370*552f7358SJed Brown 
2371*552f7358SJed Brown   Output Parameters:
2372*552f7358SJed Brown + numCoveredPoints - The number of points in the meet
2373*552f7358SJed Brown - coveredPoints - The points in the meet
2374*552f7358SJed Brown 
2375*552f7358SJed Brown   Level: intermediate
2376*552f7358SJed Brown 
2377*552f7358SJed Brown .keywords: mesh
2378*552f7358SJed Brown .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin()
2379*552f7358SJed Brown @*/
2380*552f7358SJed Brown PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
2381*552f7358SJed Brown {
2382*552f7358SJed Brown   PetscErrorCode ierr;
2383*552f7358SJed Brown 
2384*552f7358SJed Brown   PetscFunctionBegin;
2385*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2386*552f7358SJed Brown   PetscValidPointer(coveredPoints, 4);
2387*552f7358SJed Brown   ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void *) coveredPoints);CHKERRQ(ierr);
2388*552f7358SJed Brown   PetscFunctionReturn(0);
2389*552f7358SJed Brown }
2390*552f7358SJed Brown 
2391*552f7358SJed Brown #undef __FUNCT__
2392*552f7358SJed Brown #define __FUNCT__ "DMPlexGetFullMeet"
2393*552f7358SJed Brown /*@C
2394*552f7358SJed Brown   DMPlexGetFullMeet - Get an array for the meet of the set of points
2395*552f7358SJed Brown 
2396*552f7358SJed Brown   Not Collective
2397*552f7358SJed Brown 
2398*552f7358SJed Brown   Input Parameters:
2399*552f7358SJed Brown + dm - The DMPlex object
2400*552f7358SJed Brown . numPoints - The number of input points for the meet
2401*552f7358SJed Brown - points - The input points
2402*552f7358SJed Brown 
2403*552f7358SJed Brown   Output Parameters:
2404*552f7358SJed Brown + numCoveredPoints - The number of points in the meet
2405*552f7358SJed Brown - coveredPoints - The points in the meet
2406*552f7358SJed Brown 
2407*552f7358SJed Brown   Level: intermediate
2408*552f7358SJed Brown 
2409*552f7358SJed Brown .keywords: mesh
2410*552f7358SJed Brown .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin()
2411*552f7358SJed Brown @*/
2412*552f7358SJed Brown PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
2413*552f7358SJed Brown {
2414*552f7358SJed Brown   DM_Plex    *mesh = (DM_Plex *) dm->data;
2415*552f7358SJed Brown   PetscInt      *offsets, **closures;
2416*552f7358SJed Brown   PetscInt      *meet[2];
2417*552f7358SJed Brown   PetscInt       height = 0, maxSize, meetSize = 0, i = 0;
2418*552f7358SJed Brown   PetscInt       p, h, c, m;
2419*552f7358SJed Brown   PetscErrorCode ierr;
2420*552f7358SJed Brown 
2421*552f7358SJed Brown   PetscFunctionBegin;
2422*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2423*552f7358SJed Brown   PetscValidPointer(points, 2);
2424*552f7358SJed Brown   PetscValidPointer(numCoveredPoints, 3);
2425*552f7358SJed Brown   PetscValidPointer(coveredPoints, 4);
2426*552f7358SJed Brown 
2427*552f7358SJed Brown   ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr);
2428*552f7358SJed Brown   ierr = PetscMalloc(numPoints * sizeof(PetscInt *), &closures);CHKERRQ(ierr);
2429*552f7358SJed Brown   ierr = DMGetWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr);
2430*552f7358SJed Brown   maxSize = (PetscInt) (pow((PetscReal) mesh->maxConeSize, height)+1);
2431*552f7358SJed Brown   ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[0]);CHKERRQ(ierr);
2432*552f7358SJed Brown   ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[1]);CHKERRQ(ierr);
2433*552f7358SJed Brown 
2434*552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
2435*552f7358SJed Brown     PetscInt closureSize;
2436*552f7358SJed Brown 
2437*552f7358SJed Brown     ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr);
2438*552f7358SJed Brown     offsets[p*(height+2)+0] = 0;
2439*552f7358SJed Brown     for (h = 0; h < height+1; ++h) {
2440*552f7358SJed Brown       PetscInt pStart, pEnd, i;
2441*552f7358SJed Brown 
2442*552f7358SJed Brown       ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr);
2443*552f7358SJed Brown       for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) {
2444*552f7358SJed Brown         if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) {
2445*552f7358SJed Brown           offsets[p*(height+2)+h+1] = i;
2446*552f7358SJed Brown           break;
2447*552f7358SJed Brown         }
2448*552f7358SJed Brown       }
2449*552f7358SJed Brown       if (i == closureSize) offsets[p*(height+2)+h+1] = i;
2450*552f7358SJed Brown     }
2451*552f7358SJed Brown     if (offsets[p*(height+2)+height+1] != closureSize) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(height+2)+height+1], closureSize);
2452*552f7358SJed Brown   }
2453*552f7358SJed Brown   for (h = 0; h < height+1; ++h) {
2454*552f7358SJed Brown     PetscInt dof;
2455*552f7358SJed Brown 
2456*552f7358SJed Brown     /* Copy in cone of first point */
2457*552f7358SJed Brown     dof = offsets[h+1] - offsets[h];
2458*552f7358SJed Brown     for (meetSize = 0; meetSize < dof; ++meetSize) {
2459*552f7358SJed Brown       meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2];
2460*552f7358SJed Brown     }
2461*552f7358SJed Brown     /* Check each successive cone */
2462*552f7358SJed Brown     for (p = 1; p < numPoints && meetSize; ++p) {
2463*552f7358SJed Brown       PetscInt newMeetSize = 0;
2464*552f7358SJed Brown 
2465*552f7358SJed Brown       dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h];
2466*552f7358SJed Brown       for (c = 0; c < dof; ++c) {
2467*552f7358SJed Brown         const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2];
2468*552f7358SJed Brown 
2469*552f7358SJed Brown         for (m = 0; m < meetSize; ++m) {
2470*552f7358SJed Brown           if (point == meet[i][m]) {
2471*552f7358SJed Brown             meet[1-i][newMeetSize++] = point;
2472*552f7358SJed Brown             break;
2473*552f7358SJed Brown           }
2474*552f7358SJed Brown         }
2475*552f7358SJed Brown       }
2476*552f7358SJed Brown       meetSize = newMeetSize;
2477*552f7358SJed Brown       i = 1-i;
2478*552f7358SJed Brown     }
2479*552f7358SJed Brown     if (meetSize) break;
2480*552f7358SJed Brown   }
2481*552f7358SJed Brown   *numCoveredPoints = meetSize;
2482*552f7358SJed Brown   *coveredPoints    = meet[i];
2483*552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
2484*552f7358SJed Brown     ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, PETSC_NULL, &closures[p]);CHKERRQ(ierr);
2485*552f7358SJed Brown   }
2486*552f7358SJed Brown   ierr = PetscFree(closures);CHKERRQ(ierr);
2487*552f7358SJed Brown   ierr = DMRestoreWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr);
2488*552f7358SJed Brown   ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr);
2489*552f7358SJed Brown   PetscFunctionReturn(0);
2490*552f7358SJed Brown }
2491*552f7358SJed Brown 
2492*552f7358SJed Brown #undef __FUNCT__
2493*552f7358SJed Brown #define __FUNCT__ "DMPlexGetNumFaceVertices"
2494*552f7358SJed Brown static PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt numCorners, PetscInt *numFaceVertices) {
2495*552f7358SJed Brown   MPI_Comm       comm = ((PetscObject) dm)->comm;
2496*552f7358SJed Brown   PetscInt       cellDim;
2497*552f7358SJed Brown   PetscErrorCode ierr;
2498*552f7358SJed Brown 
2499*552f7358SJed Brown   PetscFunctionBegin;
2500*552f7358SJed Brown   PetscValidPointer(numFaceVertices,3);
2501*552f7358SJed Brown   ierr = DMPlexGetDimension(dm, &cellDim);CHKERRQ(ierr);
2502*552f7358SJed Brown   switch(cellDim) {
2503*552f7358SJed Brown   case 0:
2504*552f7358SJed Brown     *numFaceVertices = 0;
2505*552f7358SJed Brown     break;
2506*552f7358SJed Brown   case 1:
2507*552f7358SJed Brown     *numFaceVertices = 1;
2508*552f7358SJed Brown     break;
2509*552f7358SJed Brown   case 2:
2510*552f7358SJed Brown     switch(numCorners) {
2511*552f7358SJed Brown     case 3: // triangle
2512*552f7358SJed Brown       *numFaceVertices = 2; // Edge has 2 vertices
2513*552f7358SJed Brown       break;
2514*552f7358SJed Brown     case 4: // quadrilateral
2515*552f7358SJed Brown       *numFaceVertices = 2; // Edge has 2 vertices
2516*552f7358SJed Brown       break;
2517*552f7358SJed Brown     case 6: // quadratic triangle, tri and quad cohesive Lagrange cells
2518*552f7358SJed Brown       *numFaceVertices = 3; // Edge has 3 vertices
2519*552f7358SJed Brown       break;
2520*552f7358SJed Brown     case 9: // quadratic quadrilateral, quadratic quad cohesive Lagrange cells
2521*552f7358SJed Brown       *numFaceVertices = 3; // Edge has 3 vertices
2522*552f7358SJed Brown       break;
2523*552f7358SJed Brown     default:
2524*552f7358SJed Brown       SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim);
2525*552f7358SJed Brown     }
2526*552f7358SJed Brown     break;
2527*552f7358SJed Brown   case 3:
2528*552f7358SJed Brown     switch(numCorners)	{
2529*552f7358SJed Brown     case 4: // tetradehdron
2530*552f7358SJed Brown       *numFaceVertices = 3; // Face has 3 vertices
2531*552f7358SJed Brown       break;
2532*552f7358SJed Brown     case 6: // tet cohesive cells
2533*552f7358SJed Brown       *numFaceVertices = 4; // Face has 4 vertices
2534*552f7358SJed Brown       break;
2535*552f7358SJed Brown     case 8: // hexahedron
2536*552f7358SJed Brown       *numFaceVertices = 4; // Face has 4 vertices
2537*552f7358SJed Brown       break;
2538*552f7358SJed Brown     case 9: // tet cohesive Lagrange cells
2539*552f7358SJed Brown       *numFaceVertices = 6; // Face has 6 vertices
2540*552f7358SJed Brown       break;
2541*552f7358SJed Brown     case 10: // quadratic tetrahedron
2542*552f7358SJed Brown       *numFaceVertices = 6; // Face has 6 vertices
2543*552f7358SJed Brown       break;
2544*552f7358SJed Brown     case 12: // hex cohesive Lagrange cells
2545*552f7358SJed Brown       *numFaceVertices = 6; // Face has 6 vertices
2546*552f7358SJed Brown       break;
2547*552f7358SJed Brown     case 18: // quadratic tet cohesive Lagrange cells
2548*552f7358SJed Brown       *numFaceVertices = 6; // Face has 6 vertices
2549*552f7358SJed Brown       break;
2550*552f7358SJed Brown     case 27: // quadratic hexahedron, quadratic hex cohesive Lagrange cells
2551*552f7358SJed Brown       *numFaceVertices = 9; // Face has 9 vertices
2552*552f7358SJed Brown       break;
2553*552f7358SJed Brown     default:
2554*552f7358SJed Brown       SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim);
2555*552f7358SJed Brown     }
2556*552f7358SJed Brown     break;
2557*552f7358SJed Brown   default:
2558*552f7358SJed Brown     SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %d", cellDim);
2559*552f7358SJed Brown   }
2560*552f7358SJed Brown   PetscFunctionReturn(0);
2561*552f7358SJed Brown }
2562*552f7358SJed Brown 
2563*552f7358SJed Brown #undef __FUNCT__
2564*552f7358SJed Brown #define __FUNCT__ "DMPlexCreateNeighborCSR"
2565*552f7358SJed Brown PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) {
2566*552f7358SJed Brown   const PetscInt maxFaceCases = 30;
2567*552f7358SJed Brown   PetscInt       numFaceCases = 0;
2568*552f7358SJed Brown   PetscInt       numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */
2569*552f7358SJed Brown   PetscInt      *off, *adj;
2570*552f7358SJed Brown   PetscInt      *neighborCells, *tmpClosure;
2571*552f7358SJed Brown   PetscInt       maxConeSize, maxSupportSize, maxClosure, maxNeighbors;
2572*552f7358SJed Brown   PetscInt       dim, depth = 0, cStart, cEnd, c, numCells, cell;
2573*552f7358SJed Brown   PetscErrorCode ierr;
2574*552f7358SJed Brown 
2575*552f7358SJed Brown   PetscFunctionBegin;
2576*552f7358SJed Brown   /* For parallel partitioning, I think you have to communicate supports */
2577*552f7358SJed Brown   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
2578*552f7358SJed Brown   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
2579*552f7358SJed Brown   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
2580*552f7358SJed Brown   ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr);
2581*552f7358SJed Brown   if (cEnd - cStart == 0) {
2582*552f7358SJed Brown     if (numVertices) *numVertices = 0;
2583*552f7358SJed Brown     if (offsets)     *offsets     = PETSC_NULL;
2584*552f7358SJed Brown     if (adjacency)   *adjacency   = PETSC_NULL;
2585*552f7358SJed Brown     PetscFunctionReturn(0);
2586*552f7358SJed Brown   }
2587*552f7358SJed Brown   numCells = cEnd - cStart;
2588*552f7358SJed Brown   /* Setup face recognition */
2589*552f7358SJed Brown   {
2590*552f7358SJed Brown     PetscInt cornersSeen[30] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /* Could use PetscBT */
2591*552f7358SJed Brown 
2592*552f7358SJed Brown     for (c = cStart; c < cEnd; ++c) {
2593*552f7358SJed Brown       PetscInt corners;
2594*552f7358SJed Brown 
2595*552f7358SJed Brown       ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr);
2596*552f7358SJed Brown       if (!cornersSeen[corners]) {
2597*552f7358SJed Brown         PetscInt nFV;
2598*552f7358SJed Brown 
2599*552f7358SJed Brown         if (numFaceCases >= maxFaceCases) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases");
2600*552f7358SJed Brown         cornersSeen[corners] = 1;
2601*552f7358SJed Brown         ierr = DMPlexGetNumFaceVertices(dm, corners, &nFV);CHKERRQ(ierr);
2602*552f7358SJed Brown         numFaceVertices[numFaceCases++] = nFV;
2603*552f7358SJed Brown       }
2604*552f7358SJed Brown     }
2605*552f7358SJed Brown   }
2606*552f7358SJed Brown   maxClosure   = (PetscInt) (2*PetscMax(pow((PetscReal) maxConeSize, depth)+1, pow((PetscReal) maxSupportSize, depth)+1));
2607*552f7358SJed Brown   maxNeighbors = (PetscInt) (pow((PetscReal) maxConeSize, depth)*pow((PetscReal) maxSupportSize, depth)+1);
2608*552f7358SJed Brown   ierr = PetscMalloc2(maxNeighbors,PetscInt,&neighborCells,maxClosure,PetscInt,&tmpClosure);CHKERRQ(ierr);
2609*552f7358SJed Brown   ierr = PetscMalloc((numCells+1) * sizeof(PetscInt), &off);CHKERRQ(ierr);
2610*552f7358SJed Brown   ierr = PetscMemzero(off, (numCells+1) * sizeof(PetscInt));CHKERRQ(ierr);
2611*552f7358SJed Brown   /* Count neighboring cells */
2612*552f7358SJed Brown   for (cell = cStart; cell < cEnd; ++cell) {
2613*552f7358SJed Brown     PetscInt numNeighbors = maxNeighbors, n;
2614*552f7358SJed Brown 
2615*552f7358SJed Brown     ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr);
2616*552f7358SJed Brown     /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */
2617*552f7358SJed Brown     for (n = 0; n < numNeighbors; ++n) {
2618*552f7358SJed Brown       PetscInt        cellPair[2] = {cell, neighborCells[n]};
2619*552f7358SJed Brown       PetscBool       found       = depth > 1 ? PETSC_TRUE : PETSC_FALSE;
2620*552f7358SJed Brown       PetscInt        meetSize    = 0;
2621*552f7358SJed Brown       const PetscInt *meet        = PETSC_NULL;
2622*552f7358SJed Brown 
2623*552f7358SJed Brown       if (cellPair[0] == cellPair[1]) continue;
2624*552f7358SJed Brown       if (!found) {
2625*552f7358SJed Brown         ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr);
2626*552f7358SJed Brown         if (meetSize) {
2627*552f7358SJed Brown           PetscInt f;
2628*552f7358SJed Brown 
2629*552f7358SJed Brown           for (f = 0; f < numFaceCases; ++f) {
2630*552f7358SJed Brown             if (numFaceVertices[f] == meetSize) {
2631*552f7358SJed Brown               found = PETSC_TRUE;
2632*552f7358SJed Brown               break;
2633*552f7358SJed Brown             }
2634*552f7358SJed Brown           }
2635*552f7358SJed Brown         }
2636*552f7358SJed Brown         ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr);
2637*552f7358SJed Brown       }
2638*552f7358SJed Brown       if (found) {
2639*552f7358SJed Brown         ++off[cell-cStart+1];
2640*552f7358SJed Brown       }
2641*552f7358SJed Brown     }
2642*552f7358SJed Brown   }
2643*552f7358SJed Brown   /* Prefix sum */
2644*552f7358SJed Brown   for (cell = 1; cell <= numCells; ++cell) {
2645*552f7358SJed Brown     off[cell] += off[cell-1];
2646*552f7358SJed Brown   }
2647*552f7358SJed Brown   if (adjacency) {
2648*552f7358SJed Brown     ierr = PetscMalloc(off[numCells] * sizeof(PetscInt), &adj);CHKERRQ(ierr);
2649*552f7358SJed Brown     /* Get neighboring cells */
2650*552f7358SJed Brown     for (cell = cStart; cell < cEnd; ++cell) {
2651*552f7358SJed Brown       PetscInt numNeighbors = maxNeighbors, n;
2652*552f7358SJed Brown       PetscInt cellOffset   = 0;
2653*552f7358SJed Brown 
2654*552f7358SJed Brown       ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr);
2655*552f7358SJed Brown       /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */
2656*552f7358SJed Brown       for (n = 0; n < numNeighbors; ++n) {
2657*552f7358SJed Brown         PetscInt        cellPair[2] = {cell, neighborCells[n]};
2658*552f7358SJed Brown         PetscBool       found       = depth > 1 ? PETSC_TRUE : PETSC_FALSE;
2659*552f7358SJed Brown         PetscInt        meetSize    = 0;
2660*552f7358SJed Brown         const PetscInt *meet        = PETSC_NULL;
2661*552f7358SJed Brown 
2662*552f7358SJed Brown         if (cellPair[0] == cellPair[1]) continue;
2663*552f7358SJed Brown         if (!found) {
2664*552f7358SJed Brown           ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr);
2665*552f7358SJed Brown           if (meetSize) {
2666*552f7358SJed Brown             PetscInt f;
2667*552f7358SJed Brown 
2668*552f7358SJed Brown             for (f = 0; f < numFaceCases; ++f) {
2669*552f7358SJed Brown               if (numFaceVertices[f] == meetSize) {
2670*552f7358SJed Brown                 found = PETSC_TRUE;
2671*552f7358SJed Brown                 break;
2672*552f7358SJed Brown               }
2673*552f7358SJed Brown             }
2674*552f7358SJed Brown           }
2675*552f7358SJed Brown           ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr);
2676*552f7358SJed Brown         }
2677*552f7358SJed Brown         if (found) {
2678*552f7358SJed Brown           adj[off[cell-cStart]+cellOffset] = neighborCells[n];
2679*552f7358SJed Brown           ++cellOffset;
2680*552f7358SJed Brown         }
2681*552f7358SJed Brown       }
2682*552f7358SJed Brown     }
2683*552f7358SJed Brown   }
2684*552f7358SJed Brown   ierr = PetscFree2(neighborCells,tmpClosure);CHKERRQ(ierr);
2685*552f7358SJed Brown   if (numVertices) *numVertices = numCells;
2686*552f7358SJed Brown   if (offsets)     *offsets     = off;
2687*552f7358SJed Brown   if (adjacency)   *adjacency   = adj;
2688*552f7358SJed Brown   PetscFunctionReturn(0);
2689*552f7358SJed Brown }
2690*552f7358SJed Brown 
2691*552f7358SJed Brown #ifdef PETSC_HAVE_CHACO
2692*552f7358SJed Brown #ifdef PETSC_HAVE_UNISTD_H
2693*552f7358SJed Brown #include <unistd.h>
2694*552f7358SJed Brown #endif
2695*552f7358SJed Brown /* Chaco does not have an include file */
2696*552f7358SJed Brown PETSC_EXTERN_C int interface(int nvtxs, int *start, int *adjacency, int *vwgts,
2697*552f7358SJed Brown                        float *ewgts, float *x, float *y, float *z, char *outassignname,
2698*552f7358SJed Brown                        char *outfilename, short *assignment, int architecture, int ndims_tot,
2699*552f7358SJed Brown                        int mesh_dims[3], double *goal, int global_method, int local_method,
2700*552f7358SJed Brown                        int rqi_flag, int vmax, int ndims, double eigtol, long seed);
2701*552f7358SJed Brown 
2702*552f7358SJed Brown extern int FREE_GRAPH;
2703*552f7358SJed Brown 
2704*552f7358SJed Brown #undef __FUNCT__
2705*552f7358SJed Brown #define __FUNCT__ "DMPlexPartition_Chaco"
2706*552f7358SJed Brown PetscErrorCode DMPlexPartition_Chaco(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition)
2707*552f7358SJed Brown {
2708*552f7358SJed Brown   enum {DEFAULT_METHOD = 1, INERTIAL_METHOD = 3};
2709*552f7358SJed Brown   MPI_Comm comm = ((PetscObject) dm)->comm;
2710*552f7358SJed Brown   int nvtxs = numVertices;                /* number of vertices in full graph */
2711*552f7358SJed Brown   int *vwgts = NULL;                      /* weights for all vertices */
2712*552f7358SJed Brown   float *ewgts = NULL;                    /* weights for all edges */
2713*552f7358SJed Brown   float *x = NULL, *y = NULL, *z = NULL;  /* coordinates for inertial method */
2714*552f7358SJed Brown   char *outassignname = NULL;             /*  name of assignment output file */
2715*552f7358SJed Brown   char *outfilename = NULL;               /* output file name */
2716*552f7358SJed Brown   int architecture = 1;                   /* 0 => hypercube, d => d-dimensional mesh */
2717*552f7358SJed Brown   int ndims_tot = 0;                      /* total number of cube dimensions to divide */
2718*552f7358SJed Brown   int mesh_dims[3];                       /* dimensions of mesh of processors */
2719*552f7358SJed Brown   double *goal = NULL;                    /* desired set sizes for each set */
2720*552f7358SJed Brown   int global_method = 1;                  /* global partitioning algorithm */
2721*552f7358SJed Brown   int local_method = 1;                   /* local partitioning algorithm */
2722*552f7358SJed Brown   int rqi_flag = 0;                       /* should I use RQI/Symmlq eigensolver? */
2723*552f7358SJed Brown   int vmax = 200;                         /* how many vertices to coarsen down to? */
2724*552f7358SJed Brown   int ndims = 1;                          /* number of eigenvectors (2^d sets) */
2725*552f7358SJed Brown   double eigtol = 0.001;                  /* tolerance on eigenvectors */
2726*552f7358SJed Brown   long seed = 123636512;                  /* for random graph mutations */
2727*552f7358SJed Brown   short int *assignment;                  /* Output partition */
2728*552f7358SJed Brown   int fd_stdout, fd_pipe[2];
2729*552f7358SJed Brown   PetscInt      *points;
2730*552f7358SJed Brown   PetscMPIInt    commSize;
2731*552f7358SJed Brown   int            i, v, p;
2732*552f7358SJed Brown   PetscErrorCode ierr;
2733*552f7358SJed Brown 
2734*552f7358SJed Brown   PetscFunctionBegin;
2735*552f7358SJed Brown   ierr = MPI_Comm_size(comm, &commSize);CHKERRQ(ierr);
2736*552f7358SJed Brown   if (!numVertices) {
2737*552f7358SJed Brown     ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr);
2738*552f7358SJed Brown     ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr);
2739*552f7358SJed Brown     ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr);
2740*552f7358SJed Brown     ierr = ISCreateGeneral(comm, 0, PETSC_NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr);
2741*552f7358SJed Brown     PetscFunctionReturn(0);
2742*552f7358SJed Brown   }
2743*552f7358SJed Brown   FREE_GRAPH = 0;                         /* Do not let Chaco free my memory */
2744*552f7358SJed Brown   for (i = 0; i < start[numVertices]; ++i) {
2745*552f7358SJed Brown     ++adjacency[i];
2746*552f7358SJed Brown   }
2747*552f7358SJed Brown   if (global_method == INERTIAL_METHOD) {
2748*552f7358SJed Brown     /* manager.createCellCoordinates(nvtxs, &x, &y, &z); */
2749*552f7358SJed Brown     SETERRQ(comm, PETSC_ERR_SUP, "Inertial partitioning not yet supported");
2750*552f7358SJed Brown   }
2751*552f7358SJed Brown   mesh_dims[0] = commSize;
2752*552f7358SJed Brown   mesh_dims[1] = 1;
2753*552f7358SJed Brown   mesh_dims[2] = 1;
2754*552f7358SJed Brown   ierr = PetscMalloc(nvtxs * sizeof(short int), &assignment);CHKERRQ(ierr);
2755*552f7358SJed Brown   /* Chaco outputs to stdout. We redirect this to a buffer. */
2756*552f7358SJed Brown   /* TODO: check error codes for UNIX calls */
2757*552f7358SJed Brown #ifdef PETSC_HAVE_UNISTD_H
2758*552f7358SJed Brown   {
2759*552f7358SJed Brown     fd_stdout = dup(1);
2760*552f7358SJed Brown     pipe(fd_pipe);
2761*552f7358SJed Brown     close(1);
2762*552f7358SJed Brown     dup2(fd_pipe[1], 1);
2763*552f7358SJed Brown   }
2764*552f7358SJed Brown #endif
2765*552f7358SJed Brown   ierr = interface(nvtxs, (int *) start, (int *) adjacency, vwgts, ewgts, x, y, z, outassignname, outfilename,
2766*552f7358SJed Brown                    assignment, architecture, ndims_tot, mesh_dims, goal, global_method, local_method, rqi_flag,
2767*552f7358SJed Brown                    vmax, ndims, eigtol, seed);
2768*552f7358SJed Brown #ifdef PETSC_HAVE_UNISTD_H
2769*552f7358SJed Brown   {
2770*552f7358SJed Brown     char msgLog[10000];
2771*552f7358SJed Brown     int  count;
2772*552f7358SJed Brown 
2773*552f7358SJed Brown     fflush(stdout);
2774*552f7358SJed Brown     count = read(fd_pipe[0], msgLog, (10000-1)*sizeof(char));
2775*552f7358SJed Brown     if (count < 0) count = 0;
2776*552f7358SJed Brown     msgLog[count] = 0;
2777*552f7358SJed Brown     close(1);
2778*552f7358SJed Brown     dup2(fd_stdout, 1);
2779*552f7358SJed Brown     close(fd_stdout);
2780*552f7358SJed Brown     close(fd_pipe[0]);
2781*552f7358SJed Brown     close(fd_pipe[1]);
2782*552f7358SJed Brown     if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", msgLog);
2783*552f7358SJed Brown   }
2784*552f7358SJed Brown #endif
2785*552f7358SJed Brown   /* Convert to PetscSection+IS */
2786*552f7358SJed Brown   ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr);
2787*552f7358SJed Brown   ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr);
2788*552f7358SJed Brown   for (v = 0; v < nvtxs; ++v) {
2789*552f7358SJed Brown     ierr = PetscSectionAddDof(*partSection, assignment[v], 1);CHKERRQ(ierr);
2790*552f7358SJed Brown   }
2791*552f7358SJed Brown   ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr);
2792*552f7358SJed Brown   ierr = PetscMalloc(nvtxs * sizeof(PetscInt), &points);CHKERRQ(ierr);
2793*552f7358SJed Brown   for (p = 0, i = 0; p < commSize; ++p) {
2794*552f7358SJed Brown     for (v = 0; v < nvtxs; ++v) {
2795*552f7358SJed Brown       if (assignment[v] == p) points[i++] = v;
2796*552f7358SJed Brown     }
2797*552f7358SJed Brown   }
2798*552f7358SJed Brown   if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs);
2799*552f7358SJed Brown   ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr);
2800*552f7358SJed Brown   if (global_method == INERTIAL_METHOD) {
2801*552f7358SJed Brown     /* manager.destroyCellCoordinates(nvtxs, &x, &y, &z); */
2802*552f7358SJed Brown   }
2803*552f7358SJed Brown   ierr = PetscFree(assignment);CHKERRQ(ierr);
2804*552f7358SJed Brown   for (i = 0; i < start[numVertices]; ++i) {
2805*552f7358SJed Brown     --adjacency[i];
2806*552f7358SJed Brown   }
2807*552f7358SJed Brown   PetscFunctionReturn(0);
2808*552f7358SJed Brown }
2809*552f7358SJed Brown #endif
2810*552f7358SJed Brown 
2811*552f7358SJed Brown #ifdef PETSC_HAVE_PARMETIS
2812*552f7358SJed Brown #undef __FUNCT__
2813*552f7358SJed Brown #define __FUNCT__ "DMPlexPartition_ParMetis"
2814*552f7358SJed Brown PetscErrorCode DMPlexPartition_ParMetis(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition)
2815*552f7358SJed Brown {
2816*552f7358SJed Brown   PetscFunctionBegin;
2817*552f7358SJed Brown   SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "ParMetis not yet supported");
2818*552f7358SJed Brown   PetscFunctionReturn(0);
2819*552f7358SJed Brown }
2820*552f7358SJed Brown #endif
2821*552f7358SJed Brown 
2822*552f7358SJed Brown #undef __FUNCT__
2823*552f7358SJed Brown #define __FUNCT__ "DMPlexEnlargePartition"
2824*552f7358SJed Brown /* Expand the partition by BFS on the adjacency graph */
2825*552f7358SJed Brown PetscErrorCode DMPlexEnlargePartition(DM dm, const PetscInt start[], const PetscInt adjacency[], PetscSection origPartSection, IS origPartition, PetscSection *partSection, IS *partition) {
2826*552f7358SJed Brown   PetscHashI      h;
2827*552f7358SJed Brown   const PetscInt *points;
2828*552f7358SJed Brown   PetscInt      **tmpPoints, *newPoints, totPoints = 0;
2829*552f7358SJed Brown   PetscInt        pStart, pEnd, part, q;
2830*552f7358SJed Brown   PetscErrorCode  ierr;
2831*552f7358SJed Brown 
2832*552f7358SJed Brown   PetscFunctionBegin;
2833*552f7358SJed Brown   PetscHashICreate(h);
2834*552f7358SJed Brown   ierr = PetscSectionCreate(((PetscObject) dm)->comm, partSection);CHKERRQ(ierr);
2835*552f7358SJed Brown   ierr = PetscSectionGetChart(origPartSection, &pStart, &pEnd);CHKERRQ(ierr);
2836*552f7358SJed Brown   ierr = PetscSectionSetChart(*partSection, pStart, pEnd);CHKERRQ(ierr);
2837*552f7358SJed Brown   ierr = ISGetIndices(origPartition, &points);CHKERRQ(ierr);
2838*552f7358SJed Brown   ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt *), &tmpPoints);CHKERRQ(ierr);
2839*552f7358SJed Brown   for(part = pStart; part < pEnd; ++part) {
2840*552f7358SJed Brown     PetscInt numPoints, nP, numNewPoints, off, p, n = 0;
2841*552f7358SJed Brown 
2842*552f7358SJed Brown     PetscHashIClear(h);
2843*552f7358SJed Brown     ierr = PetscSectionGetDof(origPartSection, part, &numPoints);CHKERRQ(ierr);
2844*552f7358SJed Brown     ierr = PetscSectionGetOffset(origPartSection, part, &off);CHKERRQ(ierr);
2845*552f7358SJed Brown     /* Add all existing points to h */
2846*552f7358SJed Brown     for(p = 0; p < numPoints; ++p) {
2847*552f7358SJed Brown       const PetscInt point = points[off+p];
2848*552f7358SJed Brown       PetscHashIAdd(h, point, 1);
2849*552f7358SJed Brown     }
2850*552f7358SJed Brown     PetscHashISize(h, nP);
2851*552f7358SJed Brown     if (nP != numPoints) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Invalid partition has %d points, but only %d were unique", numPoints, nP);
2852*552f7358SJed Brown     /* Add all points in next BFS level */
2853*552f7358SJed Brown     /*   TODO We are brute forcing here, but could check the adjacency size to find the boundary */
2854*552f7358SJed Brown     for(p = 0; p < numPoints; ++p) {
2855*552f7358SJed Brown       const PetscInt point = points[off+p];
2856*552f7358SJed Brown       PetscInt s = start[point], e = start[point+1], a;
2857*552f7358SJed Brown 
2858*552f7358SJed Brown       for(a = s; a < e; ++a) {
2859*552f7358SJed Brown         PetscHashIAdd(h, adjacency[a], 1);
2860*552f7358SJed Brown       }
2861*552f7358SJed Brown     }
2862*552f7358SJed Brown     PetscHashISize(h, numNewPoints);
2863*552f7358SJed Brown     ierr = PetscSectionSetDof(*partSection, part, numNewPoints);CHKERRQ(ierr);
2864*552f7358SJed Brown     ierr = PetscMalloc(numNewPoints * sizeof(PetscInt), &tmpPoints[part]);CHKERRQ(ierr);
2865*552f7358SJed Brown     if (numNewPoints) {PetscHashIGetKeys(h, n, tmpPoints[part]);} /* Should not need this conditional */
2866*552f7358SJed Brown     totPoints += numNewPoints;
2867*552f7358SJed Brown   }
2868*552f7358SJed Brown   ierr = ISRestoreIndices(origPartition, &points);CHKERRQ(ierr);
2869*552f7358SJed Brown   PetscHashIDestroy(h);
2870*552f7358SJed Brown   ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr);
2871*552f7358SJed Brown   ierr = PetscMalloc(totPoints * sizeof(PetscInt), &newPoints);CHKERRQ(ierr);
2872*552f7358SJed Brown   for(part = pStart, q = 0; part < pEnd; ++part) {
2873*552f7358SJed Brown     PetscInt numPoints, p;
2874*552f7358SJed Brown 
2875*552f7358SJed Brown     ierr = PetscSectionGetDof(*partSection, part, &numPoints);CHKERRQ(ierr);
2876*552f7358SJed Brown     for(p = 0; p < numPoints; ++p, ++q) {
2877*552f7358SJed Brown       newPoints[q] = tmpPoints[part][p];
2878*552f7358SJed Brown     }
2879*552f7358SJed Brown     ierr = PetscFree(tmpPoints[part]);CHKERRQ(ierr);
2880*552f7358SJed Brown   }
2881*552f7358SJed Brown   ierr = PetscFree(tmpPoints);CHKERRQ(ierr);
2882*552f7358SJed Brown   ierr = ISCreateGeneral(((PetscObject) dm)->comm, totPoints, newPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr);
2883*552f7358SJed Brown   PetscFunctionReturn(0);
2884*552f7358SJed Brown }
2885*552f7358SJed Brown 
2886*552f7358SJed Brown #undef __FUNCT__
2887*552f7358SJed Brown #define __FUNCT__ "DMPlexCreatePartition"
2888*552f7358SJed Brown /*
2889*552f7358SJed Brown   DMPlexCreatePartition - Create a non-overlapping partition of the points at the given height
2890*552f7358SJed Brown 
2891*552f7358SJed Brown   Collective on DM
2892*552f7358SJed Brown 
2893*552f7358SJed Brown   Input Parameters:
2894*552f7358SJed Brown   + dm - The DM
2895*552f7358SJed Brown   . height - The height for points in the partition
2896*552f7358SJed Brown   - enlarge - Expand each partition with neighbors
2897*552f7358SJed Brown 
2898*552f7358SJed Brown   Output Parameters:
2899*552f7358SJed Brown   + partSection - The PetscSection giving the division of points by partition
2900*552f7358SJed Brown   . partition - The list of points by partition
2901*552f7358SJed Brown   . origPartSection - If enlarge is true, the PetscSection giving the division of points before enlarging by partition, otherwise PETSC_NULL
2902*552f7358SJed Brown   - origPartition - If enlarge is true, the list of points before enlarging by partition, otherwise PETSC_NULL
2903*552f7358SJed Brown 
2904*552f7358SJed Brown   Level: developer
2905*552f7358SJed Brown 
2906*552f7358SJed Brown .seealso DMPlexDistribute()
2907*552f7358SJed Brown */
2908*552f7358SJed Brown PetscErrorCode DMPlexCreatePartition(DM dm, PetscInt height, PetscBool enlarge, PetscSection *partSection, IS *partition, PetscSection *origPartSection, IS *origPartition) {
2909*552f7358SJed Brown   PetscMPIInt    size;
2910*552f7358SJed Brown   PetscErrorCode ierr;
2911*552f7358SJed Brown 
2912*552f7358SJed Brown   PetscFunctionBegin;
2913*552f7358SJed Brown   ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr);
2914*552f7358SJed Brown   *origPartSection = PETSC_NULL;
2915*552f7358SJed Brown   *origPartition   = PETSC_NULL;
2916*552f7358SJed Brown   if (size == 1) {
2917*552f7358SJed Brown     PetscInt *points;
2918*552f7358SJed Brown     PetscInt  cStart, cEnd, c;
2919*552f7358SJed Brown 
2920*552f7358SJed Brown     ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
2921*552f7358SJed Brown     ierr = PetscSectionCreate(((PetscObject) dm)->comm, partSection);CHKERRQ(ierr);
2922*552f7358SJed Brown     ierr = PetscSectionSetChart(*partSection, 0, size);CHKERRQ(ierr);
2923*552f7358SJed Brown     ierr = PetscSectionSetDof(*partSection, 0, cEnd-cStart);CHKERRQ(ierr);
2924*552f7358SJed Brown     ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr);
2925*552f7358SJed Brown     ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscInt), &points);CHKERRQ(ierr);
2926*552f7358SJed Brown     for (c = cStart; c < cEnd; ++c) {
2927*552f7358SJed Brown       points[c] = c;
2928*552f7358SJed Brown     }
2929*552f7358SJed Brown     ierr = ISCreateGeneral(((PetscObject) dm)->comm, cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr);
2930*552f7358SJed Brown     PetscFunctionReturn(0);
2931*552f7358SJed Brown   }
2932*552f7358SJed Brown   if (height == 0) {
2933*552f7358SJed Brown     PetscInt  numVertices;
2934*552f7358SJed Brown     PetscInt *start     = PETSC_NULL;
2935*552f7358SJed Brown     PetscInt *adjacency = PETSC_NULL;
2936*552f7358SJed Brown 
2937*552f7358SJed Brown     ierr = DMPlexCreateNeighborCSR(dm, &numVertices, &start, &adjacency);CHKERRQ(ierr);
2938*552f7358SJed Brown     if (1) {
2939*552f7358SJed Brown #ifdef PETSC_HAVE_CHACO
2940*552f7358SJed Brown       ierr = DMPlexPartition_Chaco(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr);
2941*552f7358SJed Brown #endif
2942*552f7358SJed Brown     } else {
2943*552f7358SJed Brown #ifdef PETSC_HAVE_PARMETIS
2944*552f7358SJed Brown       ierr = DMPlexPartition_ParMetis(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr);
2945*552f7358SJed Brown #endif
2946*552f7358SJed Brown     }
2947*552f7358SJed Brown     if (enlarge) {
2948*552f7358SJed Brown       *origPartSection = *partSection;
2949*552f7358SJed Brown       *origPartition   = *partition;
2950*552f7358SJed Brown       ierr = DMPlexEnlargePartition(dm, start, adjacency, *origPartSection, *origPartition, partSection, partition);CHKERRQ(ierr);
2951*552f7358SJed Brown     }
2952*552f7358SJed Brown     ierr = PetscFree(start);CHKERRQ(ierr);
2953*552f7358SJed Brown     ierr = PetscFree(adjacency);CHKERRQ(ierr);
2954*552f7358SJed Brown # if 0
2955*552f7358SJed Brown   } else if (height == 1) {
2956*552f7358SJed Brown     /* Build the dual graph for faces and partition the hypergraph */
2957*552f7358SJed Brown     PetscInt numEdges;
2958*552f7358SJed Brown 
2959*552f7358SJed Brown     buildFaceCSRV(mesh, mesh->getFactory()->getNumbering(mesh, mesh->depth()-1), &numEdges, &start, &adjacency, GraphPartitioner::zeroBase());
2960*552f7358SJed Brown     GraphPartitioner().partition(numEdges, start, adjacency, partition, manager);
2961*552f7358SJed Brown     destroyCSR(numEdges, start, adjacency);
2962*552f7358SJed Brown #endif
2963*552f7358SJed Brown   } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid partition height %D", height);
2964*552f7358SJed Brown   PetscFunctionReturn(0);
2965*552f7358SJed Brown }
2966*552f7358SJed Brown 
2967*552f7358SJed Brown #undef __FUNCT__
2968*552f7358SJed Brown #define __FUNCT__ "DMPlexCreatePartitionClosure"
2969*552f7358SJed Brown PetscErrorCode DMPlexCreatePartitionClosure(DM dm, PetscSection pointSection, IS pointPartition, PetscSection *section, IS *partition) {
2970*552f7358SJed Brown   /* const PetscInt  height = 0; */
2971*552f7358SJed Brown   const PetscInt *partArray;
2972*552f7358SJed Brown   PetscInt       *allPoints, *partPoints = PETSC_NULL;
2973*552f7358SJed Brown   PetscInt        rStart, rEnd, rank, maxPartSize = 0, newSize;
2974*552f7358SJed Brown   PetscErrorCode  ierr;
2975*552f7358SJed Brown 
2976*552f7358SJed Brown   PetscFunctionBegin;
2977*552f7358SJed Brown   ierr = PetscSectionGetChart(pointSection, &rStart, &rEnd);CHKERRQ(ierr);
2978*552f7358SJed Brown   ierr = ISGetIndices(pointPartition, &partArray);CHKERRQ(ierr);
2979*552f7358SJed Brown   ierr = PetscSectionCreate(((PetscObject) dm)->comm, section);CHKERRQ(ierr);
2980*552f7358SJed Brown   ierr = PetscSectionSetChart(*section, rStart, rEnd);CHKERRQ(ierr);
2981*552f7358SJed Brown   for (rank = rStart; rank < rEnd; ++rank) {
2982*552f7358SJed Brown     PetscInt partSize = 0;
2983*552f7358SJed Brown     PetscInt numPoints, offset, p;
2984*552f7358SJed Brown 
2985*552f7358SJed Brown     ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr);
2986*552f7358SJed Brown     ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr);
2987*552f7358SJed Brown     for (p = 0; p < numPoints; ++p) {
2988*552f7358SJed Brown       PetscInt  point   = partArray[offset+p], closureSize, c;
2989*552f7358SJed Brown       PetscInt *closure = PETSC_NULL;
2990*552f7358SJed Brown 
2991*552f7358SJed Brown       /* TODO Include support for height > 0 case */
2992*552f7358SJed Brown       ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
2993*552f7358SJed Brown       /* Merge into existing points */
2994*552f7358SJed Brown       if (partSize+closureSize > maxPartSize) {
2995*552f7358SJed Brown         PetscInt *tmpPoints;
2996*552f7358SJed Brown 
2997*552f7358SJed Brown         maxPartSize = PetscMax(partSize+closureSize, 2*maxPartSize);
2998*552f7358SJed Brown         ierr = PetscMalloc(maxPartSize * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr);
2999*552f7358SJed Brown         ierr = PetscMemcpy(tmpPoints, partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr);
3000*552f7358SJed Brown         ierr = PetscFree(partPoints);CHKERRQ(ierr);
3001*552f7358SJed Brown         partPoints = tmpPoints;
3002*552f7358SJed Brown       }
3003*552f7358SJed Brown       for (c = 0; c < closureSize; ++c) {
3004*552f7358SJed Brown         partPoints[partSize+c] = closure[c*2];
3005*552f7358SJed Brown       }
3006*552f7358SJed Brown       partSize += closureSize;
3007*552f7358SJed Brown       ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr);
3008*552f7358SJed Brown       ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
3009*552f7358SJed Brown     }
3010*552f7358SJed Brown     ierr = PetscSectionSetDof(*section, rank, partSize);CHKERRQ(ierr);
3011*552f7358SJed Brown   }
3012*552f7358SJed Brown   ierr = PetscSectionSetUp(*section);CHKERRQ(ierr);
3013*552f7358SJed Brown   ierr = PetscSectionGetStorageSize(*section, &newSize);CHKERRQ(ierr);
3014*552f7358SJed Brown   ierr = PetscMalloc(newSize * sizeof(PetscInt), &allPoints);CHKERRQ(ierr);
3015*552f7358SJed Brown 
3016*552f7358SJed Brown   for (rank = rStart; rank < rEnd; ++rank) {
3017*552f7358SJed Brown     PetscInt partSize = 0, newOffset;
3018*552f7358SJed Brown     PetscInt numPoints, offset, p;
3019*552f7358SJed Brown 
3020*552f7358SJed Brown     ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr);
3021*552f7358SJed Brown     ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr);
3022*552f7358SJed Brown     for (p = 0; p < numPoints; ++p) {
3023*552f7358SJed Brown       PetscInt  point   = partArray[offset+p], closureSize, c;
3024*552f7358SJed Brown       PetscInt *closure = PETSC_NULL;
3025*552f7358SJed Brown 
3026*552f7358SJed Brown       /* TODO Include support for height > 0 case */
3027*552f7358SJed Brown       ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
3028*552f7358SJed Brown       /* Merge into existing points */
3029*552f7358SJed Brown       for (c = 0; c < closureSize; ++c) {
3030*552f7358SJed Brown         partPoints[partSize+c] = closure[c*2];
3031*552f7358SJed Brown       }
3032*552f7358SJed Brown       partSize += closureSize;
3033*552f7358SJed Brown       ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr);
3034*552f7358SJed Brown       ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
3035*552f7358SJed Brown     }
3036*552f7358SJed Brown     ierr = PetscSectionGetOffset(*section, rank, &newOffset);CHKERRQ(ierr);
3037*552f7358SJed Brown     ierr = PetscMemcpy(&allPoints[newOffset], partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr);
3038*552f7358SJed Brown   }
3039*552f7358SJed Brown   ierr = ISRestoreIndices(pointPartition, &partArray);CHKERRQ(ierr);
3040*552f7358SJed Brown   ierr = PetscFree(partPoints);CHKERRQ(ierr);
3041*552f7358SJed Brown   ierr = ISCreateGeneral(((PetscObject) dm)->comm, newSize, allPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr);
3042*552f7358SJed Brown   PetscFunctionReturn(0);
3043*552f7358SJed Brown }
3044*552f7358SJed Brown 
3045*552f7358SJed Brown #undef __FUNCT__
3046*552f7358SJed Brown #define __FUNCT__ "DMPlexDistributeField"
3047*552f7358SJed Brown /*
3048*552f7358SJed Brown   Input Parameters:
3049*552f7358SJed Brown . originalSection
3050*552f7358SJed Brown , originalVec
3051*552f7358SJed Brown 
3052*552f7358SJed Brown   Output Parameters:
3053*552f7358SJed Brown . newSection
3054*552f7358SJed Brown . newVec
3055*552f7358SJed Brown */
3056*552f7358SJed Brown PetscErrorCode DMPlexDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec)
3057*552f7358SJed Brown {
3058*552f7358SJed Brown   PetscSF         fieldSF;
3059*552f7358SJed Brown   PetscInt       *remoteOffsets, fieldSize;
3060*552f7358SJed Brown   PetscScalar    *originalValues, *newValues;
3061*552f7358SJed Brown   PetscErrorCode  ierr;
3062*552f7358SJed Brown 
3063*552f7358SJed Brown   PetscFunctionBegin;
3064*552f7358SJed Brown   ierr = PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection);CHKERRQ(ierr);
3065*552f7358SJed Brown 
3066*552f7358SJed Brown   ierr = PetscSectionGetStorageSize(newSection, &fieldSize);CHKERRQ(ierr);
3067*552f7358SJed Brown   ierr = VecSetSizes(newVec, fieldSize, PETSC_DETERMINE);CHKERRQ(ierr);
3068*552f7358SJed Brown   ierr = VecSetFromOptions(newVec);CHKERRQ(ierr);
3069*552f7358SJed Brown 
3070*552f7358SJed Brown   ierr = VecGetArray(originalVec, &originalValues);CHKERRQ(ierr);
3071*552f7358SJed Brown   ierr = VecGetArray(newVec, &newValues);CHKERRQ(ierr);
3072*552f7358SJed Brown   ierr = PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF);CHKERRQ(ierr);
3073*552f7358SJed Brown   ierr = PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr);
3074*552f7358SJed Brown   ierr = PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr);
3075*552f7358SJed Brown   ierr = PetscSFDestroy(&fieldSF);CHKERRQ(ierr);
3076*552f7358SJed Brown   ierr = VecRestoreArray(newVec, &newValues);CHKERRQ(ierr);
3077*552f7358SJed Brown   ierr = VecRestoreArray(originalVec, &originalValues);CHKERRQ(ierr);
3078*552f7358SJed Brown   PetscFunctionReturn(0);
3079*552f7358SJed Brown }
3080*552f7358SJed Brown 
3081*552f7358SJed Brown #undef __FUNCT__
3082*552f7358SJed Brown #define __FUNCT__ "DMPlexDistribute"
3083*552f7358SJed Brown /*@C
3084*552f7358SJed Brown   DMPlexDistribute - Distributes the mesh and any associated sections.
3085*552f7358SJed Brown 
3086*552f7358SJed Brown   Not Collective
3087*552f7358SJed Brown 
3088*552f7358SJed Brown   Input Parameter:
3089*552f7358SJed Brown + dm  - The original DMPlex object
3090*552f7358SJed Brown . partitioner - The partitioning package, or NULL for the default
3091*552f7358SJed Brown - overlap - The overlap of partitions, 0 is the default
3092*552f7358SJed Brown 
3093*552f7358SJed Brown   Output Parameter:
3094*552f7358SJed Brown . parallelMesh - The distributed DMPlex object, or PETSC_NULL
3095*552f7358SJed Brown 
3096*552f7358SJed Brown   Note: If the mesh was not distributed, the return value is PETSC_NULL
3097*552f7358SJed Brown 
3098*552f7358SJed Brown   Level: intermediate
3099*552f7358SJed Brown 
3100*552f7358SJed Brown .keywords: mesh, elements
3101*552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexDistributeByFace()
3102*552f7358SJed Brown @*/
3103*552f7358SJed Brown PetscErrorCode DMPlexDistribute(DM dm, const char partitioner[], PetscInt overlap, DM *dmParallel)
3104*552f7358SJed Brown {
3105*552f7358SJed Brown   DM_Plex    *mesh   = (DM_Plex *) dm->data, *pmesh;
3106*552f7358SJed Brown   MPI_Comm       comm   = ((PetscObject) dm)->comm;
3107*552f7358SJed Brown   const PetscInt height = 0;
3108*552f7358SJed Brown   PetscInt       dim, numRemoteRanks;
3109*552f7358SJed Brown   IS             origCellPart,        cellPart,        part;
3110*552f7358SJed Brown   PetscSection   origCellPartSection, cellPartSection, partSection;
3111*552f7358SJed Brown   PetscSFNode   *remoteRanks;
3112*552f7358SJed Brown   PetscSF        partSF, pointSF, coneSF;
3113*552f7358SJed Brown   ISLocalToGlobalMapping renumbering;
3114*552f7358SJed Brown   PetscSection   originalConeSection, newConeSection;
3115*552f7358SJed Brown   PetscInt      *remoteOffsets;
3116*552f7358SJed Brown   PetscInt      *cones, *newCones, newConesSize;
3117*552f7358SJed Brown   PetscBool      flg;
3118*552f7358SJed Brown   PetscMPIInt    rank, numProcs, p;
3119*552f7358SJed Brown   PetscErrorCode ierr;
3120*552f7358SJed Brown 
3121*552f7358SJed Brown   PetscFunctionBegin;
3122*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3123*552f7358SJed Brown   PetscValidPointer(dmParallel,4);
3124*552f7358SJed Brown   ierr = PetscLogEventBegin(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr);
3125*552f7358SJed Brown   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
3126*552f7358SJed Brown   ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr);
3127*552f7358SJed Brown   *dmParallel = PETSC_NULL;
3128*552f7358SJed Brown   if (numProcs == 1) PetscFunctionReturn(0);
3129*552f7358SJed Brown 
3130*552f7358SJed Brown   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
3131*552f7358SJed Brown   /* Create cell partition - We need to rewrite to use IS, use the MatPartition stuff */
3132*552f7358SJed Brown   if (overlap > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Overlap > 1 not yet implemented");
3133*552f7358SJed Brown   ierr = DMPlexCreatePartition(dm, height, overlap > 0 ? PETSC_TRUE : PETSC_FALSE, &cellPartSection, &cellPart, &origCellPartSection, &origCellPart);CHKERRQ(ierr);
3134*552f7358SJed Brown   /* Create SF assuming a serial partition for all processes: Could check for IS length here */
3135*552f7358SJed Brown   if (!rank) {
3136*552f7358SJed Brown     numRemoteRanks = numProcs;
3137*552f7358SJed Brown   } else {
3138*552f7358SJed Brown     numRemoteRanks = 0;
3139*552f7358SJed Brown   }
3140*552f7358SJed Brown   ierr = PetscMalloc(numRemoteRanks * sizeof(PetscSFNode), &remoteRanks);CHKERRQ(ierr);
3141*552f7358SJed Brown   for (p = 0; p < numRemoteRanks; ++p) {
3142*552f7358SJed Brown     remoteRanks[p].rank  = p;
3143*552f7358SJed Brown     remoteRanks[p].index = 0;
3144*552f7358SJed Brown   }
3145*552f7358SJed Brown   ierr = PetscSFCreate(comm, &partSF);CHKERRQ(ierr);
3146*552f7358SJed Brown   ierr = PetscSFSetGraph(partSF, 1, numRemoteRanks, PETSC_NULL, PETSC_OWN_POINTER, remoteRanks, PETSC_OWN_POINTER);CHKERRQ(ierr);
3147*552f7358SJed Brown   ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-partition_view", &flg);CHKERRQ(ierr);
3148*552f7358SJed Brown   if (flg) {
3149*552f7358SJed Brown     ierr = PetscPrintf(comm, "Cell Partition:\n");CHKERRQ(ierr);
3150*552f7358SJed Brown     ierr = PetscSectionView(cellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
3151*552f7358SJed Brown     ierr = ISView(cellPart, PETSC_NULL);CHKERRQ(ierr);
3152*552f7358SJed Brown     if (origCellPart) {
3153*552f7358SJed Brown       ierr = PetscPrintf(comm, "Original Cell Partition:\n");CHKERRQ(ierr);
3154*552f7358SJed Brown       ierr = PetscSectionView(origCellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
3155*552f7358SJed Brown       ierr = ISView(origCellPart, PETSC_NULL);CHKERRQ(ierr);
3156*552f7358SJed Brown     }
3157*552f7358SJed Brown     ierr = PetscSFView(partSF, PETSC_NULL);CHKERRQ(ierr);
3158*552f7358SJed Brown   }
3159*552f7358SJed Brown   /* Close the partition over the mesh */
3160*552f7358SJed Brown   ierr = DMPlexCreatePartitionClosure(dm, cellPartSection, cellPart, &partSection, &part);CHKERRQ(ierr);
3161*552f7358SJed Brown   ierr = ISDestroy(&cellPart);CHKERRQ(ierr);
3162*552f7358SJed Brown   ierr = PetscSectionDestroy(&cellPartSection);CHKERRQ(ierr);
3163*552f7358SJed Brown   /* Create new mesh */
3164*552f7358SJed Brown   ierr = DMPlexCreate(comm, dmParallel);CHKERRQ(ierr);
3165*552f7358SJed Brown   ierr = DMPlexSetDimension(*dmParallel, dim);CHKERRQ(ierr);
3166*552f7358SJed Brown   ierr = PetscObjectSetName((PetscObject) *dmParallel, "Parallel Mesh");CHKERRQ(ierr);
3167*552f7358SJed Brown   pmesh = (DM_Plex *) (*dmParallel)->data;
3168*552f7358SJed Brown   /* Distribute sieve points and the global point numbering (replaces creating remote bases) */
3169*552f7358SJed Brown   ierr = PetscSFConvertPartition(partSF, partSection, part, &renumbering, &pointSF);CHKERRQ(ierr);
3170*552f7358SJed Brown   if (flg) {
3171*552f7358SJed Brown     ierr = PetscPrintf(comm, "Point Partition:\n");CHKERRQ(ierr);
3172*552f7358SJed Brown     ierr = PetscSectionView(partSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
3173*552f7358SJed Brown     ierr = ISView(part, PETSC_NULL);CHKERRQ(ierr);
3174*552f7358SJed Brown     ierr = PetscSFView(pointSF, PETSC_NULL);CHKERRQ(ierr);
3175*552f7358SJed Brown     ierr = PetscPrintf(comm, "Point Renumbering after partition:\n");CHKERRQ(ierr);
3176*552f7358SJed Brown     ierr = ISLocalToGlobalMappingView(renumbering, PETSC_NULL);CHKERRQ(ierr);
3177*552f7358SJed Brown   }
3178*552f7358SJed Brown   /* Distribute cone section */
3179*552f7358SJed Brown   ierr = DMPlexGetConeSection(dm, &originalConeSection);CHKERRQ(ierr);
3180*552f7358SJed Brown   ierr = DMPlexGetConeSection(*dmParallel, &newConeSection);CHKERRQ(ierr);
3181*552f7358SJed Brown   ierr = PetscSFDistributeSection(pointSF, originalConeSection, &remoteOffsets, newConeSection);CHKERRQ(ierr);
3182*552f7358SJed Brown   ierr = DMSetUp(*dmParallel);CHKERRQ(ierr);
3183*552f7358SJed Brown   {
3184*552f7358SJed Brown     PetscInt pStart, pEnd, p;
3185*552f7358SJed Brown 
3186*552f7358SJed Brown     ierr = PetscSectionGetChart(newConeSection, &pStart, &pEnd);CHKERRQ(ierr);
3187*552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
3188*552f7358SJed Brown       PetscInt coneSize;
3189*552f7358SJed Brown       ierr = PetscSectionGetDof(newConeSection, p, &coneSize);CHKERRQ(ierr);
3190*552f7358SJed Brown       pmesh->maxConeSize = PetscMax(pmesh->maxConeSize, coneSize);
3191*552f7358SJed Brown     }
3192*552f7358SJed Brown   }
3193*552f7358SJed Brown   /* Communicate and renumber cones */
3194*552f7358SJed Brown   ierr = PetscSFCreateSectionSF(pointSF, originalConeSection, remoteOffsets, newConeSection, &coneSF);CHKERRQ(ierr);
3195*552f7358SJed Brown   ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr);
3196*552f7358SJed Brown   ierr = DMPlexGetCones(*dmParallel, &newCones);CHKERRQ(ierr);
3197*552f7358SJed Brown   ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr);
3198*552f7358SJed Brown   ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr);
3199*552f7358SJed Brown   ierr = PetscSectionGetStorageSize(newConeSection, &newConesSize);CHKERRQ(ierr);
3200*552f7358SJed Brown   ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newConesSize, newCones, PETSC_NULL, newCones);CHKERRQ(ierr);
3201*552f7358SJed Brown   ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-cones_view", &flg);CHKERRQ(ierr);
3202*552f7358SJed Brown   if (flg) {
3203*552f7358SJed Brown     ierr = PetscPrintf(comm, "Serial Cone Section:\n");CHKERRQ(ierr);
3204*552f7358SJed Brown     ierr = PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
3205*552f7358SJed Brown     ierr = PetscPrintf(comm, "Parallel Cone Section:\n");CHKERRQ(ierr);
3206*552f7358SJed Brown     ierr = PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
3207*552f7358SJed Brown     ierr = PetscSFView(coneSF, PETSC_NULL);CHKERRQ(ierr);
3208*552f7358SJed Brown   }
3209*552f7358SJed Brown   ierr = DMPlexGetConeOrientations(dm, &cones);CHKERRQ(ierr);
3210*552f7358SJed Brown   ierr = DMPlexGetConeOrientations(*dmParallel, &newCones);CHKERRQ(ierr);
3211*552f7358SJed Brown   ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr);
3212*552f7358SJed Brown   ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr);
3213*552f7358SJed Brown   ierr = PetscSFDestroy(&coneSF);CHKERRQ(ierr);
3214*552f7358SJed Brown   /* Create supports and stratify sieve */
3215*552f7358SJed Brown   {
3216*552f7358SJed Brown     PetscInt pStart, pEnd;
3217*552f7358SJed Brown 
3218*552f7358SJed Brown     ierr = PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr);
3219*552f7358SJed Brown     ierr = PetscSectionSetChart(pmesh->supportSection, pStart, pEnd);CHKERRQ(ierr);
3220*552f7358SJed Brown   }
3221*552f7358SJed Brown   ierr = DMPlexSymmetrize(*dmParallel);CHKERRQ(ierr);
3222*552f7358SJed Brown   ierr = DMPlexStratify(*dmParallel);CHKERRQ(ierr);
3223*552f7358SJed Brown   /* Distribute Coordinates */
3224*552f7358SJed Brown   {
3225*552f7358SJed Brown     PetscSection originalCoordSection, newCoordSection;
3226*552f7358SJed Brown     Vec          originalCoordinates, newCoordinates;
3227*552f7358SJed Brown     const char  *name;
3228*552f7358SJed Brown 
3229*552f7358SJed Brown     ierr = DMPlexGetCoordinateSection(dm, &originalCoordSection);CHKERRQ(ierr);
3230*552f7358SJed Brown     ierr = DMPlexGetCoordinateSection(*dmParallel, &newCoordSection);CHKERRQ(ierr);
3231*552f7358SJed Brown     ierr = DMGetCoordinatesLocal(dm, &originalCoordinates);CHKERRQ(ierr);
3232*552f7358SJed Brown     ierr = VecCreate(comm, &newCoordinates);CHKERRQ(ierr);
3233*552f7358SJed Brown     ierr = PetscObjectGetName((PetscObject) originalCoordinates, &name);CHKERRQ(ierr);
3234*552f7358SJed Brown     ierr = PetscObjectSetName((PetscObject) newCoordinates, name);CHKERRQ(ierr);
3235*552f7358SJed Brown 
3236*552f7358SJed Brown     ierr = DMPlexDistributeField(dm, pointSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates);CHKERRQ(ierr);
3237*552f7358SJed Brown     ierr = DMSetCoordinatesLocal(*dmParallel, newCoordinates);CHKERRQ(ierr);
3238*552f7358SJed Brown     ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr);
3239*552f7358SJed Brown   }
3240*552f7358SJed Brown   /* Distribute labels */
3241*552f7358SJed Brown   {
3242*552f7358SJed Brown     DMLabel    next      = mesh->labels, newNext = pmesh->labels;
3243*552f7358SJed Brown     PetscInt   numLabels = 0, l;
3244*552f7358SJed Brown 
3245*552f7358SJed Brown     /* Bcast number of labels */
3246*552f7358SJed Brown     while(next) {++numLabels; next = next->next;}
3247*552f7358SJed Brown     ierr = MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm);CHKERRQ(ierr);
3248*552f7358SJed Brown     next = mesh->labels;
3249*552f7358SJed Brown     for (l = 0; l < numLabels; ++l) {
3250*552f7358SJed Brown       DMLabel         newLabel;
3251*552f7358SJed Brown       const PetscInt *partArray;
3252*552f7358SJed Brown       char           *name;
3253*552f7358SJed Brown       PetscInt       *stratumSizes = PETSC_NULL, *points = PETSC_NULL;
3254*552f7358SJed Brown       PetscMPIInt    *sendcnts = PETSC_NULL, *offsets = PETSC_NULL, *displs = PETSC_NULL;
3255*552f7358SJed Brown       PetscInt        nameSize, s, p;
3256*552f7358SJed Brown       PetscBool       isdepth;
3257*552f7358SJed Brown       size_t          len = 0;
3258*552f7358SJed Brown 
3259*552f7358SJed Brown       /* Bcast name (could filter for no points) */
3260*552f7358SJed Brown       if (!rank) {ierr = PetscStrlen(next->name, &len);CHKERRQ(ierr);}
3261*552f7358SJed Brown       nameSize = len;
3262*552f7358SJed Brown       ierr = MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);CHKERRQ(ierr);
3263*552f7358SJed Brown       ierr = PetscMalloc(nameSize+1, &name);CHKERRQ(ierr);
3264*552f7358SJed Brown       if (!rank) {ierr = PetscMemcpy(name, next->name, nameSize+1);CHKERRQ(ierr);}
3265*552f7358SJed Brown       ierr = MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm);CHKERRQ(ierr);
3266*552f7358SJed Brown       ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr);
3267*552f7358SJed Brown       if (isdepth) {ierr = PetscFree(name);CHKERRQ(ierr); continue;}
3268*552f7358SJed Brown       ierr = PetscNew(struct _n_DMLabel, &newLabel);CHKERRQ(ierr);
3269*552f7358SJed Brown       newLabel->name = name;
3270*552f7358SJed Brown       /* Bcast numStrata (could filter for no points in stratum) */
3271*552f7358SJed Brown       if (!rank) {newLabel->numStrata = next->numStrata;}
3272*552f7358SJed Brown       ierr = MPI_Bcast(&newLabel->numStrata, 1, MPIU_INT, 0, comm);CHKERRQ(ierr);
3273*552f7358SJed Brown       ierr = PetscMalloc3(newLabel->numStrata,PetscInt,&newLabel->stratumValues,
3274*552f7358SJed Brown                           newLabel->numStrata,PetscInt,&newLabel->stratumSizes,
3275*552f7358SJed Brown                           newLabel->numStrata+1,PetscInt,&newLabel->stratumOffsets);CHKERRQ(ierr);
3276*552f7358SJed Brown       /* Bcast stratumValues (could filter for no points in stratum) */
3277*552f7358SJed Brown       if (!rank) {ierr = PetscMemcpy(newLabel->stratumValues, next->stratumValues, next->numStrata * sizeof(PetscInt));CHKERRQ(ierr);}
3278*552f7358SJed Brown       ierr = MPI_Bcast(newLabel->stratumValues, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr);
3279*552f7358SJed Brown       /* Find size on each process and Scatter */
3280*552f7358SJed Brown       if (!rank) {
3281*552f7358SJed Brown         ierr = ISGetIndices(part, &partArray);CHKERRQ(ierr);
3282*552f7358SJed Brown         ierr = PetscMalloc(numProcs*next->numStrata * sizeof(PetscInt), &stratumSizes);CHKERRQ(ierr);
3283*552f7358SJed Brown         ierr = PetscMemzero(stratumSizes, numProcs*next->numStrata * sizeof(PetscInt));CHKERRQ(ierr);
3284*552f7358SJed Brown         for (s = 0; s < next->numStrata; ++s) {
3285*552f7358SJed Brown           for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) {
3286*552f7358SJed Brown             const PetscInt point = next->points[p];
3287*552f7358SJed Brown             PetscInt       proc;
3288*552f7358SJed Brown 
3289*552f7358SJed Brown             for (proc = 0; proc < numProcs; ++proc) {
3290*552f7358SJed Brown               PetscInt dof, off, pPart;
3291*552f7358SJed Brown 
3292*552f7358SJed Brown               ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr);
3293*552f7358SJed Brown               ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr);
3294*552f7358SJed Brown               for (pPart = off; pPart < off+dof; ++pPart) {
3295*552f7358SJed Brown                 if (partArray[pPart] == point) {
3296*552f7358SJed Brown                   ++stratumSizes[proc*next->numStrata+s];
3297*552f7358SJed Brown                   break;
3298*552f7358SJed Brown                 }
3299*552f7358SJed Brown               }
3300*552f7358SJed Brown             }
3301*552f7358SJed Brown           }
3302*552f7358SJed Brown         }
3303*552f7358SJed Brown         ierr = ISRestoreIndices(part, &partArray);CHKERRQ(ierr);
3304*552f7358SJed Brown       }
3305*552f7358SJed Brown       ierr = MPI_Scatter(stratumSizes, newLabel->numStrata, MPIU_INT, newLabel->stratumSizes, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr);
3306*552f7358SJed Brown       /* Calculate stratumOffsets */
3307*552f7358SJed Brown       newLabel->stratumOffsets[0] = 0;
3308*552f7358SJed Brown       for (s = 0; s < newLabel->numStrata; ++s) {
3309*552f7358SJed Brown         newLabel->stratumOffsets[s+1] = newLabel->stratumSizes[s] + newLabel->stratumOffsets[s];
3310*552f7358SJed Brown       }
3311*552f7358SJed Brown       /* Pack points and Scatter */
3312*552f7358SJed Brown       if (!rank) {
3313*552f7358SJed Brown         ierr = PetscMalloc3(numProcs,PetscMPIInt,&sendcnts,numProcs,PetscMPIInt,&offsets,numProcs+1,PetscMPIInt,&displs);CHKERRQ(ierr);
3314*552f7358SJed Brown         displs[0] = 0;
3315*552f7358SJed Brown         for (p = 0; p < numProcs; ++p) {
3316*552f7358SJed Brown           sendcnts[p] = 0;
3317*552f7358SJed Brown           for (s = 0; s < next->numStrata; ++s) {
3318*552f7358SJed Brown             sendcnts[p] += stratumSizes[p*next->numStrata+s];
3319*552f7358SJed Brown           }
3320*552f7358SJed Brown           offsets[p]  = displs[p];
3321*552f7358SJed Brown           displs[p+1] = displs[p] + sendcnts[p];
3322*552f7358SJed Brown         }
3323*552f7358SJed Brown         ierr = PetscMalloc(displs[numProcs] * sizeof(PetscInt), &points);CHKERRQ(ierr);
3324*552f7358SJed Brown         for (s = 0; s < next->numStrata; ++s) {
3325*552f7358SJed Brown           for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) {
3326*552f7358SJed Brown             const PetscInt point = next->points[p];
3327*552f7358SJed Brown             PetscInt       proc;
3328*552f7358SJed Brown 
3329*552f7358SJed Brown             for (proc = 0; proc < numProcs; ++proc) {
3330*552f7358SJed Brown               PetscInt dof, off, pPart;
3331*552f7358SJed Brown 
3332*552f7358SJed Brown               ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr);
3333*552f7358SJed Brown               ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr);
3334*552f7358SJed Brown               for (pPart = off; pPart < off+dof; ++pPart) {
3335*552f7358SJed Brown                 if (partArray[pPart] == point) {
3336*552f7358SJed Brown                   points[offsets[proc]++] = point;
3337*552f7358SJed Brown                   break;
3338*552f7358SJed Brown                 }
3339*552f7358SJed Brown               }
3340*552f7358SJed Brown             }
3341*552f7358SJed Brown           }
3342*552f7358SJed Brown         }
3343*552f7358SJed Brown       }
3344*552f7358SJed Brown       ierr = PetscMalloc(newLabel->stratumOffsets[newLabel->numStrata] * sizeof(PetscInt), &newLabel->points);CHKERRQ(ierr);
3345*552f7358SJed Brown       ierr = MPI_Scatterv(points, sendcnts, displs, MPIU_INT, newLabel->points, newLabel->stratumOffsets[newLabel->numStrata], MPIU_INT, 0, comm);CHKERRQ(ierr);
3346*552f7358SJed Brown       ierr = PetscFree(points);CHKERRQ(ierr);
3347*552f7358SJed Brown       ierr = PetscFree3(sendcnts,offsets,displs);CHKERRQ(ierr);
3348*552f7358SJed Brown       ierr = PetscFree(stratumSizes);CHKERRQ(ierr);
3349*552f7358SJed Brown       /* Renumber points */
3350*552f7358SJed Brown       ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newLabel->stratumOffsets[newLabel->numStrata], newLabel->points, PETSC_NULL, newLabel->points);CHKERRQ(ierr);
3351*552f7358SJed Brown       /* Sort points */
3352*552f7358SJed Brown       for (s = 0; s < newLabel->numStrata; ++s) {
3353*552f7358SJed Brown         ierr = PetscSortInt(newLabel->stratumSizes[s], &newLabel->points[newLabel->stratumOffsets[s]]);CHKERRQ(ierr);
3354*552f7358SJed Brown       }
3355*552f7358SJed Brown       /* Insert into list */
3356*552f7358SJed Brown       if (newNext) {
3357*552f7358SJed Brown         newNext->next = newLabel;
3358*552f7358SJed Brown       } else {
3359*552f7358SJed Brown         pmesh->labels = newLabel;
3360*552f7358SJed Brown       }
3361*552f7358SJed Brown       newNext = newLabel;
3362*552f7358SJed Brown       if (!rank) {next = next->next;}
3363*552f7358SJed Brown     }
3364*552f7358SJed Brown   }
3365*552f7358SJed Brown   /* Cleanup Partition */
3366*552f7358SJed Brown   ierr = ISLocalToGlobalMappingDestroy(&renumbering);CHKERRQ(ierr);
3367*552f7358SJed Brown   ierr = PetscSFDestroy(&partSF);CHKERRQ(ierr);
3368*552f7358SJed Brown   ierr = PetscSectionDestroy(&partSection);CHKERRQ(ierr);
3369*552f7358SJed Brown   ierr = ISDestroy(&part);CHKERRQ(ierr);
3370*552f7358SJed Brown   /* Create point SF for parallel mesh */
3371*552f7358SJed Brown   {
3372*552f7358SJed Brown     const PetscInt *leaves;
3373*552f7358SJed Brown     PetscSFNode    *remotePoints, *rowners, *lowners;
3374*552f7358SJed Brown     PetscInt        numRoots, numLeaves, numGhostPoints = 0, p, gp, *ghostPoints;
3375*552f7358SJed Brown     PetscInt        pStart, pEnd;
3376*552f7358SJed Brown 
3377*552f7358SJed Brown     ierr = DMPlexGetChart(*dmParallel, &pStart, &pEnd);CHKERRQ(ierr);
3378*552f7358SJed Brown     ierr = PetscSFGetGraph(pointSF, &numRoots, &numLeaves, &leaves, PETSC_NULL);CHKERRQ(ierr);
3379*552f7358SJed Brown     ierr = PetscMalloc2(numRoots,PetscSFNode,&rowners,numLeaves,PetscSFNode,&lowners);CHKERRQ(ierr);
3380*552f7358SJed Brown     for (p=0; p<numRoots; p++) {
3381*552f7358SJed Brown       rowners[p].rank = -1;
3382*552f7358SJed Brown       rowners[p].index = -1;
3383*552f7358SJed Brown     }
3384*552f7358SJed Brown     if (origCellPart) {
3385*552f7358SJed Brown       /* Make sure cells in the original partition are not assigned to other procs */
3386*552f7358SJed Brown       const PetscInt *origCells;
3387*552f7358SJed Brown 
3388*552f7358SJed Brown       ierr = ISGetIndices(origCellPart, &origCells);CHKERRQ(ierr);
3389*552f7358SJed Brown       for (p = 0; p < numProcs; ++p) {
3390*552f7358SJed Brown         PetscInt dof, off, d;
3391*552f7358SJed Brown 
3392*552f7358SJed Brown         ierr = PetscSectionGetDof(origCellPartSection, p, &dof);CHKERRQ(ierr);
3393*552f7358SJed Brown         ierr = PetscSectionGetOffset(origCellPartSection, p, &off);CHKERRQ(ierr);
3394*552f7358SJed Brown         for(d = off; d < off+dof; ++d) {
3395*552f7358SJed Brown           rowners[origCells[d]].rank = p;
3396*552f7358SJed Brown         }
3397*552f7358SJed Brown       }
3398*552f7358SJed Brown       ierr = ISRestoreIndices(origCellPart, &origCells);CHKERRQ(ierr);
3399*552f7358SJed Brown     }
3400*552f7358SJed Brown     ierr = ISDestroy(&origCellPart);CHKERRQ(ierr);
3401*552f7358SJed Brown     ierr = PetscSectionDestroy(&origCellPartSection);CHKERRQ(ierr);
3402*552f7358SJed Brown 
3403*552f7358SJed Brown     ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr);
3404*552f7358SJed Brown     ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr);
3405*552f7358SJed Brown     for (p = 0; p < numLeaves; ++p) {
3406*552f7358SJed Brown       if (lowners[p].rank < 0 || lowners[p].rank == rank) { /* Either put in a bid or we know we own it */
3407*552f7358SJed Brown         lowners[p].rank = rank;
3408*552f7358SJed Brown         lowners[p].index = leaves ? leaves[p] : p;
3409*552f7358SJed Brown       } else if (lowners[p].rank >= 0) { /* Point already claimed so flag so that MAXLOC does not listen to us */
3410*552f7358SJed Brown         lowners[p].rank = -2;
3411*552f7358SJed Brown         lowners[p].index = -2;
3412*552f7358SJed Brown       }
3413*552f7358SJed Brown     }
3414*552f7358SJed Brown     for (p=0; p<numRoots; p++) { /* Root must not participate in the rediction, flag so that MAXLOC does not use */
3415*552f7358SJed Brown       rowners[p].rank = -3;
3416*552f7358SJed Brown       rowners[p].index = -3;
3417*552f7358SJed Brown     }
3418*552f7358SJed Brown     ierr = PetscSFReduceBegin(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr);
3419*552f7358SJed Brown     ierr = PetscSFReduceEnd(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr);
3420*552f7358SJed Brown     ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr);
3421*552f7358SJed Brown     ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr);
3422*552f7358SJed Brown     for (p = 0; p < numLeaves; ++p) {
3423*552f7358SJed Brown       if (lowners[p].rank < 0 || lowners[p].index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cell partition corrupt: point not claimed");
3424*552f7358SJed Brown       if (lowners[p].rank != rank) ++numGhostPoints;
3425*552f7358SJed Brown     }
3426*552f7358SJed Brown     ierr = PetscMalloc(numGhostPoints * sizeof(PetscInt),    &ghostPoints);CHKERRQ(ierr);
3427*552f7358SJed Brown     ierr = PetscMalloc(numGhostPoints * sizeof(PetscSFNode), &remotePoints);CHKERRQ(ierr);
3428*552f7358SJed Brown     for (p = 0, gp = 0; p < numLeaves; ++p) {
3429*552f7358SJed Brown       if (lowners[p].rank != rank) {
3430*552f7358SJed Brown         ghostPoints[gp]       = leaves ? leaves[p] : p;
3431*552f7358SJed Brown         remotePoints[gp].rank  = lowners[p].rank;
3432*552f7358SJed Brown         remotePoints[gp].index = lowners[p].index;
3433*552f7358SJed Brown         ++gp;
3434*552f7358SJed Brown       }
3435*552f7358SJed Brown     }
3436*552f7358SJed Brown     ierr = PetscFree2(rowners,lowners);CHKERRQ(ierr);
3437*552f7358SJed Brown     ierr = PetscSFSetGraph((*dmParallel)->sf, pEnd - pStart, numGhostPoints, ghostPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr);
3438*552f7358SJed Brown     ierr = PetscSFSetFromOptions((*dmParallel)->sf);CHKERRQ(ierr);
3439*552f7358SJed Brown   }
3440*552f7358SJed Brown   /* Cleanup */
3441*552f7358SJed Brown   ierr = PetscSFDestroy(&pointSF);CHKERRQ(ierr);
3442*552f7358SJed Brown   ierr = DMSetFromOptions(*dmParallel);CHKERRQ(ierr);
3443*552f7358SJed Brown   ierr = PetscLogEventEnd(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr);
3444*552f7358SJed Brown   PetscFunctionReturn(0);
3445*552f7358SJed Brown }
3446*552f7358SJed Brown 
3447*552f7358SJed Brown #undef __FUNCT__
3448*552f7358SJed Brown #define __FUNCT__ "DMPlexRenumber_Private"
3449*552f7358SJed Brown /*
3450*552f7358SJed Brown   Reasons to renumber:
3451*552f7358SJed Brown 
3452*552f7358SJed Brown   1) Permute points, e.g. bandwidth reduction (Renumber)
3453*552f7358SJed Brown 
3454*552f7358SJed Brown     a) Must not mix strata
3455*552f7358SJed Brown 
3456*552f7358SJed Brown   2) Shift numbers for point insertion (Shift)
3457*552f7358SJed Brown 
3458*552f7358SJed Brown     a) Want operation brken into parts so that insertion can be interleaved
3459*552f7358SJed Brown 
3460*552f7358SJed Brown   renumbering - An IS which provides the new numbering
3461*552f7358SJed Brown */
3462*552f7358SJed Brown PetscErrorCode DMPlexRenumber_Private(DM dm, IS renumbering)
3463*552f7358SJed Brown {
3464*552f7358SJed Brown   PetscFunctionBegin;
3465*552f7358SJed Brown   PetscFunctionReturn(0);
3466*552f7358SJed Brown }
3467*552f7358SJed Brown 
3468*552f7358SJed Brown #undef __FUNCT__
3469*552f7358SJed Brown #define __FUNCT__ "DMPlexShiftPoint_Private"
3470*552f7358SJed Brown PETSC_STATIC_INLINE PetscInt DMPlexShiftPoint_Private(PetscInt p, PetscInt depth, PetscInt depthEnd[], PetscInt depthShift[])
3471*552f7358SJed Brown {
3472*552f7358SJed Brown   if (depth < 0) return p;
3473*552f7358SJed Brown   /* Cells    */ if (p < depthEnd[depth])   return p;
3474*552f7358SJed Brown   /* Vertices */ if (p < depthEnd[0])       return p + depthShift[depth];
3475*552f7358SJed Brown   /* Faces    */ if (p < depthEnd[depth-1]) return p + depthShift[depth] + depthShift[0];
3476*552f7358SJed Brown   /* Edges    */                            return p + depthShift[depth] + depthShift[0] + depthShift[depth-1];
3477*552f7358SJed Brown }
3478*552f7358SJed Brown 
3479*552f7358SJed Brown #undef __FUNCT__
3480*552f7358SJed Brown #define __FUNCT__ "DMPlexShiftSizes_Private"
3481*552f7358SJed Brown PetscErrorCode DMPlexShiftSizes_Private(DM dm, PetscInt depthShift[], DM dmNew)
3482*552f7358SJed Brown {
3483*552f7358SJed Brown   PetscInt      *depthEnd;
3484*552f7358SJed Brown   PetscInt       depth = 0, d, pStart, pEnd, p;
3485*552f7358SJed Brown   PetscErrorCode ierr;
3486*552f7358SJed Brown 
3487*552f7358SJed Brown   PetscFunctionBegin;
3488*552f7358SJed Brown   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
3489*552f7358SJed Brown   if (depth < 0) PetscFunctionReturn(0);
3490*552f7358SJed Brown   ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr);
3491*552f7358SJed Brown   /* Step 1: Expand chart */
3492*552f7358SJed Brown   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
3493*552f7358SJed Brown   for(d = 0; d <= depth; ++d) {
3494*552f7358SJed Brown     pEnd += depthShift[d];
3495*552f7358SJed Brown     ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr);
3496*552f7358SJed Brown   }
3497*552f7358SJed Brown   ierr = DMPlexSetChart(dmNew, pStart, pEnd);CHKERRQ(ierr);
3498*552f7358SJed Brown   /* Step 2: Set cone and support sizes */
3499*552f7358SJed Brown   for(d = 0; d <= depth; ++d) {
3500*552f7358SJed Brown     ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr);
3501*552f7358SJed Brown     for(p = pStart; p < pEnd; ++p) {
3502*552f7358SJed Brown       PetscInt newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift);
3503*552f7358SJed Brown       PetscInt size;
3504*552f7358SJed Brown 
3505*552f7358SJed Brown       ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr);
3506*552f7358SJed Brown       ierr = DMPlexSetConeSize(dmNew, newp, size);CHKERRQ(ierr);
3507*552f7358SJed Brown       ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr);
3508*552f7358SJed Brown       ierr = DMPlexSetSupportSize(dmNew, newp, size);CHKERRQ(ierr);
3509*552f7358SJed Brown     }
3510*552f7358SJed Brown   }
3511*552f7358SJed Brown   ierr = PetscFree(depthEnd);CHKERRQ(ierr);
3512*552f7358SJed Brown   PetscFunctionReturn(0);
3513*552f7358SJed Brown }
3514*552f7358SJed Brown 
3515*552f7358SJed Brown #undef __FUNCT__
3516*552f7358SJed Brown #define __FUNCT__ "DMPlexShiftPoints_Private"
3517*552f7358SJed Brown PetscErrorCode DMPlexShiftPoints_Private(DM dm, PetscInt depthShift[], DM dmNew)
3518*552f7358SJed Brown {
3519*552f7358SJed Brown   PetscInt      *depthEnd, *newpoints;
3520*552f7358SJed Brown   PetscInt       depth = 0, d, maxConeSize, maxSupportSize, pStart, pEnd, p;
3521*552f7358SJed Brown   PetscErrorCode ierr;
3522*552f7358SJed Brown 
3523*552f7358SJed Brown   PetscFunctionBegin;
3524*552f7358SJed Brown   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
3525*552f7358SJed Brown   if (depth < 0) PetscFunctionReturn(0);
3526*552f7358SJed Brown   ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr);
3527*552f7358SJed Brown   ierr = PetscMalloc2(depth+1,PetscInt,&depthEnd,PetscMax(maxConeSize, maxSupportSize),PetscInt,&newpoints);CHKERRQ(ierr);
3528*552f7358SJed Brown   for(d = 0; d <= depth; ++d) {
3529*552f7358SJed Brown     ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr);
3530*552f7358SJed Brown   }
3531*552f7358SJed Brown   /* Step 5: Set cones and supports */
3532*552f7358SJed Brown   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
3533*552f7358SJed Brown   for(p = pStart; p < pEnd; ++p) {
3534*552f7358SJed Brown     const PetscInt *points = PETSC_NULL, *orientations = PETSC_NULL;
3535*552f7358SJed Brown     PetscInt        size, i, newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift);
3536*552f7358SJed Brown 
3537*552f7358SJed Brown     ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr);
3538*552f7358SJed Brown     ierr = DMPlexGetCone(dm, p, &points);CHKERRQ(ierr);
3539*552f7358SJed Brown     ierr = DMPlexGetConeOrientation(dm, p, &orientations);CHKERRQ(ierr);
3540*552f7358SJed Brown     for(i = 0; i < size; ++i) {
3541*552f7358SJed Brown       newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift);
3542*552f7358SJed Brown     }
3543*552f7358SJed Brown     ierr = DMPlexSetCone(dmNew, newp, newpoints);CHKERRQ(ierr);
3544*552f7358SJed Brown     ierr = DMPlexSetConeOrientation(dmNew, newp, orientations);CHKERRQ(ierr);
3545*552f7358SJed Brown     ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr);
3546*552f7358SJed Brown     ierr = DMPlexGetSupport(dm, p, &points);CHKERRQ(ierr);
3547*552f7358SJed Brown     for(i = 0; i < size; ++i) {
3548*552f7358SJed Brown       newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift);
3549*552f7358SJed Brown     }
3550*552f7358SJed Brown     ierr = DMPlexSetSupport(dmNew, newp, newpoints);CHKERRQ(ierr);
3551*552f7358SJed Brown   }
3552*552f7358SJed Brown   ierr = PetscFree2(depthEnd,newpoints);CHKERRQ(ierr);
3553*552f7358SJed Brown   PetscFunctionReturn(0);
3554*552f7358SJed Brown }
3555*552f7358SJed Brown 
3556*552f7358SJed Brown #undef __FUNCT__
3557*552f7358SJed Brown #define __FUNCT__ "DMPlexShiftCoordinates_Private"
3558*552f7358SJed Brown PetscErrorCode DMPlexShiftCoordinates_Private(DM dm, PetscInt depthShift[], DM dmNew)
3559*552f7358SJed Brown {
3560*552f7358SJed Brown   PetscSection   coordSection, newCoordSection;
3561*552f7358SJed Brown   Vec            coordinates;
3562*552f7358SJed Brown   PetscInt      *depthEnd;
3563*552f7358SJed Brown   PetscInt       dim, depth = 0, d, vStart, vEnd, v;
3564*552f7358SJed Brown   PetscErrorCode ierr;
3565*552f7358SJed Brown 
3566*552f7358SJed Brown   PetscFunctionBegin;
3567*552f7358SJed Brown   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
3568*552f7358SJed Brown   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
3569*552f7358SJed Brown   ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr);
3570*552f7358SJed Brown   for(d = 0; d <= depth; ++d) {
3571*552f7358SJed Brown     ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr);
3572*552f7358SJed Brown   }
3573*552f7358SJed Brown   /* Step 8: Convert coordinates */
3574*552f7358SJed Brown   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
3575*552f7358SJed Brown   ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr);
3576*552f7358SJed Brown   ierr = PetscSectionCreate(((PetscObject) dm)->comm, &newCoordSection);CHKERRQ(ierr);
3577*552f7358SJed Brown   ierr = PetscSectionSetNumFields(newCoordSection, 1);CHKERRQ(ierr);
3578*552f7358SJed Brown   ierr = PetscSectionSetFieldComponents(newCoordSection, 0, dim);CHKERRQ(ierr);
3579*552f7358SJed Brown   ierr = PetscSectionSetChart(newCoordSection, DMPlexShiftPoint_Private(vStart, depth, depthEnd, depthShift), DMPlexShiftPoint_Private(vEnd, depth, depthEnd, depthShift));CHKERRQ(ierr);
3580*552f7358SJed Brown   for(v = vStart; v < vEnd; ++v) {
3581*552f7358SJed Brown     const PetscInt newv = DMPlexShiftPoint_Private(v, depth, depthEnd, depthShift);
3582*552f7358SJed Brown     ierr = PetscSectionSetDof(newCoordSection, newv, dim);CHKERRQ(ierr);
3583*552f7358SJed Brown     ierr = PetscSectionSetFieldDof(newCoordSection, newv, 0, dim);CHKERRQ(ierr);
3584*552f7358SJed Brown   }
3585*552f7358SJed Brown   ierr = PetscSectionSetUp(newCoordSection);CHKERRQ(ierr);
3586*552f7358SJed Brown   ierr = DMPlexSetCoordinateSection(dmNew, newCoordSection);CHKERRQ(ierr);
3587*552f7358SJed Brown   ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
3588*552f7358SJed Brown   ierr = DMSetCoordinatesLocal(dmNew, coordinates);CHKERRQ(ierr);
3589*552f7358SJed Brown   ierr = PetscFree(depthEnd);CHKERRQ(ierr);
3590*552f7358SJed Brown   PetscFunctionReturn(0);
3591*552f7358SJed Brown }
3592*552f7358SJed Brown 
3593*552f7358SJed Brown #undef __FUNCT__
3594*552f7358SJed Brown #define __FUNCT__ "DMPlexShiftSF_Private"
3595*552f7358SJed Brown PetscErrorCode DMPlexShiftSF_Private(DM dm, PetscInt depthShift[], DM dmNew)
3596*552f7358SJed Brown {
3597*552f7358SJed Brown   PetscInt          *depthEnd;
3598*552f7358SJed Brown   PetscInt           depth = 0, d;
3599*552f7358SJed Brown   PetscSF            sfPoint, sfPointNew;
3600*552f7358SJed Brown   const PetscSFNode *remotePoints;
3601*552f7358SJed Brown   PetscSFNode       *gremotePoints;
3602*552f7358SJed Brown   const PetscInt    *localPoints;
3603*552f7358SJed Brown   PetscInt          *glocalPoints, *newLocation, *newRemoteLocation;
3604*552f7358SJed Brown   PetscInt           numRoots, numLeaves, l, pStart, pEnd, totShift = 0;
3605*552f7358SJed Brown   PetscMPIInt        numProcs;
3606*552f7358SJed Brown   PetscErrorCode     ierr;
3607*552f7358SJed Brown 
3608*552f7358SJed Brown   PetscFunctionBegin;
3609*552f7358SJed Brown   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
3610*552f7358SJed Brown   ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr);
3611*552f7358SJed Brown   for(d = 0; d <= depth; ++d) {
3612*552f7358SJed Brown     totShift += depthShift[d];
3613*552f7358SJed Brown     ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr);
3614*552f7358SJed Brown   }
3615*552f7358SJed Brown   /* Step 9: Convert pointSF */
3616*552f7358SJed Brown   ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr);
3617*552f7358SJed Brown   ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr);
3618*552f7358SJed Brown   ierr = DMGetPointSF(dmNew, &sfPointNew);CHKERRQ(ierr);
3619*552f7358SJed Brown   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
3620*552f7358SJed Brown   ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr);
3621*552f7358SJed Brown   if (numRoots >= 0) {
3622*552f7358SJed Brown     ierr = PetscMalloc2(numRoots,PetscInt,&newLocation,pEnd-pStart,PetscInt,&newRemoteLocation);CHKERRQ(ierr);
3623*552f7358SJed Brown     for(l=0; l<numRoots; l++) newLocation[l] = DMPlexShiftPoint_Private(l, depth, depthEnd, depthShift);
3624*552f7358SJed Brown     ierr = PetscSFBcastBegin(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr);
3625*552f7358SJed Brown     ierr = PetscSFBcastEnd(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr);
3626*552f7358SJed Brown     ierr = PetscMalloc(numLeaves * sizeof(PetscInt),    &glocalPoints);CHKERRQ(ierr);
3627*552f7358SJed Brown     ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &gremotePoints);CHKERRQ(ierr);
3628*552f7358SJed Brown     for(l = 0; l < numLeaves; ++l) {
3629*552f7358SJed Brown       glocalPoints[l]        = DMPlexShiftPoint_Private(localPoints[l], depth, depthEnd, depthShift);
3630*552f7358SJed Brown       gremotePoints[l].rank  = remotePoints[l].rank;
3631*552f7358SJed Brown       gremotePoints[l].index = newRemoteLocation[localPoints[l]];
3632*552f7358SJed Brown     }
3633*552f7358SJed Brown     ierr = PetscFree2(newLocation,newRemoteLocation);CHKERRQ(ierr);
3634*552f7358SJed Brown     ierr = PetscSFSetGraph(sfPointNew, numRoots + totShift, numLeaves, glocalPoints, PETSC_OWN_POINTER, gremotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr);
3635*552f7358SJed Brown   }
3636*552f7358SJed Brown   ierr = PetscFree(depthEnd);CHKERRQ(ierr);
3637*552f7358SJed Brown   PetscFunctionReturn(0);
3638*552f7358SJed Brown }
3639*552f7358SJed Brown 
3640*552f7358SJed Brown #undef __FUNCT__
3641*552f7358SJed Brown #define __FUNCT__ "DMPlexShiftLabels_Private"
3642*552f7358SJed Brown PetscErrorCode DMPlexShiftLabels_Private(DM dm, PetscInt depthShift[], DM dmNew)
3643*552f7358SJed Brown {
3644*552f7358SJed Brown   PetscSF        sfPoint;
3645*552f7358SJed Brown   DMLabel        vtkLabel, ghostLabel;
3646*552f7358SJed Brown   PetscInt      *depthEnd;
3647*552f7358SJed Brown   const PetscSFNode *leafRemote;
3648*552f7358SJed Brown   const PetscInt    *leafLocal;
3649*552f7358SJed Brown   PetscInt       depth = 0, d, numLeaves, numLabels, l, cStart, cEnd, c, fStart, fEnd, f;
3650*552f7358SJed Brown   PetscMPIInt    rank;
3651*552f7358SJed Brown   PetscErrorCode ierr;
3652*552f7358SJed Brown 
3653*552f7358SJed Brown   PetscFunctionBegin;
3654*552f7358SJed Brown   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
3655*552f7358SJed Brown   ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr);
3656*552f7358SJed Brown   for(d = 0; d <= depth; ++d) {
3657*552f7358SJed Brown     ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr);
3658*552f7358SJed Brown   }
3659*552f7358SJed Brown   /* Step 10: Convert labels */
3660*552f7358SJed Brown   ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr);
3661*552f7358SJed Brown   for(l = 0; l < numLabels; ++l) {
3662*552f7358SJed Brown     DMLabel         label, newlabel;
3663*552f7358SJed Brown     const char     *lname;
3664*552f7358SJed Brown     PetscBool       isDepth;
3665*552f7358SJed Brown     IS              valueIS;
3666*552f7358SJed Brown     const PetscInt *values;
3667*552f7358SJed Brown     PetscInt        numValues, val;
3668*552f7358SJed Brown 
3669*552f7358SJed Brown     ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr);
3670*552f7358SJed Brown     ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr);
3671*552f7358SJed Brown     if (isDepth) continue;
3672*552f7358SJed Brown     ierr = DMPlexCreateLabel(dmNew, lname);CHKERRQ(ierr);
3673*552f7358SJed Brown     ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr);
3674*552f7358SJed Brown     ierr = DMPlexGetLabel(dmNew, lname, &newlabel);CHKERRQ(ierr);
3675*552f7358SJed Brown     ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr);
3676*552f7358SJed Brown     ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr);
3677*552f7358SJed Brown     ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr);
3678*552f7358SJed Brown     for(val = 0; val < numValues; ++val) {
3679*552f7358SJed Brown       IS              pointIS;
3680*552f7358SJed Brown       const PetscInt *points;
3681*552f7358SJed Brown       PetscInt        numPoints, p;
3682*552f7358SJed Brown 
3683*552f7358SJed Brown       ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr);
3684*552f7358SJed Brown       ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr);
3685*552f7358SJed Brown       ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr);
3686*552f7358SJed Brown       for(p = 0; p < numPoints; ++p) {
3687*552f7358SJed Brown         const PetscInt newpoint = DMPlexShiftPoint_Private(points[p], depth, depthEnd, depthShift);
3688*552f7358SJed Brown 
3689*552f7358SJed Brown         ierr = DMLabelSetValue(newlabel, newpoint, values[val]);CHKERRQ(ierr);
3690*552f7358SJed Brown       }
3691*552f7358SJed Brown       ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr);
3692*552f7358SJed Brown       ierr = ISDestroy(&pointIS);CHKERRQ(ierr);
3693*552f7358SJed Brown     }
3694*552f7358SJed Brown     ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr);
3695*552f7358SJed Brown     ierr = ISDestroy(&valueIS);CHKERRQ(ierr);
3696*552f7358SJed Brown   }
3697*552f7358SJed Brown   ierr = PetscFree(depthEnd);CHKERRQ(ierr);
3698*552f7358SJed Brown   /* Step 11: Make label for output (vtk) and to mark ghost points (ghost) */
3699*552f7358SJed Brown   ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr);
3700*552f7358SJed Brown   ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr);
3701*552f7358SJed Brown   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
3702*552f7358SJed Brown   ierr = PetscSFGetGraph(sfPoint, PETSC_NULL, &numLeaves, &leafLocal, &leafRemote);CHKERRQ(ierr);
3703*552f7358SJed Brown   ierr = DMPlexCreateLabel(dmNew, "vtk");CHKERRQ(ierr);
3704*552f7358SJed Brown   ierr = DMPlexCreateLabel(dmNew, "ghost");CHKERRQ(ierr);
3705*552f7358SJed Brown   ierr = DMPlexGetLabel(dmNew, "vtk", &vtkLabel);CHKERRQ(ierr);
3706*552f7358SJed Brown   ierr = DMPlexGetLabel(dmNew, "ghost", &ghostLabel);CHKERRQ(ierr);
3707*552f7358SJed Brown   for(l = 0, c = cStart; l < numLeaves && c < cEnd; ++l, ++c) {
3708*552f7358SJed Brown     for(; c < leafLocal[l] && c < cEnd; ++c) {
3709*552f7358SJed Brown       ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr);
3710*552f7358SJed Brown     }
3711*552f7358SJed Brown     if (leafLocal[l] >= cEnd) break;
3712*552f7358SJed Brown     if (leafRemote[l].rank == rank) {
3713*552f7358SJed Brown       ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr);
3714*552f7358SJed Brown     } else {
3715*552f7358SJed Brown       ierr = DMLabelSetValue(ghostLabel, c, 2);CHKERRQ(ierr);
3716*552f7358SJed Brown     }
3717*552f7358SJed Brown   }
3718*552f7358SJed Brown   for(; c < cEnd; ++c) {
3719*552f7358SJed Brown     ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr);
3720*552f7358SJed Brown   }
3721*552f7358SJed Brown   if (0) {
3722*552f7358SJed Brown     ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr);
3723*552f7358SJed Brown     ierr = DMLabelView(vtkLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
3724*552f7358SJed Brown     ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
3725*552f7358SJed Brown   }
3726*552f7358SJed Brown   ierr = DMPlexGetHeightStratum(dmNew, 1, &fStart, &fEnd);CHKERRQ(ierr);
3727*552f7358SJed Brown   for(f = fStart; f < fEnd; ++f) {
3728*552f7358SJed Brown     PetscInt numCells;
3729*552f7358SJed Brown 
3730*552f7358SJed Brown     ierr = DMPlexGetSupportSize(dmNew, f, &numCells);CHKERRQ(ierr);
3731*552f7358SJed Brown     if (numCells < 2) {
3732*552f7358SJed Brown       ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr);
3733*552f7358SJed Brown     } else {
3734*552f7358SJed Brown       const PetscInt *cells = PETSC_NULL;
3735*552f7358SJed Brown       PetscInt        vA, vB;
3736*552f7358SJed Brown 
3737*552f7358SJed Brown       ierr = DMPlexGetSupport(dmNew, f, &cells);CHKERRQ(ierr);
3738*552f7358SJed Brown       ierr = DMLabelGetValue(vtkLabel, cells[0], &vA);CHKERRQ(ierr);
3739*552f7358SJed Brown       ierr = DMLabelGetValue(vtkLabel, cells[1], &vB);CHKERRQ(ierr);
3740*552f7358SJed Brown       if (!vA && !vB) {ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr);}
3741*552f7358SJed Brown     }
3742*552f7358SJed Brown   }
3743*552f7358SJed Brown   if (0) {
3744*552f7358SJed Brown     ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr);
3745*552f7358SJed Brown     ierr = DMLabelView(ghostLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
3746*552f7358SJed Brown     ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
3747*552f7358SJed Brown   }
3748*552f7358SJed Brown   PetscFunctionReturn(0);
3749*552f7358SJed Brown }
3750*552f7358SJed Brown 
3751*552f7358SJed Brown #undef __FUNCT__
3752*552f7358SJed Brown #define __FUNCT__ "DMPlexConstructGhostCells_2D"
3753*552f7358SJed Brown /*@C
3754*552f7358SJed Brown   DMPlexConstructGhostCells - Construct ghost cells which connect to every boundary face
3755*552f7358SJed Brown 
3756*552f7358SJed Brown   Collective on dm
3757*552f7358SJed Brown 
3758*552f7358SJed Brown   Input Parameters:
3759*552f7358SJed Brown + dm - The original DM
3760*552f7358SJed Brown - labelName - The label specifying the boundary faces (this could be auto-generated)
3761*552f7358SJed Brown 
3762*552f7358SJed Brown   Output Parameters:
3763*552f7358SJed Brown + numGhostCells - The number of ghost cells added to the DM
3764*552f7358SJed Brown - dmGhosted - The new DM
3765*552f7358SJed Brown 
3766*552f7358SJed Brown   Level: developer
3767*552f7358SJed Brown 
3768*552f7358SJed Brown .seealso: DMCreate()
3769*552f7358SJed Brown */
3770*552f7358SJed Brown PetscErrorCode DMPlexConstructGhostCells_2D(DM dm, const char labelName[], PetscInt *numGhostCells, DM gdm)
3771*552f7358SJed Brown {
3772*552f7358SJed Brown   DMLabel         label;
3773*552f7358SJed Brown   IS              valueIS;
3774*552f7358SJed Brown   const PetscInt *values;
3775*552f7358SJed Brown   PetscInt       *depthShift;
3776*552f7358SJed Brown   PetscInt        depth = 0, numFS, fs, ghostCell, cEnd, c;
3777*552f7358SJed Brown   PetscErrorCode  ierr;
3778*552f7358SJed Brown 
3779*552f7358SJed Brown   PetscFunctionBegin;
3780*552f7358SJed Brown   /* Count ghost cells */
3781*552f7358SJed Brown   ierr = DMPlexGetLabel(dm, labelName ? labelName : "Face Sets", &label);CHKERRQ(ierr);
3782*552f7358SJed Brown   ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr);
3783*552f7358SJed Brown   ierr = ISGetLocalSize(valueIS, &numFS);CHKERRQ(ierr);
3784*552f7358SJed Brown   ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr);
3785*552f7358SJed Brown   *numGhostCells = 0;
3786*552f7358SJed Brown   for(fs = 0; fs < numFS; ++fs) {
3787*552f7358SJed Brown     PetscInt numBdFaces;
3788*552f7358SJed Brown 
3789*552f7358SJed Brown     ierr = DMLabelGetStratumSize(label, values[fs], &numBdFaces);CHKERRQ(ierr);
3790*552f7358SJed Brown     *numGhostCells += numBdFaces;
3791*552f7358SJed Brown   }
3792*552f7358SJed Brown   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
3793*552f7358SJed Brown   ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthShift);CHKERRQ(ierr);
3794*552f7358SJed Brown   ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr);
3795*552f7358SJed Brown   if (depth >= 0) {depthShift[depth] = *numGhostCells;}
3796*552f7358SJed Brown   ierr = DMPlexShiftSizes_Private(dm, depthShift, gdm);CHKERRQ(ierr);
3797*552f7358SJed Brown   /* Step 3: Set cone/support sizes for new points */
3798*552f7358SJed Brown   ierr = DMPlexGetHeightStratum(dm, 0, PETSC_NULL, &cEnd);CHKERRQ(ierr);
3799*552f7358SJed Brown   for(c = cEnd; c < cEnd + *numGhostCells; ++c) {
3800*552f7358SJed Brown     ierr = DMPlexSetConeSize(gdm, c, 1);CHKERRQ(ierr);
3801*552f7358SJed Brown   }
3802*552f7358SJed Brown   for(fs = 0; fs < numFS; ++fs) {
3803*552f7358SJed Brown     IS              faceIS;
3804*552f7358SJed Brown     const PetscInt *faces;
3805*552f7358SJed Brown     PetscInt        numFaces, f;
3806*552f7358SJed Brown 
3807*552f7358SJed Brown     ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr);
3808*552f7358SJed Brown     ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr);
3809*552f7358SJed Brown     ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr);
3810*552f7358SJed Brown     for(f = 0; f < numFaces; ++f) {
3811*552f7358SJed Brown       PetscInt size;
3812*552f7358SJed Brown 
3813*552f7358SJed Brown       ierr = DMPlexGetSupportSize(dm, faces[f], &size);CHKERRQ(ierr);
3814*552f7358SJed Brown       if (size != 1) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "DM has boundary face %d with %d support cells", faces[f], size);
3815*552f7358SJed Brown       ierr = DMPlexSetSupportSize(gdm, faces[f] + *numGhostCells, 2);CHKERRQ(ierr);
3816*552f7358SJed Brown     }
3817*552f7358SJed Brown     ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr);
3818*552f7358SJed Brown     ierr = ISDestroy(&faceIS);CHKERRQ(ierr);
3819*552f7358SJed Brown   }
3820*552f7358SJed Brown   /* Step 4: Setup ghosted DM */
3821*552f7358SJed Brown   ierr = DMSetUp(gdm);CHKERRQ(ierr);
3822*552f7358SJed Brown   ierr = DMPlexShiftPoints_Private(dm, depthShift, gdm);CHKERRQ(ierr);
3823*552f7358SJed Brown   /* Step 6: Set cones and supports for new points */
3824*552f7358SJed Brown   ghostCell = cEnd;
3825*552f7358SJed Brown   for(fs = 0; fs < numFS; ++fs) {
3826*552f7358SJed Brown     IS              faceIS;
3827*552f7358SJed Brown     const PetscInt *faces;
3828*552f7358SJed Brown     PetscInt        numFaces, f;
3829*552f7358SJed Brown 
3830*552f7358SJed Brown     ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr);
3831*552f7358SJed Brown     ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr);
3832*552f7358SJed Brown     ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr);
3833*552f7358SJed Brown     for(f = 0; f < numFaces; ++f, ++ghostCell) {
3834*552f7358SJed Brown       PetscInt newFace = faces[f] + *numGhostCells;
3835*552f7358SJed Brown 
3836*552f7358SJed Brown       ierr = DMPlexSetCone(gdm, ghostCell, &newFace);CHKERRQ(ierr);
3837*552f7358SJed Brown       ierr = DMPlexInsertSupport(gdm, newFace, 1, ghostCell);CHKERRQ(ierr);
3838*552f7358SJed Brown     }
3839*552f7358SJed Brown     ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr);
3840*552f7358SJed Brown     ierr = ISDestroy(&faceIS);CHKERRQ(ierr);
3841*552f7358SJed Brown   }
3842*552f7358SJed Brown   ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr);
3843*552f7358SJed Brown   ierr = ISDestroy(&valueIS);CHKERRQ(ierr);
3844*552f7358SJed Brown   /* Step 7: Stratify */
3845*552f7358SJed Brown   ierr = DMPlexStratify(gdm);CHKERRQ(ierr);
3846*552f7358SJed Brown   ierr = DMPlexShiftCoordinates_Private(dm, depthShift, gdm);CHKERRQ(ierr);
3847*552f7358SJed Brown   ierr = DMPlexShiftSF_Private(dm, depthShift, gdm);CHKERRQ(ierr);
3848*552f7358SJed Brown   ierr = DMPlexShiftLabels_Private(dm, depthShift, gdm);CHKERRQ(ierr);
3849*552f7358SJed Brown   ierr = PetscFree(depthShift);CHKERRQ(ierr);
3850*552f7358SJed Brown   PetscFunctionReturn(0);
3851*552f7358SJed Brown }
3852*552f7358SJed Brown 
3853*552f7358SJed Brown #undef __FUNCT__
3854*552f7358SJed Brown #define __FUNCT__ "DMPlexConstructGhostCells"
3855*552f7358SJed Brown /*@C
3856*552f7358SJed Brown   DMPlexConstructGhostCells - Construct ghost cells which connect to every boundary face
3857*552f7358SJed Brown 
3858*552f7358SJed Brown   Collective on dm
3859*552f7358SJed Brown 
3860*552f7358SJed Brown   Input Parameters:
3861*552f7358SJed Brown + dm - The original DM
3862*552f7358SJed Brown - labelName - The label specifying the boundary faces (this could be auto-generated)
3863*552f7358SJed Brown 
3864*552f7358SJed Brown   Output Parameters:
3865*552f7358SJed Brown + numGhostCells - The number of ghost cells added to the DM
3866*552f7358SJed Brown - dmGhosted - The new DM
3867*552f7358SJed Brown 
3868*552f7358SJed Brown   Level: developer
3869*552f7358SJed Brown 
3870*552f7358SJed Brown .seealso: DMCreate()
3871*552f7358SJed Brown */
3872*552f7358SJed Brown PetscErrorCode DMPlexConstructGhostCells(DM dm, const char labelName[], PetscInt *numGhostCells, DM *dmGhosted)
3873*552f7358SJed Brown {
3874*552f7358SJed Brown   DM             gdm;
3875*552f7358SJed Brown   PetscInt       dim;
3876*552f7358SJed Brown   PetscErrorCode ierr;
3877*552f7358SJed Brown 
3878*552f7358SJed Brown   PetscFunctionBegin;
3879*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3880*552f7358SJed Brown   PetscValidPointer(numGhostCells, 3);
3881*552f7358SJed Brown   PetscValidPointer(dmGhosted, 4);
3882*552f7358SJed Brown   ierr = DMCreate(((PetscObject) dm)->comm, &gdm);CHKERRQ(ierr);
3883*552f7358SJed Brown   ierr = DMSetType(gdm, DMPLEX);CHKERRQ(ierr);
3884*552f7358SJed Brown   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
3885*552f7358SJed Brown   ierr = DMPlexSetDimension(gdm, dim);CHKERRQ(ierr);
3886*552f7358SJed Brown   switch(dim) {
3887*552f7358SJed Brown   case 2:
3888*552f7358SJed Brown     ierr = DMPlexConstructGhostCells_2D(dm, labelName, numGhostCells, gdm);CHKERRQ(ierr);
3889*552f7358SJed Brown     break;
3890*552f7358SJed Brown   default:
3891*552f7358SJed Brown     SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct ghost cells for dimension %d", dim);
3892*552f7358SJed Brown   }
3893*552f7358SJed Brown   ierr = DMSetFromOptions(gdm);CHKERRQ(ierr);
3894*552f7358SJed Brown   *dmGhosted = gdm;
3895*552f7358SJed Brown   PetscFunctionReturn(0);
3896*552f7358SJed Brown }
3897*552f7358SJed Brown 
3898*552f7358SJed Brown #undef __FUNCT__
3899*552f7358SJed Brown #define __FUNCT__ "DMPlexInterpolate_2D"
3900*552f7358SJed Brown PetscErrorCode DMPlexInterpolate_2D(DM dm, DM *dmInt)
3901*552f7358SJed Brown {
3902*552f7358SJed Brown   DM             idm;
3903*552f7358SJed Brown   DM_Plex    *mesh;
3904*552f7358SJed Brown   PetscHashIJ    edgeTable;
3905*552f7358SJed Brown   PetscInt      *off;
3906*552f7358SJed Brown   PetscInt       dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd;
3907*552f7358SJed Brown   PetscInt       numEdges, firstEdge, edge, e;
3908*552f7358SJed Brown   PetscErrorCode ierr;
3909*552f7358SJed Brown 
3910*552f7358SJed Brown   PetscFunctionBegin;
3911*552f7358SJed Brown   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
3912*552f7358SJed Brown   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
3913*552f7358SJed Brown   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
3914*552f7358SJed Brown   numCells    = cEnd - cStart;
3915*552f7358SJed Brown   numVertices = vEnd - vStart;
3916*552f7358SJed Brown   firstEdge   = numCells + numVertices;
3917*552f7358SJed Brown   numEdges    = 0 ;
3918*552f7358SJed Brown   /* Count edges using algorithm from CreateNeighborCSR */
3919*552f7358SJed Brown   ierr = DMPlexCreateNeighborCSR(dm, PETSC_NULL, &off, PETSC_NULL);CHKERRQ(ierr);
3920*552f7358SJed Brown   if (off) {
3921*552f7358SJed Brown     PetscInt numCorners = 0;
3922*552f7358SJed Brown 
3923*552f7358SJed Brown     numEdges = off[numCells]/2;
3924*552f7358SJed Brown #if 0
3925*552f7358SJed Brown     /* Account for boundary edges: \sum_c 3 - neighbors = 3*numCells - totalNeighbors */
3926*552f7358SJed Brown     numEdges += 3*numCells - off[numCells];
3927*552f7358SJed Brown #else
3928*552f7358SJed Brown     /* Account for boundary edges: \sum_c #faces - #neighbors = \sum_c #cellVertices - #neighbors = totalCorners - totalNeighbors */
3929*552f7358SJed Brown     for(c = cStart; c < cEnd; ++c) {
3930*552f7358SJed Brown       PetscInt coneSize;
3931*552f7358SJed Brown 
3932*552f7358SJed Brown       ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr);
3933*552f7358SJed Brown       numCorners += coneSize;
3934*552f7358SJed Brown     }
3935*552f7358SJed Brown     numEdges += numCorners - off[numCells];
3936*552f7358SJed Brown #endif
3937*552f7358SJed Brown   }
3938*552f7358SJed Brown #if 0
3939*552f7358SJed Brown   /* Check Euler characteristic V - E + F = 1 */
3940*552f7358SJed Brown   if (numVertices && (numVertices-numEdges+numCells != 1)) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Euler characteristic of mesh is %d  != 1", numVertices-numEdges+numCells);
3941*552f7358SJed Brown #endif
3942*552f7358SJed Brown   /* Create interpolated mesh */
3943*552f7358SJed Brown   ierr = DMCreate(((PetscObject) dm)->comm, &idm);CHKERRQ(ierr);
3944*552f7358SJed Brown   ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr);
3945*552f7358SJed Brown   ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr);
3946*552f7358SJed Brown   ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numEdges);CHKERRQ(ierr);
3947*552f7358SJed Brown   for (c = 0; c < numCells; ++c) {
3948*552f7358SJed Brown     PetscInt numCorners;
3949*552f7358SJed Brown 
3950*552f7358SJed Brown     ierr = DMPlexGetConeSize(dm, c, &numCorners);CHKERRQ(ierr);
3951*552f7358SJed Brown     ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr);
3952*552f7358SJed Brown   }
3953*552f7358SJed Brown   for (e = firstEdge; e < firstEdge+numEdges; ++e) {
3954*552f7358SJed Brown     ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr);
3955*552f7358SJed Brown   }
3956*552f7358SJed Brown   ierr = DMSetUp(idm);CHKERRQ(ierr);
3957*552f7358SJed Brown   /* Get edge cones from subsets of cell vertices */
3958*552f7358SJed Brown   ierr = PetscHashIJCreate(&edgeTable);CHKERRQ(ierr);
3959*552f7358SJed Brown   ierr = PetscHashIJSetMultivalued(edgeTable, PETSC_FALSE);CHKERRQ(ierr);
3960*552f7358SJed Brown 
3961*552f7358SJed Brown   for (c = 0, edge = firstEdge; c < numCells; ++c) {
3962*552f7358SJed Brown     const PetscInt *cellFaces;
3963*552f7358SJed Brown     PetscInt        numCellFaces, faceSize, cf;
3964*552f7358SJed Brown 
3965*552f7358SJed Brown     ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr);
3966*552f7358SJed Brown     if (faceSize != 2) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize);
3967*552f7358SJed Brown     for (cf = 0; cf < numCellFaces; ++cf) {
3968*552f7358SJed Brown #if 1
3969*552f7358SJed Brown       PetscHashIJKey key = {PetscMin(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1]),
3970*552f7358SJed Brown                             PetscMax(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1])};
3971*552f7358SJed Brown 
3972*552f7358SJed Brown       ierr = PetscHashIJGet(edgeTable, key, &e);CHKERRQ(ierr);
3973*552f7358SJed Brown       if (e < 0) {
3974*552f7358SJed Brown         ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr);
3975*552f7358SJed Brown         ierr = PetscHashIJAdd(edgeTable, key, edge);CHKERRQ(ierr);
3976*552f7358SJed Brown         e    = edge++;
3977*552f7358SJed Brown       }
3978*552f7358SJed Brown #else
3979*552f7358SJed Brown       PetscBool found = PETSC_FALSE;
3980*552f7358SJed Brown 
3981*552f7358SJed Brown       /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */
3982*552f7358SJed Brown       for (e = firstEdge; e < edge; ++e) {
3983*552f7358SJed Brown         const PetscInt *cone;
3984*552f7358SJed Brown 
3985*552f7358SJed Brown         ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr);
3986*552f7358SJed Brown         if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) ||
3987*552f7358SJed Brown             ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) {
3988*552f7358SJed Brown           found = PETSC_TRUE;
3989*552f7358SJed Brown           break;
3990*552f7358SJed Brown         }
3991*552f7358SJed Brown       }
3992*552f7358SJed Brown       if (!found) {
3993*552f7358SJed Brown         ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr);
3994*552f7358SJed Brown         ++edge;
3995*552f7358SJed Brown       }
3996*552f7358SJed Brown #endif
3997*552f7358SJed Brown       ierr = DMPlexInsertCone(idm, c, cf, e);CHKERRQ(ierr);
3998*552f7358SJed Brown     }
3999*552f7358SJed Brown   }
4000*552f7358SJed Brown   if (edge != firstEdge+numEdges) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges);
4001*552f7358SJed Brown   ierr = PetscHashIJDestroy(&edgeTable);CHKERRQ(ierr);
4002*552f7358SJed Brown   ierr = PetscFree(off);CHKERRQ(ierr);
4003*552f7358SJed Brown   ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr);
4004*552f7358SJed Brown   ierr = DMPlexStratify(idm);CHKERRQ(ierr);
4005*552f7358SJed Brown   mesh = (DM_Plex *) (idm)->data;
4006*552f7358SJed Brown   /* Orient edges */
4007*552f7358SJed Brown   for (c = 0; c < numCells; ++c) {
4008*552f7358SJed Brown     const PetscInt *cone = PETSC_NULL, *cellFaces;
4009*552f7358SJed Brown     PetscInt        coneSize, coff, numCellFaces, faceSize, cf;
4010*552f7358SJed Brown 
4011*552f7358SJed Brown     ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr);
4012*552f7358SJed Brown     ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr);
4013*552f7358SJed Brown     ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr);
4014*552f7358SJed Brown     ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr);
4015*552f7358SJed Brown     if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for cell %D should be %D", coneSize, c, numCellFaces);
4016*552f7358SJed Brown     for (cf = 0; cf < numCellFaces; ++cf) {
4017*552f7358SJed Brown       const PetscInt *econe = PETSC_NULL;
4018*552f7358SJed Brown       PetscInt        esize;
4019*552f7358SJed Brown 
4020*552f7358SJed Brown       ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr);
4021*552f7358SJed Brown       ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr);
4022*552f7358SJed Brown       if (esize != 2) SETERRQ2(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edge endpoints %D for edge %D should be 2", esize, cone[cf]);
4023*552f7358SJed Brown       if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) {
4024*552f7358SJed Brown         /* Correctly oriented */
4025*552f7358SJed Brown         mesh->coneOrientations[coff+cf] = 0;
4026*552f7358SJed Brown       } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) {
4027*552f7358SJed Brown         /* Start at index 1, and reverse orientation */
4028*552f7358SJed Brown         mesh->coneOrientations[coff+cf] = -(1+1);
4029*552f7358SJed Brown       }
4030*552f7358SJed Brown     }
4031*552f7358SJed Brown   }
4032*552f7358SJed Brown   *dmInt  = idm;
4033*552f7358SJed Brown   PetscFunctionReturn(0);
4034*552f7358SJed Brown }
4035*552f7358SJed Brown 
4036*552f7358SJed Brown #undef __FUNCT__
4037*552f7358SJed Brown #define __FUNCT__ "DMPlexInterpolate_3D"
4038*552f7358SJed Brown PetscErrorCode DMPlexInterpolate_3D(DM dm, DM *dmInt)
4039*552f7358SJed Brown {
4040*552f7358SJed Brown   DM             idm, fdm;
4041*552f7358SJed Brown   DM_Plex    *mesh;
4042*552f7358SJed Brown   PetscInt      *off;
4043*552f7358SJed Brown   const PetscInt numCorners = 4;
4044*552f7358SJed Brown   PetscInt       dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd;
4045*552f7358SJed Brown   PetscInt       numFaces, firstFace, face, f, numEdges, firstEdge, edge, e;
4046*552f7358SJed Brown   PetscErrorCode ierr;
4047*552f7358SJed Brown 
4048*552f7358SJed Brown   PetscFunctionBegin;
4049*552f7358SJed Brown   {
4050*552f7358SJed Brown     ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr);
4051*552f7358SJed Brown     ierr = DMView(dm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
4052*552f7358SJed Brown     ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
4053*552f7358SJed Brown   }
4054*552f7358SJed Brown   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
4055*552f7358SJed Brown   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
4056*552f7358SJed Brown   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
4057*552f7358SJed Brown   numCells    = cEnd - cStart;
4058*552f7358SJed Brown   numVertices = vEnd - vStart;
4059*552f7358SJed Brown   firstFace   = numCells + numVertices;
4060*552f7358SJed Brown   numFaces    = 0 ;
4061*552f7358SJed Brown   /* Count faces using algorithm from CreateNeighborCSR */
4062*552f7358SJed Brown   ierr = DMPlexCreateNeighborCSR(dm, PETSC_NULL, &off, PETSC_NULL);CHKERRQ(ierr);
4063*552f7358SJed Brown   if (off) {
4064*552f7358SJed Brown     numFaces = off[numCells]/2;
4065*552f7358SJed Brown     /* Account for boundary faces: \sum_c 4 - neighbors = 4*numCells - totalNeighbors */
4066*552f7358SJed Brown     numFaces += 4*numCells - off[numCells];
4067*552f7358SJed Brown   }
4068*552f7358SJed Brown   /* Use Euler characteristic to get edges V - E + F - C = 1 */
4069*552f7358SJed Brown   firstEdge = firstFace + numFaces;
4070*552f7358SJed Brown   numEdges  = numVertices + numFaces - numCells - 1;
4071*552f7358SJed Brown   /* Create interpolated mesh */
4072*552f7358SJed Brown   ierr = DMCreate(((PetscObject) dm)->comm, &idm);CHKERRQ(ierr);
4073*552f7358SJed Brown   ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr);
4074*552f7358SJed Brown   ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr);
4075*552f7358SJed Brown   ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numFaces+numEdges);CHKERRQ(ierr);
4076*552f7358SJed Brown   for (c = 0; c < numCells; ++c) {
4077*552f7358SJed Brown     ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr);
4078*552f7358SJed Brown   }
4079*552f7358SJed Brown   for (f = firstFace; f < firstFace+numFaces; ++f) {
4080*552f7358SJed Brown     ierr = DMPlexSetConeSize(idm, f, 3);CHKERRQ(ierr);
4081*552f7358SJed Brown   }
4082*552f7358SJed Brown   for (e = firstEdge; e < firstEdge+numEdges; ++e) {
4083*552f7358SJed Brown     ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr);
4084*552f7358SJed Brown   }
4085*552f7358SJed Brown   ierr = DMSetUp(idm);CHKERRQ(ierr);
4086*552f7358SJed Brown   /* Get face cones from subsets of cell vertices */
4087*552f7358SJed Brown   ierr = DMCreate(((PetscObject) dm)->comm, &fdm);CHKERRQ(ierr);
4088*552f7358SJed Brown   ierr = DMSetType(fdm, DMPLEX);CHKERRQ(ierr);
4089*552f7358SJed Brown   ierr = DMPlexSetDimension(fdm, dim);CHKERRQ(ierr);
4090*552f7358SJed Brown   ierr = DMPlexSetChart(fdm, numCells, firstFace+numFaces);CHKERRQ(ierr);
4091*552f7358SJed Brown   for (f = firstFace; f < firstFace+numFaces; ++f) {
4092*552f7358SJed Brown     ierr = DMPlexSetConeSize(fdm, f, 3);CHKERRQ(ierr);
4093*552f7358SJed Brown   }
4094*552f7358SJed Brown   ierr = DMSetUp(fdm);CHKERRQ(ierr);
4095*552f7358SJed Brown   for (c = 0, face = firstFace; c < numCells; ++c) {
4096*552f7358SJed Brown     const PetscInt *cellFaces;
4097*552f7358SJed Brown     PetscInt        numCellFaces, faceSize, cf;
4098*552f7358SJed Brown 
4099*552f7358SJed Brown     ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr);
4100*552f7358SJed Brown     if (faceSize != 3) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Tetrahedra cannot have face of size %D", faceSize);
4101*552f7358SJed Brown     for (cf = 0; cf < numCellFaces; ++cf) {
4102*552f7358SJed Brown       PetscBool found = PETSC_FALSE;
4103*552f7358SJed Brown 
4104*552f7358SJed Brown       /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */
4105*552f7358SJed Brown       for (f = firstFace; f < face; ++f) {
4106*552f7358SJed Brown         const PetscInt *cone = PETSC_NULL;
4107*552f7358SJed Brown 
4108*552f7358SJed Brown         ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr);
4109*552f7358SJed Brown         if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[2])) ||
4110*552f7358SJed Brown             ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[0])) ||
4111*552f7358SJed Brown             ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[1])) ||
4112*552f7358SJed Brown             ((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[1])) ||
4113*552f7358SJed Brown             ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[0])) ||
4114*552f7358SJed Brown             ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[2]))) {
4115*552f7358SJed Brown           found = PETSC_TRUE;
4116*552f7358SJed Brown           break;
4117*552f7358SJed Brown         }
4118*552f7358SJed Brown       }
4119*552f7358SJed Brown       if (!found) {
4120*552f7358SJed Brown         ierr = DMPlexSetCone(idm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr);
4121*552f7358SJed Brown         /* Save the vertices for orientation calculation */
4122*552f7358SJed Brown         ierr = DMPlexSetCone(fdm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr);
4123*552f7358SJed Brown         ++face;
4124*552f7358SJed Brown       }
4125*552f7358SJed Brown       ierr = DMPlexInsertCone(idm, c, cf, f);CHKERRQ(ierr);
4126*552f7358SJed Brown     }
4127*552f7358SJed Brown   }
4128*552f7358SJed Brown   if (face != firstFace+numFaces) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of faces %D should be %D", face-firstFace, numFaces);
4129*552f7358SJed Brown   /* Get edge cones from subsets of face vertices */
4130*552f7358SJed Brown   for (f = firstFace, edge = firstEdge; f < firstFace+numFaces; ++f) {
4131*552f7358SJed Brown     const PetscInt *cellFaces;
4132*552f7358SJed Brown     PetscInt        numCellFaces, faceSize, cf;
4133*552f7358SJed Brown 
4134*552f7358SJed Brown     ierr = DMPlexGetFaces(idm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr);
4135*552f7358SJed Brown     if (faceSize != 2) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize);
4136*552f7358SJed Brown     for (cf = 0; cf < numCellFaces; ++cf) {
4137*552f7358SJed Brown       PetscBool found = PETSC_FALSE;
4138*552f7358SJed Brown 
4139*552f7358SJed Brown       /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */
4140*552f7358SJed Brown       for (e = firstEdge; e < edge; ++e) {
4141*552f7358SJed Brown         const PetscInt *cone = PETSC_NULL;
4142*552f7358SJed Brown 
4143*552f7358SJed Brown         ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr);
4144*552f7358SJed Brown         if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) ||
4145*552f7358SJed Brown             ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) {
4146*552f7358SJed Brown           found = PETSC_TRUE;
4147*552f7358SJed Brown           break;
4148*552f7358SJed Brown         }
4149*552f7358SJed Brown       }
4150*552f7358SJed Brown       if (!found) {
4151*552f7358SJed Brown         ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr);
4152*552f7358SJed Brown         ++edge;
4153*552f7358SJed Brown       }
4154*552f7358SJed Brown       ierr = DMPlexInsertCone(idm, f, cf, e);CHKERRQ(ierr);
4155*552f7358SJed Brown     }
4156*552f7358SJed Brown   }
4157*552f7358SJed Brown   if (edge != firstEdge+numEdges) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges);
4158*552f7358SJed Brown   ierr = PetscFree(off);CHKERRQ(ierr);
4159*552f7358SJed Brown   ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr);
4160*552f7358SJed Brown   ierr = DMPlexStratify(idm);CHKERRQ(ierr);
4161*552f7358SJed Brown   mesh = (DM_Plex *) (idm)->data;
4162*552f7358SJed Brown   /* Orient edges */
4163*552f7358SJed Brown   for (f = firstFace; f < firstFace+numFaces; ++f) {
4164*552f7358SJed Brown     const PetscInt *cone, *cellFaces;
4165*552f7358SJed Brown     PetscInt        coneSize, coff, numCellFaces, faceSize, cf;
4166*552f7358SJed Brown 
4167*552f7358SJed Brown     ierr = DMPlexGetConeSize(idm, f, &coneSize);CHKERRQ(ierr);
4168*552f7358SJed Brown     ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr);
4169*552f7358SJed Brown     ierr = PetscSectionGetOffset(mesh->coneSection, f, &coff);CHKERRQ(ierr);
4170*552f7358SJed Brown     ierr = DMPlexGetFaces(fdm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr);
4171*552f7358SJed Brown     if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for face %D should be %D", coneSize, f, numCellFaces);
4172*552f7358SJed Brown     for (cf = 0; cf < numCellFaces; ++cf) {
4173*552f7358SJed Brown       const PetscInt *econe;
4174*552f7358SJed Brown       PetscInt        esize;
4175*552f7358SJed Brown 
4176*552f7358SJed Brown       ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr);
4177*552f7358SJed Brown       ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr);
4178*552f7358SJed Brown       if (esize != 2) SETERRQ2(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edge endpoints %D for edge %D should be 2", esize, cone[cf]);
4179*552f7358SJed Brown       if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) {
4180*552f7358SJed Brown         /* Correctly oriented */
4181*552f7358SJed Brown         mesh->coneOrientations[coff+cf] = 0;
4182*552f7358SJed Brown       } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) {
4183*552f7358SJed Brown         /* Start at index 1, and reverse orientation */
4184*552f7358SJed Brown         mesh->coneOrientations[coff+cf] = -(1+1);
4185*552f7358SJed Brown       }
4186*552f7358SJed Brown     }
4187*552f7358SJed Brown   }
4188*552f7358SJed Brown   ierr = DMDestroy(&fdm);CHKERRQ(ierr);
4189*552f7358SJed Brown   /* Orient faces */
4190*552f7358SJed Brown   for (c = 0; c < numCells; ++c) {
4191*552f7358SJed Brown     const PetscInt *cone, *cellFaces;
4192*552f7358SJed Brown     PetscInt        coneSize, coff, numCellFaces, faceSize, cf;
4193*552f7358SJed Brown 
4194*552f7358SJed Brown     ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr);
4195*552f7358SJed Brown     ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr);
4196*552f7358SJed Brown     ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr);
4197*552f7358SJed Brown     ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr);
4198*552f7358SJed Brown     if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for cell %D should be %D", coneSize, c, numCellFaces);
4199*552f7358SJed Brown     for (cf = 0; cf < numCellFaces; ++cf) {
4200*552f7358SJed Brown       PetscInt *origClosure = PETSC_NULL, *closure;
4201*552f7358SJed Brown       PetscInt  closureSize, i;
4202*552f7358SJed Brown 
4203*552f7358SJed Brown       ierr = DMPlexGetTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr);
4204*552f7358SJed Brown       if (closureSize != 7) SETERRQ2(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid closure size %D for face %D should be 7", closureSize, cone[cf]);
4205*552f7358SJed Brown       for (i = 4; i < 7; ++i) {
4206*552f7358SJed Brown         if ((origClosure[i*2] < vStart) || (origClosure[i*2] >= vEnd)) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid closure point %D should be a vertex in [%D, %D)", origClosure[i*2], vStart, vEnd);
4207*552f7358SJed Brown       }
4208*552f7358SJed Brown       closure = &origClosure[4*2];
4209*552f7358SJed Brown       /* Remember that this is the orientation for edges, not vertices */
4210*552f7358SJed Brown       if        ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) {
4211*552f7358SJed Brown         /* Correctly oriented */
4212*552f7358SJed Brown         mesh->coneOrientations[coff+cf] = 0;
4213*552f7358SJed Brown       } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) {
4214*552f7358SJed Brown         /* Shifted by 1 */
4215*552f7358SJed Brown         mesh->coneOrientations[coff+cf] = 1;
4216*552f7358SJed Brown       } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) {
4217*552f7358SJed Brown         /* Shifted by 2 */
4218*552f7358SJed Brown         mesh->coneOrientations[coff+cf] = 2;
4219*552f7358SJed Brown       } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) {
4220*552f7358SJed Brown         /* Start at edge 1, and reverse orientation */
4221*552f7358SJed Brown         mesh->coneOrientations[coff+cf] = -(1+1);
4222*552f7358SJed Brown       } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) {
4223*552f7358SJed Brown         /* Start at index 0, and reverse orientation */
4224*552f7358SJed Brown         mesh->coneOrientations[coff+cf] = -(0+1);
4225*552f7358SJed Brown       } else if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) {
4226*552f7358SJed Brown         /* Start at index 2, and reverse orientation */
4227*552f7358SJed Brown         mesh->coneOrientations[coff+cf] = -(2+1);
4228*552f7358SJed Brown       } else SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Face %D did not match local face %D in cell %D for any orientation", cone[cf], cf, c);
4229*552f7358SJed Brown       ierr = DMPlexRestoreTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr);
4230*552f7358SJed Brown     }
4231*552f7358SJed Brown   }
4232*552f7358SJed Brown   {
4233*552f7358SJed Brown     ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr);
4234*552f7358SJed Brown     ierr = DMView(idm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
4235*552f7358SJed Brown     ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
4236*552f7358SJed Brown   }
4237*552f7358SJed Brown   *dmInt  = idm;
4238*552f7358SJed Brown   PetscFunctionReturn(0);
4239*552f7358SJed Brown }
4240*552f7358SJed Brown 
4241*552f7358SJed Brown #undef __FUNCT__
4242*552f7358SJed Brown #define __FUNCT__ "DMPlexBuildFromCellList_Private"
4243*552f7358SJed Brown /*
4244*552f7358SJed Brown   This takes as input the common mesh generator output, a list of the vertices for each cell
4245*552f7358SJed Brown */
4246*552f7358SJed Brown PetscErrorCode DMPlexBuildFromCellList_Private(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const int cells[])
4247*552f7358SJed Brown {
4248*552f7358SJed Brown   PetscInt      *cone, c, p;
4249*552f7358SJed Brown   PetscErrorCode ierr;
4250*552f7358SJed Brown 
4251*552f7358SJed Brown   PetscFunctionBegin;
4252*552f7358SJed Brown   ierr = DMPlexSetChart(dm, 0, numCells+numVertices);CHKERRQ(ierr);
4253*552f7358SJed Brown   for (c = 0; c < numCells; ++c) {
4254*552f7358SJed Brown     ierr = DMPlexSetConeSize(dm, c, numCorners);CHKERRQ(ierr);
4255*552f7358SJed Brown   }
4256*552f7358SJed Brown   ierr = DMSetUp(dm);CHKERRQ(ierr);
4257*552f7358SJed Brown   ierr = DMGetWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr);
4258*552f7358SJed Brown   for (c = 0; c < numCells; ++c) {
4259*552f7358SJed Brown     for (p = 0; p < numCorners; ++p) {
4260*552f7358SJed Brown       cone[p] = cells[c*numCorners+p]+numCells;
4261*552f7358SJed Brown     }
4262*552f7358SJed Brown     ierr = DMPlexSetCone(dm, c, cone);CHKERRQ(ierr);
4263*552f7358SJed Brown   }
4264*552f7358SJed Brown   ierr = DMRestoreWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr);
4265*552f7358SJed Brown   ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr);
4266*552f7358SJed Brown   ierr = DMPlexStratify(dm);CHKERRQ(ierr);
4267*552f7358SJed Brown   PetscFunctionReturn(0);
4268*552f7358SJed Brown }
4269*552f7358SJed Brown 
4270*552f7358SJed Brown #undef __FUNCT__
4271*552f7358SJed Brown #define __FUNCT__ "DMPlexBuildCoordinates_Private"
4272*552f7358SJed Brown /*
4273*552f7358SJed Brown   This takes as input the coordinates for each vertex
4274*552f7358SJed Brown */
4275*552f7358SJed Brown PetscErrorCode DMPlexBuildCoordinates_Private(DM dm, PetscInt spaceDim, PetscInt numCells, PetscInt numVertices, const double vertexCoords[])
4276*552f7358SJed Brown {
4277*552f7358SJed Brown   PetscSection   coordSection;
4278*552f7358SJed Brown   Vec            coordinates;
4279*552f7358SJed Brown   PetscScalar   *coords;
4280*552f7358SJed Brown   PetscInt       coordSize, v, d;
4281*552f7358SJed Brown   PetscErrorCode ierr;
4282*552f7358SJed Brown 
4283*552f7358SJed Brown   PetscFunctionBegin;
4284*552f7358SJed Brown   ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr);
4285*552f7358SJed Brown   ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr);
4286*552f7358SJed Brown   ierr = PetscSectionSetFieldComponents(coordSection, 0, spaceDim);CHKERRQ(ierr);
4287*552f7358SJed Brown   ierr = PetscSectionSetChart(coordSection, numCells, numCells + numVertices);CHKERRQ(ierr);
4288*552f7358SJed Brown   for (v = numCells; v < numCells+numVertices; ++v) {
4289*552f7358SJed Brown     ierr = PetscSectionSetDof(coordSection, v, spaceDim);CHKERRQ(ierr);
4290*552f7358SJed Brown     ierr = PetscSectionSetFieldDof(coordSection, v, 0, spaceDim);CHKERRQ(ierr);
4291*552f7358SJed Brown   }
4292*552f7358SJed Brown   ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr);
4293*552f7358SJed Brown   ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr);
4294*552f7358SJed Brown   ierr = VecCreate(((PetscObject) dm)->comm, &coordinates);CHKERRQ(ierr);
4295*552f7358SJed Brown   ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr);
4296*552f7358SJed Brown   ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr);
4297*552f7358SJed Brown   ierr = VecSetFromOptions(coordinates);CHKERRQ(ierr);
4298*552f7358SJed Brown   ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr);
4299*552f7358SJed Brown   for (v = 0; v < numVertices; ++v) {
4300*552f7358SJed Brown     for (d = 0; d < spaceDim; ++d) {
4301*552f7358SJed Brown       coords[v*spaceDim+d] = vertexCoords[v*spaceDim+d];
4302*552f7358SJed Brown     }
4303*552f7358SJed Brown   }
4304*552f7358SJed Brown   ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr);
4305*552f7358SJed Brown   ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr);
4306*552f7358SJed Brown   ierr = VecDestroy(&coordinates);CHKERRQ(ierr);
4307*552f7358SJed Brown   PetscFunctionReturn(0);
4308*552f7358SJed Brown }
4309*552f7358SJed Brown 
4310*552f7358SJed Brown #undef __FUNCT__
4311*552f7358SJed Brown #define __FUNCT__ "DMPlexCreateFromCellList"
4312*552f7358SJed Brown /*
4313*552f7358SJed Brown   This takes as input the common mesh generator output, a list of the vertices for each cell
4314*552f7358SJed Brown */
4315*552f7358SJed Brown PetscErrorCode DMPlexCreateFromCellList(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, PetscBool interpolate, const int cells[], const double vertexCoords[], DM *dm)
4316*552f7358SJed Brown {
4317*552f7358SJed Brown   PetscErrorCode ierr;
4318*552f7358SJed Brown 
4319*552f7358SJed Brown   PetscFunctionBegin;
4320*552f7358SJed Brown   ierr = DMCreate(comm, dm);CHKERRQ(ierr);
4321*552f7358SJed Brown   ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr);
4322*552f7358SJed Brown   ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr);
4323*552f7358SJed Brown   ierr = DMPlexBuildFromCellList_Private(*dm, numCells, numVertices, numCorners, cells);CHKERRQ(ierr);
4324*552f7358SJed Brown   if (interpolate) {
4325*552f7358SJed Brown     DM idm;
4326*552f7358SJed Brown 
4327*552f7358SJed Brown     switch(dim) {
4328*552f7358SJed Brown     case 2:
4329*552f7358SJed Brown       ierr = DMPlexInterpolate_2D(*dm, &idm);CHKERRQ(ierr);break;
4330*552f7358SJed Brown     case 3:
4331*552f7358SJed Brown       ierr = DMPlexInterpolate_3D(*dm, &idm);CHKERRQ(ierr);break;
4332*552f7358SJed Brown     default:
4333*552f7358SJed Brown       SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "No mesh interpolation support for dimension %D", dim);
4334*552f7358SJed Brown     }
4335*552f7358SJed Brown     ierr = DMDestroy(dm);CHKERRQ(ierr);
4336*552f7358SJed Brown     *dm  = idm;
4337*552f7358SJed Brown   }
4338*552f7358SJed Brown   ierr = DMPlexBuildCoordinates_Private(*dm, dim, numCells, numVertices, vertexCoords);CHKERRQ(ierr);
4339*552f7358SJed Brown   PetscFunctionReturn(0);
4340*552f7358SJed Brown }
4341*552f7358SJed Brown 
4342*552f7358SJed Brown #ifdef PETSC_HAVE_TRIANGLE
4343*552f7358SJed Brown #include <triangle.h>
4344*552f7358SJed Brown 
4345*552f7358SJed Brown #undef __FUNCT__
4346*552f7358SJed Brown #define __FUNCT__ "InitInput_Triangle"
4347*552f7358SJed Brown PetscErrorCode InitInput_Triangle(struct triangulateio *inputCtx) {
4348*552f7358SJed Brown   PetscFunctionBegin;
4349*552f7358SJed Brown   inputCtx->numberofpoints = 0;
4350*552f7358SJed Brown   inputCtx->numberofpointattributes = 0;
4351*552f7358SJed Brown   inputCtx->pointlist = PETSC_NULL;
4352*552f7358SJed Brown   inputCtx->pointattributelist = PETSC_NULL;
4353*552f7358SJed Brown   inputCtx->pointmarkerlist = PETSC_NULL;
4354*552f7358SJed Brown   inputCtx->numberofsegments = 0;
4355*552f7358SJed Brown   inputCtx->segmentlist = PETSC_NULL;
4356*552f7358SJed Brown   inputCtx->segmentmarkerlist = PETSC_NULL;
4357*552f7358SJed Brown   inputCtx->numberoftriangleattributes = 0;
4358*552f7358SJed Brown   inputCtx->trianglelist = PETSC_NULL;
4359*552f7358SJed Brown   inputCtx->numberofholes = 0;
4360*552f7358SJed Brown   inputCtx->holelist = PETSC_NULL;
4361*552f7358SJed Brown   inputCtx->numberofregions = 0;
4362*552f7358SJed Brown   inputCtx->regionlist = PETSC_NULL;
4363*552f7358SJed Brown   PetscFunctionReturn(0);
4364*552f7358SJed Brown }
4365*552f7358SJed Brown 
4366*552f7358SJed Brown #undef __FUNCT__
4367*552f7358SJed Brown #define __FUNCT__ "InitOutput_Triangle"
4368*552f7358SJed Brown PetscErrorCode InitOutput_Triangle(struct triangulateio *outputCtx) {
4369*552f7358SJed Brown   PetscFunctionBegin;
4370*552f7358SJed Brown   outputCtx->numberofpoints = 0;
4371*552f7358SJed Brown   outputCtx->pointlist = PETSC_NULL;
4372*552f7358SJed Brown   outputCtx->pointattributelist = PETSC_NULL;
4373*552f7358SJed Brown   outputCtx->pointmarkerlist = PETSC_NULL;
4374*552f7358SJed Brown   outputCtx->numberoftriangles = 0;
4375*552f7358SJed Brown   outputCtx->trianglelist = PETSC_NULL;
4376*552f7358SJed Brown   outputCtx->triangleattributelist = PETSC_NULL;
4377*552f7358SJed Brown   outputCtx->neighborlist = PETSC_NULL;
4378*552f7358SJed Brown   outputCtx->segmentlist = PETSC_NULL;
4379*552f7358SJed Brown   outputCtx->segmentmarkerlist = PETSC_NULL;
4380*552f7358SJed Brown   outputCtx->numberofedges = 0;
4381*552f7358SJed Brown   outputCtx->edgelist = PETSC_NULL;
4382*552f7358SJed Brown   outputCtx->edgemarkerlist = PETSC_NULL;
4383*552f7358SJed Brown   PetscFunctionReturn(0);
4384*552f7358SJed Brown }
4385*552f7358SJed Brown 
4386*552f7358SJed Brown #undef __FUNCT__
4387*552f7358SJed Brown #define __FUNCT__ "FiniOutput_Triangle"
4388*552f7358SJed Brown PetscErrorCode FiniOutput_Triangle(struct triangulateio *outputCtx) {
4389*552f7358SJed Brown   PetscFunctionBegin;
4390*552f7358SJed Brown   free(outputCtx->pointmarkerlist);
4391*552f7358SJed Brown   free(outputCtx->edgelist);
4392*552f7358SJed Brown   free(outputCtx->edgemarkerlist);
4393*552f7358SJed Brown   free(outputCtx->trianglelist);
4394*552f7358SJed Brown   free(outputCtx->neighborlist);
4395*552f7358SJed Brown   PetscFunctionReturn(0);
4396*552f7358SJed Brown }
4397*552f7358SJed Brown 
4398*552f7358SJed Brown #undef __FUNCT__
4399*552f7358SJed Brown #define __FUNCT__ "DMPlexGenerate_Triangle"
4400*552f7358SJed Brown PetscErrorCode DMPlexGenerate_Triangle(DM boundary, PetscBool interpolate, DM *dm)
4401*552f7358SJed Brown {
4402*552f7358SJed Brown   MPI_Comm             comm = ((PetscObject) boundary)->comm;
4403*552f7358SJed Brown   PetscInt             dim              = 2;
4404*552f7358SJed Brown   const PetscBool      createConvexHull = PETSC_FALSE;
4405*552f7358SJed Brown   const PetscBool      constrained      = PETSC_FALSE;
4406*552f7358SJed Brown   struct triangulateio in;
4407*552f7358SJed Brown   struct triangulateio out;
4408*552f7358SJed Brown   PetscInt             vStart, vEnd, v, eStart, eEnd, e;
4409*552f7358SJed Brown   PetscMPIInt          rank;
4410*552f7358SJed Brown   PetscErrorCode       ierr;
4411*552f7358SJed Brown 
4412*552f7358SJed Brown   PetscFunctionBegin;
4413*552f7358SJed Brown   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
4414*552f7358SJed Brown   ierr = InitInput_Triangle(&in);CHKERRQ(ierr);
4415*552f7358SJed Brown   ierr = InitOutput_Triangle(&out);CHKERRQ(ierr);
4416*552f7358SJed Brown   ierr  = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr);
4417*552f7358SJed Brown   in.numberofpoints = vEnd - vStart;
4418*552f7358SJed Brown   if (in.numberofpoints > 0) {
4419*552f7358SJed Brown     PetscSection coordSection;
4420*552f7358SJed Brown     Vec          coordinates;
4421*552f7358SJed Brown     PetscScalar *array;
4422*552f7358SJed Brown 
4423*552f7358SJed Brown     ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr);
4424*552f7358SJed Brown     ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr);
4425*552f7358SJed Brown     ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr);
4426*552f7358SJed Brown     ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr);
4427*552f7358SJed Brown     ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr);
4428*552f7358SJed Brown     for (v = vStart; v < vEnd; ++v) {
4429*552f7358SJed Brown       const PetscInt idx = v - vStart;
4430*552f7358SJed Brown       PetscInt       off, d;
4431*552f7358SJed Brown 
4432*552f7358SJed Brown       ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr);
4433*552f7358SJed Brown       for (d = 0; d < dim; ++d) {
4434*552f7358SJed Brown         in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]);
4435*552f7358SJed Brown       }
4436*552f7358SJed Brown       ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr);
4437*552f7358SJed Brown     }
4438*552f7358SJed Brown     ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr);
4439*552f7358SJed Brown   }
4440*552f7358SJed Brown   ierr  = DMPlexGetHeightStratum(boundary, 0, &eStart, &eEnd);CHKERRQ(ierr);
4441*552f7358SJed Brown   in.numberofsegments = eEnd - eStart;
4442*552f7358SJed Brown   if (in.numberofsegments > 0) {
4443*552f7358SJed Brown     ierr = PetscMalloc(in.numberofsegments*2 * sizeof(int), &in.segmentlist);CHKERRQ(ierr);
4444*552f7358SJed Brown     ierr = PetscMalloc(in.numberofsegments   * sizeof(int), &in.segmentmarkerlist);CHKERRQ(ierr);
4445*552f7358SJed Brown     for (e = eStart; e < eEnd; ++e) {
4446*552f7358SJed Brown       const PetscInt  idx = e - eStart;
4447*552f7358SJed Brown       const PetscInt *cone;
4448*552f7358SJed Brown 
4449*552f7358SJed Brown       ierr = DMPlexGetCone(boundary, e, &cone);CHKERRQ(ierr);
4450*552f7358SJed Brown       in.segmentlist[idx*2+0] = cone[0] - vStart;
4451*552f7358SJed Brown       in.segmentlist[idx*2+1] = cone[1] - vStart;
4452*552f7358SJed Brown       ierr = DMPlexGetLabelValue(boundary, "marker", e, &in.segmentmarkerlist[idx]);CHKERRQ(ierr);
4453*552f7358SJed Brown     }
4454*552f7358SJed Brown   }
4455*552f7358SJed Brown #if 0 /* Do not currently support holes */
4456*552f7358SJed Brown   PetscReal *holeCoords;
4457*552f7358SJed Brown   PetscInt   h, d;
4458*552f7358SJed Brown 
4459*552f7358SJed Brown   ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr);
4460*552f7358SJed Brown   if (in.numberofholes > 0) {
4461*552f7358SJed Brown     ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr);
4462*552f7358SJed Brown     for (h = 0; h < in.numberofholes; ++h) {
4463*552f7358SJed Brown       for (d = 0; d < dim; ++d) {
4464*552f7358SJed Brown         in.holelist[h*dim+d] = holeCoords[h*dim+d];
4465*552f7358SJed Brown       }
4466*552f7358SJed Brown     }
4467*552f7358SJed Brown   }
4468*552f7358SJed Brown #endif
4469*552f7358SJed Brown   if (!rank) {
4470*552f7358SJed Brown     char args[32];
4471*552f7358SJed Brown 
4472*552f7358SJed Brown     /* Take away 'Q' for verbose output */
4473*552f7358SJed Brown     ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr);
4474*552f7358SJed Brown     if (createConvexHull) {
4475*552f7358SJed Brown       ierr = PetscStrcat(args, "c");CHKERRQ(ierr);
4476*552f7358SJed Brown     }
4477*552f7358SJed Brown     if (constrained) {
4478*552f7358SJed Brown       ierr = PetscStrcpy(args, "zepDQ");CHKERRQ(ierr);
4479*552f7358SJed Brown     }
4480*552f7358SJed Brown     triangulate(args, &in, &out, PETSC_NULL);
4481*552f7358SJed Brown   }
4482*552f7358SJed Brown   ierr = PetscFree(in.pointlist);CHKERRQ(ierr);
4483*552f7358SJed Brown   ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr);
4484*552f7358SJed Brown   ierr = PetscFree(in.segmentlist);CHKERRQ(ierr);
4485*552f7358SJed Brown   ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr);
4486*552f7358SJed Brown   ierr = PetscFree(in.holelist);CHKERRQ(ierr);
4487*552f7358SJed Brown 
4488*552f7358SJed Brown   {
4489*552f7358SJed Brown     const PetscInt numCorners  = 3;
4490*552f7358SJed Brown     const PetscInt numCells    = out.numberoftriangles;
4491*552f7358SJed Brown     const PetscInt numVertices = out.numberofpoints;
4492*552f7358SJed Brown     const int     *cells       = out.trianglelist;
4493*552f7358SJed Brown     const double  *meshCoords  = out.pointlist;
4494*552f7358SJed Brown 
4495*552f7358SJed Brown     ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr);
4496*552f7358SJed Brown     /* Set labels */
4497*552f7358SJed Brown     for (v = 0; v < numVertices; ++v) {
4498*552f7358SJed Brown       if (out.pointmarkerlist[v]) {
4499*552f7358SJed Brown         ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr);
4500*552f7358SJed Brown       }
4501*552f7358SJed Brown     }
4502*552f7358SJed Brown     if (interpolate) {
4503*552f7358SJed Brown       for (e = 0; e < out.numberofedges; e++) {
4504*552f7358SJed Brown         if (out.edgemarkerlist[e]) {
4505*552f7358SJed Brown           const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells};
4506*552f7358SJed Brown           const PetscInt *edges;
4507*552f7358SJed Brown           PetscInt        numEdges;
4508*552f7358SJed Brown 
4509*552f7358SJed Brown           ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr);
4510*552f7358SJed Brown           if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges);
4511*552f7358SJed Brown           ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr);
4512*552f7358SJed Brown           ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr);
4513*552f7358SJed Brown         }
4514*552f7358SJed Brown       }
4515*552f7358SJed Brown     }
4516*552f7358SJed Brown     ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr);
4517*552f7358SJed Brown   }
4518*552f7358SJed Brown #if 0 /* Do not currently support holes */
4519*552f7358SJed Brown   ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr);
4520*552f7358SJed Brown #endif
4521*552f7358SJed Brown   ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr);
4522*552f7358SJed Brown   PetscFunctionReturn(0);
4523*552f7358SJed Brown }
4524*552f7358SJed Brown 
4525*552f7358SJed Brown #undef __FUNCT__
4526*552f7358SJed Brown #define __FUNCT__ "DMPlexRefine_Triangle"
4527*552f7358SJed Brown PetscErrorCode DMPlexRefine_Triangle(DM dm, double *maxVolumes, DM *dmRefined)
4528*552f7358SJed Brown {
4529*552f7358SJed Brown   MPI_Comm             comm = ((PetscObject) dm)->comm;
4530*552f7358SJed Brown   PetscInt             dim  = 2;
4531*552f7358SJed Brown   struct triangulateio in;
4532*552f7358SJed Brown   struct triangulateio out;
4533*552f7358SJed Brown   PetscInt             vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal;
4534*552f7358SJed Brown   PetscMPIInt          rank;
4535*552f7358SJed Brown   PetscErrorCode       ierr;
4536*552f7358SJed Brown 
4537*552f7358SJed Brown   PetscFunctionBegin;
4538*552f7358SJed Brown   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
4539*552f7358SJed Brown   ierr = InitInput_Triangle(&in);CHKERRQ(ierr);
4540*552f7358SJed Brown   ierr = InitOutput_Triangle(&out);CHKERRQ(ierr);
4541*552f7358SJed Brown   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
4542*552f7358SJed Brown   ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr);
4543*552f7358SJed Brown   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
4544*552f7358SJed Brown   in.numberofpoints = vEnd - vStart;
4545*552f7358SJed Brown   if (in.numberofpoints > 0) {
4546*552f7358SJed Brown     PetscSection coordSection;
4547*552f7358SJed Brown     Vec          coordinates;
4548*552f7358SJed Brown     PetscScalar *array;
4549*552f7358SJed Brown 
4550*552f7358SJed Brown     ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr);
4551*552f7358SJed Brown     ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr);
4552*552f7358SJed Brown     ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
4553*552f7358SJed Brown     ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr);
4554*552f7358SJed Brown     ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr);
4555*552f7358SJed Brown     for (v = vStart; v < vEnd; ++v) {
4556*552f7358SJed Brown       const PetscInt idx = v - vStart;
4557*552f7358SJed Brown       PetscInt       off, d;
4558*552f7358SJed Brown 
4559*552f7358SJed Brown       ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr);
4560*552f7358SJed Brown       for (d = 0; d < dim; ++d) {
4561*552f7358SJed Brown         in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]);
4562*552f7358SJed Brown       }
4563*552f7358SJed Brown       ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr);
4564*552f7358SJed Brown     }
4565*552f7358SJed Brown     ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr);
4566*552f7358SJed Brown   }
4567*552f7358SJed Brown   ierr  = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
4568*552f7358SJed Brown   in.numberofcorners   = 3;
4569*552f7358SJed Brown   in.numberoftriangles = cEnd - cStart;
4570*552f7358SJed Brown   in.trianglearealist  = (double *) maxVolumes;
4571*552f7358SJed Brown   if (in.numberoftriangles > 0) {
4572*552f7358SJed Brown     ierr = PetscMalloc(in.numberoftriangles*in.numberofcorners * sizeof(int), &in.trianglelist);CHKERRQ(ierr);
4573*552f7358SJed Brown     for (c = cStart; c < cEnd; ++c) {
4574*552f7358SJed Brown       const PetscInt idx     = c - cStart;
4575*552f7358SJed Brown       PetscInt      *closure = PETSC_NULL;
4576*552f7358SJed Brown       PetscInt       closureSize;
4577*552f7358SJed Brown 
4578*552f7358SJed Brown       ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
4579*552f7358SJed Brown       if ((closureSize != 4) && (closureSize != 7)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a triangle, %D vertices in closure", closureSize);
4580*552f7358SJed Brown       for (v = 0; v < 3; ++v) {
4581*552f7358SJed Brown         in.trianglelist[idx*in.numberofcorners + v] = closure[(v+closureSize-3)*2] - vStart;
4582*552f7358SJed Brown       }
4583*552f7358SJed Brown       ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
4584*552f7358SJed Brown     }
4585*552f7358SJed Brown   }
4586*552f7358SJed Brown   /* TODO: Segment markers are missing on input */
4587*552f7358SJed Brown #if 0 /* Do not currently support holes */
4588*552f7358SJed Brown   PetscReal *holeCoords;
4589*552f7358SJed Brown   PetscInt   h, d;
4590*552f7358SJed Brown 
4591*552f7358SJed Brown   ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr);
4592*552f7358SJed Brown   if (in.numberofholes > 0) {
4593*552f7358SJed Brown     ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr);
4594*552f7358SJed Brown     for (h = 0; h < in.numberofholes; ++h) {
4595*552f7358SJed Brown       for (d = 0; d < dim; ++d) {
4596*552f7358SJed Brown         in.holelist[h*dim+d] = holeCoords[h*dim+d];
4597*552f7358SJed Brown       }
4598*552f7358SJed Brown     }
4599*552f7358SJed Brown   }
4600*552f7358SJed Brown #endif
4601*552f7358SJed Brown   if (!rank) {
4602*552f7358SJed Brown     char args[32];
4603*552f7358SJed Brown 
4604*552f7358SJed Brown     /* Take away 'Q' for verbose output */
4605*552f7358SJed Brown     ierr = PetscStrcpy(args, "pqezQra");CHKERRQ(ierr);
4606*552f7358SJed Brown     triangulate(args, &in, &out, PETSC_NULL);
4607*552f7358SJed Brown   }
4608*552f7358SJed Brown   ierr = PetscFree(in.pointlist);CHKERRQ(ierr);
4609*552f7358SJed Brown   ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr);
4610*552f7358SJed Brown   ierr = PetscFree(in.segmentlist);CHKERRQ(ierr);
4611*552f7358SJed Brown   ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr);
4612*552f7358SJed Brown   ierr = PetscFree(in.trianglelist);CHKERRQ(ierr);
4613*552f7358SJed Brown 
4614*552f7358SJed Brown   {
4615*552f7358SJed Brown     const PetscInt numCorners  = 3;
4616*552f7358SJed Brown     const PetscInt numCells    = out.numberoftriangles;
4617*552f7358SJed Brown     const PetscInt numVertices = out.numberofpoints;
4618*552f7358SJed Brown     const int     *cells       = out.trianglelist;
4619*552f7358SJed Brown     const double  *meshCoords  = out.pointlist;
4620*552f7358SJed Brown     PetscBool      interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE;
4621*552f7358SJed Brown 
4622*552f7358SJed Brown     ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr);
4623*552f7358SJed Brown     /* Set labels */
4624*552f7358SJed Brown     for (v = 0; v < numVertices; ++v) {
4625*552f7358SJed Brown       if (out.pointmarkerlist[v]) {
4626*552f7358SJed Brown         ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr);
4627*552f7358SJed Brown       }
4628*552f7358SJed Brown     }
4629*552f7358SJed Brown     if (interpolate) {
4630*552f7358SJed Brown       PetscInt e;
4631*552f7358SJed Brown 
4632*552f7358SJed Brown       for (e = 0; e < out.numberofedges; e++) {
4633*552f7358SJed Brown         if (out.edgemarkerlist[e]) {
4634*552f7358SJed Brown           const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells};
4635*552f7358SJed Brown           const PetscInt *edges;
4636*552f7358SJed Brown           PetscInt        numEdges;
4637*552f7358SJed Brown 
4638*552f7358SJed Brown           ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr);
4639*552f7358SJed Brown           if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges);
4640*552f7358SJed Brown           ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr);
4641*552f7358SJed Brown           ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr);
4642*552f7358SJed Brown         }
4643*552f7358SJed Brown       }
4644*552f7358SJed Brown     }
4645*552f7358SJed Brown     ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr);
4646*552f7358SJed Brown   }
4647*552f7358SJed Brown #if 0 /* Do not currently support holes */
4648*552f7358SJed Brown   ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr);
4649*552f7358SJed Brown #endif
4650*552f7358SJed Brown   ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr);
4651*552f7358SJed Brown   PetscFunctionReturn(0);
4652*552f7358SJed Brown }
4653*552f7358SJed Brown #endif
4654*552f7358SJed Brown 
4655*552f7358SJed Brown #ifdef PETSC_HAVE_TETGEN
4656*552f7358SJed Brown #include <tetgen.h>
4657*552f7358SJed Brown #undef __FUNCT__
4658*552f7358SJed Brown #define __FUNCT__ "DMPlexGenerate_Tetgen"
4659*552f7358SJed Brown PetscErrorCode DMPlexGenerate_Tetgen(DM boundary, PetscBool interpolate, DM *dm)
4660*552f7358SJed Brown {
4661*552f7358SJed Brown   MPI_Comm       comm = ((PetscObject) boundary)->comm;
4662*552f7358SJed Brown   const PetscInt dim  = 3;
4663*552f7358SJed Brown   ::tetgenio     in;
4664*552f7358SJed Brown   ::tetgenio     out;
4665*552f7358SJed Brown   PetscInt       vStart, vEnd, v, fStart, fEnd, f;
4666*552f7358SJed Brown   PetscMPIInt    rank;
4667*552f7358SJed Brown   PetscErrorCode ierr;
4668*552f7358SJed Brown 
4669*552f7358SJed Brown   PetscFunctionBegin;
4670*552f7358SJed Brown   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
4671*552f7358SJed Brown   ierr  = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr);
4672*552f7358SJed Brown   in.numberofpoints = vEnd - vStart;
4673*552f7358SJed Brown   if (in.numberofpoints > 0) {
4674*552f7358SJed Brown     PetscSection coordSection;
4675*552f7358SJed Brown     Vec          coordinates;
4676*552f7358SJed Brown     PetscScalar *array;
4677*552f7358SJed Brown 
4678*552f7358SJed Brown     in.pointlist       = new double[in.numberofpoints*dim];
4679*552f7358SJed Brown     in.pointmarkerlist = new int[in.numberofpoints];
4680*552f7358SJed Brown     ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr);
4681*552f7358SJed Brown     ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr);
4682*552f7358SJed Brown     ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr);
4683*552f7358SJed Brown     for (v = vStart; v < vEnd; ++v) {
4684*552f7358SJed Brown       const PetscInt idx = v - vStart;
4685*552f7358SJed Brown       PetscInt       off, d;
4686*552f7358SJed Brown 
4687*552f7358SJed Brown       ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr);
4688*552f7358SJed Brown       for (d = 0; d < dim; ++d) {
4689*552f7358SJed Brown         in.pointlist[idx*dim + d] = array[off+d];
4690*552f7358SJed Brown       }
4691*552f7358SJed Brown       ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr);
4692*552f7358SJed Brown     }
4693*552f7358SJed Brown     ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr);
4694*552f7358SJed Brown   }
4695*552f7358SJed Brown   ierr  = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr);
4696*552f7358SJed Brown   in.numberoffacets = fEnd - fStart;
4697*552f7358SJed Brown   if (in.numberoffacets > 0) {
4698*552f7358SJed Brown     in.facetlist       = new tetgenio::facet[in.numberoffacets];
4699*552f7358SJed Brown     in.facetmarkerlist = new int[in.numberoffacets];
4700*552f7358SJed Brown     for (f = fStart; f < fEnd; ++f) {
4701*552f7358SJed Brown       const PetscInt idx    = f - fStart;
4702*552f7358SJed Brown       PetscInt      *points = PETSC_NULL, numPoints, p, numVertices = 0, v;
4703*552f7358SJed Brown 
4704*552f7358SJed Brown       in.facetlist[idx].numberofpolygons = 1;
4705*552f7358SJed Brown       in.facetlist[idx].polygonlist      = new tetgenio::polygon[in.facetlist[idx].numberofpolygons];
4706*552f7358SJed Brown       in.facetlist[idx].numberofholes    = 0;
4707*552f7358SJed Brown       in.facetlist[idx].holelist         = NULL;
4708*552f7358SJed Brown 
4709*552f7358SJed Brown       ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);
4710*552f7358SJed Brown       for (p = 0; p < numPoints*2; p += 2) {
4711*552f7358SJed Brown         const PetscInt point = points[p];
4712*552f7358SJed Brown         if ((point >= vStart) && (point < vEnd)) {
4713*552f7358SJed Brown           points[numVertices++] = point;
4714*552f7358SJed Brown         }
4715*552f7358SJed Brown       }
4716*552f7358SJed Brown 
4717*552f7358SJed Brown       tetgenio::polygon *poly = in.facetlist[idx].polygonlist;
4718*552f7358SJed Brown       poly->numberofvertices = numVertices;
4719*552f7358SJed Brown       poly->vertexlist       = new int[poly->numberofvertices];
4720*552f7358SJed Brown       for (v = 0; v < numVertices; ++v) {
4721*552f7358SJed Brown         const PetscInt vIdx = points[v] - vStart;
4722*552f7358SJed Brown         poly->vertexlist[v] = vIdx;
4723*552f7358SJed Brown       }
4724*552f7358SJed Brown       ierr = DMPlexGetLabelValue(boundary, "marker", f, &in.facetmarkerlist[idx]);CHKERRQ(ierr);
4725*552f7358SJed Brown       ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);
4726*552f7358SJed Brown     }
4727*552f7358SJed Brown   }
4728*552f7358SJed Brown   if (!rank) {
4729*552f7358SJed Brown     char args[32];
4730*552f7358SJed Brown 
4731*552f7358SJed Brown     /* Take away 'Q' for verbose output */
4732*552f7358SJed Brown     ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr);
4733*552f7358SJed Brown     ::tetrahedralize(args, &in, &out);
4734*552f7358SJed Brown   }
4735*552f7358SJed Brown   {
4736*552f7358SJed Brown     const PetscInt numCorners  = 4;
4737*552f7358SJed Brown     const PetscInt numCells    = out.numberoftetrahedra;
4738*552f7358SJed Brown     const PetscInt numVertices = out.numberofpoints;
4739*552f7358SJed Brown     const int     *cells       = out.tetrahedronlist;
4740*552f7358SJed Brown     const double  *meshCoords  = out.pointlist;
4741*552f7358SJed Brown 
4742*552f7358SJed Brown     ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr);
4743*552f7358SJed Brown     /* Set labels */
4744*552f7358SJed Brown     for (v = 0; v < numVertices; ++v) {
4745*552f7358SJed Brown       if (out.pointmarkerlist[v]) {
4746*552f7358SJed Brown         ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr);
4747*552f7358SJed Brown       }
4748*552f7358SJed Brown     }
4749*552f7358SJed Brown     if (interpolate) {
4750*552f7358SJed Brown       PetscInt e;
4751*552f7358SJed Brown 
4752*552f7358SJed Brown       for (e = 0; e < out.numberofedges; e++) {
4753*552f7358SJed Brown         if (out.edgemarkerlist[e]) {
4754*552f7358SJed Brown           const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells};
4755*552f7358SJed Brown           const PetscInt *edges;
4756*552f7358SJed Brown           PetscInt        numEdges;
4757*552f7358SJed Brown 
4758*552f7358SJed Brown           ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr);
4759*552f7358SJed Brown           if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges);
4760*552f7358SJed Brown           ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr);
4761*552f7358SJed Brown           ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr);
4762*552f7358SJed Brown         }
4763*552f7358SJed Brown       }
4764*552f7358SJed Brown       for (f = 0; f < out.numberoftrifaces; f++) {
4765*552f7358SJed Brown         if (out.trifacemarkerlist[f]) {
4766*552f7358SJed Brown           const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells};
4767*552f7358SJed Brown           const PetscInt *faces;
4768*552f7358SJed Brown           PetscInt        numFaces;
4769*552f7358SJed Brown 
4770*552f7358SJed Brown           ierr = DMPlexGetJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr);
4771*552f7358SJed Brown           if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces);
4772*552f7358SJed Brown           ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr);
4773*552f7358SJed Brown           ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr);
4774*552f7358SJed Brown         }
4775*552f7358SJed Brown       }
4776*552f7358SJed Brown     }
4777*552f7358SJed Brown     ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr);
4778*552f7358SJed Brown   }
4779*552f7358SJed Brown   PetscFunctionReturn(0);
4780*552f7358SJed Brown }
4781*552f7358SJed Brown 
4782*552f7358SJed Brown #undef __FUNCT__
4783*552f7358SJed Brown #define __FUNCT__ "DMPlexRefine_Tetgen"
4784*552f7358SJed Brown PetscErrorCode DMPlexRefine_Tetgen(DM dm, double *maxVolumes, DM *dmRefined)
4785*552f7358SJed Brown {
4786*552f7358SJed Brown   MPI_Comm       comm = ((PetscObject) dm)->comm;
4787*552f7358SJed Brown   const PetscInt dim  = 3;
4788*552f7358SJed Brown   ::tetgenio     in;
4789*552f7358SJed Brown   ::tetgenio     out;
4790*552f7358SJed Brown   PetscInt       vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal;
4791*552f7358SJed Brown   PetscMPIInt    rank;
4792*552f7358SJed Brown   PetscErrorCode ierr;
4793*552f7358SJed Brown 
4794*552f7358SJed Brown   PetscFunctionBegin;
4795*552f7358SJed Brown   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
4796*552f7358SJed Brown   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
4797*552f7358SJed Brown   ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr);
4798*552f7358SJed Brown   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
4799*552f7358SJed Brown   in.numberofpoints = vEnd - vStart;
4800*552f7358SJed Brown   if (in.numberofpoints > 0) {
4801*552f7358SJed Brown     PetscSection coordSection;
4802*552f7358SJed Brown     Vec          coordinates;
4803*552f7358SJed Brown     PetscScalar *array;
4804*552f7358SJed Brown 
4805*552f7358SJed Brown     in.pointlist       = new double[in.numberofpoints*dim];
4806*552f7358SJed Brown     in.pointmarkerlist = new int[in.numberofpoints];
4807*552f7358SJed Brown     ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
4808*552f7358SJed Brown     ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr);
4809*552f7358SJed Brown     ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr);
4810*552f7358SJed Brown     for (v = vStart; v < vEnd; ++v) {
4811*552f7358SJed Brown       const PetscInt idx = v - vStart;
4812*552f7358SJed Brown       PetscInt       off, d;
4813*552f7358SJed Brown 
4814*552f7358SJed Brown       ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr);
4815*552f7358SJed Brown       for (d = 0; d < dim; ++d) {
4816*552f7358SJed Brown         in.pointlist[idx*dim + d] = array[off+d];
4817*552f7358SJed Brown       }
4818*552f7358SJed Brown       ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr);
4819*552f7358SJed Brown     }
4820*552f7358SJed Brown     ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr);
4821*552f7358SJed Brown   }
4822*552f7358SJed Brown   ierr  = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
4823*552f7358SJed Brown   in.numberofcorners       = 4;
4824*552f7358SJed Brown   in.numberoftetrahedra    = cEnd - cStart;
4825*552f7358SJed Brown   in.tetrahedronvolumelist = (double *) maxVolumes;
4826*552f7358SJed Brown   if (in.numberoftetrahedra > 0) {
4827*552f7358SJed Brown     in.tetrahedronlist = new int[in.numberoftetrahedra*in.numberofcorners];
4828*552f7358SJed Brown     for (c = cStart; c < cEnd; ++c) {
4829*552f7358SJed Brown       const PetscInt idx     = c - cStart;
4830*552f7358SJed Brown       PetscInt      *closure = PETSC_NULL;
4831*552f7358SJed Brown       PetscInt       closureSize;
4832*552f7358SJed Brown 
4833*552f7358SJed Brown       ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
4834*552f7358SJed Brown       if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize);
4835*552f7358SJed Brown       for (v = 0; v < 4; ++v) {
4836*552f7358SJed Brown         in.tetrahedronlist[idx*in.numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart;
4837*552f7358SJed Brown       }
4838*552f7358SJed Brown       ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
4839*552f7358SJed Brown     }
4840*552f7358SJed Brown   }
4841*552f7358SJed Brown   // TODO: Put in boundary faces with markers
4842*552f7358SJed Brown   if (!rank) {
4843*552f7358SJed Brown     char args[32];
4844*552f7358SJed Brown 
4845*552f7358SJed Brown     /* Take away 'Q' for verbose output */
4846*552f7358SJed Brown     //ierr = PetscStrcpy(args, "qezQra");CHKERRQ(ierr);
4847*552f7358SJed Brown     ierr = PetscStrcpy(args, "qezraVVVV");CHKERRQ(ierr);
4848*552f7358SJed Brown     ::tetrahedralize(args, &in, &out);
4849*552f7358SJed Brown   }
4850*552f7358SJed Brown   in.tetrahedronvolumelist = NULL;
4851*552f7358SJed Brown 
4852*552f7358SJed Brown   {
4853*552f7358SJed Brown     const PetscInt numCorners  = 4;
4854*552f7358SJed Brown     const PetscInt numCells    = out.numberoftetrahedra;
4855*552f7358SJed Brown     const PetscInt numVertices = out.numberofpoints;
4856*552f7358SJed Brown     const int     *cells       = out.tetrahedronlist;
4857*552f7358SJed Brown     const double  *meshCoords  = out.pointlist;
4858*552f7358SJed Brown     PetscBool      interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE;
4859*552f7358SJed Brown 
4860*552f7358SJed Brown     ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr);
4861*552f7358SJed Brown     /* Set labels */
4862*552f7358SJed Brown     for (v = 0; v < numVertices; ++v) {
4863*552f7358SJed Brown       if (out.pointmarkerlist[v]) {
4864*552f7358SJed Brown         ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr);
4865*552f7358SJed Brown       }
4866*552f7358SJed Brown     }
4867*552f7358SJed Brown     if (interpolate) {
4868*552f7358SJed Brown       PetscInt e, f;
4869*552f7358SJed Brown 
4870*552f7358SJed Brown       for (e = 0; e < out.numberofedges; e++) {
4871*552f7358SJed Brown         if (out.edgemarkerlist[e]) {
4872*552f7358SJed Brown           const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells};
4873*552f7358SJed Brown           const PetscInt *edges;
4874*552f7358SJed Brown           PetscInt        numEdges;
4875*552f7358SJed Brown 
4876*552f7358SJed Brown           ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr);
4877*552f7358SJed Brown           if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges);
4878*552f7358SJed Brown           ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr);
4879*552f7358SJed Brown           ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr);
4880*552f7358SJed Brown         }
4881*552f7358SJed Brown       }
4882*552f7358SJed Brown       for (f = 0; f < out.numberoftrifaces; f++) {
4883*552f7358SJed Brown         if (out.trifacemarkerlist[f]) {
4884*552f7358SJed Brown           const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells};
4885*552f7358SJed Brown           const PetscInt *faces;
4886*552f7358SJed Brown           PetscInt        numFaces;
4887*552f7358SJed Brown 
4888*552f7358SJed Brown           ierr = DMPlexGetJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr);
4889*552f7358SJed Brown           if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces);
4890*552f7358SJed Brown           ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr);
4891*552f7358SJed Brown           ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr);
4892*552f7358SJed Brown         }
4893*552f7358SJed Brown       }
4894*552f7358SJed Brown     }
4895*552f7358SJed Brown     ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr);
4896*552f7358SJed Brown   }
4897*552f7358SJed Brown   PetscFunctionReturn(0);
4898*552f7358SJed Brown }
4899*552f7358SJed Brown #endif
4900*552f7358SJed Brown 
4901*552f7358SJed Brown #ifdef PETSC_HAVE_CTETGEN
4902*552f7358SJed Brown #include "ctetgen.h"
4903*552f7358SJed Brown 
4904*552f7358SJed Brown #undef __FUNCT__
4905*552f7358SJed Brown #define __FUNCT__ "DMPlexGenerate_CTetgen"
4906*552f7358SJed Brown PetscErrorCode DMPlexGenerate_CTetgen(DM boundary, PetscBool interpolate, DM *dm)
4907*552f7358SJed Brown {
4908*552f7358SJed Brown   MPI_Comm       comm = ((PetscObject) boundary)->comm;
4909*552f7358SJed Brown   const PetscInt dim  = 3;
4910*552f7358SJed Brown   PLC           *in, *out;
4911*552f7358SJed Brown   PetscInt       verbose = 0, vStart, vEnd, v, fStart, fEnd, f;
4912*552f7358SJed Brown   PetscMPIInt    rank;
4913*552f7358SJed Brown   PetscErrorCode ierr;
4914*552f7358SJed Brown 
4915*552f7358SJed Brown   PetscFunctionBegin;
4916*552f7358SJed Brown   ierr = PetscOptionsGetInt(((PetscObject) boundary)->prefix, "-ctetgen_verbose", &verbose, PETSC_NULL);CHKERRQ(ierr);
4917*552f7358SJed Brown   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
4918*552f7358SJed Brown   ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr);
4919*552f7358SJed Brown   ierr = PLCCreate(&in);CHKERRQ(ierr);
4920*552f7358SJed Brown   ierr = PLCCreate(&out);CHKERRQ(ierr);
4921*552f7358SJed Brown   in->numberofpoints = vEnd - vStart;
4922*552f7358SJed Brown   if (in->numberofpoints > 0) {
4923*552f7358SJed Brown     PetscSection coordSection;
4924*552f7358SJed Brown     Vec          coordinates;
4925*552f7358SJed Brown     PetscScalar *array;
4926*552f7358SJed Brown 
4927*552f7358SJed Brown     ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr);
4928*552f7358SJed Brown     ierr = PetscMalloc(in->numberofpoints     * sizeof(int),       &in->pointmarkerlist);CHKERRQ(ierr);
4929*552f7358SJed Brown     ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr);
4930*552f7358SJed Brown     ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr);
4931*552f7358SJed Brown     ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr);
4932*552f7358SJed Brown     for (v = vStart; v < vEnd; ++v) {
4933*552f7358SJed Brown       const PetscInt idx = v - vStart;
4934*552f7358SJed Brown       PetscInt       off, d, m;
4935*552f7358SJed Brown 
4936*552f7358SJed Brown       ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr);
4937*552f7358SJed Brown       for (d = 0; d < dim; ++d) {
4938*552f7358SJed Brown         in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]);
4939*552f7358SJed Brown       }
4940*552f7358SJed Brown       ierr = DMPlexGetLabelValue(boundary, "marker", v, &m);CHKERRQ(ierr);
4941*552f7358SJed Brown       in->pointmarkerlist[idx] = (int) m;
4942*552f7358SJed Brown     }
4943*552f7358SJed Brown     ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr);
4944*552f7358SJed Brown   }
4945*552f7358SJed Brown   ierr  = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr);
4946*552f7358SJed Brown   in->numberoffacets = fEnd - fStart;
4947*552f7358SJed Brown   if (in->numberoffacets > 0) {
4948*552f7358SJed Brown     ierr = PetscMalloc(in->numberoffacets * sizeof(facet), &in->facetlist);CHKERRQ(ierr);
4949*552f7358SJed Brown     ierr = PetscMalloc(in->numberoffacets * sizeof(int),   &in->facetmarkerlist);CHKERRQ(ierr);
4950*552f7358SJed Brown     for (f = fStart; f < fEnd; ++f) {
4951*552f7358SJed Brown       const PetscInt idx    = f - fStart;
4952*552f7358SJed Brown       PetscInt      *points = PETSC_NULL, numPoints, p, numVertices = 0, v, m;
4953*552f7358SJed Brown       polygon       *poly;
4954*552f7358SJed Brown 
4955*552f7358SJed Brown       in->facetlist[idx].numberofpolygons = 1;
4956*552f7358SJed Brown       ierr = PetscMalloc(in->facetlist[idx].numberofpolygons * sizeof(polygon), &in->facetlist[idx].polygonlist);CHKERRQ(ierr);
4957*552f7358SJed Brown       in->facetlist[idx].numberofholes    = 0;
4958*552f7358SJed Brown       in->facetlist[idx].holelist         = PETSC_NULL;
4959*552f7358SJed Brown 
4960*552f7358SJed Brown       ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);
4961*552f7358SJed Brown       for (p = 0; p < numPoints*2; p += 2) {
4962*552f7358SJed Brown         const PetscInt point = points[p];
4963*552f7358SJed Brown         if ((point >= vStart) && (point < vEnd)) {
4964*552f7358SJed Brown           points[numVertices++] = point;
4965*552f7358SJed Brown         }
4966*552f7358SJed Brown       }
4967*552f7358SJed Brown 
4968*552f7358SJed Brown       poly = in->facetlist[idx].polygonlist;
4969*552f7358SJed Brown       poly->numberofvertices = numVertices;
4970*552f7358SJed Brown       ierr = PetscMalloc(poly->numberofvertices * sizeof(int), &poly->vertexlist);CHKERRQ(ierr);
4971*552f7358SJed Brown       for (v = 0; v < numVertices; ++v) {
4972*552f7358SJed Brown         const PetscInt vIdx = points[v] - vStart;
4973*552f7358SJed Brown         poly->vertexlist[v] = vIdx;
4974*552f7358SJed Brown       }
4975*552f7358SJed Brown       ierr = DMPlexGetLabelValue(boundary, "marker", f, &m);CHKERRQ(ierr);
4976*552f7358SJed Brown       in->facetmarkerlist[idx] = (int) m;
4977*552f7358SJed Brown       ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);
4978*552f7358SJed Brown     }
4979*552f7358SJed Brown   }
4980*552f7358SJed Brown   if (!rank) {
4981*552f7358SJed Brown     TetGenOpts t;
4982*552f7358SJed Brown 
4983*552f7358SJed Brown     ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr);
4984*552f7358SJed Brown     t.in        = boundary; /* Should go away */
4985*552f7358SJed Brown     t.plc       = 1;
4986*552f7358SJed Brown     t.quality   = 1;
4987*552f7358SJed Brown     t.edgesout  = 1;
4988*552f7358SJed Brown     t.zeroindex = 1;
4989*552f7358SJed Brown     t.quiet     = 1;
4990*552f7358SJed Brown     t.verbose   = verbose;
4991*552f7358SJed Brown     ierr = TetGenCheckOpts(&t);CHKERRQ(ierr);
4992*552f7358SJed Brown     ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr);
4993*552f7358SJed Brown   }
4994*552f7358SJed Brown   {
4995*552f7358SJed Brown     const PetscInt numCorners  = 4;
4996*552f7358SJed Brown     const PetscInt numCells    = out->numberoftetrahedra;
4997*552f7358SJed Brown     const PetscInt numVertices = out->numberofpoints;
4998*552f7358SJed Brown     const int     *cells       = out->tetrahedronlist;
4999*552f7358SJed Brown     const double  *meshCoords  = out->pointlist;
5000*552f7358SJed Brown 
5001*552f7358SJed Brown     ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr);
5002*552f7358SJed Brown     /* Set labels */
5003*552f7358SJed Brown     for (v = 0; v < numVertices; ++v) {
5004*552f7358SJed Brown       if (out->pointmarkerlist[v]) {
5005*552f7358SJed Brown         ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr);
5006*552f7358SJed Brown       }
5007*552f7358SJed Brown     }
5008*552f7358SJed Brown     if (interpolate) {
5009*552f7358SJed Brown       PetscInt e;
5010*552f7358SJed Brown 
5011*552f7358SJed Brown       for (e = 0; e < out->numberofedges; e++) {
5012*552f7358SJed Brown         if (out->edgemarkerlist[e]) {
5013*552f7358SJed Brown           const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells};
5014*552f7358SJed Brown           const PetscInt *edges;
5015*552f7358SJed Brown           PetscInt        numEdges;
5016*552f7358SJed Brown 
5017*552f7358SJed Brown           ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr);
5018*552f7358SJed Brown           if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges);
5019*552f7358SJed Brown           ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr);
5020*552f7358SJed Brown           ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr);
5021*552f7358SJed Brown         }
5022*552f7358SJed Brown       }
5023*552f7358SJed Brown       for (f = 0; f < out->numberoftrifaces; f++) {
5024*552f7358SJed Brown         if (out->trifacemarkerlist[f]) {
5025*552f7358SJed Brown           const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells};
5026*552f7358SJed Brown           const PetscInt *faces;
5027*552f7358SJed Brown           PetscInt        numFaces;
5028*552f7358SJed Brown 
5029*552f7358SJed Brown           ierr = DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr);
5030*552f7358SJed Brown           if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces);
5031*552f7358SJed Brown           ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr);
5032*552f7358SJed Brown           ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr);
5033*552f7358SJed Brown         }
5034*552f7358SJed Brown       }
5035*552f7358SJed Brown     }
5036*552f7358SJed Brown     ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr);
5037*552f7358SJed Brown   }
5038*552f7358SJed Brown 
5039*552f7358SJed Brown   ierr = PLCDestroy(&in);CHKERRQ(ierr);
5040*552f7358SJed Brown   ierr = PLCDestroy(&out);CHKERRQ(ierr);
5041*552f7358SJed Brown   PetscFunctionReturn(0);
5042*552f7358SJed Brown }
5043*552f7358SJed Brown 
5044*552f7358SJed Brown #undef __FUNCT__
5045*552f7358SJed Brown #define __FUNCT__ "DMPlexRefine_CTetgen"
5046*552f7358SJed Brown PetscErrorCode DMPlexRefine_CTetgen(DM dm, PetscReal *maxVolumes, DM *dmRefined)
5047*552f7358SJed Brown {
5048*552f7358SJed Brown   MPI_Comm       comm = ((PetscObject) dm)->comm;
5049*552f7358SJed Brown   const PetscInt dim  = 3;
5050*552f7358SJed Brown   PLC           *in, *out;
5051*552f7358SJed Brown   PetscInt       verbose = 0, vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal;
5052*552f7358SJed Brown   PetscMPIInt    rank;
5053*552f7358SJed Brown   PetscErrorCode ierr;
5054*552f7358SJed Brown 
5055*552f7358SJed Brown   PetscFunctionBegin;
5056*552f7358SJed Brown   ierr = PetscOptionsGetInt(((PetscObject) dm)->prefix, "-ctetgen_verbose", &verbose, PETSC_NULL);CHKERRQ(ierr);
5057*552f7358SJed Brown   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
5058*552f7358SJed Brown   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
5059*552f7358SJed Brown   ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr);
5060*552f7358SJed Brown   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
5061*552f7358SJed Brown   ierr = PLCCreate(&in);CHKERRQ(ierr);
5062*552f7358SJed Brown   ierr = PLCCreate(&out);CHKERRQ(ierr);
5063*552f7358SJed Brown   in->numberofpoints = vEnd - vStart;
5064*552f7358SJed Brown   if (in->numberofpoints > 0) {
5065*552f7358SJed Brown     PetscSection coordSection;
5066*552f7358SJed Brown     Vec          coordinates;
5067*552f7358SJed Brown     PetscScalar *array;
5068*552f7358SJed Brown 
5069*552f7358SJed Brown     ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr);
5070*552f7358SJed Brown     ierr = PetscMalloc(in->numberofpoints     * sizeof(int),       &in->pointmarkerlist);CHKERRQ(ierr);
5071*552f7358SJed Brown     ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
5072*552f7358SJed Brown     ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr);
5073*552f7358SJed Brown     ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr);
5074*552f7358SJed Brown     for (v = vStart; v < vEnd; ++v) {
5075*552f7358SJed Brown       const PetscInt idx = v - vStart;
5076*552f7358SJed Brown       PetscInt       off, d, m;
5077*552f7358SJed Brown 
5078*552f7358SJed Brown       ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr);
5079*552f7358SJed Brown       for (d = 0; d < dim; ++d) {
5080*552f7358SJed Brown         in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]);
5081*552f7358SJed Brown       }
5082*552f7358SJed Brown       ierr = DMPlexGetLabelValue(dm, "marker", v, &m);CHKERRQ(ierr);
5083*552f7358SJed Brown       in->pointmarkerlist[idx] = (int) m;
5084*552f7358SJed Brown     }
5085*552f7358SJed Brown     ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr);
5086*552f7358SJed Brown   }
5087*552f7358SJed Brown   ierr  = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
5088*552f7358SJed Brown   in->numberofcorners       = 4;
5089*552f7358SJed Brown   in->numberoftetrahedra    = cEnd - cStart;
5090*552f7358SJed Brown   in->tetrahedronvolumelist = maxVolumes;
5091*552f7358SJed Brown   if (in->numberoftetrahedra > 0) {
5092*552f7358SJed Brown     ierr = PetscMalloc(in->numberoftetrahedra*in->numberofcorners * sizeof(int), &in->tetrahedronlist);CHKERRQ(ierr);
5093*552f7358SJed Brown     for (c = cStart; c < cEnd; ++c) {
5094*552f7358SJed Brown       const PetscInt idx     = c - cStart;
5095*552f7358SJed Brown       PetscInt      *closure = PETSC_NULL;
5096*552f7358SJed Brown       PetscInt       closureSize;
5097*552f7358SJed Brown 
5098*552f7358SJed Brown       ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
5099*552f7358SJed Brown       if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize);
5100*552f7358SJed Brown       for (v = 0; v < 4; ++v) {
5101*552f7358SJed Brown         in->tetrahedronlist[idx*in->numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart;
5102*552f7358SJed Brown       }
5103*552f7358SJed Brown       ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
5104*552f7358SJed Brown     }
5105*552f7358SJed Brown   }
5106*552f7358SJed Brown   if (!rank) {
5107*552f7358SJed Brown     TetGenOpts t;
5108*552f7358SJed Brown 
5109*552f7358SJed Brown     ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr);
5110*552f7358SJed Brown     t.in        = dm; /* Should go away */
5111*552f7358SJed Brown     t.refine    = 1;
5112*552f7358SJed Brown     t.varvolume = 1;
5113*552f7358SJed Brown     t.quality   = 1;
5114*552f7358SJed Brown     t.edgesout  = 1;
5115*552f7358SJed Brown     t.zeroindex = 1;
5116*552f7358SJed Brown     t.quiet     = 1;
5117*552f7358SJed Brown     t.verbose   = verbose; /* Change this */
5118*552f7358SJed Brown     ierr = TetGenCheckOpts(&t);CHKERRQ(ierr);
5119*552f7358SJed Brown     ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr);
5120*552f7358SJed Brown   }
5121*552f7358SJed Brown   {
5122*552f7358SJed Brown     const PetscInt numCorners  = 4;
5123*552f7358SJed Brown     const PetscInt numCells    = out->numberoftetrahedra;
5124*552f7358SJed Brown     const PetscInt numVertices = out->numberofpoints;
5125*552f7358SJed Brown     const int     *cells       = out->tetrahedronlist;
5126*552f7358SJed Brown     const double  *meshCoords  = out->pointlist;
5127*552f7358SJed Brown     PetscBool      interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE;
5128*552f7358SJed Brown 
5129*552f7358SJed Brown     ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr);
5130*552f7358SJed Brown     /* Set labels */
5131*552f7358SJed Brown     for (v = 0; v < numVertices; ++v) {
5132*552f7358SJed Brown       if (out->pointmarkerlist[v]) {
5133*552f7358SJed Brown         ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr);
5134*552f7358SJed Brown       }
5135*552f7358SJed Brown     }
5136*552f7358SJed Brown     if (interpolate) {
5137*552f7358SJed Brown       PetscInt e, f;
5138*552f7358SJed Brown 
5139*552f7358SJed Brown       for (e = 0; e < out->numberofedges; e++) {
5140*552f7358SJed Brown         if (out->edgemarkerlist[e]) {
5141*552f7358SJed Brown           const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells};
5142*552f7358SJed Brown           const PetscInt *edges;
5143*552f7358SJed Brown           PetscInt        numEdges;
5144*552f7358SJed Brown 
5145*552f7358SJed Brown           ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr);
5146*552f7358SJed Brown           if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges);
5147*552f7358SJed Brown           ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr);
5148*552f7358SJed Brown           ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr);
5149*552f7358SJed Brown         }
5150*552f7358SJed Brown       }
5151*552f7358SJed Brown       for (f = 0; f < out->numberoftrifaces; f++) {
5152*552f7358SJed Brown         if (out->trifacemarkerlist[f]) {
5153*552f7358SJed Brown           const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells};
5154*552f7358SJed Brown           const PetscInt *faces;
5155*552f7358SJed Brown           PetscInt        numFaces;
5156*552f7358SJed Brown 
5157*552f7358SJed Brown           ierr = DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr);
5158*552f7358SJed Brown           if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces);
5159*552f7358SJed Brown           ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr);
5160*552f7358SJed Brown           ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr);
5161*552f7358SJed Brown         }
5162*552f7358SJed Brown       }
5163*552f7358SJed Brown     }
5164*552f7358SJed Brown     ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr);
5165*552f7358SJed Brown   }
5166*552f7358SJed Brown   ierr = PLCDestroy(&in);CHKERRQ(ierr);
5167*552f7358SJed Brown   ierr = PLCDestroy(&out);CHKERRQ(ierr);
5168*552f7358SJed Brown   PetscFunctionReturn(0);
5169*552f7358SJed Brown }
5170*552f7358SJed Brown #endif
5171*552f7358SJed Brown 
5172*552f7358SJed Brown #undef __FUNCT__
5173*552f7358SJed Brown #define __FUNCT__ "DMPlexGenerate"
5174*552f7358SJed Brown /*@C
5175*552f7358SJed Brown   DMPlexGenerate - Generates a mesh.
5176*552f7358SJed Brown 
5177*552f7358SJed Brown   Not Collective
5178*552f7358SJed Brown 
5179*552f7358SJed Brown   Input Parameters:
5180*552f7358SJed Brown + boundary - The DMPlex boundary object
5181*552f7358SJed Brown . name - The mesh generation package name
5182*552f7358SJed Brown - interpolate - Flag to create intermediate mesh elements
5183*552f7358SJed Brown 
5184*552f7358SJed Brown   Output Parameter:
5185*552f7358SJed Brown . mesh - The DMPlex object
5186*552f7358SJed Brown 
5187*552f7358SJed Brown   Level: intermediate
5188*552f7358SJed Brown 
5189*552f7358SJed Brown .keywords: mesh, elements
5190*552f7358SJed Brown .seealso: DMPlexCreate(), DMRefine()
5191*552f7358SJed Brown @*/
5192*552f7358SJed Brown PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh)
5193*552f7358SJed Brown {
5194*552f7358SJed Brown   PetscInt       dim;
5195*552f7358SJed Brown   char           genname[1024];
5196*552f7358SJed Brown   PetscBool      isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg;
5197*552f7358SJed Brown   PetscErrorCode ierr;
5198*552f7358SJed Brown 
5199*552f7358SJed Brown   PetscFunctionBegin;
5200*552f7358SJed Brown   PetscValidHeaderSpecific(boundary, DM_CLASSID, 1);
5201*552f7358SJed Brown   PetscValidLogicalCollectiveBool(boundary, interpolate, 2);
5202*552f7358SJed Brown   ierr = DMPlexGetDimension(boundary, &dim);CHKERRQ(ierr);
5203*552f7358SJed Brown   ierr = PetscOptionsGetString(((PetscObject) boundary)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr);
5204*552f7358SJed Brown   if (flg) {name = genname;}
5205*552f7358SJed Brown   if (name) {
5206*552f7358SJed Brown     ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr);
5207*552f7358SJed Brown     ierr = PetscStrcmp(name, "tetgen",   &isTetgen);CHKERRQ(ierr);
5208*552f7358SJed Brown     ierr = PetscStrcmp(name, "ctetgen",  &isCTetgen);CHKERRQ(ierr);
5209*552f7358SJed Brown   }
5210*552f7358SJed Brown   switch(dim) {
5211*552f7358SJed Brown   case 1:
5212*552f7358SJed Brown     if (!name || isTriangle) {
5213*552f7358SJed Brown #ifdef PETSC_HAVE_TRIANGLE
5214*552f7358SJed Brown       ierr = DMPlexGenerate_Triangle(boundary, interpolate, mesh);CHKERRQ(ierr);
5215*552f7358SJed Brown #else
5216*552f7358SJed Brown       SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Mesh generation needs external package support.\nPlease reconfigure with --download-triangle.");
5217*552f7358SJed Brown #endif
5218*552f7358SJed Brown     } else SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name);
5219*552f7358SJed Brown     break;
5220*552f7358SJed Brown   case 2:
5221*552f7358SJed Brown     if (!name || isCTetgen) {
5222*552f7358SJed Brown #ifdef PETSC_HAVE_CTETGEN
5223*552f7358SJed Brown       ierr = DMPlexGenerate_CTetgen(boundary, interpolate, mesh);CHKERRQ(ierr);
5224*552f7358SJed Brown #else
5225*552f7358SJed Brown       SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen.");
5226*552f7358SJed Brown #endif
5227*552f7358SJed Brown     } else if (isTetgen) {
5228*552f7358SJed Brown #ifdef PETSC_HAVE_TETGEN
5229*552f7358SJed Brown       ierr = DMPlexGenerate_Tetgen(boundary, interpolate, mesh);CHKERRQ(ierr);
5230*552f7358SJed Brown #else
5231*552f7358SJed Brown       SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen.");
5232*552f7358SJed Brown #endif
5233*552f7358SJed Brown     } else SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name);
5234*552f7358SJed Brown     break;
5235*552f7358SJed Brown   default:
5236*552f7358SJed Brown     SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Mesh generation for a dimension %d boundary is not supported.", dim);
5237*552f7358SJed Brown   }
5238*552f7358SJed Brown   PetscFunctionReturn(0);
5239*552f7358SJed Brown }
5240*552f7358SJed Brown 
5241*552f7358SJed Brown typedef PetscInt CellRefiner;
5242*552f7358SJed Brown 
5243*552f7358SJed Brown #undef __FUNCT__
5244*552f7358SJed Brown #define __FUNCT__ "GetDepthStart_Private"
5245*552f7358SJed Brown PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart)
5246*552f7358SJed Brown {
5247*552f7358SJed Brown   PetscFunctionBegin;
5248*552f7358SJed Brown   if (cStart) *cStart = 0;
5249*552f7358SJed Brown   if (vStart) *vStart = depthSize[depth];
5250*552f7358SJed Brown   if (fStart) *fStart = depthSize[depth] + depthSize[0];
5251*552f7358SJed Brown   if (eStart) *eStart = depthSize[depth] + depthSize[0] + depthSize[depth-1];
5252*552f7358SJed Brown   PetscFunctionReturn(0);
5253*552f7358SJed Brown }
5254*552f7358SJed Brown 
5255*552f7358SJed Brown #undef __FUNCT__
5256*552f7358SJed Brown #define __FUNCT__ "GetDepthEnd_Private"
5257*552f7358SJed Brown PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd)
5258*552f7358SJed Brown {
5259*552f7358SJed Brown   PetscFunctionBegin;
5260*552f7358SJed Brown   if (cEnd) *cEnd = depthSize[depth];
5261*552f7358SJed Brown   if (vEnd) *vEnd = depthSize[depth] + depthSize[0];
5262*552f7358SJed Brown   if (fEnd) *fEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1];
5263*552f7358SJed Brown   if (eEnd) *eEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1];
5264*552f7358SJed Brown   PetscFunctionReturn(0);
5265*552f7358SJed Brown }
5266*552f7358SJed Brown 
5267*552f7358SJed Brown #undef __FUNCT__
5268*552f7358SJed Brown #define __FUNCT__ "CellRefinerGetSizes"
5269*552f7358SJed Brown PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[])
5270*552f7358SJed Brown {
5271*552f7358SJed Brown   PetscInt       cStart, cEnd, vStart, vEnd, fStart, fEnd, eStart, eEnd;
5272*552f7358SJed Brown   PetscErrorCode ierr;
5273*552f7358SJed Brown 
5274*552f7358SJed Brown   PetscFunctionBegin;
5275*552f7358SJed Brown   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
5276*552f7358SJed Brown   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
5277*552f7358SJed Brown   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
5278*552f7358SJed Brown   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
5279*552f7358SJed Brown   switch(refiner) {
5280*552f7358SJed Brown   case 1:
5281*552f7358SJed Brown     /* Simplicial 2D */
5282*552f7358SJed Brown     depthSize[0] = vEnd - vStart + fEnd - fStart;         /* Add a vertex on every face */
5283*552f7358SJed Brown     depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */
5284*552f7358SJed Brown     depthSize[2] = 4*(cEnd - cStart);                     /* Every cell split into 4 cells */
5285*552f7358SJed Brown     break;
5286*552f7358SJed Brown   case 2:
5287*552f7358SJed Brown     /* Hex 2D */
5288*552f7358SJed Brown     depthSize[0] = vEnd - vStart + cEnd - cStart + fEnd - fStart; /* Add a vertex on every face and cell */
5289*552f7358SJed Brown     depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart);         /* Every face is split into 2 faces and 4 faces are added for each cell */
5290*552f7358SJed Brown     depthSize[2] = 4*(cEnd - cStart);                             /* Every cell split into 4 cells */
5291*552f7358SJed Brown     break;
5292*552f7358SJed Brown   default:
5293*552f7358SJed Brown     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
5294*552f7358SJed Brown   }
5295*552f7358SJed Brown   PetscFunctionReturn(0);
5296*552f7358SJed Brown }
5297*552f7358SJed Brown 
5298*552f7358SJed Brown #undef __FUNCT__
5299*552f7358SJed Brown #define __FUNCT__ "CellRefinerSetConeSizes"
5300*552f7358SJed Brown PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
5301*552f7358SJed Brown {
5302*552f7358SJed Brown   PetscInt       depth, cStart, cStartNew, cEnd, c, vStart, vStartNew, vEnd, v, fStart, fStartNew, fEnd, f, eStart, eStartNew, eEnd, r;
5303*552f7358SJed Brown   PetscErrorCode ierr;
5304*552f7358SJed Brown 
5305*552f7358SJed Brown   PetscFunctionBegin;
5306*552f7358SJed Brown   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
5307*552f7358SJed Brown   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
5308*552f7358SJed Brown   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
5309*552f7358SJed Brown   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
5310*552f7358SJed Brown   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
5311*552f7358SJed Brown   ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr);
5312*552f7358SJed Brown   switch(refiner) {
5313*552f7358SJed Brown   case 1:
5314*552f7358SJed Brown     /* Simplicial 2D */
5315*552f7358SJed Brown     /* All cells have 3 faces */
5316*552f7358SJed Brown     for(c = cStart; c < cEnd; ++c) {
5317*552f7358SJed Brown       for(r = 0; r < 4; ++r) {
5318*552f7358SJed Brown         const PetscInt newp = (c - cStart)*4 + r;
5319*552f7358SJed Brown 
5320*552f7358SJed Brown         ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr);
5321*552f7358SJed Brown       }
5322*552f7358SJed Brown     }
5323*552f7358SJed Brown     /* Split faces have 2 vertices and the same cells as the parent */
5324*552f7358SJed Brown     for(f = fStart; f < fEnd; ++f) {
5325*552f7358SJed Brown       for(r = 0; r < 2; ++r) {
5326*552f7358SJed Brown         const PetscInt newp = fStartNew + (f - fStart)*2 + r;
5327*552f7358SJed Brown         PetscInt       size;
5328*552f7358SJed Brown 
5329*552f7358SJed Brown         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
5330*552f7358SJed Brown         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
5331*552f7358SJed Brown         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
5332*552f7358SJed Brown       }
5333*552f7358SJed Brown     }
5334*552f7358SJed Brown     /* Interior faces have 2 vertices and 2 cells */
5335*552f7358SJed Brown     for(c = cStart; c < cEnd; ++c) {
5336*552f7358SJed Brown       for(r = 0; r < 3; ++r) {
5337*552f7358SJed Brown         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r;
5338*552f7358SJed Brown 
5339*552f7358SJed Brown         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
5340*552f7358SJed Brown         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
5341*552f7358SJed Brown       }
5342*552f7358SJed Brown     }
5343*552f7358SJed Brown     /* Old vertices have identical supports */
5344*552f7358SJed Brown     for(v = vStart; v < vEnd; ++v) {
5345*552f7358SJed Brown       const PetscInt newp = vStartNew + (v - vStart);
5346*552f7358SJed Brown       PetscInt       size;
5347*552f7358SJed Brown 
5348*552f7358SJed Brown       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
5349*552f7358SJed Brown       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
5350*552f7358SJed Brown     }
5351*552f7358SJed Brown     /* Face vertices have 2 + cells*2 supports */
5352*552f7358SJed Brown     for(f = fStart; f < fEnd; ++f) {
5353*552f7358SJed Brown       const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
5354*552f7358SJed Brown       PetscInt       size;
5355*552f7358SJed Brown 
5356*552f7358SJed Brown       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
5357*552f7358SJed Brown       ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2);CHKERRQ(ierr);
5358*552f7358SJed Brown     }
5359*552f7358SJed Brown     break;
5360*552f7358SJed Brown   case 2:
5361*552f7358SJed Brown     /* Hex 2D */
5362*552f7358SJed Brown     /* All cells have 4 faces */
5363*552f7358SJed Brown     for(c = cStart; c < cEnd; ++c) {
5364*552f7358SJed Brown       for(r = 0; r < 4; ++r) {
5365*552f7358SJed Brown         const PetscInt newp = (c - cStart)*4 + r;
5366*552f7358SJed Brown 
5367*552f7358SJed Brown         ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr);
5368*552f7358SJed Brown       }
5369*552f7358SJed Brown     }
5370*552f7358SJed Brown     /* Split faces have 2 vertices and the same cells as the parent */
5371*552f7358SJed Brown     for(f = fStart; f < fEnd; ++f) {
5372*552f7358SJed Brown       for(r = 0; r < 2; ++r) {
5373*552f7358SJed Brown         const PetscInt newp = fStartNew + (f - fStart)*2 + r;
5374*552f7358SJed Brown         PetscInt       size;
5375*552f7358SJed Brown 
5376*552f7358SJed Brown         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
5377*552f7358SJed Brown         ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
5378*552f7358SJed Brown         ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
5379*552f7358SJed Brown       }
5380*552f7358SJed Brown     }
5381*552f7358SJed Brown     /* Interior faces have 2 vertices and 2 cells */
5382*552f7358SJed Brown     for(c = cStart; c < cEnd; ++c) {
5383*552f7358SJed Brown       for(r = 0; r < 4; ++r) {
5384*552f7358SJed Brown         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r;
5385*552f7358SJed Brown 
5386*552f7358SJed Brown         ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr);
5387*552f7358SJed Brown         ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr);
5388*552f7358SJed Brown       }
5389*552f7358SJed Brown     }
5390*552f7358SJed Brown     /* Old vertices have identical supports */
5391*552f7358SJed Brown     for(v = vStart; v < vEnd; ++v) {
5392*552f7358SJed Brown       const PetscInt newp = vStartNew + (v - vStart);
5393*552f7358SJed Brown       PetscInt       size;
5394*552f7358SJed Brown 
5395*552f7358SJed Brown       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
5396*552f7358SJed Brown       ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr);
5397*552f7358SJed Brown     }
5398*552f7358SJed Brown     /* Face vertices have 2 + cells supports */
5399*552f7358SJed Brown     for(f = fStart; f < fEnd; ++f) {
5400*552f7358SJed Brown       const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart);
5401*552f7358SJed Brown       PetscInt       size;
5402*552f7358SJed Brown 
5403*552f7358SJed Brown       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
5404*552f7358SJed Brown       ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr);
5405*552f7358SJed Brown     }
5406*552f7358SJed Brown     /* Cell vertices have 4 supports */
5407*552f7358SJed Brown     for(c = cStart; c < cEnd; ++c) {
5408*552f7358SJed Brown       const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart);
5409*552f7358SJed Brown 
5410*552f7358SJed Brown       ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr);
5411*552f7358SJed Brown     }
5412*552f7358SJed Brown     break;
5413*552f7358SJed Brown   default:
5414*552f7358SJed Brown     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
5415*552f7358SJed Brown   }
5416*552f7358SJed Brown   PetscFunctionReturn(0);
5417*552f7358SJed Brown }
5418*552f7358SJed Brown 
5419*552f7358SJed Brown #undef __FUNCT__
5420*552f7358SJed Brown #define __FUNCT__ "CellRefinerSetCones"
5421*552f7358SJed Brown PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
5422*552f7358SJed Brown {
5423*552f7358SJed Brown   PetscInt       depth, cStart, cEnd, cStartNew, cEndNew, c, vStart, vEnd, vStartNew, vEndNew, v, fStart, fEnd, fStartNew, fEndNew, f, eStart, eEnd, eStartNew, eEndNew, r, p;
5424*552f7358SJed Brown   PetscInt       maxSupportSize, *supportRef;
5425*552f7358SJed Brown   PetscErrorCode ierr;
5426*552f7358SJed Brown 
5427*552f7358SJed Brown   PetscFunctionBegin;
5428*552f7358SJed Brown   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
5429*552f7358SJed Brown   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
5430*552f7358SJed Brown   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
5431*552f7358SJed Brown   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
5432*552f7358SJed Brown   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
5433*552f7358SJed Brown   ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr);
5434*552f7358SJed Brown   ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr);
5435*552f7358SJed Brown   switch(refiner) {
5436*552f7358SJed Brown   case 1:
5437*552f7358SJed Brown     /* Simplicial 2D */
5438*552f7358SJed Brown     /*
5439*552f7358SJed Brown      2
5440*552f7358SJed Brown      |\
5441*552f7358SJed Brown      | \
5442*552f7358SJed Brown      |  \
5443*552f7358SJed Brown      |   \
5444*552f7358SJed Brown      | C  \
5445*552f7358SJed Brown      |     \
5446*552f7358SJed Brown      |      \
5447*552f7358SJed Brown      2---1---1
5448*552f7358SJed Brown      |\  D  / \
5449*552f7358SJed Brown      | 2   0   \
5450*552f7358SJed Brown      |A \ /  B  \
5451*552f7358SJed Brown      0---0-------1
5452*552f7358SJed Brown      */
5453*552f7358SJed Brown     /* All cells have 3 faces */
5454*552f7358SJed Brown     for(c = cStart; c < cEnd; ++c) {
5455*552f7358SJed Brown       const PetscInt  newp = (c - cStart)*4;
5456*552f7358SJed Brown       const PetscInt *cone, *ornt;
5457*552f7358SJed Brown       PetscInt        coneNew[3], orntNew[3];
5458*552f7358SJed Brown 
5459*552f7358SJed Brown       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
5460*552f7358SJed Brown       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
5461*552f7358SJed Brown       /* A triangle */
5462*552f7358SJed Brown       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
5463*552f7358SJed Brown       orntNew[0] = ornt[0];
5464*552f7358SJed Brown       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 2;
5465*552f7358SJed Brown       orntNew[1] = -2;
5466*552f7358SJed Brown       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
5467*552f7358SJed Brown       orntNew[2] = ornt[2];
5468*552f7358SJed Brown       ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
5469*552f7358SJed Brown       ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
5470*552f7358SJed Brown #if 1
5471*552f7358SJed Brown       if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew);
5472*552f7358SJed Brown       for(p = 0; p < 3; ++p) {
5473*552f7358SJed Brown         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
5474*552f7358SJed Brown       }
5475*552f7358SJed Brown #endif
5476*552f7358SJed Brown       /* B triangle */
5477*552f7358SJed Brown       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
5478*552f7358SJed Brown       orntNew[0] = ornt[0];
5479*552f7358SJed Brown       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
5480*552f7358SJed Brown       orntNew[1] = ornt[1];
5481*552f7358SJed Brown       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 0;
5482*552f7358SJed Brown       orntNew[2] = -2;
5483*552f7358SJed Brown       ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
5484*552f7358SJed Brown       ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
5485*552f7358SJed Brown #if 1
5486*552f7358SJed Brown       if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew);
5487*552f7358SJed Brown       for(p = 0; p < 3; ++p) {
5488*552f7358SJed Brown         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
5489*552f7358SJed Brown       }
5490*552f7358SJed Brown #endif
5491*552f7358SJed Brown       /* C triangle */
5492*552f7358SJed Brown       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 1;
5493*552f7358SJed Brown       orntNew[0] = -2;
5494*552f7358SJed Brown       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
5495*552f7358SJed Brown       orntNew[1] = ornt[1];
5496*552f7358SJed Brown       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
5497*552f7358SJed Brown       orntNew[2] = ornt[2];
5498*552f7358SJed Brown       ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
5499*552f7358SJed Brown       ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
5500*552f7358SJed Brown #if 1
5501*552f7358SJed Brown       if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew);
5502*552f7358SJed Brown       for(p = 0; p < 3; ++p) {
5503*552f7358SJed Brown         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
5504*552f7358SJed Brown       }
5505*552f7358SJed Brown #endif
5506*552f7358SJed Brown       /* D triangle */
5507*552f7358SJed Brown       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 0;
5508*552f7358SJed Brown       orntNew[0] = 0;
5509*552f7358SJed Brown       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 1;
5510*552f7358SJed Brown       orntNew[1] = 0;
5511*552f7358SJed Brown       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*3 + 2;
5512*552f7358SJed Brown       orntNew[2] = 0;
5513*552f7358SJed Brown       ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
5514*552f7358SJed Brown       ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
5515*552f7358SJed Brown #if 1
5516*552f7358SJed Brown       if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew);
5517*552f7358SJed Brown       for(p = 0; p < 3; ++p) {
5518*552f7358SJed Brown         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
5519*552f7358SJed Brown       }
5520*552f7358SJed Brown #endif
5521*552f7358SJed Brown     }
5522*552f7358SJed Brown     /* Split faces have 2 vertices and the same cells as the parent */
5523*552f7358SJed Brown     ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr);
5524*552f7358SJed Brown     ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr);
5525*552f7358SJed Brown     for(f = fStart; f < fEnd; ++f) {
5526*552f7358SJed Brown       const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
5527*552f7358SJed Brown 
5528*552f7358SJed Brown       for(r = 0; r < 2; ++r) {
5529*552f7358SJed Brown         const PetscInt  newp = fStartNew + (f - fStart)*2 + r;
5530*552f7358SJed Brown         const PetscInt *cone, *support;
5531*552f7358SJed Brown         PetscInt        coneNew[2], coneSize, c, supportSize, s;
5532*552f7358SJed Brown 
5533*552f7358SJed Brown         ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
5534*552f7358SJed Brown         coneNew[0] = vStartNew + (cone[0] - vStart);
5535*552f7358SJed Brown         coneNew[1] = vStartNew + (cone[1] - vStart);
5536*552f7358SJed Brown         coneNew[(r+1)%2] = newv;
5537*552f7358SJed Brown         ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
5538*552f7358SJed Brown #if 1
5539*552f7358SJed Brown         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
5540*552f7358SJed Brown         for(p = 0; p < 2; ++p) {
5541*552f7358SJed Brown           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
5542*552f7358SJed Brown         }
5543*552f7358SJed Brown #endif
5544*552f7358SJed Brown         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
5545*552f7358SJed Brown         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
5546*552f7358SJed Brown         for(s = 0; s < supportSize; ++s) {
5547*552f7358SJed Brown           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
5548*552f7358SJed Brown           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
5549*552f7358SJed Brown           for(c = 0; c < coneSize; ++c) {
5550*552f7358SJed Brown             if (cone[c] == f) {
5551*552f7358SJed Brown               break;
5552*552f7358SJed Brown             }
5553*552f7358SJed Brown           }
5554*552f7358SJed Brown           supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3;
5555*552f7358SJed Brown         }
5556*552f7358SJed Brown         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
5557*552f7358SJed Brown #if 1
5558*552f7358SJed Brown         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
5559*552f7358SJed Brown         for(p = 0; p < supportSize; ++p) {
5560*552f7358SJed Brown           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew);
5561*552f7358SJed Brown         }
5562*552f7358SJed Brown #endif
5563*552f7358SJed Brown       }
5564*552f7358SJed Brown     }
5565*552f7358SJed Brown     /* Interior faces have 2 vertices and 2 cells */
5566*552f7358SJed Brown     for(c = cStart; c < cEnd; ++c) {
5567*552f7358SJed Brown       const PetscInt *cone;
5568*552f7358SJed Brown 
5569*552f7358SJed Brown       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
5570*552f7358SJed Brown       for(r = 0; r < 3; ++r) {
5571*552f7358SJed Brown         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r;
5572*552f7358SJed Brown         PetscInt       coneNew[2];
5573*552f7358SJed Brown         PetscInt       supportNew[2];
5574*552f7358SJed Brown 
5575*552f7358SJed Brown         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r]       - fStart);
5576*552f7358SJed Brown         coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart);
5577*552f7358SJed Brown         ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
5578*552f7358SJed Brown #if 1
5579*552f7358SJed Brown         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
5580*552f7358SJed Brown         for(p = 0; p < 2; ++p) {
5581*552f7358SJed Brown           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
5582*552f7358SJed Brown         }
5583*552f7358SJed Brown #endif
5584*552f7358SJed Brown         supportNew[0] = (c - cStart)*4 + r;
5585*552f7358SJed Brown         supportNew[1] = (c - cStart)*4 + 3;
5586*552f7358SJed Brown         ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
5587*552f7358SJed Brown #if 1
5588*552f7358SJed Brown         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
5589*552f7358SJed Brown         for(p = 0; p < 2; ++p) {
5590*552f7358SJed Brown           if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
5591*552f7358SJed Brown         }
5592*552f7358SJed Brown #endif
5593*552f7358SJed Brown       }
5594*552f7358SJed Brown     }
5595*552f7358SJed Brown     /* Old vertices have identical supports */
5596*552f7358SJed Brown     for(v = vStart; v < vEnd; ++v) {
5597*552f7358SJed Brown       const PetscInt  newp = vStartNew + (v - vStart);
5598*552f7358SJed Brown       const PetscInt *support, *cone;
5599*552f7358SJed Brown       PetscInt        size, s;
5600*552f7358SJed Brown 
5601*552f7358SJed Brown       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
5602*552f7358SJed Brown       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
5603*552f7358SJed Brown       for(s = 0; s < size; ++s) {
5604*552f7358SJed Brown         PetscInt r = 0;
5605*552f7358SJed Brown 
5606*552f7358SJed Brown         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
5607*552f7358SJed Brown         if (cone[1] == v) r = 1;
5608*552f7358SJed Brown         supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
5609*552f7358SJed Brown       }
5610*552f7358SJed Brown       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
5611*552f7358SJed Brown #if 1
5612*552f7358SJed Brown       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
5613*552f7358SJed Brown       for(p = 0; p < size; ++p) {
5614*552f7358SJed Brown         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
5615*552f7358SJed Brown       }
5616*552f7358SJed Brown #endif
5617*552f7358SJed Brown     }
5618*552f7358SJed Brown     /* Face vertices have 2 + cells*2 supports */
5619*552f7358SJed Brown     for(f = fStart; f < fEnd; ++f) {
5620*552f7358SJed Brown       const PetscInt  newp = vStartNew + (vEnd - vStart) + (f - fStart);
5621*552f7358SJed Brown       const PetscInt *cone, *support;
5622*552f7358SJed Brown       PetscInt        size, s;
5623*552f7358SJed Brown 
5624*552f7358SJed Brown       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
5625*552f7358SJed Brown       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
5626*552f7358SJed Brown       supportRef[0] = fStartNew + (f - fStart)*2 + 0;
5627*552f7358SJed Brown       supportRef[1] = fStartNew + (f - fStart)*2 + 1;
5628*552f7358SJed Brown       for(s = 0; s < size; ++s) {
5629*552f7358SJed Brown         PetscInt r = 0;
5630*552f7358SJed Brown 
5631*552f7358SJed Brown         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
5632*552f7358SJed Brown         if      (cone[1] == f) r = 1;
5633*552f7358SJed Brown         else if (cone[2] == f) r = 2;
5634*552f7358SJed Brown         supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3;
5635*552f7358SJed Brown         supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r;
5636*552f7358SJed Brown       }
5637*552f7358SJed Brown       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
5638*552f7358SJed Brown #if 1
5639*552f7358SJed Brown       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
5640*552f7358SJed Brown       for(p = 0; p < 2+size*2; ++p) {
5641*552f7358SJed Brown         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
5642*552f7358SJed Brown       }
5643*552f7358SJed Brown #endif
5644*552f7358SJed Brown     }
5645*552f7358SJed Brown     ierr = PetscFree(supportRef);CHKERRQ(ierr);
5646*552f7358SJed Brown     break;
5647*552f7358SJed Brown   case 2:
5648*552f7358SJed Brown     /* Hex 2D */
5649*552f7358SJed Brown     /*
5650*552f7358SJed Brown      3---------2---------2
5651*552f7358SJed Brown      |         |         |
5652*552f7358SJed Brown      |    D    2    C    |
5653*552f7358SJed Brown      |         |         |
5654*552f7358SJed Brown      3----3----0----1----1
5655*552f7358SJed Brown      |         |         |
5656*552f7358SJed Brown      |    A    0    B    |
5657*552f7358SJed Brown      |         |         |
5658*552f7358SJed Brown      0---------0---------1
5659*552f7358SJed Brown      */
5660*552f7358SJed Brown     /* All cells have 4 faces */
5661*552f7358SJed Brown     for(c = cStart; c < cEnd; ++c) {
5662*552f7358SJed Brown       const PetscInt  newp = (c - cStart)*4;
5663*552f7358SJed Brown       const PetscInt *cone, *ornt;
5664*552f7358SJed Brown       PetscInt        coneNew[4], orntNew[4];
5665*552f7358SJed Brown 
5666*552f7358SJed Brown       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
5667*552f7358SJed Brown       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
5668*552f7358SJed Brown       /* A quad */
5669*552f7358SJed Brown       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0);
5670*552f7358SJed Brown       orntNew[0] = ornt[0];
5671*552f7358SJed Brown       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 0;
5672*552f7358SJed Brown       orntNew[1] = 0;
5673*552f7358SJed Brown       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 3;
5674*552f7358SJed Brown       orntNew[2] = -2;
5675*552f7358SJed Brown       coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1);
5676*552f7358SJed Brown       orntNew[3] = ornt[3];
5677*552f7358SJed Brown       ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr);
5678*552f7358SJed Brown       ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr);
5679*552f7358SJed Brown #if 1
5680*552f7358SJed Brown       if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew);
5681*552f7358SJed Brown       for(p = 0; p < 4; ++p) {
5682*552f7358SJed Brown         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
5683*552f7358SJed Brown       }
5684*552f7358SJed Brown #endif
5685*552f7358SJed Brown       /* B quad */
5686*552f7358SJed Brown       coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1);
5687*552f7358SJed Brown       orntNew[0] = ornt[0];
5688*552f7358SJed Brown       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0);
5689*552f7358SJed Brown       orntNew[1] = ornt[1];
5690*552f7358SJed Brown       coneNew[2] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 1;
5691*552f7358SJed Brown       orntNew[2] = 0;
5692*552f7358SJed Brown       coneNew[3] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 0;
5693*552f7358SJed Brown       orntNew[3] = -2;
5694*552f7358SJed Brown       ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr);
5695*552f7358SJed Brown       ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr);
5696*552f7358SJed Brown #if 1
5697*552f7358SJed Brown       if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew);
5698*552f7358SJed Brown       for(p = 0; p < 4; ++p) {
5699*552f7358SJed Brown         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
5700*552f7358SJed Brown       }
5701*552f7358SJed Brown #endif
5702*552f7358SJed Brown       /* C quad */
5703*552f7358SJed Brown       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 1;
5704*552f7358SJed Brown       orntNew[0] = -2;
5705*552f7358SJed Brown       coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1);
5706*552f7358SJed Brown       orntNew[1] = ornt[1];
5707*552f7358SJed Brown       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0);
5708*552f7358SJed Brown       orntNew[2] = ornt[2];
5709*552f7358SJed Brown       coneNew[3] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 2;
5710*552f7358SJed Brown       orntNew[3] = 0;
5711*552f7358SJed Brown       ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr);
5712*552f7358SJed Brown       ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr);
5713*552f7358SJed Brown #if 1
5714*552f7358SJed Brown       if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew);
5715*552f7358SJed Brown       for(p = 0; p < 4; ++p) {
5716*552f7358SJed Brown         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
5717*552f7358SJed Brown       }
5718*552f7358SJed Brown #endif
5719*552f7358SJed Brown       /* D quad */
5720*552f7358SJed Brown       coneNew[0] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 3;
5721*552f7358SJed Brown       orntNew[0] = 0;
5722*552f7358SJed Brown       coneNew[1] = fStartNew + (fEnd    - fStart)*2 + (c - cStart)*4 + 2;
5723*552f7358SJed Brown       orntNew[1] = -2;
5724*552f7358SJed Brown       coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1);
5725*552f7358SJed Brown       orntNew[2] = ornt[2];
5726*552f7358SJed Brown       coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0);
5727*552f7358SJed Brown       orntNew[3] = ornt[3];
5728*552f7358SJed Brown       ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr);
5729*552f7358SJed Brown       ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr);
5730*552f7358SJed Brown #if 1
5731*552f7358SJed Brown       if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew);
5732*552f7358SJed Brown       for(p = 0; p < 4; ++p) {
5733*552f7358SJed Brown         if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew);
5734*552f7358SJed Brown       }
5735*552f7358SJed Brown #endif
5736*552f7358SJed Brown     }
5737*552f7358SJed Brown     /* Split faces have 2 vertices and the same cells as the parent */
5738*552f7358SJed Brown     ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr);
5739*552f7358SJed Brown     ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr);
5740*552f7358SJed Brown     for(f = fStart; f < fEnd; ++f) {
5741*552f7358SJed Brown       const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart);
5742*552f7358SJed Brown 
5743*552f7358SJed Brown       for(r = 0; r < 2; ++r) {
5744*552f7358SJed Brown         const PetscInt  newp = fStartNew + (f - fStart)*2 + r;
5745*552f7358SJed Brown         const PetscInt *cone, *support;
5746*552f7358SJed Brown         PetscInt        coneNew[2], coneSize, c, supportSize, s;
5747*552f7358SJed Brown 
5748*552f7358SJed Brown         ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
5749*552f7358SJed Brown         coneNew[0] = vStartNew + (cone[0] - vStart);
5750*552f7358SJed Brown         coneNew[1] = vStartNew + (cone[1] - vStart);
5751*552f7358SJed Brown         coneNew[(r+1)%2] = newv;
5752*552f7358SJed Brown         ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
5753*552f7358SJed Brown #if 1
5754*552f7358SJed Brown         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
5755*552f7358SJed Brown         for(p = 0; p < 2; ++p) {
5756*552f7358SJed Brown           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
5757*552f7358SJed Brown         }
5758*552f7358SJed Brown #endif
5759*552f7358SJed Brown         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
5760*552f7358SJed Brown         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
5761*552f7358SJed Brown         for(s = 0; s < supportSize; ++s) {
5762*552f7358SJed Brown           ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
5763*552f7358SJed Brown           ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
5764*552f7358SJed Brown           for(c = 0; c < coneSize; ++c) {
5765*552f7358SJed Brown             if (cone[c] == f) {
5766*552f7358SJed Brown               break;
5767*552f7358SJed Brown             }
5768*552f7358SJed Brown           }
5769*552f7358SJed Brown           supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%4;
5770*552f7358SJed Brown         }
5771*552f7358SJed Brown         ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
5772*552f7358SJed Brown #if 1
5773*552f7358SJed Brown         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
5774*552f7358SJed Brown         for(p = 0; p < supportSize; ++p) {
5775*552f7358SJed Brown           if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew);
5776*552f7358SJed Brown         }
5777*552f7358SJed Brown #endif
5778*552f7358SJed Brown       }
5779*552f7358SJed Brown     }
5780*552f7358SJed Brown     /* Interior faces have 2 vertices and 2 cells */
5781*552f7358SJed Brown     for(c = cStart; c < cEnd; ++c) {
5782*552f7358SJed Brown       const PetscInt *cone;
5783*552f7358SJed Brown       PetscInt        coneNew[2], supportNew[2];
5784*552f7358SJed Brown 
5785*552f7358SJed Brown       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
5786*552f7358SJed Brown       for(r = 0; r < 4; ++r) {
5787*552f7358SJed Brown         const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r;
5788*552f7358SJed Brown 
5789*552f7358SJed Brown         coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart);
5790*552f7358SJed Brown         coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd    - fStart) + (c - cStart);
5791*552f7358SJed Brown         ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr);
5792*552f7358SJed Brown #if 1
5793*552f7358SJed Brown         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
5794*552f7358SJed Brown         for(p = 0; p < 2; ++p) {
5795*552f7358SJed Brown           if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew);
5796*552f7358SJed Brown         }
5797*552f7358SJed Brown #endif
5798*552f7358SJed Brown         supportNew[0] = (c - cStart)*4 + r;
5799*552f7358SJed Brown         supportNew[1] = (c - cStart)*4 + (r+1)%4;
5800*552f7358SJed Brown         ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
5801*552f7358SJed Brown #if 1
5802*552f7358SJed Brown         if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew);
5803*552f7358SJed Brown         for(p = 0; p < 2; ++p) {
5804*552f7358SJed Brown           if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew);
5805*552f7358SJed Brown         }
5806*552f7358SJed Brown #endif
5807*552f7358SJed Brown       }
5808*552f7358SJed Brown     }
5809*552f7358SJed Brown     /* Old vertices have identical supports */
5810*552f7358SJed Brown     for(v = vStart; v < vEnd; ++v) {
5811*552f7358SJed Brown       const PetscInt  newp = vStartNew + (v - vStart);
5812*552f7358SJed Brown       const PetscInt *support, *cone;
5813*552f7358SJed Brown       PetscInt        size, s;
5814*552f7358SJed Brown 
5815*552f7358SJed Brown       ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr);
5816*552f7358SJed Brown       ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr);
5817*552f7358SJed Brown       for(s = 0; s < size; ++s) {
5818*552f7358SJed Brown         PetscInt r = 0;
5819*552f7358SJed Brown 
5820*552f7358SJed Brown         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
5821*552f7358SJed Brown         if (cone[1] == v) r = 1;
5822*552f7358SJed Brown         supportRef[s] = fStartNew + (support[s] - fStart)*2 + r;
5823*552f7358SJed Brown       }
5824*552f7358SJed Brown       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
5825*552f7358SJed Brown #if 1
5826*552f7358SJed Brown       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
5827*552f7358SJed Brown       for(p = 0; p < size; ++p) {
5828*552f7358SJed Brown         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
5829*552f7358SJed Brown       }
5830*552f7358SJed Brown #endif
5831*552f7358SJed Brown     }
5832*552f7358SJed Brown     /* Face vertices have 2 + cells supports */
5833*552f7358SJed Brown     for(f = fStart; f < fEnd; ++f) {
5834*552f7358SJed Brown       const PetscInt  newp = vStartNew + (vEnd - vStart) + (f - fStart);
5835*552f7358SJed Brown       const PetscInt *cone, *support;
5836*552f7358SJed Brown       PetscInt        size, s;
5837*552f7358SJed Brown 
5838*552f7358SJed Brown       ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr);
5839*552f7358SJed Brown       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
5840*552f7358SJed Brown       supportRef[0] = fStartNew + (f - fStart)*2 + 0;
5841*552f7358SJed Brown       supportRef[1] = fStartNew + (f - fStart)*2 + 1;
5842*552f7358SJed Brown       for(s = 0; s < size; ++s) {
5843*552f7358SJed Brown         PetscInt r = 0;
5844*552f7358SJed Brown 
5845*552f7358SJed Brown         ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
5846*552f7358SJed Brown         if      (cone[1] == f) r = 1;
5847*552f7358SJed Brown         else if (cone[2] == f) r = 2;
5848*552f7358SJed Brown         else if (cone[3] == f) r = 3;
5849*552f7358SJed Brown         supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r;
5850*552f7358SJed Brown       }
5851*552f7358SJed Brown       ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr);
5852*552f7358SJed Brown #if 1
5853*552f7358SJed Brown       if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew);
5854*552f7358SJed Brown       for(p = 0; p < 2+size; ++p) {
5855*552f7358SJed Brown         if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew);
5856*552f7358SJed Brown       }
5857*552f7358SJed Brown #endif
5858*552f7358SJed Brown     }
5859*552f7358SJed Brown     /* Cell vertices have 4 supports */
5860*552f7358SJed Brown     for(c = cStart; c < cEnd; ++c) {
5861*552f7358SJed Brown       const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart);
5862*552f7358SJed Brown       PetscInt       supportNew[4];
5863*552f7358SJed Brown 
5864*552f7358SJed Brown       for(r = 0; r < 4; ++r) {
5865*552f7358SJed Brown         supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r;
5866*552f7358SJed Brown       }
5867*552f7358SJed Brown       ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr);
5868*552f7358SJed Brown     }
5869*552f7358SJed Brown     break;
5870*552f7358SJed Brown   default:
5871*552f7358SJed Brown     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
5872*552f7358SJed Brown   }
5873*552f7358SJed Brown   PetscFunctionReturn(0);
5874*552f7358SJed Brown }
5875*552f7358SJed Brown 
5876*552f7358SJed Brown #undef __FUNCT__
5877*552f7358SJed Brown #define __FUNCT__ "CellRefinerSetCoordinates"
5878*552f7358SJed Brown PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
5879*552f7358SJed Brown {
5880*552f7358SJed Brown   PetscSection   coordSection, coordSectionNew;
5881*552f7358SJed Brown   Vec            coordinates, coordinatesNew;
5882*552f7358SJed Brown   PetscScalar   *coords, *coordsNew;
5883*552f7358SJed Brown   PetscInt       dim, depth, coordSizeNew, cStart, cEnd, c, vStart, vStartNew, vEnd, v, fStart, fEnd, f;
5884*552f7358SJed Brown   PetscErrorCode ierr;
5885*552f7358SJed Brown 
5886*552f7358SJed Brown   PetscFunctionBegin;
5887*552f7358SJed Brown   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
5888*552f7358SJed Brown   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
5889*552f7358SJed Brown   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
5890*552f7358SJed Brown   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
5891*552f7358SJed Brown   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
5892*552f7358SJed Brown   ierr = GetDepthStart_Private(depth, depthSize, PETSC_NULL, PETSC_NULL, PETSC_NULL, &vStartNew);CHKERRQ(ierr);
5893*552f7358SJed Brown   ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr);
5894*552f7358SJed Brown   ierr = PetscSectionCreate(((PetscObject) dm)->comm, &coordSectionNew);CHKERRQ(ierr);
5895*552f7358SJed Brown   ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr);
5896*552f7358SJed Brown   ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dim);CHKERRQ(ierr);
5897*552f7358SJed Brown   ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+depthSize[0]);CHKERRQ(ierr);
5898*552f7358SJed Brown   switch(refiner) {
5899*552f7358SJed Brown   case 1:
5900*552f7358SJed Brown   case 2:
5901*552f7358SJed Brown     /* Simplicial and Hex 2D */
5902*552f7358SJed Brown     /* All vertices have the dim coordinates */
5903*552f7358SJed Brown     for(v = vStartNew; v < vStartNew+depthSize[0]; ++v) {
5904*552f7358SJed Brown       ierr = PetscSectionSetDof(coordSectionNew, v, dim);CHKERRQ(ierr);
5905*552f7358SJed Brown       ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dim);CHKERRQ(ierr);
5906*552f7358SJed Brown     }
5907*552f7358SJed Brown     ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr);
5908*552f7358SJed Brown     ierr = DMPlexSetCoordinateSection(rdm, coordSectionNew);CHKERRQ(ierr);
5909*552f7358SJed Brown     ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
5910*552f7358SJed Brown     ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr);
5911*552f7358SJed Brown     ierr = VecCreate(((PetscObject) dm)->comm, &coordinatesNew);CHKERRQ(ierr);
5912*552f7358SJed Brown     ierr = PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");CHKERRQ(ierr);
5913*552f7358SJed Brown     ierr = VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr);
5914*552f7358SJed Brown     ierr = VecSetFromOptions(coordinatesNew);CHKERRQ(ierr);
5915*552f7358SJed Brown     ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr);
5916*552f7358SJed Brown     ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr);
5917*552f7358SJed Brown     /* Old vertices have the same coordinates */
5918*552f7358SJed Brown     for(v = vStart; v < vEnd; ++v) {
5919*552f7358SJed Brown       const PetscInt newv = vStartNew + (v - vStart);
5920*552f7358SJed Brown       PetscInt       off, offnew, d;
5921*552f7358SJed Brown 
5922*552f7358SJed Brown       ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr);
5923*552f7358SJed Brown       ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr);
5924*552f7358SJed Brown       for(d = 0; d < dim; ++d) {
5925*552f7358SJed Brown         coordsNew[offnew+d] = coords[off+d];
5926*552f7358SJed Brown       }
5927*552f7358SJed Brown     }
5928*552f7358SJed Brown     /* Face vertices have the average of endpoint coordinates */
5929*552f7358SJed Brown     for(f = fStart; f < fEnd; ++f) {
5930*552f7358SJed Brown       const PetscInt  newv = vStartNew + (vEnd - vStart) + (f - fStart);
5931*552f7358SJed Brown       const PetscInt *cone;
5932*552f7358SJed Brown       PetscInt        coneSize, offA, offB, offnew, d;
5933*552f7358SJed Brown 
5934*552f7358SJed Brown       ierr = DMPlexGetConeSize(dm, f, &coneSize);CHKERRQ(ierr);
5935*552f7358SJed Brown       if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Face %d cone should have two vertices, not %d", f, coneSize);
5936*552f7358SJed Brown       ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr);
5937*552f7358SJed Brown       ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr);
5938*552f7358SJed Brown       ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr);
5939*552f7358SJed Brown       ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr);
5940*552f7358SJed Brown       for(d = 0; d < dim; ++d) {
5941*552f7358SJed Brown         coordsNew[offnew+d] = 0.5*(coords[offA+d] + coords[offB+d]);
5942*552f7358SJed Brown       }
5943*552f7358SJed Brown     }
5944*552f7358SJed Brown     /* Just Hex 2D */
5945*552f7358SJed Brown     if (refiner == 2) {
5946*552f7358SJed Brown       /* Cell vertices have the average of corner coordinates */
5947*552f7358SJed Brown       for(c = cStart; c < cEnd; ++c) {
5948*552f7358SJed Brown         const PetscInt newv = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart);
5949*552f7358SJed Brown         PetscInt      *cone = PETSC_NULL;
5950*552f7358SJed Brown         PetscInt       closureSize, coneSize = 0, offA, offB, offC, offD, offnew, p, d;
5951*552f7358SJed Brown 
5952*552f7358SJed Brown         ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr);
5953*552f7358SJed Brown         for(p = 0; p < closureSize*2; p += 2) {
5954*552f7358SJed Brown           const PetscInt point = cone[p];
5955*552f7358SJed Brown           if ((point >= vStart) && (point < vEnd)) {
5956*552f7358SJed Brown             cone[coneSize++] = point;
5957*552f7358SJed Brown           }
5958*552f7358SJed Brown         }
5959*552f7358SJed Brown         if (coneSize != 4) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Quad %d cone should have four vertices, not %d", c, coneSize);
5960*552f7358SJed Brown         ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr);
5961*552f7358SJed Brown         ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr);
5962*552f7358SJed Brown         ierr = PetscSectionGetOffset(coordSection, cone[2], &offC);CHKERRQ(ierr);
5963*552f7358SJed Brown         ierr = PetscSectionGetOffset(coordSection, cone[3], &offD);CHKERRQ(ierr);
5964*552f7358SJed Brown         ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr);
5965*552f7358SJed Brown         for(d = 0; d < dim; ++d) {
5966*552f7358SJed Brown           coordsNew[offnew+d] = 0.25*(coords[offA+d] + coords[offB+d] + coords[offC+d] + coords[offD+d]);
5967*552f7358SJed Brown         }
5968*552f7358SJed Brown         ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr);
5969*552f7358SJed Brown       }
5970*552f7358SJed Brown     }
5971*552f7358SJed Brown     ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr);
5972*552f7358SJed Brown     ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr);
5973*552f7358SJed Brown     ierr = DMSetCoordinatesLocal(rdm, coordinatesNew);CHKERRQ(ierr);
5974*552f7358SJed Brown     ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr);
5975*552f7358SJed Brown     break;
5976*552f7358SJed Brown   default:
5977*552f7358SJed Brown     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
5978*552f7358SJed Brown   }
5979*552f7358SJed Brown   PetscFunctionReturn(0);
5980*552f7358SJed Brown }
5981*552f7358SJed Brown 
5982*552f7358SJed Brown #undef __FUNCT__
5983*552f7358SJed Brown #define __FUNCT__ "DMPlexCreateProcessSF"
5984*552f7358SJed Brown PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess)
5985*552f7358SJed Brown {
5986*552f7358SJed Brown   PetscInt           numRoots, numLeaves, l;
5987*552f7358SJed Brown   const PetscInt    *localPoints;
5988*552f7358SJed Brown   const PetscSFNode *remotePoints;
5989*552f7358SJed Brown   PetscInt          *localPointsNew;
5990*552f7358SJed Brown   PetscSFNode       *remotePointsNew;
5991*552f7358SJed Brown   PetscInt          *ranks, *ranksNew;
5992*552f7358SJed Brown   PetscErrorCode     ierr;
5993*552f7358SJed Brown 
5994*552f7358SJed Brown   PetscFunctionBegin;
5995*552f7358SJed Brown   ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr);
5996*552f7358SJed Brown   ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranks);CHKERRQ(ierr);
5997*552f7358SJed Brown   for(l = 0; l < numLeaves; ++l) {
5998*552f7358SJed Brown     ranks[l] = remotePoints[l].rank;
5999*552f7358SJed Brown   }
6000*552f7358SJed Brown   ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr);
6001*552f7358SJed Brown   ierr = PetscMalloc(numLeaves * sizeof(PetscInt),    &ranksNew);CHKERRQ(ierr);
6002*552f7358SJed Brown   ierr = PetscMalloc(numLeaves * sizeof(PetscInt),    &localPointsNew);CHKERRQ(ierr);
6003*552f7358SJed Brown   ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr);
6004*552f7358SJed Brown   for(l = 0; l < numLeaves; ++l) {
6005*552f7358SJed Brown     ranksNew[l]              = ranks[l];
6006*552f7358SJed Brown     localPointsNew[l]        = l;
6007*552f7358SJed Brown     remotePointsNew[l].index = 0;
6008*552f7358SJed Brown     remotePointsNew[l].rank  = ranksNew[l];
6009*552f7358SJed Brown   }
6010*552f7358SJed Brown   ierr = PetscFree(ranks);CHKERRQ(ierr);
6011*552f7358SJed Brown   ierr = ISCreateGeneral(((PetscObject) dm)->comm, numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr);
6012*552f7358SJed Brown   ierr = PetscSFCreate(((PetscObject) dm)->comm, sfProcess);CHKERRQ(ierr);
6013*552f7358SJed Brown   ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr);
6014*552f7358SJed Brown   ierr = PetscSFSetGraph(*sfProcess, 1, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr);
6015*552f7358SJed Brown   PetscFunctionReturn(0);
6016*552f7358SJed Brown }
6017*552f7358SJed Brown 
6018*552f7358SJed Brown #undef __FUNCT__
6019*552f7358SJed Brown #define __FUNCT__ "CellRefinerCreateSF"
6020*552f7358SJed Brown PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
6021*552f7358SJed Brown {
6022*552f7358SJed Brown   PetscSF            sf, sfNew, sfProcess;
6023*552f7358SJed Brown   IS                 processRanks;
6024*552f7358SJed Brown   MPI_Datatype       depthType;
6025*552f7358SJed Brown   PetscInt           numRoots, numLeaves, numLeavesNew = 0, l, m;
6026*552f7358SJed Brown   const PetscInt    *localPoints, *neighbors;
6027*552f7358SJed Brown   const PetscSFNode *remotePoints;
6028*552f7358SJed Brown   PetscInt          *localPointsNew;
6029*552f7358SJed Brown   PetscSFNode       *remotePointsNew;
6030*552f7358SJed Brown   PetscInt          *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew;
6031*552f7358SJed Brown   PetscInt           depth, numNeighbors, pStartNew, pEndNew, cStart, cStartNew, cEnd, vStart, vStartNew, vEnd, fStart, fStartNew, fEnd, eStart, eStartNew, eEnd, r, n;
6032*552f7358SJed Brown   PetscErrorCode     ierr;
6033*552f7358SJed Brown 
6034*552f7358SJed Brown   PetscFunctionBegin;
6035*552f7358SJed Brown   ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr);
6036*552f7358SJed Brown   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
6037*552f7358SJed Brown   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
6038*552f7358SJed Brown   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
6039*552f7358SJed Brown   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
6040*552f7358SJed Brown   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
6041*552f7358SJed Brown   ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr);
6042*552f7358SJed Brown   ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr);
6043*552f7358SJed Brown   ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr);
6044*552f7358SJed Brown   /* Caculate size of new SF */
6045*552f7358SJed Brown   ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr);
6046*552f7358SJed Brown   if (numRoots < 0) PetscFunctionReturn(0);
6047*552f7358SJed Brown   for(l = 0; l < numLeaves; ++l) {
6048*552f7358SJed Brown     const PetscInt p = localPoints[l];
6049*552f7358SJed Brown 
6050*552f7358SJed Brown     switch(refiner) {
6051*552f7358SJed Brown     case 1:
6052*552f7358SJed Brown       /* Simplicial 2D */
6053*552f7358SJed Brown       if ((p >= vStart) && (p < vEnd)) {
6054*552f7358SJed Brown         /* Old vertices stay the same */
6055*552f7358SJed Brown         ++numLeavesNew;
6056*552f7358SJed Brown       } else if ((p >= fStart) && (p < fEnd)) {
6057*552f7358SJed Brown         /* Old faces add new faces and vertex */
6058*552f7358SJed Brown         numLeavesNew += 1 + 2;
6059*552f7358SJed Brown       } else if ((p >= cStart) && (p < cEnd)) {
6060*552f7358SJed Brown         /* Old cells add new cells and interior faces */
6061*552f7358SJed Brown         numLeavesNew += 4 + 3;
6062*552f7358SJed Brown       }
6063*552f7358SJed Brown       break;
6064*552f7358SJed Brown     case 2:
6065*552f7358SJed Brown       /* Hex 2D */
6066*552f7358SJed Brown       if ((p >= vStart) && (p < vEnd)) {
6067*552f7358SJed Brown         /* Old vertices stay the same */
6068*552f7358SJed Brown         ++numLeavesNew;
6069*552f7358SJed Brown       } else if ((p >= fStart) && (p < fEnd)) {
6070*552f7358SJed Brown         /* Old faces add new faces and vertex */
6071*552f7358SJed Brown         numLeavesNew += 1 + 2;
6072*552f7358SJed Brown       } else if ((p >= cStart) && (p < cEnd)) {
6073*552f7358SJed Brown         /* Old cells add new cells and interior faces */
6074*552f7358SJed Brown         numLeavesNew += 4 + 4;
6075*552f7358SJed Brown       }
6076*552f7358SJed Brown       break;
6077*552f7358SJed Brown     default:
6078*552f7358SJed Brown       SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
6079*552f7358SJed Brown     }
6080*552f7358SJed Brown   }
6081*552f7358SJed Brown   /* Communicate depthSizes for each remote rank */
6082*552f7358SJed Brown   ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr);
6083*552f7358SJed Brown   ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr);
6084*552f7358SJed Brown   ierr = PetscMalloc5((depth+1)*numNeighbors,PetscInt,&rdepthSize,numNeighbors,PetscInt,&rvStartNew,numNeighbors,PetscInt,&reStartNew,numNeighbors,PetscInt,&rfStartNew,numNeighbors,PetscInt,&rcStartNew);CHKERRQ(ierr);
6085*552f7358SJed Brown   ierr = PetscMalloc6(depth+1,PetscInt,&depthSizeOld,(depth+1)*numNeighbors,PetscInt,&rdepthSizeOld,numNeighbors,PetscInt,&rvStart,numNeighbors,PetscInt,&reStart,numNeighbors,PetscInt,&rfStart,numNeighbors,PetscInt,&rcStart);CHKERRQ(ierr);
6086*552f7358SJed Brown   ierr = MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);CHKERRQ(ierr);
6087*552f7358SJed Brown   ierr = MPI_Type_commit(&depthType);CHKERRQ(ierr);
6088*552f7358SJed Brown   ierr = PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr);
6089*552f7358SJed Brown   ierr = PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr);
6090*552f7358SJed Brown   for(n = 0; n < numNeighbors; ++n) {
6091*552f7358SJed Brown     ierr = GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);CHKERRQ(ierr);
6092*552f7358SJed Brown   }
6093*552f7358SJed Brown   depthSizeOld[depth]   = cEnd - cStart;
6094*552f7358SJed Brown   depthSizeOld[0]       = vEnd - vStart;
6095*552f7358SJed Brown   depthSizeOld[depth-1] = fEnd - fStart;
6096*552f7358SJed Brown   depthSizeOld[1]       = eEnd - eStart;
6097*552f7358SJed Brown   ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr);
6098*552f7358SJed Brown   ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr);
6099*552f7358SJed Brown   for(n = 0; n < numNeighbors; ++n) {
6100*552f7358SJed Brown     ierr = GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);CHKERRQ(ierr);
6101*552f7358SJed Brown   }
6102*552f7358SJed Brown   ierr = MPI_Type_free(&depthType);CHKERRQ(ierr);
6103*552f7358SJed Brown   ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr);
6104*552f7358SJed Brown   /* Calculate new point SF */
6105*552f7358SJed Brown   ierr = PetscMalloc(numLeavesNew * sizeof(PetscInt),    &localPointsNew);CHKERRQ(ierr);
6106*552f7358SJed Brown   ierr = PetscMalloc(numLeavesNew * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr);
6107*552f7358SJed Brown   ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr);
6108*552f7358SJed Brown   for(l = 0, m = 0; l < numLeaves; ++l) {
6109*552f7358SJed Brown     PetscInt    p     = localPoints[l];
6110*552f7358SJed Brown     PetscInt    rp    = remotePoints[l].index, n;
6111*552f7358SJed Brown     PetscMPIInt rrank = remotePoints[l].rank;
6112*552f7358SJed Brown 
6113*552f7358SJed Brown     ierr = PetscFindInt(rrank, numNeighbors, neighbors, &n);CHKERRQ(ierr);
6114*552f7358SJed Brown     if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank);
6115*552f7358SJed Brown     switch(refiner) {
6116*552f7358SJed Brown     case 1:
6117*552f7358SJed Brown       /* Simplicial 2D */
6118*552f7358SJed Brown       if ((p >= vStart) && (p < vEnd)) {
6119*552f7358SJed Brown         /* Old vertices stay the same */
6120*552f7358SJed Brown         localPointsNew[m]        = vStartNew     + (p  - vStart);
6121*552f7358SJed Brown         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
6122*552f7358SJed Brown         remotePointsNew[m].rank  = rrank;
6123*552f7358SJed Brown         ++m;
6124*552f7358SJed Brown       } else if ((p >= fStart) && (p < fEnd)) {
6125*552f7358SJed Brown         /* Old faces add new faces and vertex */
6126*552f7358SJed Brown         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - fStart);
6127*552f7358SJed Brown         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
6128*552f7358SJed Brown         remotePointsNew[m].rank  = rrank;
6129*552f7358SJed Brown         ++m;
6130*552f7358SJed Brown         for(r = 0; r < 2; ++r, ++m) {
6131*552f7358SJed Brown           localPointsNew[m]        = fStartNew     + (p  - fStart)*2     + r;
6132*552f7358SJed Brown           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
6133*552f7358SJed Brown           remotePointsNew[m].rank  = rrank;
6134*552f7358SJed Brown         }
6135*552f7358SJed Brown       } else if ((p >= cStart) && (p < cEnd)) {
6136*552f7358SJed Brown         /* Old cells add new cells and interior faces */
6137*552f7358SJed Brown         for(r = 0; r < 4; ++r, ++m) {
6138*552f7358SJed Brown           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r;
6139*552f7358SJed Brown           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
6140*552f7358SJed Brown           remotePointsNew[m].rank  = rrank;
6141*552f7358SJed Brown         }
6142*552f7358SJed Brown         for(r = 0; r < 3; ++r, ++m) {
6143*552f7358SJed Brown           localPointsNew[m]        = fStartNew     + (fEnd - fStart)*2                    + (p  - cStart)*3     + r;
6144*552f7358SJed Brown           remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r;
6145*552f7358SJed Brown           remotePointsNew[m].rank  = rrank;
6146*552f7358SJed Brown         }
6147*552f7358SJed Brown       }
6148*552f7358SJed Brown       break;
6149*552f7358SJed Brown     case 2:
6150*552f7358SJed Brown       /* Hex 2D */
6151*552f7358SJed Brown       if ((p >= vStart) && (p < vEnd)) {
6152*552f7358SJed Brown         /* Old vertices stay the same */
6153*552f7358SJed Brown         localPointsNew[m]        = vStartNew     + (p  - vStart);
6154*552f7358SJed Brown         remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]);
6155*552f7358SJed Brown         remotePointsNew[m].rank  = rrank;
6156*552f7358SJed Brown         ++m;
6157*552f7358SJed Brown       } else if ((p >= fStart) && (p < fEnd)) {
6158*552f7358SJed Brown         /* Old faces add new faces and vertex */
6159*552f7358SJed Brown         localPointsNew[m]        = vStartNew     + (vEnd - vStart)              + (p  - fStart);
6160*552f7358SJed Brown         remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]);
6161*552f7358SJed Brown         remotePointsNew[m].rank  = rrank;
6162*552f7358SJed Brown         ++m;
6163*552f7358SJed Brown         for(r = 0; r < 2; ++r, ++m) {
6164*552f7358SJed Brown           localPointsNew[m]        = fStartNew     + (p  - fStart)*2     + r;
6165*552f7358SJed Brown           remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r;
6166*552f7358SJed Brown           remotePointsNew[m].rank  = rrank;
6167*552f7358SJed Brown         }
6168*552f7358SJed Brown       } else if ((p >= cStart) && (p < cEnd)) {
6169*552f7358SJed Brown         /* Old cells add new cells and interior faces */
6170*552f7358SJed Brown         for(r = 0; r < 4; ++r, ++m) {
6171*552f7358SJed Brown           localPointsNew[m]        = cStartNew     + (p  - cStart)*4     + r;
6172*552f7358SJed Brown           remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r;
6173*552f7358SJed Brown           remotePointsNew[m].rank  = rrank;
6174*552f7358SJed Brown         }
6175*552f7358SJed Brown         for(r = 0; r < 4; ++r, ++m) {
6176*552f7358SJed Brown           localPointsNew[m]        = fStartNew     + (fEnd - fStart)*2                    + (p  - cStart)*4     + r;
6177*552f7358SJed Brown           remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*4 + r;
6178*552f7358SJed Brown           remotePointsNew[m].rank  = rrank;
6179*552f7358SJed Brown         }
6180*552f7358SJed Brown       }
6181*552f7358SJed Brown       break;
6182*552f7358SJed Brown     default:
6183*552f7358SJed Brown       SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
6184*552f7358SJed Brown     }
6185*552f7358SJed Brown   }
6186*552f7358SJed Brown   ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr);
6187*552f7358SJed Brown   ierr = ISDestroy(&processRanks);CHKERRQ(ierr);
6188*552f7358SJed Brown   ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr);
6189*552f7358SJed Brown   ierr = PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);CHKERRQ(ierr);
6190*552f7358SJed Brown   ierr = PetscFree6(depthSizeOld,rdepthSizeOld,rvStart,reStart,rfStart,rcStart);CHKERRQ(ierr);
6191*552f7358SJed Brown   PetscFunctionReturn(0);
6192*552f7358SJed Brown }
6193*552f7358SJed Brown 
6194*552f7358SJed Brown #undef __FUNCT__
6195*552f7358SJed Brown #define __FUNCT__ "CellRefinerCreateLabels"
6196*552f7358SJed Brown PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm)
6197*552f7358SJed Brown {
6198*552f7358SJed Brown   PetscInt       numLabels, l;
6199*552f7358SJed Brown   PetscInt       newp, cStart, cEnd, vStart, vStartNew, vEnd, fStart, fStartNew, fEnd, eStart, eEnd, r;
6200*552f7358SJed Brown   PetscErrorCode ierr;
6201*552f7358SJed Brown 
6202*552f7358SJed Brown   PetscFunctionBegin;
6203*552f7358SJed Brown   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
6204*552f7358SJed Brown   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
6205*552f7358SJed Brown   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
6206*552f7358SJed Brown   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
6207*552f7358SJed Brown   vStartNew = depthSize[2];
6208*552f7358SJed Brown   fStartNew = depthSize[2] + depthSize[0];
6209*552f7358SJed Brown   ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr);
6210*552f7358SJed Brown   for(l = 0; l < numLabels; ++l) {
6211*552f7358SJed Brown     DMLabel         label, labelNew;
6212*552f7358SJed Brown     const char     *lname;
6213*552f7358SJed Brown     PetscBool       isDepth;
6214*552f7358SJed Brown     IS              valueIS;
6215*552f7358SJed Brown     const PetscInt *values;
6216*552f7358SJed Brown     PetscInt        numValues, val;
6217*552f7358SJed Brown 
6218*552f7358SJed Brown     ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr);
6219*552f7358SJed Brown     ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr);
6220*552f7358SJed Brown     if (isDepth) continue;
6221*552f7358SJed Brown     ierr = DMPlexCreateLabel(rdm, lname);CHKERRQ(ierr);
6222*552f7358SJed Brown     ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr);
6223*552f7358SJed Brown     ierr = DMPlexGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr);
6224*552f7358SJed Brown     ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr);
6225*552f7358SJed Brown     ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr);
6226*552f7358SJed Brown     ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr);
6227*552f7358SJed Brown     for(val = 0; val < numValues; ++val) {
6228*552f7358SJed Brown       IS              pointIS;
6229*552f7358SJed Brown       const PetscInt *points;
6230*552f7358SJed Brown       PetscInt        numPoints, n;
6231*552f7358SJed Brown 
6232*552f7358SJed Brown       ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr);
6233*552f7358SJed Brown       ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr);
6234*552f7358SJed Brown       ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr);
6235*552f7358SJed Brown       for(n = 0; n < numPoints; ++n) {
6236*552f7358SJed Brown         const PetscInt p = points[n];
6237*552f7358SJed Brown         switch(refiner) {
6238*552f7358SJed Brown         case 1:
6239*552f7358SJed Brown           /* Simplicial 2D */
6240*552f7358SJed Brown           if ((p >= vStart) && (p < vEnd)) {
6241*552f7358SJed Brown             /* Old vertices stay the same */
6242*552f7358SJed Brown             newp = vStartNew + (p - vStart);
6243*552f7358SJed Brown             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
6244*552f7358SJed Brown           } else if ((p >= fStart) && (p < fEnd)) {
6245*552f7358SJed Brown             /* Old faces add new faces and vertex */
6246*552f7358SJed Brown             newp = vStartNew + (vEnd - vStart) + (p - fStart);
6247*552f7358SJed Brown             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
6248*552f7358SJed Brown             for(r = 0; r < 2; ++r) {
6249*552f7358SJed Brown               newp = fStartNew + (p - fStart)*2 + r;
6250*552f7358SJed Brown               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
6251*552f7358SJed Brown             }
6252*552f7358SJed Brown           } else if ((p >= cStart) && (p < cEnd)) {
6253*552f7358SJed Brown             /* Old cells add new cells and interior faces */
6254*552f7358SJed Brown             for(r = 0; r < 4; ++r) {
6255*552f7358SJed Brown               newp = (p - cStart)*4 + r;
6256*552f7358SJed Brown               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
6257*552f7358SJed Brown             }
6258*552f7358SJed Brown             for(r = 0; r < 3; ++r) {
6259*552f7358SJed Brown               newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r;
6260*552f7358SJed Brown               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
6261*552f7358SJed Brown             }
6262*552f7358SJed Brown           }
6263*552f7358SJed Brown           break;
6264*552f7358SJed Brown         case 2:
6265*552f7358SJed Brown           /* Hex 2D */
6266*552f7358SJed Brown           if ((p >= vStart) && (p < vEnd)) {
6267*552f7358SJed Brown             /* Old vertices stay the same */
6268*552f7358SJed Brown             newp = vStartNew + (p - vStart);
6269*552f7358SJed Brown             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
6270*552f7358SJed Brown           } else if ((p >= fStart) && (p < fEnd)) {
6271*552f7358SJed Brown             /* Old faces add new faces and vertex */
6272*552f7358SJed Brown             newp = vStartNew + (vEnd - vStart) + (p - fStart);
6273*552f7358SJed Brown             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
6274*552f7358SJed Brown             for(r = 0; r < 2; ++r) {
6275*552f7358SJed Brown               newp = fStartNew + (p - fStart)*2 + r;
6276*552f7358SJed Brown               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
6277*552f7358SJed Brown             }
6278*552f7358SJed Brown           } else if ((p >= cStart) && (p < cEnd)) {
6279*552f7358SJed Brown             /* Old cells add new cells and interior faces and vertex */
6280*552f7358SJed Brown             for(r = 0; r < 4; ++r) {
6281*552f7358SJed Brown               newp = (p - cStart)*4 + r;
6282*552f7358SJed Brown               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
6283*552f7358SJed Brown             }
6284*552f7358SJed Brown             for(r = 0; r < 4; ++r) {
6285*552f7358SJed Brown               newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r;
6286*552f7358SJed Brown               ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
6287*552f7358SJed Brown             }
6288*552f7358SJed Brown             newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart);
6289*552f7358SJed Brown             ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr);
6290*552f7358SJed Brown           }
6291*552f7358SJed Brown           break;
6292*552f7358SJed Brown         default:
6293*552f7358SJed Brown           SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner);
6294*552f7358SJed Brown         }
6295*552f7358SJed Brown       }
6296*552f7358SJed Brown       ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr);
6297*552f7358SJed Brown       ierr = ISDestroy(&pointIS);CHKERRQ(ierr);
6298*552f7358SJed Brown     }
6299*552f7358SJed Brown     ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr);
6300*552f7358SJed Brown     ierr = ISDestroy(&valueIS);CHKERRQ(ierr);
6301*552f7358SJed Brown     if (0) {
6302*552f7358SJed Brown       ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr);
6303*552f7358SJed Brown       ierr = DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
6304*552f7358SJed Brown       ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
6305*552f7358SJed Brown     }
6306*552f7358SJed Brown   }
6307*552f7358SJed Brown   PetscFunctionReturn(0);
6308*552f7358SJed Brown }
6309*552f7358SJed Brown 
6310*552f7358SJed Brown #undef __FUNCT__
6311*552f7358SJed Brown #define __FUNCT__ "DMPlexRefine_Uniform"
6312*552f7358SJed Brown /* This will only work for interpolated meshes */
6313*552f7358SJed Brown PetscErrorCode DMPlexRefine_Uniform(DM dm, CellRefiner cellRefiner, DM *dmRefined)
6314*552f7358SJed Brown {
6315*552f7358SJed Brown   DM              rdm;
6316*552f7358SJed Brown   PetscInt       *depthSize;
6317*552f7358SJed Brown   PetscInt        dim, depth = 0, d, pStart = 0, pEnd = 0;
6318*552f7358SJed Brown   PetscErrorCode  ierr;
6319*552f7358SJed Brown 
6320*552f7358SJed Brown   PetscFunctionBegin;
6321*552f7358SJed Brown   ierr = DMCreate(((PetscObject) dm)->comm, &rdm);CHKERRQ(ierr);
6322*552f7358SJed Brown   ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr);
6323*552f7358SJed Brown   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
6324*552f7358SJed Brown   ierr = DMPlexSetDimension(rdm, dim);CHKERRQ(ierr);
6325*552f7358SJed Brown   /* Calculate number of new points of each depth */
6326*552f7358SJed Brown   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
6327*552f7358SJed Brown   ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthSize);CHKERRQ(ierr);
6328*552f7358SJed Brown   ierr = PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr);
6329*552f7358SJed Brown   ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr);
6330*552f7358SJed Brown   /* Step 1: Set chart */
6331*552f7358SJed Brown   for(d = 0; d <= depth; ++d) {
6332*552f7358SJed Brown     pEnd += depthSize[d];
6333*552f7358SJed Brown   }
6334*552f7358SJed Brown   ierr = DMPlexSetChart(rdm, pStart, pEnd);CHKERRQ(ierr);
6335*552f7358SJed Brown   /* Step 2: Set cone/support sizes */
6336*552f7358SJed Brown   ierr = CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
6337*552f7358SJed Brown   /* Step 3: Setup refined DM */
6338*552f7358SJed Brown   ierr = DMSetUp(rdm);CHKERRQ(ierr);
6339*552f7358SJed Brown   /* Step 4: Set cones and supports */
6340*552f7358SJed Brown   ierr = CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
6341*552f7358SJed Brown   /* Step 5: Stratify */
6342*552f7358SJed Brown   ierr = DMPlexStratify(rdm);CHKERRQ(ierr);
6343*552f7358SJed Brown   /* Step 6: Set coordinates for vertices */
6344*552f7358SJed Brown   ierr = CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
6345*552f7358SJed Brown   /* Step 7: Create pointSF */
6346*552f7358SJed Brown   ierr = CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
6347*552f7358SJed Brown   /* Step 8: Create labels */
6348*552f7358SJed Brown   ierr = CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr);
6349*552f7358SJed Brown   ierr = PetscFree(depthSize);CHKERRQ(ierr);
6350*552f7358SJed Brown 
6351*552f7358SJed Brown   *dmRefined = rdm;
6352*552f7358SJed Brown #if 0
6353*552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *) dm->data;
6354*552f7358SJed Brown   PetscInt    dim, cStart, cEnd, cMax, c, vStart, vEnd, vMax;
6355*552f7358SJed Brown   //ALE::ISieveVisitor::PointRetriever<mesh_type::sieve_type> cV(std::max(1, sieve->getMaxConeSize()));
6356*552f7358SJed Brown 
6357*552f7358SJed Brown   PetscFunctionBegin;
6358*552f7358SJed Brown   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
6359*552f7358SJed Brown   /* PyLith: _refineCensored(newMesh, mesh, refiner); */
6360*552f7358SJed Brown   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
6361*552f7358SJed Brown   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
6362*552f7358SJed Brown   ierr = DMPlexGetVTKBounds(dm, &cMax, &vMax);CHKERRQ(ierr);
6363*552f7358SJed Brown 
6364*552f7358SJed Brown   /* Count number of new cells which are normal and extra */
6365*552f7358SJed Brown   PetscInt cEnd2 = cMax >= 0 ? cMax : cEnd;
6366*552f7358SJed Brown   PetscInt newNumCellsNormal = 0, newNumCellsExtra = 0, newNumCells;
6367*552f7358SJed Brown   for(c = cStart; c < cEnd2; ++c) {
6368*552f7358SJed Brown     PetscInt n;
6369*552f7358SJed Brown     ierr = CellRefinerGetNumSubcells(c, &n);CHKERRQ(ierr); // refiner.numNewCells
6370*552f7358SJed Brown     newNumCellsNormal += n;
6371*552f7358SJed Brown   }
6372*552f7358SJed Brown   for(c = cEnd2; c < cEnd; ++c) {
6373*552f7358SJed Brown     PetscInt n;
6374*552f7358SJed Brown     ierr = CellRefinerGetNumSubcells(c, &n);CHKERRQ(ierr); // refiner.numNewCells
6375*552f7358SJed Brown     newNumCellsExtra += n;
6376*552f7358SJed Brown   }
6377*552f7358SJed Brown   newNumCells = newNumCellsNormal + newNumCellsExtra;
6378*552f7358SJed Brown   /* Count number of new vertices which are normal and extra */
6379*552f7358SJed Brown   PetscInt vEnd2 = vMax >= 0 ? vMax : vEnd;
6380*552f7358SJed Brown   PetscInt newNumVertices, newNumVerticesNormal, newNumVerticesExtra, newFirstVertex = newNumCells + (vEnd2 - vStart), newVertex = newFirstVertex;
6381*552f7358SJed Brown   for(c = cStart; c < cEnd; ++c) {
6382*552f7358SJed Brown     PetscInt *closure = PETSC_NULL;
6383*552f7358SJed Brown     PetscInt  closureSize, numCorners = 0, p;
6384*552f7358SJed Brown 
6385*552f7358SJed Brown     ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
6386*552f7358SJed Brown     for(p = 0; p < closureSize*2; p += 2) {
6387*552f7358SJed Brown       const PetscInt point = closure[p];
6388*552f7358SJed Brown       if ((point >= vStart) && (point < vEnd)) {
6389*552f7358SJed Brown         closure[numCorners++] = point;
6390*552f7358SJed Brown       }
6391*552f7358SJed Brown     }
6392*552f7358SJed Brown     ierr = CellRefinerSplitCell(c, closure, numCorners, &newVertex);CHKERRQ(ierr); // refiner.splitCell
6393*552f7358SJed Brown     ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
6394*552f7358SJed Brown   }
6395*552f7358SJed Brown   newNumVerticesNormal = newVertex - newFirstVertex + (vEnd2 - vStart);
6396*552f7358SJed Brown   for(c = cEnd2; c < cEnd; ++c) {
6397*552f7358SJed Brown     PetscInt *closure = PETSC_NULL;
6398*552f7358SJed Brown     PetscInt  closureSize, numCorners = 0, p;
6399*552f7358SJed Brown 
6400*552f7358SJed Brown     ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
6401*552f7358SJed Brown     for(p = 0; p < closureSize*2; p += 2) {
6402*552f7358SJed Brown       const PetscInt point = closure[p];
6403*552f7358SJed Brown       if ((point >= vStart) && (point < vEnd)) {
6404*552f7358SJed Brown         closure[numCorners++] = point;
6405*552f7358SJed Brown       }
6406*552f7358SJed Brown     }
6407*552f7358SJed Brown     ierr = CellRefinerSplitCellExtra(c, closure, numCorners, &newVertex);CHKERRQ(ierr); // refiner.splitCellUncensored
6408*552f7358SJed Brown     ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
6409*552f7358SJed Brown   } // for
6410*552f7358SJed Brown   newNumVerticesExtra = newVertex - newFirstVertex - newNumVerticesNormal;
6411*552f7358SJed Brown   newNumVertices = newNumVerticesNormal + newNumVerticesExtra;
6412*552f7358SJed Brown 
6413*552f7358SJed Brown #if 1
6414*552f7358SJed Brown   PetscInt oldNumCellsNormal   = cEnd2 - cStart;
6415*552f7358SJed Brown   PetscInt oldNumCellsExtra = cEnd  - cEnd2;
6416*552f7358SJed Brown   ierr = PetscSynchronizedPrintf(comm, "[%d]Old normal cells    [%d, %d)\n", rank, 0, oldNumCellsNormal);
6417*552f7358SJed Brown   ierr = PetscSynchronizedPrintf(comm, "[%d]Old fault  cells    [%d, %d)\n", rank, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra+oldNumCellsExtra);
6418*552f7358SJed Brown   ierr = PetscSynchronizedPrintf(comm, "[%d]Old normal vertices [%d, %d)\n", rank, oldNumCellsNormal, oldNumCellsNormal+oldNumVerticesNormal);
6419*552f7358SJed Brown   ierr = PetscSynchronizedPrintf(comm, "[%d]Old fault  vertices [%d, %d)\n", rank, oldNumCellsNormal+oldNumVerticesNormal, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra);
6420*552f7358SJed Brown   ierr = PetscSynchronizedPrintf(comm, "[%d]New normal cells    [%d, %d)\n", rank, 0, newNumCellsNormal);
6421*552f7358SJed Brown   ierr = PetscSynchronizedPrintf(comm, "[%d]New fault  cells    [%d, %d)\n", rank, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra+newNumCellsExtra);
6422*552f7358SJed Brown   ierr = PetscSynchronizedPrintf(comm, "[%d]New normal vertices [%d, %d)\n", rank, newNumCellsNormal, newNumCellsNormal+newNumVerticesNormal);
6423*552f7358SJed Brown   ierr = PetscSynchronizedPrintf(comm, "[%d]New fault  vertices [%d, %d)\n", rank, newNumCellsNormal+newNumVerticesNormal, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra);
6424*552f7358SJed Brown   ierr = PetscSynchronizedFlush(comm);
6425*552f7358SJed Brown #endif
6426*552f7358SJed Brown 
6427*552f7358SJed Brown   ierr = DMCreate(comm, dmRefined);CHKERRQ(ierr);
6428*552f7358SJed Brown   ierr = DMSetType(*dmRefined, DMPLEX);CHKERRQ(ierr);
6429*552f7358SJed Brown   ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr);
6430*552f7358SJed Brown   ierr = DMPlexSetChart(*dmRefined, 0, newNumCells+newNumVertices);CHKERRQ(ierr);
6431*552f7358SJed Brown   ierr = DMPlexGetVTKBounds(*dmRefined, newNumCellsNormal, newFirstVertex+newNumVerticesNormal);CHKERRQ(ierr);
6432*552f7358SJed Brown   /* Set cone and support sizes for new normal cells */
6433*552f7358SJed Brown   PetscInt newCell = 0;
6434*552f7358SJed Brown   for(c = cStart; c < cEnd2; ++c) {
6435*552f7358SJed Brown     PetscInt coneSize, n, i;
6436*552f7358SJed Brown 
6437*552f7358SJed Brown     ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr);
6438*552f7358SJed Brown     ierr = CellRefinerGetNumSubcells(refiner, c, &n); // refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh);
6439*552f7358SJed Brown     for(i = 0; i < n; ++i, ++newCell) {
6440*552f7358SJed Brown       ierr = DMPlexSetConeSize(*dmRefined, newCell, coneSize);CHKERRQ(ierr);
6441*552f7358SJed Brown     }
6442*552f7358SJed Brown 
6443*552f7358SJed Brown     PetscInt *closure = PETSC_NULL;
6444*552f7358SJed Brown     PetscInt  closureSize, numCorners = 0, p;
6445*552f7358SJed Brown 
6446*552f7358SJed Brown     ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
6447*552f7358SJed Brown     for(p = 0; p < closureSize*2; p += 2) {
6448*552f7358SJed Brown       const PetscInt point = closure[p];
6449*552f7358SJed Brown       if ((point >= vStart) && (point < vEnd)) {
6450*552f7358SJed Brown         closure[numCorners++] = point;
6451*552f7358SJed Brown       }
6452*552f7358SJed Brown     }
6453*552f7358SJed Brown     // ierr = CellRefinerGetSubcells(refiner, c, numCorners, closure, &numNewCells, &newCells);CHKERRQ(ierr); // refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh);
6454*552f7358SJed Brown     ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
6455*552f7358SJed Brown   }
6456*552f7358SJed Brown 
6457*552f7358SJed Brown   // Reset current new cell value and loop over censored cells.
6458*552f7358SJed Brown   curNewCell = _orderNewMesh->cellsCensored().min();
6459*552f7358SJed Brown   oldCellsEnd = _orderOldMesh->cellsCensored().end();
6460*552f7358SJed Brown   for (interval_type::const_iterator c_iter=_orderOldMesh->cellsCensored().begin(); c_iter != oldCellsEnd; ++c_iter) {
6461*552f7358SJed Brown     // Set new cone and support sizes
6462*552f7358SJed Brown     cV.clear();
6463*552f7358SJed Brown     sieve->cone(*c_iter, cV);
6464*552f7358SJed Brown     const point_type* cone = cV.getPoints();
6465*552f7358SJed Brown     const int coneSize = cV.getSize();
6466*552f7358SJed Brown 
6467*552f7358SJed Brown     const point_type* newCells;
6468*552f7358SJed Brown     int numNewCells = 0;
6469*552f7358SJed Brown     refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh);
6470*552f7358SJed Brown 
6471*552f7358SJed Brown     for(int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) {
6472*552f7358SJed Brown       newSieve->setConeSize(curNewCell, coneSize);
6473*552f7358SJed Brown       for(int iVertex=0; iVertex < coneSize; ++iVertex) {
6474*552f7358SJed Brown 	newSieve->addSupportSize(newCells[iCell*coneSize+iVertex], 1);
6475*552f7358SJed Brown       } // for
6476*552f7358SJed Brown     } // for
6477*552f7358SJed Brown   } // for
6478*552f7358SJed Brown   newSieve->allocate();
6479*552f7358SJed Brown 
6480*552f7358SJed Brown   ierr = DMPlexSymmetrizeSizes();CHKERRQ(ierr);
6481*552f7358SJed Brown 
6482*552f7358SJed Brown   // Create refined cells in new sieve.
6483*552f7358SJed Brown   curNewCell = _orderNewMesh->cellsNormal().min();
6484*552f7358SJed Brown   oldCellsEnd = _orderOldMesh->cellsNormal().end();
6485*552f7358SJed Brown   for (interval_type::const_iterator c_iter=_orderOldMesh->cellsNormal().begin(); c_iter != oldCellsEnd; ++c_iter) {
6486*552f7358SJed Brown     cV.clear();
6487*552f7358SJed Brown     sieve->cone(*c_iter, cV);
6488*552f7358SJed Brown     const point_type *cone = cV.getPoints();
6489*552f7358SJed Brown     const int coneSize = cV.getSize();
6490*552f7358SJed Brown 
6491*552f7358SJed Brown     const point_type* newCells;
6492*552f7358SJed Brown     int numNewCells = 0;
6493*552f7358SJed Brown     refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh);
6494*552f7358SJed Brown 
6495*552f7358SJed Brown     for(int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) {
6496*552f7358SJed Brown       newSieve->setCone(&newCells[iCell*coneSize], curNewCell);
6497*552f7358SJed Brown     } // for
6498*552f7358SJed Brown   } // for
6499*552f7358SJed Brown   curNewCell = _orderNewMesh->cellsCensored().min();
6500*552f7358SJed Brown   oldCellsEnd = _orderOldMesh->cellsCensored().end();
6501*552f7358SJed Brown   for (interval_type::const_iterator c_iter=_orderOldMesh->cellsCensored().begin(); c_iter != oldCellsEnd; ++c_iter) {
6502*552f7358SJed Brown     cV.clear();
6503*552f7358SJed Brown     sieve->cone(*c_iter, cV);
6504*552f7358SJed Brown     const point_type *cone = cV.getPoints();
6505*552f7358SJed Brown     const int coneSize = cV.getSize();
6506*552f7358SJed Brown 
6507*552f7358SJed Brown     const point_type* newCells;
6508*552f7358SJed Brown     int numNewCells = 0;
6509*552f7358SJed Brown     refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh);
6510*552f7358SJed Brown 
6511*552f7358SJed Brown     for(int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) {
6512*552f7358SJed Brown       newSieve->setCone(&newCells[iCell*coneSize], curNewCell);
6513*552f7358SJed Brown     } // for
6514*552f7358SJed Brown   } // for
6515*552f7358SJed Brown   newSieve->symmetrize();
6516*552f7358SJed Brown 
6517*552f7358SJed Brown   // Set coordinates in refined mesh.
6518*552f7358SJed Brown   const Obj<mesh_type::real_section_type>& coordinates = mesh->getRealSection("coordinates");
6519*552f7358SJed Brown   assert(!coordinates.isNull());
6520*552f7358SJed Brown   const Obj<mesh_type::real_section_type>& newCoordinates = newMesh->getRealSection("coordinates");
6521*552f7358SJed Brown   assert(!newCoordinates.isNull());
6522*552f7358SJed Brown 
6523*552f7358SJed Brown   const mesh_type::label_sequence::const_iterator verticesEnd = vertices->end();
6524*552f7358SJed Brown   assert(vertices->size() > 0);
6525*552f7358SJed Brown   const int spaceDim = coordinates->getFiberDimension(*vertices->begin());
6526*552f7358SJed Brown   assert(spaceDim > 0);
6527*552f7358SJed Brown   newCoordinates->setChart(mesh_type::sieve_type::chart_type(_orderNewMesh->verticesNormal().min(), _orderNewMesh->verticesCensored().max()));
6528*552f7358SJed Brown 
6529*552f7358SJed Brown   const interval_type::const_iterator newVerticesEnd = _orderNewMesh->verticesCensored().end();
6530*552f7358SJed Brown   for (interval_type::const_iterator v_iter=_orderNewMesh->verticesNormal().begin(); v_iter != newVerticesEnd; ++v_iter) {
6531*552f7358SJed Brown     newCoordinates->setFiberDimension(*v_iter, spaceDim);
6532*552f7358SJed Brown   } // for
6533*552f7358SJed Brown   newCoordinates->allocatePoint();
6534*552f7358SJed Brown 
6535*552f7358SJed Brown   interval_type::const_iterator oldVerticesEnd = _orderOldMesh->verticesNormal().end();
6536*552f7358SJed Brown   for (interval_type::const_iterator vOld_iter=_orderOldMesh->verticesNormal().begin(), vNew_iter=_orderNewMesh->verticesNormal().begin(); vOld_iter != oldVerticesEnd; ++vOld_iter, ++vNew_iter) {
6537*552f7358SJed Brown     //std::cout << "Copy coordinates from old vertex " << *vOld_iter << " to new vertex " << *vNew_iter << std::endl;
6538*552f7358SJed Brown     newCoordinates->updatePoint(*vNew_iter, coordinates->restrictPoint(*vOld_iter));
6539*552f7358SJed Brown   } // for
6540*552f7358SJed Brown   oldVerticesEnd = _orderOldMesh->verticesCensored().end();
6541*552f7358SJed Brown   for (interval_type::const_iterator vOld_iter=_orderOldMesh->verticesCensored().begin(), vNew_iter=_orderNewMesh->verticesCensored().begin(); vOld_iter != oldVerticesEnd; ++vOld_iter, ++vNew_iter) {
6542*552f7358SJed Brown     //std::cout << "Copy coordinates from old vertex " << *vOld_iter << " to new vertex " << *vNew_iter << std::endl;
6543*552f7358SJed Brown     newCoordinates->updatePoint(*vNew_iter, coordinates->restrictPoint(*vOld_iter));
6544*552f7358SJed Brown   } // for
6545*552f7358SJed Brown 
6546*552f7358SJed Brown   refiner.setCoordsNewVertices(newCoordinates, coordinates);
6547*552f7358SJed Brown 
6548*552f7358SJed Brown   // Create sensored depth
6549*552f7358SJed Brown   const ALE::Obj<SieveFlexMesh::label_type>& censoredLabel = newMesh->createLabel("censored depth");
6550*552f7358SJed Brown   assert(!censoredLabel.isNull());
6551*552f7358SJed Brown 
6552*552f7358SJed Brown   mesh_type::DepthVisitor depthVisitor(*newSieve, _orderNewMesh->verticesCensored().min(), *censoredLabel);
6553*552f7358SJed Brown 
6554*552f7358SJed Brown   newSieve->roots(depthVisitor);
6555*552f7358SJed Brown   while(depthVisitor.isModified()) {
6556*552f7358SJed Brown     // FIX: Avoid the copy here somehow by fixing the traversal
6557*552f7358SJed Brown     std::vector<mesh_type::point_type> modifiedPoints(depthVisitor.getModifiedPoints().begin(), depthVisitor.getModifiedPoints().end());
6558*552f7358SJed Brown 
6559*552f7358SJed Brown     depthVisitor.clear();
6560*552f7358SJed Brown     newSieve->support(modifiedPoints, depthVisitor);
6561*552f7358SJed Brown   } // while
6562*552f7358SJed Brown   // Stratify refined mesh
6563*552f7358SJed Brown   // Calculate new point SF
6564*552f7358SJed Brown   _calcNewOverlap(newMesh, mesh, refiner);
6565*552f7358SJed Brown   // Calculate new labels
6566*552f7358SJed Brown   _createLabels(newMesh, mesh, refiner);
6567*552f7358SJed Brown #endif
6568*552f7358SJed Brown   PetscFunctionReturn(0);
6569*552f7358SJed Brown }
6570*552f7358SJed Brown 
6571*552f7358SJed Brown #undef __FUNCT__
6572*552f7358SJed Brown #define __FUNCT__ "DMPlexSetRefinementUniform"
6573*552f7358SJed Brown PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform)
6574*552f7358SJed Brown {
6575*552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *) dm->data;
6576*552f7358SJed Brown 
6577*552f7358SJed Brown   PetscFunctionBegin;
6578*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6579*552f7358SJed Brown   mesh->refinementUniform = refinementUniform;
6580*552f7358SJed Brown   PetscFunctionReturn(0);
6581*552f7358SJed Brown }
6582*552f7358SJed Brown 
6583*552f7358SJed Brown #undef __FUNCT__
6584*552f7358SJed Brown #define __FUNCT__ "DMPlexGetRefinementUniform"
6585*552f7358SJed Brown PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform)
6586*552f7358SJed Brown {
6587*552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *) dm->data;
6588*552f7358SJed Brown 
6589*552f7358SJed Brown   PetscFunctionBegin;
6590*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6591*552f7358SJed Brown   PetscValidPointer(refinementUniform,  2);
6592*552f7358SJed Brown   *refinementUniform = mesh->refinementUniform;
6593*552f7358SJed Brown   PetscFunctionReturn(0);
6594*552f7358SJed Brown }
6595*552f7358SJed Brown 
6596*552f7358SJed Brown #undef __FUNCT__
6597*552f7358SJed Brown #define __FUNCT__ "DMPlexSetRefinementLimit"
6598*552f7358SJed Brown PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit)
6599*552f7358SJed Brown {
6600*552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *) dm->data;
6601*552f7358SJed Brown 
6602*552f7358SJed Brown   PetscFunctionBegin;
6603*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6604*552f7358SJed Brown   mesh->refinementLimit = refinementLimit;
6605*552f7358SJed Brown   PetscFunctionReturn(0);
6606*552f7358SJed Brown }
6607*552f7358SJed Brown 
6608*552f7358SJed Brown #undef __FUNCT__
6609*552f7358SJed Brown #define __FUNCT__ "DMPlexGetRefinementLimit"
6610*552f7358SJed Brown PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit)
6611*552f7358SJed Brown {
6612*552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *) dm->data;
6613*552f7358SJed Brown 
6614*552f7358SJed Brown   PetscFunctionBegin;
6615*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6616*552f7358SJed Brown   PetscValidPointer(refinementLimit,  2);
6617*552f7358SJed Brown   /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */
6618*552f7358SJed Brown   *refinementLimit = mesh->refinementLimit;
6619*552f7358SJed Brown   PetscFunctionReturn(0);
6620*552f7358SJed Brown }
6621*552f7358SJed Brown 
6622*552f7358SJed Brown #undef __FUNCT__
6623*552f7358SJed Brown #define __FUNCT__ "DMPlexGetCellRefiner_Private"
6624*552f7358SJed Brown PetscErrorCode DMPlexGetCellRefiner_Private(DM dm, CellRefiner *cellRefiner)
6625*552f7358SJed Brown {
6626*552f7358SJed Brown   PetscInt       dim, cStart, coneSize;
6627*552f7358SJed Brown   PetscErrorCode ierr;
6628*552f7358SJed Brown 
6629*552f7358SJed Brown   PetscFunctionBegin;
6630*552f7358SJed Brown   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
6631*552f7358SJed Brown   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, PETSC_NULL);CHKERRQ(ierr);
6632*552f7358SJed Brown   ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr);
6633*552f7358SJed Brown   switch(dim) {
6634*552f7358SJed Brown   case 2:
6635*552f7358SJed Brown     switch(coneSize) {
6636*552f7358SJed Brown     case 3:
6637*552f7358SJed Brown       *cellRefiner = 1;break;
6638*552f7358SJed Brown     case 4:
6639*552f7358SJed Brown       *cellRefiner = 2;break;
6640*552f7358SJed Brown     default:
6641*552f7358SJed Brown       SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim);
6642*552f7358SJed Brown     }
6643*552f7358SJed Brown     break;
6644*552f7358SJed Brown   default:
6645*552f7358SJed Brown     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim);
6646*552f7358SJed Brown   }
6647*552f7358SJed Brown   PetscFunctionReturn(0);
6648*552f7358SJed Brown }
6649*552f7358SJed Brown 
6650*552f7358SJed Brown #undef __FUNCT__
6651*552f7358SJed Brown #define __FUNCT__ "DMRefine_Plex"
6652*552f7358SJed Brown PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined)
6653*552f7358SJed Brown {
6654*552f7358SJed Brown   PetscReal      refinementLimit;
6655*552f7358SJed Brown   PetscInt       dim, cStart, cEnd;
6656*552f7358SJed Brown   char           genname[1024], *name = PETSC_NULL;
6657*552f7358SJed Brown   PetscBool      isUniform, isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg;
6658*552f7358SJed Brown   PetscErrorCode ierr;
6659*552f7358SJed Brown 
6660*552f7358SJed Brown   PetscFunctionBegin;
6661*552f7358SJed Brown   ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr);
6662*552f7358SJed Brown   if (isUniform) {
6663*552f7358SJed Brown     CellRefiner cellRefiner;
6664*552f7358SJed Brown 
6665*552f7358SJed Brown     ierr = DMPlexGetCellRefiner_Private(dm, &cellRefiner);CHKERRQ(ierr);
6666*552f7358SJed Brown     ierr = DMPlexRefine_Uniform(dm, cellRefiner, dmRefined);CHKERRQ(ierr);
6667*552f7358SJed Brown     PetscFunctionReturn(0);
6668*552f7358SJed Brown   }
6669*552f7358SJed Brown   ierr = DMPlexGetRefinementLimit(dm, &refinementLimit);CHKERRQ(ierr);
6670*552f7358SJed Brown   if (refinementLimit == 0.0) PetscFunctionReturn(0);
6671*552f7358SJed Brown   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
6672*552f7358SJed Brown   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
6673*552f7358SJed Brown   ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr);
6674*552f7358SJed Brown   if (flg) {name = genname;}
6675*552f7358SJed Brown   if (name) {
6676*552f7358SJed Brown     ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr);
6677*552f7358SJed Brown     ierr = PetscStrcmp(name, "tetgen",   &isTetgen);CHKERRQ(ierr);
6678*552f7358SJed Brown     ierr = PetscStrcmp(name, "ctetgen",  &isCTetgen);CHKERRQ(ierr);
6679*552f7358SJed Brown   }
6680*552f7358SJed Brown   switch(dim) {
6681*552f7358SJed Brown   case 2:
6682*552f7358SJed Brown     if (!name || isTriangle) {
6683*552f7358SJed Brown #ifdef PETSC_HAVE_TRIANGLE
6684*552f7358SJed Brown       double  *maxVolumes;
6685*552f7358SJed Brown       PetscInt c;
6686*552f7358SJed Brown 
6687*552f7358SJed Brown       ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr);
6688*552f7358SJed Brown       for (c = 0; c < cEnd-cStart; ++c) {
6689*552f7358SJed Brown         maxVolumes[c] = refinementLimit;
6690*552f7358SJed Brown       }
6691*552f7358SJed Brown       ierr = DMPlexRefine_Triangle(dm, maxVolumes, dmRefined);CHKERRQ(ierr);
6692*552f7358SJed Brown #else
6693*552f7358SJed Brown       SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Mesh refinement needs external package support.\nPlease reconfigure with --download-triangle.");
6694*552f7358SJed Brown #endif
6695*552f7358SJed Brown     } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name);
6696*552f7358SJed Brown     break;
6697*552f7358SJed Brown   case 3:
6698*552f7358SJed Brown     if (!name || isCTetgen) {
6699*552f7358SJed Brown #ifdef PETSC_HAVE_CTETGEN
6700*552f7358SJed Brown       PetscReal *maxVolumes;
6701*552f7358SJed Brown       PetscInt   c;
6702*552f7358SJed Brown 
6703*552f7358SJed Brown       ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscReal), &maxVolumes);CHKERRQ(ierr);
6704*552f7358SJed Brown       for (c = 0; c < cEnd-cStart; ++c) {
6705*552f7358SJed Brown         maxVolumes[c] = refinementLimit;
6706*552f7358SJed Brown       }
6707*552f7358SJed Brown       ierr = DMPlexRefine_CTetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr);
6708*552f7358SJed Brown #else
6709*552f7358SJed Brown       SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen.");
6710*552f7358SJed Brown #endif
6711*552f7358SJed Brown     } else if (isTetgen) {
6712*552f7358SJed Brown #ifdef PETSC_HAVE_TETGEN
6713*552f7358SJed Brown       double  *maxVolumes;
6714*552f7358SJed Brown       PetscInt c;
6715*552f7358SJed Brown 
6716*552f7358SJed Brown       ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr);
6717*552f7358SJed Brown       for (c = 0; c < cEnd-cStart; ++c) {
6718*552f7358SJed Brown         maxVolumes[c] = refinementLimit;
6719*552f7358SJed Brown       }
6720*552f7358SJed Brown       ierr = DMPlexRefine_Tetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr);
6721*552f7358SJed Brown #else
6722*552f7358SJed Brown       SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen.");
6723*552f7358SJed Brown #endif
6724*552f7358SJed Brown     } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name);
6725*552f7358SJed Brown     break;
6726*552f7358SJed Brown   default:
6727*552f7358SJed Brown     SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Mesh refinement in dimension %d is not supported.", dim);
6728*552f7358SJed Brown   }
6729*552f7358SJed Brown   PetscFunctionReturn(0);
6730*552f7358SJed Brown }
6731*552f7358SJed Brown 
6732*552f7358SJed Brown #undef __FUNCT__
6733*552f7358SJed Brown #define __FUNCT__ "DMPlexGetDepth"
6734*552f7358SJed Brown /*@
6735*552f7358SJed Brown   DMPlexGetDepth - get the number of strata
6736*552f7358SJed Brown 
6737*552f7358SJed Brown   Not Collective
6738*552f7358SJed Brown 
6739*552f7358SJed Brown   Input Parameters:
6740*552f7358SJed Brown . dm           - The DMPlex object
6741*552f7358SJed Brown 
6742*552f7358SJed Brown   Output Parameters:
6743*552f7358SJed Brown . depth - number of strata
6744*552f7358SJed Brown 
6745*552f7358SJed Brown   Level: developer
6746*552f7358SJed Brown 
6747*552f7358SJed Brown   Notes:
6748*552f7358SJed Brown   DMPlexGetHeightStratum(dm,0,..) should return the same points as DMPlexGetDepthStratum(dm,depth,..).
6749*552f7358SJed Brown 
6750*552f7358SJed Brown .keywords: mesh, points
6751*552f7358SJed Brown .seealso: DMPlexGetHeightStratum(), DMPlexGetDepthStratum()
6752*552f7358SJed Brown @*/
6753*552f7358SJed Brown PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth)
6754*552f7358SJed Brown {
6755*552f7358SJed Brown   PetscInt       d;
6756*552f7358SJed Brown   PetscErrorCode ierr;
6757*552f7358SJed Brown 
6758*552f7358SJed Brown   PetscFunctionBegin;
6759*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6760*552f7358SJed Brown   PetscValidPointer(depth, 2);
6761*552f7358SJed Brown   ierr = DMPlexGetLabelSize(dm, "depth", &d);CHKERRQ(ierr);
6762*552f7358SJed Brown   *depth = d-1;
6763*552f7358SJed Brown   PetscFunctionReturn(0);
6764*552f7358SJed Brown }
6765*552f7358SJed Brown 
6766*552f7358SJed Brown #undef __FUNCT__
6767*552f7358SJed Brown #define __FUNCT__ "DMPlexGetDepthStratum"
6768*552f7358SJed Brown /*@
6769*552f7358SJed Brown   DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth.
6770*552f7358SJed Brown 
6771*552f7358SJed Brown   Not Collective
6772*552f7358SJed Brown 
6773*552f7358SJed Brown   Input Parameters:
6774*552f7358SJed Brown + dm           - The DMPlex object
6775*552f7358SJed Brown - stratumValue - The requested depth
6776*552f7358SJed Brown 
6777*552f7358SJed Brown   Output Parameters:
6778*552f7358SJed Brown + start - The first point at this depth
6779*552f7358SJed Brown - end   - One beyond the last point at this depth
6780*552f7358SJed Brown 
6781*552f7358SJed Brown   Level: developer
6782*552f7358SJed Brown 
6783*552f7358SJed Brown .keywords: mesh, points
6784*552f7358SJed Brown .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth()
6785*552f7358SJed Brown @*/
6786*552f7358SJed Brown PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) {
6787*552f7358SJed Brown   DM_Plex    *mesh = (DM_Plex *) dm->data;
6788*552f7358SJed Brown   DMLabel        next = mesh->labels;
6789*552f7358SJed Brown   PetscBool      flg  = PETSC_FALSE;
6790*552f7358SJed Brown   PetscInt       depth;
6791*552f7358SJed Brown   PetscErrorCode ierr;
6792*552f7358SJed Brown 
6793*552f7358SJed Brown   PetscFunctionBegin;
6794*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6795*552f7358SJed Brown   if (stratumValue < 0) {
6796*552f7358SJed Brown     ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr);
6797*552f7358SJed Brown     PetscFunctionReturn(0);
6798*552f7358SJed Brown   } else {
6799*552f7358SJed Brown     PetscInt pStart, pEnd;
6800*552f7358SJed Brown 
6801*552f7358SJed Brown     if (start) {*start = 0;}
6802*552f7358SJed Brown     if (end)   {*end   = 0;}
6803*552f7358SJed Brown     ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
6804*552f7358SJed Brown     if (pStart == pEnd) {PetscFunctionReturn(0);}
6805*552f7358SJed Brown   }
6806*552f7358SJed Brown   ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr);
6807*552f7358SJed Brown   if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr);
6808*552f7358SJed Brown   /* We should have a generic GetLabel() and a Label class */
6809*552f7358SJed Brown   while(next) {
6810*552f7358SJed Brown     ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr);
6811*552f7358SJed Brown     if (flg) break;
6812*552f7358SJed Brown     next = next->next;
6813*552f7358SJed Brown   }
6814*552f7358SJed Brown   /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */
6815*552f7358SJed Brown   depth = stratumValue;
6816*552f7358SJed Brown   if ((depth < 0) || (depth >= next->numStrata)) {
6817*552f7358SJed Brown     if (start) {*start = 0;}
6818*552f7358SJed Brown     if (end)   {*end   = 0;}
6819*552f7358SJed Brown   } else {
6820*552f7358SJed Brown     if (start) {*start = next->points[next->stratumOffsets[depth]];}
6821*552f7358SJed Brown     if (end)   {*end   = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1;}
6822*552f7358SJed Brown   }
6823*552f7358SJed Brown   PetscFunctionReturn(0);
6824*552f7358SJed Brown }
6825*552f7358SJed Brown 
6826*552f7358SJed Brown #undef __FUNCT__
6827*552f7358SJed Brown #define __FUNCT__ "DMPlexGetHeightStratum"
6828*552f7358SJed Brown /*@
6829*552f7358SJed Brown   DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height.
6830*552f7358SJed Brown 
6831*552f7358SJed Brown   Not Collective
6832*552f7358SJed Brown 
6833*552f7358SJed Brown   Input Parameters:
6834*552f7358SJed Brown + dm           - The DMPlex object
6835*552f7358SJed Brown - stratumValue - The requested height
6836*552f7358SJed Brown 
6837*552f7358SJed Brown   Output Parameters:
6838*552f7358SJed Brown + start - The first point at this height
6839*552f7358SJed Brown - end   - One beyond the last point at this height
6840*552f7358SJed Brown 
6841*552f7358SJed Brown   Level: developer
6842*552f7358SJed Brown 
6843*552f7358SJed Brown .keywords: mesh, points
6844*552f7358SJed Brown .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth()
6845*552f7358SJed Brown @*/
6846*552f7358SJed Brown PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) {
6847*552f7358SJed Brown   DM_Plex    *mesh = (DM_Plex *) dm->data;
6848*552f7358SJed Brown   DMLabel        next = mesh->labels;
6849*552f7358SJed Brown   PetscBool      flg  = PETSC_FALSE;
6850*552f7358SJed Brown   PetscInt       depth;
6851*552f7358SJed Brown   PetscErrorCode ierr;
6852*552f7358SJed Brown 
6853*552f7358SJed Brown   PetscFunctionBegin;
6854*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6855*552f7358SJed Brown   if (stratumValue < 0) {
6856*552f7358SJed Brown     ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr);
6857*552f7358SJed Brown   } else {
6858*552f7358SJed Brown     PetscInt pStart, pEnd;
6859*552f7358SJed Brown 
6860*552f7358SJed Brown     if (start) {*start = 0;}
6861*552f7358SJed Brown     if (end)   {*end   = 0;}
6862*552f7358SJed Brown     ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
6863*552f7358SJed Brown     if (pStart == pEnd) {PetscFunctionReturn(0);}
6864*552f7358SJed Brown   }
6865*552f7358SJed Brown   ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr);
6866*552f7358SJed Brown   if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr);
6867*552f7358SJed Brown   /* We should have a generic GetLabel() and a Label class */
6868*552f7358SJed Brown   while(next) {
6869*552f7358SJed Brown     ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr);
6870*552f7358SJed Brown     if (flg) break;
6871*552f7358SJed Brown     next = next->next;
6872*552f7358SJed Brown   }
6873*552f7358SJed Brown   /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */
6874*552f7358SJed Brown   depth = next->stratumValues[next->numStrata-1] - stratumValue;
6875*552f7358SJed Brown   if ((depth < 0) || (depth >= next->numStrata)) {
6876*552f7358SJed Brown     if (start) {*start = 0;}
6877*552f7358SJed Brown     if (end)   {*end   = 0;}
6878*552f7358SJed Brown   } else {
6879*552f7358SJed Brown     if (start) {*start = next->points[next->stratumOffsets[depth]];}
6880*552f7358SJed Brown     if (end)   {*end   = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1;}
6881*552f7358SJed Brown   }
6882*552f7358SJed Brown   PetscFunctionReturn(0);
6883*552f7358SJed Brown }
6884*552f7358SJed Brown 
6885*552f7358SJed Brown #undef __FUNCT__
6886*552f7358SJed Brown #define __FUNCT__ "DMPlexCreateSectionInitial"
6887*552f7358SJed Brown /* Set the number of dof on each point and separate by fields */
6888*552f7358SJed Brown PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) {
6889*552f7358SJed Brown   PetscInt      *numDofTot;
6890*552f7358SJed Brown   PetscInt       pStart = 0, pEnd = 0;
6891*552f7358SJed Brown   PetscInt       p, d, f;
6892*552f7358SJed Brown   PetscErrorCode ierr;
6893*552f7358SJed Brown 
6894*552f7358SJed Brown   PetscFunctionBegin;
6895*552f7358SJed Brown   ierr = PetscMalloc((dim+1) * sizeof(PetscInt), &numDofTot);CHKERRQ(ierr);
6896*552f7358SJed Brown   for(d = 0; d <= dim; ++d) {
6897*552f7358SJed Brown     numDofTot[d] = 0;
6898*552f7358SJed Brown     for(f = 0; f < numFields; ++f) {
6899*552f7358SJed Brown       numDofTot[d] += numDof[f*(dim+1)+d];
6900*552f7358SJed Brown     }
6901*552f7358SJed Brown   }
6902*552f7358SJed Brown   ierr = PetscSectionCreate(((PetscObject) dm)->comm, section);CHKERRQ(ierr);
6903*552f7358SJed Brown   if (numFields > 0) {
6904*552f7358SJed Brown     ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr);
6905*552f7358SJed Brown     if (numComp) {
6906*552f7358SJed Brown       for(f = 0; f < numFields; ++f) {
6907*552f7358SJed Brown         ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr);
6908*552f7358SJed Brown       }
6909*552f7358SJed Brown     }
6910*552f7358SJed Brown   }
6911*552f7358SJed Brown   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
6912*552f7358SJed Brown   ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr);
6913*552f7358SJed Brown   for(d = 0; d <= dim; ++d) {
6914*552f7358SJed Brown     ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr);
6915*552f7358SJed Brown     for(p = pStart; p < pEnd; ++p) {
6916*552f7358SJed Brown       for(f = 0; f < numFields; ++f) {
6917*552f7358SJed Brown         ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr);
6918*552f7358SJed Brown       }
6919*552f7358SJed Brown       ierr = PetscSectionSetDof(*section, p, numDofTot[d]);CHKERRQ(ierr);
6920*552f7358SJed Brown     }
6921*552f7358SJed Brown   }
6922*552f7358SJed Brown   ierr = PetscFree(numDofTot);CHKERRQ(ierr);
6923*552f7358SJed Brown   PetscFunctionReturn(0);
6924*552f7358SJed Brown }
6925*552f7358SJed Brown 
6926*552f7358SJed Brown #undef __FUNCT__
6927*552f7358SJed Brown #define __FUNCT__ "DMPlexCreateSectionBCDof"
6928*552f7358SJed Brown /* Set the number of dof on each point and separate by fields
6929*552f7358SJed Brown    If constDof is PETSC_DETERMINE, constrain every dof on the point
6930*552f7358SJed Brown */
6931*552f7358SJed Brown PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscInt constDof, PetscSection section) {
6932*552f7358SJed Brown   PetscInt       numFields;
6933*552f7358SJed Brown   PetscInt       bc;
6934*552f7358SJed Brown   PetscErrorCode ierr;
6935*552f7358SJed Brown 
6936*552f7358SJed Brown   PetscFunctionBegin;
6937*552f7358SJed Brown   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
6938*552f7358SJed Brown   for (bc = 0; bc < numBC; ++bc) {
6939*552f7358SJed Brown     PetscInt        field = 0;
6940*552f7358SJed Brown     const PetscInt *idx;
6941*552f7358SJed Brown     PetscInt        n, i;
6942*552f7358SJed Brown 
6943*552f7358SJed Brown     if (numFields) {field = bcField[bc];}
6944*552f7358SJed Brown     ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr);
6945*552f7358SJed Brown     ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr);
6946*552f7358SJed Brown     for (i = 0; i < n; ++i) {
6947*552f7358SJed Brown       const PetscInt p = idx[i];
6948*552f7358SJed Brown       PetscInt       numConst = constDof;
6949*552f7358SJed Brown 
6950*552f7358SJed Brown       /* Constrain every dof on the point */
6951*552f7358SJed Brown       if (numConst < 0) {
6952*552f7358SJed Brown         if (numFields) {
6953*552f7358SJed Brown           ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr);
6954*552f7358SJed Brown         } else {
6955*552f7358SJed Brown           ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr);
6956*552f7358SJed Brown         }
6957*552f7358SJed Brown       }
6958*552f7358SJed Brown       if (numFields) {
6959*552f7358SJed Brown         ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr);
6960*552f7358SJed Brown       }
6961*552f7358SJed Brown       ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr);
6962*552f7358SJed Brown     }
6963*552f7358SJed Brown     ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr);
6964*552f7358SJed Brown   }
6965*552f7358SJed Brown   PetscFunctionReturn(0);
6966*552f7358SJed Brown }
6967*552f7358SJed Brown 
6968*552f7358SJed Brown #undef __FUNCT__
6969*552f7358SJed Brown #define __FUNCT__ "DMPlexCreateSectionBCIndicesAll"
6970*552f7358SJed Brown /* Set the constrained indices on each point and separate by fields */
6971*552f7358SJed Brown PetscErrorCode DMPlexCreateSectionBCIndicesAll(DM dm, PetscSection section) {
6972*552f7358SJed Brown   PetscInt      *maxConstraints;
6973*552f7358SJed Brown   PetscInt       numFields, f, pStart = 0, pEnd = 0, p;
6974*552f7358SJed Brown   PetscErrorCode ierr;
6975*552f7358SJed Brown 
6976*552f7358SJed Brown   PetscFunctionBegin;
6977*552f7358SJed Brown   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
6978*552f7358SJed Brown   ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr);
6979*552f7358SJed Brown   ierr = PetscMalloc((numFields+1) * sizeof(PetscInt), &maxConstraints);CHKERRQ(ierr);
6980*552f7358SJed Brown   for(f = 0; f <= numFields; ++f) {maxConstraints[f] = 0;}
6981*552f7358SJed Brown   for(p = pStart; p < pEnd; ++p) {
6982*552f7358SJed Brown     PetscInt cdof;
6983*552f7358SJed Brown 
6984*552f7358SJed Brown     if (numFields) {
6985*552f7358SJed Brown       for(f = 0; f < numFields; ++f) {
6986*552f7358SJed Brown         ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cdof);CHKERRQ(ierr);
6987*552f7358SJed Brown         maxConstraints[f] = PetscMax(maxConstraints[f], cdof);
6988*552f7358SJed Brown       }
6989*552f7358SJed Brown     } else {
6990*552f7358SJed Brown       ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr);
6991*552f7358SJed Brown       maxConstraints[0] = PetscMax(maxConstraints[0], cdof);
6992*552f7358SJed Brown     }
6993*552f7358SJed Brown   }
6994*552f7358SJed Brown   for (f = 0; f < numFields; ++f) {
6995*552f7358SJed Brown     maxConstraints[numFields] += maxConstraints[f];
6996*552f7358SJed Brown   }
6997*552f7358SJed Brown   if (maxConstraints[numFields]) {
6998*552f7358SJed Brown     PetscInt *indices;
6999*552f7358SJed Brown 
7000*552f7358SJed Brown     ierr = PetscMalloc(maxConstraints[numFields] * sizeof(PetscInt), &indices);CHKERRQ(ierr);
7001*552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
7002*552f7358SJed Brown       PetscInt cdof, d;
7003*552f7358SJed Brown 
7004*552f7358SJed Brown       ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr);
7005*552f7358SJed Brown       if (cdof) {
7006*552f7358SJed Brown         if (cdof > maxConstraints[numFields]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_LIB, "Likely memory corruption, point %D cDof %D > maxConstraints %D", p, cdof, maxConstraints[numFields]);
7007*552f7358SJed Brown         if (numFields) {
7008*552f7358SJed Brown           PetscInt numConst = 0, foff = 0;
7009*552f7358SJed Brown 
7010*552f7358SJed Brown           for (f = 0; f < numFields; ++f) {
7011*552f7358SJed Brown             PetscInt cfdof, fdof;
7012*552f7358SJed Brown 
7013*552f7358SJed Brown             ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr);
7014*552f7358SJed Brown             ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cfdof);CHKERRQ(ierr);
7015*552f7358SJed Brown             /* Change constraint numbering from absolute local dof number to field relative local dof number */
7016*552f7358SJed Brown             for(d = 0; d < cfdof; ++d) {
7017*552f7358SJed Brown               indices[numConst+d] = d;
7018*552f7358SJed Brown             }
7019*552f7358SJed Brown             ierr = PetscSectionSetFieldConstraintIndices(section, p, f, &indices[numConst]);CHKERRQ(ierr);
7020*552f7358SJed Brown             for(d = 0; d < cfdof; ++d) {
7021*552f7358SJed Brown               indices[numConst+d] += foff;
7022*552f7358SJed Brown             }
7023*552f7358SJed Brown             numConst += cfdof;
7024*552f7358SJed Brown             foff     += fdof;
7025*552f7358SJed Brown           }
7026*552f7358SJed Brown           if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof);
7027*552f7358SJed Brown         } else {
7028*552f7358SJed Brown           for (d = 0; d < cdof; ++d) {
7029*552f7358SJed Brown             indices[d] = d;
7030*552f7358SJed Brown           }
7031*552f7358SJed Brown         }
7032*552f7358SJed Brown         ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr);
7033*552f7358SJed Brown       }
7034*552f7358SJed Brown     }
7035*552f7358SJed Brown     ierr = PetscFree(indices);CHKERRQ(ierr);
7036*552f7358SJed Brown   }
7037*552f7358SJed Brown   ierr = PetscFree(maxConstraints);CHKERRQ(ierr);
7038*552f7358SJed Brown   PetscFunctionReturn(0);
7039*552f7358SJed Brown }
7040*552f7358SJed Brown 
7041*552f7358SJed Brown #undef __FUNCT__
7042*552f7358SJed Brown #define __FUNCT__ "DMPlexCreateSectionBCIndicesField"
7043*552f7358SJed Brown /* Set the constrained field indices on each point */
7044*552f7358SJed Brown PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt field, IS bcPoints, IS constraintIndices, PetscSection section) {
7045*552f7358SJed Brown   const PetscInt *points, *indices;
7046*552f7358SJed Brown   PetscInt        numFields, maxDof, numPoints, p, numConstraints;
7047*552f7358SJed Brown   PetscErrorCode  ierr;
7048*552f7358SJed Brown 
7049*552f7358SJed Brown   PetscFunctionBegin;
7050*552f7358SJed Brown   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
7051*552f7358SJed Brown   if ((field < 0) || (field >= numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, numFields);
7052*552f7358SJed Brown 
7053*552f7358SJed Brown   ierr = ISGetLocalSize(bcPoints, &numPoints);CHKERRQ(ierr);
7054*552f7358SJed Brown   ierr = ISGetIndices(bcPoints, &points);CHKERRQ(ierr);
7055*552f7358SJed Brown   if (!constraintIndices) {
7056*552f7358SJed Brown     PetscInt *idx, i;
7057*552f7358SJed Brown 
7058*552f7358SJed Brown     ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr);
7059*552f7358SJed Brown     ierr = PetscMalloc(maxDof * sizeof(PetscInt), &idx);CHKERRQ(ierr);
7060*552f7358SJed Brown     for(i = 0; i < maxDof; ++i) {idx[i] = i;}
7061*552f7358SJed Brown     for(p = 0; p < numPoints; ++p) {
7062*552f7358SJed Brown       ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, idx);CHKERRQ(ierr);
7063*552f7358SJed Brown     }
7064*552f7358SJed Brown     ierr = PetscFree(idx);CHKERRQ(ierr);
7065*552f7358SJed Brown   } else {
7066*552f7358SJed Brown     ierr = ISGetLocalSize(constraintIndices, &numConstraints);CHKERRQ(ierr);
7067*552f7358SJed Brown     ierr = ISGetIndices(constraintIndices, &indices);CHKERRQ(ierr);
7068*552f7358SJed Brown     for(p = 0; p < numPoints; ++p) {
7069*552f7358SJed Brown       PetscInt fcdof;
7070*552f7358SJed Brown 
7071*552f7358SJed Brown       ierr = PetscSectionGetFieldConstraintDof(section, points[p], field, &fcdof);CHKERRQ(ierr);
7072*552f7358SJed Brown       if (fcdof != numConstraints) SETERRQ4(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Section point %d field %d has %d constraints, but yo ugave %d indices", p, field, fcdof, numConstraints);
7073*552f7358SJed Brown       ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, indices);CHKERRQ(ierr);
7074*552f7358SJed Brown     }
7075*552f7358SJed Brown     ierr = ISRestoreIndices(constraintIndices, &indices);CHKERRQ(ierr);
7076*552f7358SJed Brown   }
7077*552f7358SJed Brown   ierr = ISRestoreIndices(bcPoints, &points);CHKERRQ(ierr);
7078*552f7358SJed Brown   PetscFunctionReturn(0);
7079*552f7358SJed Brown }
7080*552f7358SJed Brown 
7081*552f7358SJed Brown #undef __FUNCT__
7082*552f7358SJed Brown #define __FUNCT__ "DMPlexCreateSectionBCIndices"
7083*552f7358SJed Brown /* Set the constrained indices on each point and separate by fields */
7084*552f7358SJed Brown PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) {
7085*552f7358SJed Brown   PetscInt      *indices;
7086*552f7358SJed Brown   PetscInt       numFields, maxDof, f, pStart = 0, pEnd = 0, p;
7087*552f7358SJed Brown   PetscErrorCode ierr;
7088*552f7358SJed Brown 
7089*552f7358SJed Brown   PetscFunctionBegin;
7090*552f7358SJed Brown   ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr);
7091*552f7358SJed Brown   ierr = PetscMalloc(maxDof * sizeof(PetscInt), &indices);CHKERRQ(ierr);
7092*552f7358SJed Brown   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
7093*552f7358SJed Brown   if (!numFields) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "This function only works after users have set field constraint indices.");
7094*552f7358SJed Brown   ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr);
7095*552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
7096*552f7358SJed Brown     PetscInt cdof, d;
7097*552f7358SJed Brown 
7098*552f7358SJed Brown     ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr);
7099*552f7358SJed Brown     if (cdof) {
7100*552f7358SJed Brown       PetscInt numConst = 0, foff = 0;
7101*552f7358SJed Brown 
7102*552f7358SJed Brown       for (f = 0; f < numFields; ++f) {
7103*552f7358SJed Brown         const PetscInt *fcind;
7104*552f7358SJed Brown         PetscInt        fdof, fcdof;
7105*552f7358SJed Brown 
7106*552f7358SJed Brown         ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr);
7107*552f7358SJed Brown         ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr);
7108*552f7358SJed Brown         if (fcdof) {ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &fcind);CHKERRQ(ierr);}
7109*552f7358SJed Brown         /* Change constraint numbering from field relative local dof number to absolute local dof number */
7110*552f7358SJed Brown         for(d = 0; d < fcdof; ++d) {
7111*552f7358SJed Brown           indices[numConst+d] = fcind[d]+foff;
7112*552f7358SJed Brown         }
7113*552f7358SJed Brown         foff     += fdof;
7114*552f7358SJed Brown         numConst += fcdof;
7115*552f7358SJed Brown       }
7116*552f7358SJed Brown       if (cdof != numConst) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof);
7117*552f7358SJed Brown       ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr);
7118*552f7358SJed Brown     }
7119*552f7358SJed Brown   }
7120*552f7358SJed Brown   ierr = PetscFree(indices);CHKERRQ(ierr);
7121*552f7358SJed Brown   PetscFunctionReturn(0);
7122*552f7358SJed Brown }
7123*552f7358SJed Brown 
7124*552f7358SJed Brown #undef __FUNCT__
7125*552f7358SJed Brown #define __FUNCT__ "DMPlexCreateSection"
7126*552f7358SJed Brown /*@C
7127*552f7358SJed Brown   DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided.
7128*552f7358SJed Brown 
7129*552f7358SJed Brown   Not Collective
7130*552f7358SJed Brown 
7131*552f7358SJed Brown   Input Parameters:
7132*552f7358SJed Brown + dm        - The DMPlex object
7133*552f7358SJed Brown . dim       - The spatial dimension of the problem
7134*552f7358SJed Brown . numFields - The number of fields in the problem
7135*552f7358SJed Brown . numComp   - An array of size numFields that holds the number of components for each field
7136*552f7358SJed Brown . numDof    - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d
7137*552f7358SJed Brown . numBC     - The number of boundary conditions
7138*552f7358SJed Brown . bcField   - An array of size numBC giving the field number for each boundry condition
7139*552f7358SJed Brown - bcPoints  - An array of size numBC giving an IS holding the sieve points to which each boundary condition applies
7140*552f7358SJed Brown 
7141*552f7358SJed Brown   Output Parameter:
7142*552f7358SJed Brown . section - The PetscSection object
7143*552f7358SJed Brown 
7144*552f7358SJed Brown   Notes: numDof[f*(dim+1)+d] gives the number of dof for field f on sieve points of dimension d. For instance, numDof[1] is the
7145*552f7358SJed Brown   nubmer of dof for field 0 on each edge.
7146*552f7358SJed Brown 
7147*552f7358SJed Brown   Level: developer
7148*552f7358SJed Brown 
7149*552f7358SJed Brown .keywords: mesh, elements
7150*552f7358SJed Brown .seealso: DMPlexCreate(), PetscSectionCreate()
7151*552f7358SJed Brown @*/
7152*552f7358SJed Brown PetscErrorCode DMPlexCreateSection(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscSection *section) {
7153*552f7358SJed Brown   PetscErrorCode ierr;
7154*552f7358SJed Brown 
7155*552f7358SJed Brown   PetscFunctionBegin;
7156*552f7358SJed Brown   ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr);
7157*552f7358SJed Brown   ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcPoints, PETSC_DETERMINE, *section);CHKERRQ(ierr);
7158*552f7358SJed Brown   ierr = PetscSectionSetUp(*section);CHKERRQ(ierr);
7159*552f7358SJed Brown   if (numBC) {ierr = DMPlexCreateSectionBCIndicesAll(dm, *section);CHKERRQ(ierr);}
7160*552f7358SJed Brown   {
7161*552f7358SJed Brown     PetscBool view = PETSC_FALSE;
7162*552f7358SJed Brown 
7163*552f7358SJed Brown     ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-section_view", &view);CHKERRQ(ierr);
7164*552f7358SJed Brown     if (view) {ierr = PetscSectionView(*section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);}
7165*552f7358SJed Brown   }
7166*552f7358SJed Brown   PetscFunctionReturn(0);
7167*552f7358SJed Brown }
7168*552f7358SJed Brown 
7169*552f7358SJed Brown #undef __FUNCT__
7170*552f7358SJed Brown #define __FUNCT__ "DMCreateCoordinateDM_Plex"
7171*552f7358SJed Brown PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) {
7172*552f7358SJed Brown   PetscSection   section;
7173*552f7358SJed Brown   PetscErrorCode ierr;
7174*552f7358SJed Brown 
7175*552f7358SJed Brown   PetscFunctionBegin;
7176*552f7358SJed Brown   ierr = DMPlexClone(dm, cdm);CHKERRQ(ierr);
7177*552f7358SJed Brown   ierr = PetscSectionCreate(((PetscObject) dm)->comm, &section);CHKERRQ(ierr);
7178*552f7358SJed Brown   ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr);
7179*552f7358SJed Brown   PetscFunctionReturn(0);
7180*552f7358SJed Brown }
7181*552f7358SJed Brown 
7182*552f7358SJed Brown #undef __FUNCT__
7183*552f7358SJed Brown #define __FUNCT__ "DMPlexGetCoordinateSection"
7184*552f7358SJed Brown /*@
7185*552f7358SJed Brown   DMPlexGetCoordinateSection - Retrieve the layout of coordinate values over the mesh.
7186*552f7358SJed Brown 
7187*552f7358SJed Brown   Not Collective
7188*552f7358SJed Brown 
7189*552f7358SJed Brown   Input Parameter:
7190*552f7358SJed Brown . dm - The DMPlex object
7191*552f7358SJed Brown 
7192*552f7358SJed Brown   Output Parameter:
7193*552f7358SJed Brown . section - The PetscSection object
7194*552f7358SJed Brown 
7195*552f7358SJed Brown   Level: intermediate
7196*552f7358SJed Brown 
7197*552f7358SJed Brown .keywords: mesh, coordinates
7198*552f7358SJed Brown .seealso: DMGetCoordinateDM(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection()
7199*552f7358SJed Brown @*/
7200*552f7358SJed Brown PetscErrorCode DMPlexGetCoordinateSection(DM dm, PetscSection *section) {
7201*552f7358SJed Brown   DM cdm;
7202*552f7358SJed Brown   PetscErrorCode ierr;
7203*552f7358SJed Brown 
7204*552f7358SJed Brown   PetscFunctionBegin;
7205*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7206*552f7358SJed Brown   PetscValidPointer(section, 2);
7207*552f7358SJed Brown   ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
7208*552f7358SJed Brown   ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr);
7209*552f7358SJed Brown   PetscFunctionReturn(0);
7210*552f7358SJed Brown }
7211*552f7358SJed Brown 
7212*552f7358SJed Brown #undef __FUNCT__
7213*552f7358SJed Brown #define __FUNCT__ "DMPlexSetCoordinateSection"
7214*552f7358SJed Brown /*@
7215*552f7358SJed Brown   DMPlexSetCoordinateSection - Set the layout of coordinate values over the mesh.
7216*552f7358SJed Brown 
7217*552f7358SJed Brown   Not Collective
7218*552f7358SJed Brown 
7219*552f7358SJed Brown   Input Parameters:
7220*552f7358SJed Brown + dm      - The DMPlex object
7221*552f7358SJed Brown - section - The PetscSection object
7222*552f7358SJed Brown 
7223*552f7358SJed Brown   Level: intermediate
7224*552f7358SJed Brown 
7225*552f7358SJed Brown .keywords: mesh, coordinates
7226*552f7358SJed Brown .seealso: DMPlexGetCoordinateSection(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection()
7227*552f7358SJed Brown @*/
7228*552f7358SJed Brown PetscErrorCode DMPlexSetCoordinateSection(DM dm, PetscSection section) {
7229*552f7358SJed Brown   DM             cdm;
7230*552f7358SJed Brown   PetscErrorCode ierr;
7231*552f7358SJed Brown 
7232*552f7358SJed Brown   PetscFunctionBegin;
7233*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7234*552f7358SJed Brown   ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
7235*552f7358SJed Brown   ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr);
7236*552f7358SJed Brown   PetscFunctionReturn(0);
7237*552f7358SJed Brown }
7238*552f7358SJed Brown 
7239*552f7358SJed Brown #undef __FUNCT__
7240*552f7358SJed Brown #define __FUNCT__ "DMPlexGetConeSection"
7241*552f7358SJed Brown PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) {
7242*552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *) dm->data;
7243*552f7358SJed Brown 
7244*552f7358SJed Brown   PetscFunctionBegin;
7245*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7246*552f7358SJed Brown   if (section) *section = mesh->coneSection;
7247*552f7358SJed Brown   PetscFunctionReturn(0);
7248*552f7358SJed Brown }
7249*552f7358SJed Brown 
7250*552f7358SJed Brown #undef __FUNCT__
7251*552f7358SJed Brown #define __FUNCT__ "DMPlexGetCones"
7252*552f7358SJed Brown PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) {
7253*552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *) dm->data;
7254*552f7358SJed Brown 
7255*552f7358SJed Brown   PetscFunctionBegin;
7256*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7257*552f7358SJed Brown   if (cones) *cones = mesh->cones;
7258*552f7358SJed Brown   PetscFunctionReturn(0);
7259*552f7358SJed Brown }
7260*552f7358SJed Brown 
7261*552f7358SJed Brown #undef __FUNCT__
7262*552f7358SJed Brown #define __FUNCT__ "DMPlexGetConeOrientations"
7263*552f7358SJed Brown PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) {
7264*552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *) dm->data;
7265*552f7358SJed Brown 
7266*552f7358SJed Brown   PetscFunctionBegin;
7267*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7268*552f7358SJed Brown   if (coneOrientations) *coneOrientations = mesh->coneOrientations;
7269*552f7358SJed Brown   PetscFunctionReturn(0);
7270*552f7358SJed Brown }
7271*552f7358SJed Brown 
7272*552f7358SJed Brown #undef __FUNCT__
7273*552f7358SJed Brown #define __FUNCT__ "DMPlexLocatePoint_Simplex_2D"
7274*552f7358SJed Brown PetscErrorCode DMPlexLocatePoint_Simplex_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell)
7275*552f7358SJed Brown {
7276*552f7358SJed Brown   const PetscInt embedDim = 2;
7277*552f7358SJed Brown   PetscReal      v0[2], J[4], invJ[4], detJ;
7278*552f7358SJed Brown   PetscErrorCode ierr;
7279*552f7358SJed Brown 
7280*552f7358SJed Brown   PetscFunctionBegin;
7281*552f7358SJed Brown   ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr);
7282*552f7358SJed Brown   PetscReal xi  = invJ[0*embedDim+0]*(point[0] - v0[0]) + invJ[0*embedDim+1]*(point[1] - v0[1]);
7283*552f7358SJed Brown   PetscReal eta = invJ[1*embedDim+0]*(point[0] - v0[0]) + invJ[1*embedDim+1]*(point[1] - v0[1]);
7284*552f7358SJed Brown 
7285*552f7358SJed Brown   if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 2.0)) {
7286*552f7358SJed Brown     *cell = c;
7287*552f7358SJed Brown   } else {
7288*552f7358SJed Brown     *cell = -1;
7289*552f7358SJed Brown   }
7290*552f7358SJed Brown   PetscFunctionReturn(0);
7291*552f7358SJed Brown }
7292*552f7358SJed Brown 
7293*552f7358SJed Brown #undef __FUNCT__
7294*552f7358SJed Brown #define __FUNCT__ "DMPlexLocatePoint_General_2D"
7295*552f7358SJed Brown PetscErrorCode DMPlexLocatePoint_General_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell)
7296*552f7358SJed Brown {
7297*552f7358SJed Brown   PetscSection       coordSection;
7298*552f7358SJed Brown   Vec                coordsLocal;
7299*552f7358SJed Brown   const PetscScalar *coords;
7300*552f7358SJed Brown   const PetscInt     faces[8]  = {0, 1, 1, 2, 2, 3, 3, 0};
7301*552f7358SJed Brown   PetscInt           crossings = 0, f;
7302*552f7358SJed Brown   PetscErrorCode     ierr;
7303*552f7358SJed Brown 
7304*552f7358SJed Brown   PetscFunctionBegin;
7305*552f7358SJed Brown   ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr);
7306*552f7358SJed Brown   ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr);
7307*552f7358SJed Brown   ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr);
7308*552f7358SJed Brown   for(f = 0; f < 4; ++f) {
7309*552f7358SJed Brown     PetscReal x_i   = coords[faces[2*f+0]*2+0];
7310*552f7358SJed Brown     PetscReal y_i   = coords[faces[2*f+0]*2+1];
7311*552f7358SJed Brown     PetscReal x_j   = coords[faces[2*f+1]*2+0];
7312*552f7358SJed Brown     PetscReal y_j   = coords[faces[2*f+1]*2+1];
7313*552f7358SJed Brown     PetscReal slope = (y_j - y_i) / (x_j - x_i);
7314*552f7358SJed Brown     PetscBool cond1 = (x_i <= point[0]) && (point[0] < x_j) ? PETSC_TRUE : PETSC_FALSE;
7315*552f7358SJed Brown     PetscBool cond2 = (x_j <= point[0]) && (point[0] < x_i) ? PETSC_TRUE : PETSC_FALSE;
7316*552f7358SJed Brown     PetscBool above = (point[1] < slope * (point[0] - x_i) + y_i) ? PETSC_TRUE : PETSC_FALSE;
7317*552f7358SJed Brown     if ((cond1 || cond2)  && above) ++crossings;
7318*552f7358SJed Brown   }
7319*552f7358SJed Brown   if (crossings % 2) {
7320*552f7358SJed Brown     *cell = c;
7321*552f7358SJed Brown   } else {
7322*552f7358SJed Brown     *cell = -1;
7323*552f7358SJed Brown   }
7324*552f7358SJed Brown   ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr);
7325*552f7358SJed Brown   PetscFunctionReturn(0);
7326*552f7358SJed Brown }
7327*552f7358SJed Brown 
7328*552f7358SJed Brown #undef __FUNCT__
7329*552f7358SJed Brown #define __FUNCT__ "DMPlexLocatePoint_Simplex_3D"
7330*552f7358SJed Brown PetscErrorCode DMPlexLocatePoint_Simplex_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell)
7331*552f7358SJed Brown {
7332*552f7358SJed Brown   const PetscInt embedDim = 3;
7333*552f7358SJed Brown   PetscReal      v0[3], J[9], invJ[9], detJ;
7334*552f7358SJed Brown   PetscErrorCode ierr;
7335*552f7358SJed Brown 
7336*552f7358SJed Brown   PetscFunctionBegin;
7337*552f7358SJed Brown   ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr);
7338*552f7358SJed Brown   PetscReal xi   = invJ[0*embedDim+0]*(point[0] - v0[0]) + invJ[0*embedDim+1]*(point[1] - v0[1]) + invJ[0*embedDim+2]*(point[2] - v0[2]);
7339*552f7358SJed Brown   PetscReal eta  = invJ[1*embedDim+0]*(point[0] - v0[0]) + invJ[1*embedDim+1]*(point[1] - v0[1]) + invJ[1*embedDim+2]*(point[2] - v0[2]);
7340*552f7358SJed Brown   PetscReal zeta = invJ[2*embedDim+0]*(point[0] - v0[0]) + invJ[2*embedDim+1]*(point[1] - v0[1]) + invJ[2*embedDim+2]*(point[2] - v0[2]);
7341*552f7358SJed Brown 
7342*552f7358SJed Brown   if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 2.0)) {
7343*552f7358SJed Brown     *cell = c;
7344*552f7358SJed Brown   } else {
7345*552f7358SJed Brown     *cell = -1;
7346*552f7358SJed Brown   }
7347*552f7358SJed Brown   PetscFunctionReturn(0);
7348*552f7358SJed Brown }
7349*552f7358SJed Brown 
7350*552f7358SJed Brown #undef __FUNCT__
7351*552f7358SJed Brown #define __FUNCT__ "DMPlexLocatePoint_General_3D"
7352*552f7358SJed Brown PetscErrorCode DMPlexLocatePoint_General_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell)
7353*552f7358SJed Brown {
7354*552f7358SJed Brown   PetscSection       coordSection;
7355*552f7358SJed Brown   Vec                coordsLocal;
7356*552f7358SJed Brown   const PetscScalar *coords;
7357*552f7358SJed Brown   const PetscInt     faces[24] = {0, 1, 2, 3,  5, 4, 7, 6,  1, 0, 4, 5,
7358*552f7358SJed Brown                                   3, 2, 6, 7,  1, 5, 6, 2,  0, 3, 7, 4};
7359*552f7358SJed Brown   PetscBool          found     = PETSC_TRUE;
7360*552f7358SJed Brown   PetscInt           f;
7361*552f7358SJed Brown   PetscErrorCode     ierr;
7362*552f7358SJed Brown 
7363*552f7358SJed Brown   PetscFunctionBegin;
7364*552f7358SJed Brown   ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr);
7365*552f7358SJed Brown   ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr);
7366*552f7358SJed Brown   ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr);
7367*552f7358SJed Brown   for(f = 0; f < 6; ++f) {
7368*552f7358SJed Brown     /* Check the point is under plane */
7369*552f7358SJed Brown     /*   Get face normal */
7370*552f7358SJed Brown     PetscReal v_i[3]    = {coords[faces[f*4+3]*3+0]-coords[faces[f*4+0]*3+0],coords[faces[f*4+3]*3+1]-coords[faces[f*4+0]*3+1],coords[faces[f*4+3]*3+2]-coords[faces[f*4+0]*3+2]};
7371*552f7358SJed Brown     PetscReal v_j[3]    = {coords[faces[f*4+1]*3+0]-coords[faces[f*4+0]*3+0],coords[faces[f*4+1]*3+1]-coords[faces[f*4+0]*3+1],coords[faces[f*4+1]*3+2]-coords[faces[f*4+0]*3+2]};
7372*552f7358SJed Brown     PetscReal normal[3] = {v_i[1]*v_j[2] - v_i[2]*v_j[1], v_i[2]*v_j[0] - v_i[0]*v_j[2], v_i[0]*v_j[1] - v_i[1]*v_j[0]};
7373*552f7358SJed Brown     PetscReal pp[3]     = {coords[faces[f*4+0]*3+0] - point[0],coords[faces[f*4+0]*3+1] - point[1],coords[faces[f*4+0]*3+2] - point[2]};
7374*552f7358SJed Brown     PetscReal dot       = normal[0]*pp[0] + normal[1]*pp[1] + normal[2]*pp[2];
7375*552f7358SJed Brown     /* Check that projected point is in face (2D location problem) */
7376*552f7358SJed Brown     if (dot < 0.0) {
7377*552f7358SJed Brown       found = PETSC_FALSE;
7378*552f7358SJed Brown       break;
7379*552f7358SJed Brown     }
7380*552f7358SJed Brown   }
7381*552f7358SJed Brown   if (found) {
7382*552f7358SJed Brown     *cell = c;
7383*552f7358SJed Brown   } else {
7384*552f7358SJed Brown     *cell = -1;
7385*552f7358SJed Brown   }
7386*552f7358SJed Brown   ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr);
7387*552f7358SJed Brown   PetscFunctionReturn(0);
7388*552f7358SJed Brown }
7389*552f7358SJed Brown 
7390*552f7358SJed Brown #undef __FUNCT__
7391*552f7358SJed Brown #define __FUNCT__ "DMLocatePoints_Plex"
7392*552f7358SJed Brown /*
7393*552f7358SJed Brown  Need to implement using the guess
7394*552f7358SJed Brown */
7395*552f7358SJed Brown PetscErrorCode DMLocatePoints_Plex(DM dm, Vec v, IS *cellIS)
7396*552f7358SJed Brown {
7397*552f7358SJed Brown   PetscInt       cell = -1/*, guess = -1*/;
7398*552f7358SJed Brown   PetscInt       bs, numPoints, p;
7399*552f7358SJed Brown   PetscInt       dim, cStart, cEnd, cMax, c, coneSize;
7400*552f7358SJed Brown   PetscInt      *cells;
7401*552f7358SJed Brown   PetscScalar   *a;
7402*552f7358SJed Brown   PetscErrorCode ierr;
7403*552f7358SJed Brown 
7404*552f7358SJed Brown   PetscFunctionBegin;
7405*552f7358SJed Brown   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
7406*552f7358SJed Brown   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
7407*552f7358SJed Brown   ierr = DMPlexGetVTKBounds(dm, &cMax, PETSC_NULL);CHKERRQ(ierr);
7408*552f7358SJed Brown   ierr = VecGetLocalSize(v, &numPoints);CHKERRQ(ierr);
7409*552f7358SJed Brown   ierr = VecGetBlockSize(v, &bs);CHKERRQ(ierr);
7410*552f7358SJed Brown   ierr = VecGetArray(v, &a);CHKERRQ(ierr);
7411*552f7358SJed Brown   if (bs != dim) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Block size for point vector %d must be the mesh coordinate dimension %d", bs, dim);
7412*552f7358SJed Brown   numPoints /= bs;
7413*552f7358SJed Brown   ierr = PetscMalloc(numPoints * sizeof(PetscInt), &cells);CHKERRQ(ierr);
7414*552f7358SJed Brown   for(p = 0; p < numPoints; ++p) {
7415*552f7358SJed Brown     const PetscScalar *point = &a[p*bs];
7416*552f7358SJed Brown 
7417*552f7358SJed Brown     switch(dim) {
7418*552f7358SJed Brown     case 2:
7419*552f7358SJed Brown       for(c = cStart; c < cEnd; ++c) {
7420*552f7358SJed Brown         ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr);
7421*552f7358SJed Brown         switch(coneSize) {
7422*552f7358SJed Brown         case 3:
7423*552f7358SJed Brown           ierr = DMPlexLocatePoint_Simplex_2D(dm, point, c, &cell);CHKERRQ(ierr);
7424*552f7358SJed Brown           break;
7425*552f7358SJed Brown         case 4:
7426*552f7358SJed Brown           ierr = DMPlexLocatePoint_General_2D(dm, point, c, &cell);CHKERRQ(ierr);
7427*552f7358SJed Brown           break;
7428*552f7358SJed Brown         default:
7429*552f7358SJed Brown           SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize);
7430*552f7358SJed Brown         }
7431*552f7358SJed Brown         if (cell >= 0) break;
7432*552f7358SJed Brown       }
7433*552f7358SJed Brown       break;
7434*552f7358SJed Brown     case 3:
7435*552f7358SJed Brown       for(c = cStart; c < cEnd; ++c) {
7436*552f7358SJed Brown         ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr);
7437*552f7358SJed Brown         switch(coneSize) {
7438*552f7358SJed Brown         case 4:
7439*552f7358SJed Brown           ierr = DMPlexLocatePoint_Simplex_3D(dm, point, c, &cell);CHKERRQ(ierr);
7440*552f7358SJed Brown           break;
7441*552f7358SJed Brown         case 8:
7442*552f7358SJed Brown           ierr = DMPlexLocatePoint_General_3D(dm, point, c, &cell);CHKERRQ(ierr);
7443*552f7358SJed Brown           break;
7444*552f7358SJed Brown         default:
7445*552f7358SJed Brown           SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize);
7446*552f7358SJed Brown         }
7447*552f7358SJed Brown         if (cell >= 0) break;
7448*552f7358SJed Brown       }
7449*552f7358SJed Brown       break;
7450*552f7358SJed Brown     default:
7451*552f7358SJed Brown       SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for mesh dimension %d", dim);
7452*552f7358SJed Brown     }
7453*552f7358SJed Brown     cells[p] = cell;
7454*552f7358SJed Brown   }
7455*552f7358SJed Brown   ierr = VecRestoreArray(v, &a);CHKERRQ(ierr);
7456*552f7358SJed Brown   ierr = ISCreateGeneral(PETSC_COMM_SELF, numPoints, cells, PETSC_OWN_POINTER, cellIS);CHKERRQ(ierr);
7457*552f7358SJed Brown   PetscFunctionReturn(0);
7458*552f7358SJed Brown }
7459*552f7358SJed Brown 
7460*552f7358SJed Brown /******************************** FEM Support **********************************/
7461*552f7358SJed Brown 
7462*552f7358SJed Brown #undef __FUNCT__
7463*552f7358SJed Brown #define __FUNCT__ "DMPlexVecGetClosure"
7464*552f7358SJed Brown /*@C
7465*552f7358SJed Brown   DMPlexVecGetClosure - Get an array of the values on the closure of 'point'
7466*552f7358SJed Brown 
7467*552f7358SJed Brown   Not collective
7468*552f7358SJed Brown 
7469*552f7358SJed Brown   Input Parameters:
7470*552f7358SJed Brown + dm - The DM
7471*552f7358SJed Brown . section - The section describing the layout in v, or PETSC_NULL to use the default section
7472*552f7358SJed Brown . v - The local vector
7473*552f7358SJed Brown - point - The sieve point in the DM
7474*552f7358SJed Brown 
7475*552f7358SJed Brown   Output Parameters:
7476*552f7358SJed Brown + csize - The number of values in the closure, or PETSC_NULL
7477*552f7358SJed Brown - values - The array of values, which is a borrowed array and should not be freed
7478*552f7358SJed Brown 
7479*552f7358SJed Brown   Level: intermediate
7480*552f7358SJed Brown 
7481*552f7358SJed Brown .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure()
7482*552f7358SJed Brown @*/
7483*552f7358SJed Brown PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) {
7484*552f7358SJed Brown   PetscScalar    *array, *vArray;
7485*552f7358SJed Brown   PetscInt       *points = PETSC_NULL;
7486*552f7358SJed Brown   PetscInt        offsets[32];
7487*552f7358SJed Brown   PetscInt        numFields, size, numPoints, pStart, pEnd, p, q, f;
7488*552f7358SJed Brown   PetscErrorCode  ierr;
7489*552f7358SJed Brown 
7490*552f7358SJed Brown   PetscFunctionBegin;
7491*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7492*552f7358SJed Brown   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
7493*552f7358SJed Brown   if (!section) {
7494*552f7358SJed Brown     ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
7495*552f7358SJed Brown   }
7496*552f7358SJed Brown   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
7497*552f7358SJed Brown   if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields);
7498*552f7358SJed Brown   ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr);
7499*552f7358SJed Brown   ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);
7500*552f7358SJed Brown   /* Compress out points not in the section */
7501*552f7358SJed Brown   ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr);
7502*552f7358SJed Brown   for (p = 0, q = 0; p < numPoints*2; p += 2) {
7503*552f7358SJed Brown     if ((points[p] >= pStart) && (points[p] < pEnd)) {
7504*552f7358SJed Brown       points[q*2]   = points[p];
7505*552f7358SJed Brown       points[q*2+1] = points[p+1];
7506*552f7358SJed Brown       ++q;
7507*552f7358SJed Brown     }
7508*552f7358SJed Brown   }
7509*552f7358SJed Brown   numPoints = q;
7510*552f7358SJed Brown   for (p = 0, size = 0; p < numPoints*2; p += 2) {
7511*552f7358SJed Brown     PetscInt dof, fdof;
7512*552f7358SJed Brown 
7513*552f7358SJed Brown     ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr);
7514*552f7358SJed Brown     for (f = 0; f < numFields; ++f) {
7515*552f7358SJed Brown       ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr);
7516*552f7358SJed Brown       offsets[f+1] += fdof;
7517*552f7358SJed Brown     }
7518*552f7358SJed Brown     size += dof;
7519*552f7358SJed Brown   }
7520*552f7358SJed Brown   for (f = 1; f < numFields; ++f) {
7521*552f7358SJed Brown     offsets[f+1] += offsets[f];
7522*552f7358SJed Brown   }
7523*552f7358SJed Brown   if (numFields && offsets[numFields] != size) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], size);
7524*552f7358SJed Brown   ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr);
7525*552f7358SJed Brown   ierr = VecGetArray(v, &vArray);CHKERRQ(ierr);
7526*552f7358SJed Brown   for (p = 0; p < numPoints*2; p += 2) {
7527*552f7358SJed Brown     PetscInt     o = points[p+1];
7528*552f7358SJed Brown     PetscInt     dof, off, d;
7529*552f7358SJed Brown     PetscScalar *varr;
7530*552f7358SJed Brown 
7531*552f7358SJed Brown     ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr);
7532*552f7358SJed Brown     ierr = PetscSectionGetOffset(section, points[p], &off);CHKERRQ(ierr);
7533*552f7358SJed Brown     varr = &vArray[off];
7534*552f7358SJed Brown     if (numFields) {
7535*552f7358SJed Brown       PetscInt fdof, foff, fcomp, f, c;
7536*552f7358SJed Brown 
7537*552f7358SJed Brown       for (f = 0, foff = 0; f < numFields; ++f) {
7538*552f7358SJed Brown         ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr);
7539*552f7358SJed Brown         if (o >= 0) {
7540*552f7358SJed Brown           for (d = 0; d < fdof; ++d, ++offsets[f]) {
7541*552f7358SJed Brown             array[offsets[f]] = varr[foff+d];
7542*552f7358SJed Brown           }
7543*552f7358SJed Brown         } else {
7544*552f7358SJed Brown           ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr);
7545*552f7358SJed Brown           for (d = fdof/fcomp-1; d >= 0; --d) {
7546*552f7358SJed Brown             for (c = 0; c < fcomp; ++c, ++offsets[f]) {
7547*552f7358SJed Brown               array[offsets[f]] = varr[foff+d*fcomp+c];
7548*552f7358SJed Brown             }
7549*552f7358SJed Brown           }
7550*552f7358SJed Brown         }
7551*552f7358SJed Brown         foff += fdof;
7552*552f7358SJed Brown       }
7553*552f7358SJed Brown     } else {
7554*552f7358SJed Brown       if (o >= 0) {
7555*552f7358SJed Brown         for (d = 0; d < dof; ++d, ++offsets[0]) {
7556*552f7358SJed Brown           array[offsets[0]] = varr[d];
7557*552f7358SJed Brown         }
7558*552f7358SJed Brown       } else {
7559*552f7358SJed Brown         for (d = dof-1; d >= 0; --d, ++offsets[0]) {
7560*552f7358SJed Brown           array[offsets[0]] = varr[d];
7561*552f7358SJed Brown         }
7562*552f7358SJed Brown       }
7563*552f7358SJed Brown     }
7564*552f7358SJed Brown   }
7565*552f7358SJed Brown   ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);
7566*552f7358SJed Brown   ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr);
7567*552f7358SJed Brown   if (csize) *csize = size;
7568*552f7358SJed Brown   *values = array;
7569*552f7358SJed Brown   PetscFunctionReturn(0);
7570*552f7358SJed Brown }
7571*552f7358SJed Brown 
7572*552f7358SJed Brown #undef __FUNCT__
7573*552f7358SJed Brown #define __FUNCT__ "DMPlexVecRestoreClosure"
7574*552f7358SJed Brown /*@C
7575*552f7358SJed Brown   DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point'
7576*552f7358SJed Brown 
7577*552f7358SJed Brown   Not collective
7578*552f7358SJed Brown 
7579*552f7358SJed Brown   Input Parameters:
7580*552f7358SJed Brown + dm - The DM
7581*552f7358SJed Brown . section - The section describing the layout in v, or PETSC_NULL to use the default section
7582*552f7358SJed Brown . v - The local vector
7583*552f7358SJed Brown . point - The sieve point in the DM
7584*552f7358SJed Brown . csize - The number of values in the closure, or PETSC_NULL
7585*552f7358SJed Brown - values - The array of values, which is a borrowed array and should not be freed
7586*552f7358SJed Brown 
7587*552f7358SJed Brown   Level: intermediate
7588*552f7358SJed Brown 
7589*552f7358SJed Brown .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure()
7590*552f7358SJed Brown @*/
7591*552f7358SJed Brown PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) {
7592*552f7358SJed Brown   PetscInt        size = 0;
7593*552f7358SJed Brown   PetscErrorCode  ierr;
7594*552f7358SJed Brown 
7595*552f7358SJed Brown   PetscFunctionBegin;
7596*552f7358SJed Brown   /* Should work without recalculating size */
7597*552f7358SJed Brown   ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void *) values);CHKERRQ(ierr);
7598*552f7358SJed Brown   PetscFunctionReturn(0);
7599*552f7358SJed Brown }
7600*552f7358SJed Brown 
7601*552f7358SJed Brown PETSC_STATIC_INLINE void add   (PetscScalar *x, PetscScalar y) {*x += y;}
7602*552f7358SJed Brown PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x  = y;}
7603*552f7358SJed Brown 
7604*552f7358SJed Brown #undef __FUNCT__
7605*552f7358SJed Brown #define __FUNCT__ "updatePoint_private"
7606*552f7358SJed Brown PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar *, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[])
7607*552f7358SJed Brown {
7608*552f7358SJed Brown   PetscInt        cdof;  /* The number of constraints on this point */
7609*552f7358SJed Brown   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
7610*552f7358SJed Brown   PetscScalar    *a;
7611*552f7358SJed Brown   PetscInt        off, cind = 0, k;
7612*552f7358SJed Brown   PetscErrorCode  ierr;
7613*552f7358SJed Brown 
7614*552f7358SJed Brown   PetscFunctionBegin;
7615*552f7358SJed Brown   ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr);
7616*552f7358SJed Brown   ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr);
7617*552f7358SJed Brown   a    = &array[off];
7618*552f7358SJed Brown   if (!cdof || setBC) {
7619*552f7358SJed Brown     if (orientation >= 0) {
7620*552f7358SJed Brown       for (k = 0; k < dof; ++k) {
7621*552f7358SJed Brown         fuse(&a[k], values[k]);
7622*552f7358SJed Brown       }
7623*552f7358SJed Brown     } else {
7624*552f7358SJed Brown       for (k = 0; k < dof; ++k) {
7625*552f7358SJed Brown         fuse(&a[k], values[dof-k-1]);
7626*552f7358SJed Brown       }
7627*552f7358SJed Brown     }
7628*552f7358SJed Brown   } else {
7629*552f7358SJed Brown     ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr);
7630*552f7358SJed Brown     if (orientation >= 0) {
7631*552f7358SJed Brown       for (k = 0; k < dof; ++k) {
7632*552f7358SJed Brown         if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
7633*552f7358SJed Brown         fuse(&a[k], values[k]);
7634*552f7358SJed Brown       }
7635*552f7358SJed Brown     } else {
7636*552f7358SJed Brown       for (k = 0; k < dof; ++k) {
7637*552f7358SJed Brown         if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
7638*552f7358SJed Brown         fuse(&a[k], values[dof-k-1]);
7639*552f7358SJed Brown       }
7640*552f7358SJed Brown     }
7641*552f7358SJed Brown   }
7642*552f7358SJed Brown   PetscFunctionReturn(0);
7643*552f7358SJed Brown }
7644*552f7358SJed Brown 
7645*552f7358SJed Brown #undef __FUNCT__
7646*552f7358SJed Brown #define __FUNCT__ "updatePointFields_private"
7647*552f7358SJed Brown PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt foffs[], void (*fuse)(PetscScalar *, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) {
7648*552f7358SJed Brown   PetscScalar   *a;
7649*552f7358SJed Brown   PetscInt       numFields, off, foff, f;
7650*552f7358SJed Brown   PetscErrorCode ierr;
7651*552f7358SJed Brown 
7652*552f7358SJed Brown   PetscFunctionBegin;
7653*552f7358SJed Brown   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
7654*552f7358SJed Brown   ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr);
7655*552f7358SJed Brown   a    = &array[off];
7656*552f7358SJed Brown   for (f = 0, foff = 0; f < numFields; ++f) {
7657*552f7358SJed Brown     PetscInt        fdof, fcomp, fcdof;
7658*552f7358SJed Brown     const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
7659*552f7358SJed Brown     PetscInt        cind = 0, k, c;
7660*552f7358SJed Brown 
7661*552f7358SJed Brown     ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr);
7662*552f7358SJed Brown     ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr);
7663*552f7358SJed Brown     ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr);
7664*552f7358SJed Brown     if (!fcdof || setBC) {
7665*552f7358SJed Brown       if (orientation >= 0) {
7666*552f7358SJed Brown         for (k = 0; k < fdof; ++k) {
7667*552f7358SJed Brown           fuse(&a[foff+k], values[foffs[f]+k]);
7668*552f7358SJed Brown         }
7669*552f7358SJed Brown       } else {
7670*552f7358SJed Brown         for (k = fdof/fcomp-1; k >= 0; --k) {
7671*552f7358SJed Brown           for (c = 0; c < fcomp; ++c) {
7672*552f7358SJed Brown             fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]);
7673*552f7358SJed Brown           }
7674*552f7358SJed Brown         }
7675*552f7358SJed Brown       }
7676*552f7358SJed Brown     } else {
7677*552f7358SJed Brown       ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr);
7678*552f7358SJed Brown       if (orientation >= 0) {
7679*552f7358SJed Brown         for (k = 0; k < fdof; ++k) {
7680*552f7358SJed Brown           if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;}
7681*552f7358SJed Brown           fuse(&a[foff+k], values[foffs[f]+k]);
7682*552f7358SJed Brown         }
7683*552f7358SJed Brown       } else {
7684*552f7358SJed Brown         for (k = fdof/fcomp-1; k >= 0; --k) {
7685*552f7358SJed Brown           for (c = 0; c < fcomp; ++c) {
7686*552f7358SJed Brown             if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;}
7687*552f7358SJed Brown             fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]);
7688*552f7358SJed Brown           }
7689*552f7358SJed Brown         }
7690*552f7358SJed Brown       }
7691*552f7358SJed Brown     }
7692*552f7358SJed Brown     foff     += fdof;
7693*552f7358SJed Brown     foffs[f] += fdof;
7694*552f7358SJed Brown   }
7695*552f7358SJed Brown   PetscFunctionReturn(0);
7696*552f7358SJed Brown }
7697*552f7358SJed Brown 
7698*552f7358SJed Brown #undef __FUNCT__
7699*552f7358SJed Brown #define __FUNCT__ "DMPlexVecSetClosure"
7700*552f7358SJed Brown /*@C
7701*552f7358SJed Brown   DMPlexVecSetClosure - Set an array of the values on the closure of 'point'
7702*552f7358SJed Brown 
7703*552f7358SJed Brown   Not collective
7704*552f7358SJed Brown 
7705*552f7358SJed Brown   Input Parameters:
7706*552f7358SJed Brown + dm - The DM
7707*552f7358SJed Brown . section - The section describing the layout in v, or PETSC_NULL to use the default sectionw
7708*552f7358SJed Brown . v - The local vector
7709*552f7358SJed Brown . point - The sieve point in the DM
7710*552f7358SJed Brown . values - The array of values, which is a borrowed array and should not be freed
7711*552f7358SJed Brown - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions
7712*552f7358SJed Brown 
7713*552f7358SJed Brown   Level: intermediate
7714*552f7358SJed Brown 
7715*552f7358SJed Brown .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure()
7716*552f7358SJed Brown @*/
7717*552f7358SJed Brown PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) {
7718*552f7358SJed Brown   PetscScalar    *array;
7719*552f7358SJed Brown   PetscInt       *points = PETSC_NULL;
7720*552f7358SJed Brown   PetscInt        offsets[32];
7721*552f7358SJed Brown   PetscInt        numFields, numPoints, off, dof, pStart, pEnd, p, q, f;
7722*552f7358SJed Brown   PetscErrorCode  ierr;
7723*552f7358SJed Brown 
7724*552f7358SJed Brown   PetscFunctionBegin;
7725*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7726*552f7358SJed Brown   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
7727*552f7358SJed Brown   if (!section) {
7728*552f7358SJed Brown     ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
7729*552f7358SJed Brown   }
7730*552f7358SJed Brown   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
7731*552f7358SJed Brown   if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields);
7732*552f7358SJed Brown   ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr);
7733*552f7358SJed Brown   ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);
7734*552f7358SJed Brown   /* Compress out points not in the section */
7735*552f7358SJed Brown   ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr);
7736*552f7358SJed Brown   for (p = 0, q = 0; p < numPoints*2; p += 2) {
7737*552f7358SJed Brown     if ((points[p] >= pStart) && (points[p] < pEnd)) {
7738*552f7358SJed Brown       points[q*2]   = points[p];
7739*552f7358SJed Brown       points[q*2+1] = points[p+1];
7740*552f7358SJed Brown       ++q;
7741*552f7358SJed Brown     }
7742*552f7358SJed Brown   }
7743*552f7358SJed Brown   numPoints = q;
7744*552f7358SJed Brown   for (p = 0; p < numPoints*2; p += 2) {
7745*552f7358SJed Brown     PetscInt fdof;
7746*552f7358SJed Brown 
7747*552f7358SJed Brown     for (f = 0; f < numFields; ++f) {
7748*552f7358SJed Brown       ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr);
7749*552f7358SJed Brown       offsets[f+1] += fdof;
7750*552f7358SJed Brown     }
7751*552f7358SJed Brown   }
7752*552f7358SJed Brown   for (f = 1; f < numFields; ++f) {
7753*552f7358SJed Brown     offsets[f+1] += offsets[f];
7754*552f7358SJed Brown   }
7755*552f7358SJed Brown   ierr = VecGetArray(v, &array);CHKERRQ(ierr);
7756*552f7358SJed Brown   if (numFields) {
7757*552f7358SJed Brown     switch(mode) {
7758*552f7358SJed Brown     case INSERT_VALUES:
7759*552f7358SJed Brown       for (p = 0; p < numPoints*2; p += 2) {
7760*552f7358SJed Brown         PetscInt o = points[p+1];
7761*552f7358SJed Brown         updatePointFields_private(section, points[p], offsets, insert, PETSC_FALSE, o, values, array);
7762*552f7358SJed Brown       } break;
7763*552f7358SJed Brown     case INSERT_ALL_VALUES:
7764*552f7358SJed Brown       for (p = 0; p < numPoints*2; p += 2) {
7765*552f7358SJed Brown         PetscInt o = points[p+1];
7766*552f7358SJed Brown         updatePointFields_private(section, points[p], offsets, insert, PETSC_TRUE,  o, values, array);
7767*552f7358SJed Brown       } break;
7768*552f7358SJed Brown     case ADD_VALUES:
7769*552f7358SJed Brown       for (p = 0; p < numPoints*2; p += 2) {
7770*552f7358SJed Brown         PetscInt o = points[p+1];
7771*552f7358SJed Brown         updatePointFields_private(section, points[p], offsets, add,    PETSC_FALSE, o, values, array);
7772*552f7358SJed Brown       } break;
7773*552f7358SJed Brown     case ADD_ALL_VALUES:
7774*552f7358SJed Brown       for (p = 0; p < numPoints*2; p += 2) {
7775*552f7358SJed Brown         PetscInt o = points[p+1];
7776*552f7358SJed Brown         updatePointFields_private(section, points[p], offsets, add,    PETSC_TRUE,  o, values, array);
7777*552f7358SJed Brown       } break;
7778*552f7358SJed Brown     default:
7779*552f7358SJed Brown       SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode);
7780*552f7358SJed Brown     }
7781*552f7358SJed Brown   } else {
7782*552f7358SJed Brown     switch(mode) {
7783*552f7358SJed Brown     case INSERT_VALUES:
7784*552f7358SJed Brown       for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) {
7785*552f7358SJed Brown         PetscInt o = points[p+1];
7786*552f7358SJed Brown         ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr);
7787*552f7358SJed Brown         updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array);
7788*552f7358SJed Brown       } break;
7789*552f7358SJed Brown     case INSERT_ALL_VALUES:
7790*552f7358SJed Brown       for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) {
7791*552f7358SJed Brown         PetscInt o = points[p+1];
7792*552f7358SJed Brown         ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr);
7793*552f7358SJed Brown         updatePoint_private(section, points[p], dof, insert, PETSC_TRUE,  o, &values[off], array);
7794*552f7358SJed Brown       } break;
7795*552f7358SJed Brown     case ADD_VALUES:
7796*552f7358SJed Brown       for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) {
7797*552f7358SJed Brown         PetscInt o = points[p+1];
7798*552f7358SJed Brown         ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr);
7799*552f7358SJed Brown         updatePoint_private(section, points[p], dof, add,    PETSC_FALSE, o, &values[off], array);
7800*552f7358SJed Brown       } break;
7801*552f7358SJed Brown     case ADD_ALL_VALUES:
7802*552f7358SJed Brown       for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) {
7803*552f7358SJed Brown         PetscInt o = points[p+1];
7804*552f7358SJed Brown         ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr);
7805*552f7358SJed Brown         updatePoint_private(section, points[p], dof, add,    PETSC_TRUE,  o, &values[off], array);
7806*552f7358SJed Brown       } break;
7807*552f7358SJed Brown     default:
7808*552f7358SJed Brown       SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode);
7809*552f7358SJed Brown     }
7810*552f7358SJed Brown   }
7811*552f7358SJed Brown   ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);
7812*552f7358SJed Brown   ierr = VecRestoreArray(v, &array);CHKERRQ(ierr);
7813*552f7358SJed Brown   PetscFunctionReturn(0);
7814*552f7358SJed Brown }
7815*552f7358SJed Brown 
7816*552f7358SJed Brown #undef __FUNCT__
7817*552f7358SJed Brown #define __FUNCT__ "DMPlexPrintMatSetValues"
7818*552f7358SJed Brown PetscErrorCode DMPlexPrintMatSetValues(Mat A, PetscInt point, PetscInt numIndices, const PetscInt indices[], PetscScalar values[])
7819*552f7358SJed Brown {
7820*552f7358SJed Brown   PetscMPIInt    rank;
7821*552f7358SJed Brown   PetscInt       i, j;
7822*552f7358SJed Brown   PetscErrorCode ierr;
7823*552f7358SJed Brown 
7824*552f7358SJed Brown   PetscFunctionBegin;
7825*552f7358SJed Brown   ierr = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr);
7826*552f7358SJed Brown   ierr = PetscPrintf(PETSC_COMM_SELF, "[%D]mat for sieve point %D\n", rank, point);CHKERRQ(ierr);
7827*552f7358SJed Brown   for (i = 0; i < numIndices; i++) {
7828*552f7358SJed Brown     ierr = PetscPrintf(PETSC_COMM_SELF, "[%D]mat indices[%D] = %D\n", rank, i, indices[i]);CHKERRQ(ierr);
7829*552f7358SJed Brown   }
7830*552f7358SJed Brown   for (i = 0; i < numIndices; i++) {
7831*552f7358SJed Brown     ierr = PetscPrintf(PETSC_COMM_SELF, "[%D]", rank);CHKERRQ(ierr);
7832*552f7358SJed Brown     for (j = 0; j < numIndices; j++) {
7833*552f7358SJed Brown #ifdef PETSC_USE_COMPLEX
7834*552f7358SJed Brown       ierr = PetscPrintf(PETSC_COMM_SELF, " (%G,%G)", PetscRealPart(values[i*numIndices+j]), PetscImaginaryPart(values[i*numIndices+j]));CHKERRQ(ierr);
7835*552f7358SJed Brown #else
7836*552f7358SJed Brown       ierr = PetscPrintf(PETSC_COMM_SELF, " %G", values[i*numIndices+j]);CHKERRQ(ierr);
7837*552f7358SJed Brown #endif
7838*552f7358SJed Brown     }
7839*552f7358SJed Brown     ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr);
7840*552f7358SJed Brown   }
7841*552f7358SJed Brown   PetscFunctionReturn(0);
7842*552f7358SJed Brown }
7843*552f7358SJed Brown 
7844*552f7358SJed Brown #undef __FUNCT__
7845*552f7358SJed Brown #define __FUNCT__ "indicesPoint_private"
7846*552f7358SJed Brown /* . off - The global offset of this point */
7847*552f7358SJed Brown PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt dof, PetscInt off, PetscBool setBC, PetscInt orientation, PetscInt indices[]) {
7848*552f7358SJed Brown   PetscInt        cdof;  /* The number of constraints on this point */
7849*552f7358SJed Brown   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
7850*552f7358SJed Brown   PetscInt        cind = 0, k;
7851*552f7358SJed Brown   PetscErrorCode  ierr;
7852*552f7358SJed Brown 
7853*552f7358SJed Brown   PetscFunctionBegin;
7854*552f7358SJed Brown   ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr);
7855*552f7358SJed Brown   ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr);
7856*552f7358SJed Brown   if (!cdof || setBC) {
7857*552f7358SJed Brown     if (orientation >= 0) {
7858*552f7358SJed Brown       for (k = 0; k < dof; ++k) {
7859*552f7358SJed Brown         indices[k] = off+k;
7860*552f7358SJed Brown       }
7861*552f7358SJed Brown     } else {
7862*552f7358SJed Brown       for (k = 0; k < dof; ++k) {
7863*552f7358SJed Brown         indices[dof-k-1] = off+k;
7864*552f7358SJed Brown       }
7865*552f7358SJed Brown     }
7866*552f7358SJed Brown   } else {
7867*552f7358SJed Brown     ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr);
7868*552f7358SJed Brown     if (orientation >= 0) {
7869*552f7358SJed Brown       for (k = 0; k < dof; ++k) {
7870*552f7358SJed Brown         if ((cind < cdof) && (k == cdofs[cind])) {
7871*552f7358SJed Brown           /* Insert check for returning constrained indices */
7872*552f7358SJed Brown           indices[k] = -(off+k+1);
7873*552f7358SJed Brown           ++cind;
7874*552f7358SJed Brown         } else {
7875*552f7358SJed Brown           indices[k] = off+k-cind;
7876*552f7358SJed Brown         }
7877*552f7358SJed Brown       }
7878*552f7358SJed Brown     } else {
7879*552f7358SJed Brown       for (k = 0; k < dof; ++k) {
7880*552f7358SJed Brown         if ((cind < cdof) && (k == cdofs[cind])) {
7881*552f7358SJed Brown           /* Insert check for returning constrained indices */
7882*552f7358SJed Brown           indices[dof-k-1] = -(off+k+1);
7883*552f7358SJed Brown           ++cind;
7884*552f7358SJed Brown         } else {
7885*552f7358SJed Brown           indices[dof-k-1] = off+k-cind;
7886*552f7358SJed Brown         }
7887*552f7358SJed Brown       }
7888*552f7358SJed Brown     }
7889*552f7358SJed Brown   }
7890*552f7358SJed Brown   PetscFunctionReturn(0);
7891*552f7358SJed Brown }
7892*552f7358SJed Brown 
7893*552f7358SJed Brown #undef __FUNCT__
7894*552f7358SJed Brown #define __FUNCT__ "indicesPointFields_private"
7895*552f7358SJed Brown /* . off - The global offset of this point */
7896*552f7358SJed Brown PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) {
7897*552f7358SJed Brown   PetscInt       numFields, foff, f;
7898*552f7358SJed Brown   PetscErrorCode ierr;
7899*552f7358SJed Brown 
7900*552f7358SJed Brown   PetscFunctionBegin;
7901*552f7358SJed Brown   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
7902*552f7358SJed Brown   for (f = 0, foff = 0; f < numFields; ++f) {
7903*552f7358SJed Brown     PetscInt        fdof, fcomp, cfdof;
7904*552f7358SJed Brown     const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
7905*552f7358SJed Brown     PetscInt        cind = 0, k, c;
7906*552f7358SJed Brown 
7907*552f7358SJed Brown     ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr);
7908*552f7358SJed Brown     ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr);
7909*552f7358SJed Brown     ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr);
7910*552f7358SJed Brown     if (!cfdof || setBC) {
7911*552f7358SJed Brown       if (orientation >= 0) {
7912*552f7358SJed Brown         for (k = 0; k < fdof; ++k) {
7913*552f7358SJed Brown           indices[foffs[f]+k] = off+foff+k;
7914*552f7358SJed Brown         }
7915*552f7358SJed Brown       } else {
7916*552f7358SJed Brown         for (k = fdof/fcomp-1; k >= 0; --k) {
7917*552f7358SJed Brown           for (c = 0; c < fcomp; ++c) {
7918*552f7358SJed Brown             indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c;
7919*552f7358SJed Brown           }
7920*552f7358SJed Brown         }
7921*552f7358SJed Brown       }
7922*552f7358SJed Brown     } else {
7923*552f7358SJed Brown       ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr);
7924*552f7358SJed Brown       if (orientation >= 0) {
7925*552f7358SJed Brown         for (k = 0; k < fdof; ++k) {
7926*552f7358SJed Brown           if ((cind < cfdof) && (k == fcdofs[cind])) {
7927*552f7358SJed Brown             indices[foffs[f]+k] = -(off+foff+k+1);
7928*552f7358SJed Brown             ++cind;
7929*552f7358SJed Brown           } else {
7930*552f7358SJed Brown             indices[foffs[f]+k] = off+foff+k-cind;
7931*552f7358SJed Brown           }
7932*552f7358SJed Brown         }
7933*552f7358SJed Brown       } else {
7934*552f7358SJed Brown         for (k = fdof/fcomp-1; k >= 0; --k) {
7935*552f7358SJed Brown           for (c = 0; c < fcomp; ++c) {
7936*552f7358SJed Brown             if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) {
7937*552f7358SJed Brown               indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1);
7938*552f7358SJed Brown               ++cind;
7939*552f7358SJed Brown             } else {
7940*552f7358SJed Brown               indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind;
7941*552f7358SJed Brown             }
7942*552f7358SJed Brown           }
7943*552f7358SJed Brown         }
7944*552f7358SJed Brown       }
7945*552f7358SJed Brown     }
7946*552f7358SJed Brown     foff     += fdof - cfdof;
7947*552f7358SJed Brown     foffs[f] += fdof;
7948*552f7358SJed Brown   }
7949*552f7358SJed Brown   PetscFunctionReturn(0);
7950*552f7358SJed Brown }
7951*552f7358SJed Brown 
7952*552f7358SJed Brown #undef __FUNCT__
7953*552f7358SJed Brown #define __FUNCT__ "DMPlexMatSetClosure"
7954*552f7358SJed Brown PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, PetscScalar values[], InsertMode mode)
7955*552f7358SJed Brown {
7956*552f7358SJed Brown   DM_Plex     *mesh   = (DM_Plex *) dm->data;
7957*552f7358SJed Brown   PetscInt       *points = PETSC_NULL;
7958*552f7358SJed Brown   PetscInt       *indices;
7959*552f7358SJed Brown   PetscInt        offsets[32];
7960*552f7358SJed Brown   PetscInt        numFields, numPoints, numIndices, dof, off, globalOff, pStart, pEnd, p, q, f;
7961*552f7358SJed Brown   PetscBool       useDefault       =       !section ? PETSC_TRUE : PETSC_FALSE;
7962*552f7358SJed Brown   PetscBool       useGlobalDefault = !globalSection ? PETSC_TRUE : PETSC_FALSE;
7963*552f7358SJed Brown   PetscErrorCode  ierr;
7964*552f7358SJed Brown 
7965*552f7358SJed Brown   PetscFunctionBegin;
7966*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7967*552f7358SJed Brown   PetscValidHeaderSpecific(A, MAT_CLASSID, 3);
7968*552f7358SJed Brown   if (useDefault) {
7969*552f7358SJed Brown     ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
7970*552f7358SJed Brown   }
7971*552f7358SJed Brown   if (useGlobalDefault) {
7972*552f7358SJed Brown     if (useDefault) {
7973*552f7358SJed Brown       ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);
7974*552f7358SJed Brown     } else {
7975*552f7358SJed Brown       ierr = PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr);
7976*552f7358SJed Brown     }
7977*552f7358SJed Brown   }
7978*552f7358SJed Brown   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
7979*552f7358SJed Brown   if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields);
7980*552f7358SJed Brown   ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr);
7981*552f7358SJed Brown   ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);
7982*552f7358SJed Brown   /* Compress out points not in the section */
7983*552f7358SJed Brown   ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr);
7984*552f7358SJed Brown   for (p = 0, q = 0; p < numPoints*2; p += 2) {
7985*552f7358SJed Brown     if ((points[p] >= pStart) && (points[p] < pEnd)) {
7986*552f7358SJed Brown       points[q*2]   = points[p];
7987*552f7358SJed Brown       points[q*2+1] = points[p+1];
7988*552f7358SJed Brown       ++q;
7989*552f7358SJed Brown     }
7990*552f7358SJed Brown   }
7991*552f7358SJed Brown   numPoints = q;
7992*552f7358SJed Brown   for (p = 0, numIndices = 0; p < numPoints*2; p += 2) {
7993*552f7358SJed Brown     PetscInt fdof;
7994*552f7358SJed Brown 
7995*552f7358SJed Brown     ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr);
7996*552f7358SJed Brown     for (f = 0; f < numFields; ++f) {
7997*552f7358SJed Brown       ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr);
7998*552f7358SJed Brown       offsets[f+1] += fdof;
7999*552f7358SJed Brown     }
8000*552f7358SJed Brown     numIndices += dof;
8001*552f7358SJed Brown   }
8002*552f7358SJed Brown   for (f = 1; f < numFields; ++f) {
8003*552f7358SJed Brown     offsets[f+1] += offsets[f];
8004*552f7358SJed Brown   }
8005*552f7358SJed Brown   if (numFields && offsets[numFields] != numIndices) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices);
8006*552f7358SJed Brown   ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr);
8007*552f7358SJed Brown   if (numFields) {
8008*552f7358SJed Brown     for (p = 0; p < numPoints*2; p += 2) {
8009*552f7358SJed Brown       PetscInt o = points[p+1];
8010*552f7358SJed Brown       ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr);
8011*552f7358SJed Brown       indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices);
8012*552f7358SJed Brown     }
8013*552f7358SJed Brown   } else {
8014*552f7358SJed Brown     for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) {
8015*552f7358SJed Brown       PetscInt o = points[p+1];
8016*552f7358SJed Brown       ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr);
8017*552f7358SJed Brown       indicesPoint_private(section, points[p], dof, globalOff < 0 ? -(globalOff+1) : globalOff, PETSC_FALSE, o, &indices[off]);
8018*552f7358SJed Brown     }
8019*552f7358SJed Brown   }
8020*552f7358SJed Brown   if (useGlobalDefault && !useDefault) {
8021*552f7358SJed Brown     ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr);
8022*552f7358SJed Brown   }
8023*552f7358SJed Brown   if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(A, point, numIndices, indices, values);CHKERRQ(ierr);}
8024*552f7358SJed Brown   ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode);
8025*552f7358SJed Brown   if (ierr) {
8026*552f7358SJed Brown     PetscMPIInt    rank;
8027*552f7358SJed Brown     PetscErrorCode ierr2;
8028*552f7358SJed Brown 
8029*552f7358SJed Brown     ierr2 = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr2);
8030*552f7358SJed Brown     ierr2 = PetscPrintf(PETSC_COMM_SELF, "[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2);
8031*552f7358SJed Brown     ierr2 = DMPlexPrintMatSetValues(A, point, numIndices, indices, values);CHKERRQ(ierr2);
8032*552f7358SJed Brown     ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr);
8033*552f7358SJed Brown     CHKERRQ(ierr);
8034*552f7358SJed Brown   }
8035*552f7358SJed Brown   ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);
8036*552f7358SJed Brown   ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr);
8037*552f7358SJed Brown   PetscFunctionReturn(0);
8038*552f7358SJed Brown }
8039*552f7358SJed Brown 
8040*552f7358SJed Brown #undef __FUNCT__
8041*552f7358SJed Brown #define __FUNCT__ "DMPlexComputeTriangleGeometry_private"
8042*552f7358SJed Brown PetscErrorCode DMPlexComputeTriangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ)
8043*552f7358SJed Brown {
8044*552f7358SJed Brown   PetscSection       coordSection;
8045*552f7358SJed Brown   Vec                coordinates;
8046*552f7358SJed Brown   const PetscScalar *coords;
8047*552f7358SJed Brown   const PetscInt     dim = 2;
8048*552f7358SJed Brown   PetscInt           d, f;
8049*552f7358SJed Brown   PetscErrorCode     ierr;
8050*552f7358SJed Brown 
8051*552f7358SJed Brown   PetscFunctionBegin;
8052*552f7358SJed Brown   ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
8053*552f7358SJed Brown   ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr);
8054*552f7358SJed Brown   ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr);
8055*552f7358SJed Brown   if (v0) {
8056*552f7358SJed Brown     for (d = 0; d < dim; d++) {
8057*552f7358SJed Brown       v0[d] = PetscRealPart(coords[d]);
8058*552f7358SJed Brown     }
8059*552f7358SJed Brown   }
8060*552f7358SJed Brown   if (J) {
8061*552f7358SJed Brown     for (d = 0; d < dim; d++) {
8062*552f7358SJed Brown       for (f = 0; f < dim; f++) {
8063*552f7358SJed Brown         J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d]));
8064*552f7358SJed Brown       }
8065*552f7358SJed Brown     }
8066*552f7358SJed Brown     *detJ = J[0]*J[3] - J[1]*J[2];
8067*552f7358SJed Brown #if 0
8068*552f7358SJed Brown     if (detJ < 0.0) {
8069*552f7358SJed Brown       const PetscReal xLength = mesh->periodicity[0];
8070*552f7358SJed Brown 
8071*552f7358SJed Brown       if (xLength != 0.0) {
8072*552f7358SJed Brown         PetscReal v0x = coords[0*dim+0];
8073*552f7358SJed Brown 
8074*552f7358SJed Brown         if (v0x == 0.0) {
8075*552f7358SJed Brown           v0x = v0[0] = xLength;
8076*552f7358SJed Brown         }
8077*552f7358SJed Brown         for (f = 0; f < dim; f++) {
8078*552f7358SJed Brown           const PetscReal px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0];
8079*552f7358SJed Brown 
8080*552f7358SJed Brown           J[0*dim+f] = 0.5*(px - v0x);
8081*552f7358SJed Brown         }
8082*552f7358SJed Brown       }
8083*552f7358SJed Brown       detJ = J[0]*J[3] - J[1]*J[2];
8084*552f7358SJed Brown     }
8085*552f7358SJed Brown #endif
8086*552f7358SJed Brown     PetscLogFlops(8.0 + 3.0);
8087*552f7358SJed Brown   }
8088*552f7358SJed Brown   if (invJ) {
8089*552f7358SJed Brown     const PetscReal invDet = 1.0/(*detJ);
8090*552f7358SJed Brown 
8091*552f7358SJed Brown     invJ[0] =  invDet*J[3];
8092*552f7358SJed Brown     invJ[1] = -invDet*J[1];
8093*552f7358SJed Brown     invJ[2] = -invDet*J[2];
8094*552f7358SJed Brown     invJ[3] =  invDet*J[0];
8095*552f7358SJed Brown     PetscLogFlops(5.0);
8096*552f7358SJed Brown   }
8097*552f7358SJed Brown   ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr);
8098*552f7358SJed Brown   PetscFunctionReturn(0);
8099*552f7358SJed Brown }
8100*552f7358SJed Brown 
8101*552f7358SJed Brown #undef __FUNCT__
8102*552f7358SJed Brown #define __FUNCT__ "DMPlexComputeRectangleGeometry_private"
8103*552f7358SJed Brown PetscErrorCode DMPlexComputeRectangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ)
8104*552f7358SJed Brown {
8105*552f7358SJed Brown   PetscSection       coordSection;
8106*552f7358SJed Brown   Vec                coordinates;
8107*552f7358SJed Brown   const PetscScalar *coords;
8108*552f7358SJed Brown   const PetscInt     dim = 2;
8109*552f7358SJed Brown   PetscInt           d, f;
8110*552f7358SJed Brown   PetscErrorCode     ierr;
8111*552f7358SJed Brown 
8112*552f7358SJed Brown   PetscFunctionBegin;
8113*552f7358SJed Brown   ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
8114*552f7358SJed Brown   ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr);
8115*552f7358SJed Brown   ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr);
8116*552f7358SJed Brown   if (v0) {
8117*552f7358SJed Brown     for (d = 0; d < dim; d++) {
8118*552f7358SJed Brown       v0[d] = PetscRealPart(coords[d]);
8119*552f7358SJed Brown     }
8120*552f7358SJed Brown   }
8121*552f7358SJed Brown   if (J) {
8122*552f7358SJed Brown     for (d = 0; d < dim; d++) {
8123*552f7358SJed Brown       for (f = 0; f < dim; f++) {
8124*552f7358SJed Brown         J[d*dim+f] = 0.5*(PetscRealPart(coords[(f*2+1)*dim+d]) - PetscRealPart(coords[0*dim+d]));
8125*552f7358SJed Brown       }
8126*552f7358SJed Brown     }
8127*552f7358SJed Brown     *detJ = J[0]*J[3] - J[1]*J[2];
8128*552f7358SJed Brown     PetscLogFlops(8.0 + 3.0);
8129*552f7358SJed Brown   }
8130*552f7358SJed Brown   if (invJ) {
8131*552f7358SJed Brown     const PetscReal invDet = 1.0/(*detJ);
8132*552f7358SJed Brown 
8133*552f7358SJed Brown     invJ[0] =  invDet*J[3];
8134*552f7358SJed Brown     invJ[1] = -invDet*J[1];
8135*552f7358SJed Brown     invJ[2] = -invDet*J[2];
8136*552f7358SJed Brown     invJ[3] =  invDet*J[0];
8137*552f7358SJed Brown     PetscLogFlops(5.0);
8138*552f7358SJed Brown   }
8139*552f7358SJed Brown   ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr);
8140*552f7358SJed Brown   PetscFunctionReturn(0);
8141*552f7358SJed Brown }
8142*552f7358SJed Brown 
8143*552f7358SJed Brown #undef __FUNCT__
8144*552f7358SJed Brown #define __FUNCT__ "DMPlexComputeTetrahedronGeometry_private"
8145*552f7358SJed Brown PetscErrorCode DMPlexComputeTetrahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ)
8146*552f7358SJed Brown {
8147*552f7358SJed Brown   PetscSection       coordSection;
8148*552f7358SJed Brown   Vec                coordinates;
8149*552f7358SJed Brown   const PetscScalar *coords;
8150*552f7358SJed Brown   const PetscInt     dim = 3;
8151*552f7358SJed Brown   PetscInt           d, f;
8152*552f7358SJed Brown   PetscErrorCode     ierr;
8153*552f7358SJed Brown 
8154*552f7358SJed Brown   PetscFunctionBegin;
8155*552f7358SJed Brown   ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
8156*552f7358SJed Brown   ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr);
8157*552f7358SJed Brown   ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr);
8158*552f7358SJed Brown   if (v0) {
8159*552f7358SJed Brown     for (d = 0; d < dim; d++) {
8160*552f7358SJed Brown       v0[d] = PetscRealPart(coords[d]);
8161*552f7358SJed Brown     }
8162*552f7358SJed Brown   }
8163*552f7358SJed Brown   if (J) {
8164*552f7358SJed Brown     for (d = 0; d < dim; d++) {
8165*552f7358SJed Brown       for (f = 0; f < dim; f++) {
8166*552f7358SJed Brown         J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d]));
8167*552f7358SJed Brown       }
8168*552f7358SJed Brown     }
8169*552f7358SJed Brown     /* ??? This does not work with CTetGen: The minus sign is here since I orient the first face to get the outward normal */
8170*552f7358SJed Brown     *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) +
8171*552f7358SJed Brown              J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) +
8172*552f7358SJed Brown              J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]));
8173*552f7358SJed Brown     PetscLogFlops(18.0 + 12.0);
8174*552f7358SJed Brown   }
8175*552f7358SJed Brown   if (invJ) {
8176*552f7358SJed Brown     const PetscReal invDet = -1.0/(*detJ);
8177*552f7358SJed Brown 
8178*552f7358SJed Brown     invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]);
8179*552f7358SJed Brown     invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]);
8180*552f7358SJed Brown     invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]);
8181*552f7358SJed Brown     invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]);
8182*552f7358SJed Brown     invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]);
8183*552f7358SJed Brown     invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]);
8184*552f7358SJed Brown     invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]);
8185*552f7358SJed Brown     invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]);
8186*552f7358SJed Brown     invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]);
8187*552f7358SJed Brown     PetscLogFlops(37.0);
8188*552f7358SJed Brown   }
8189*552f7358SJed Brown   ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr);
8190*552f7358SJed Brown   PetscFunctionReturn(0);
8191*552f7358SJed Brown }
8192*552f7358SJed Brown 
8193*552f7358SJed Brown #undef __FUNCT__
8194*552f7358SJed Brown #define __FUNCT__ "DMPlexComputeHexahedronGeometry_private"
8195*552f7358SJed Brown PetscErrorCode DMPlexComputeHexahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ)
8196*552f7358SJed Brown {
8197*552f7358SJed Brown   PetscSection       coordSection;
8198*552f7358SJed Brown   Vec                coordinates;
8199*552f7358SJed Brown   const PetscScalar *coords;
8200*552f7358SJed Brown   const PetscInt     dim = 3;
8201*552f7358SJed Brown   PetscInt           d;
8202*552f7358SJed Brown   PetscErrorCode     ierr;
8203*552f7358SJed Brown 
8204*552f7358SJed Brown   PetscFunctionBegin;
8205*552f7358SJed Brown   ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
8206*552f7358SJed Brown   ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr);
8207*552f7358SJed Brown   ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr);
8208*552f7358SJed Brown   if (v0) {
8209*552f7358SJed Brown     for (d = 0; d < dim; d++) {
8210*552f7358SJed Brown       v0[d] = PetscRealPart(coords[d]);
8211*552f7358SJed Brown     }
8212*552f7358SJed Brown   }
8213*552f7358SJed Brown   if (J) {
8214*552f7358SJed Brown     for (d = 0; d < dim; d++) {
8215*552f7358SJed Brown       J[d*dim+0] = 0.5*(PetscRealPart(coords[(0+1)*dim+d]) - PetscRealPart(coords[0*dim+d]));
8216*552f7358SJed Brown       J[d*dim+1] = 0.5*(PetscRealPart(coords[(1+1)*dim+d]) - PetscRealPart(coords[0*dim+d]));
8217*552f7358SJed Brown       J[d*dim+2] = 0.5*(PetscRealPart(coords[(3+1)*dim+d]) - PetscRealPart(coords[0*dim+d]));
8218*552f7358SJed Brown     }
8219*552f7358SJed Brown     *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) +
8220*552f7358SJed Brown              J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) +
8221*552f7358SJed Brown              J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]));
8222*552f7358SJed Brown     PetscLogFlops(18.0 + 12.0);
8223*552f7358SJed Brown   }
8224*552f7358SJed Brown   if (invJ) {
8225*552f7358SJed Brown     const PetscReal invDet = -1.0/(*detJ);
8226*552f7358SJed Brown 
8227*552f7358SJed Brown     invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]);
8228*552f7358SJed Brown     invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]);
8229*552f7358SJed Brown     invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]);
8230*552f7358SJed Brown     invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]);
8231*552f7358SJed Brown     invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]);
8232*552f7358SJed Brown     invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]);
8233*552f7358SJed Brown     invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]);
8234*552f7358SJed Brown     invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]);
8235*552f7358SJed Brown     invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]);
8236*552f7358SJed Brown     PetscLogFlops(37.0);
8237*552f7358SJed Brown   }
8238*552f7358SJed Brown   *detJ *= 8.0;
8239*552f7358SJed Brown   ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr);
8240*552f7358SJed Brown   PetscFunctionReturn(0);
8241*552f7358SJed Brown }
8242*552f7358SJed Brown 
8243*552f7358SJed Brown #undef __FUNCT__
8244*552f7358SJed Brown #define __FUNCT__ "DMPlexComputeCellGeometry"
8245*552f7358SJed Brown /*@C
8246*552f7358SJed Brown   DMPlexComputeCellGeometry - Compute the Jacobian, inverse Jacobian, and Jacobian determinant for a given cell
8247*552f7358SJed Brown 
8248*552f7358SJed Brown   Collective on DM
8249*552f7358SJed Brown 
8250*552f7358SJed Brown   Input Arguments:
8251*552f7358SJed Brown + dm   - the DM
8252*552f7358SJed Brown - cell - the cell
8253*552f7358SJed Brown 
8254*552f7358SJed Brown   Output Arguments:
8255*552f7358SJed Brown + v0   - the translation part of this affine transform
8256*552f7358SJed Brown . J    - the Jacobian of the transform to the reference element
8257*552f7358SJed Brown . invJ - the inverse of the Jacobian
8258*552f7358SJed Brown - detJ - the Jacobian determinant
8259*552f7358SJed Brown 
8260*552f7358SJed Brown   Level: advanced
8261*552f7358SJed Brown 
8262*552f7358SJed Brown .seealso: DMPlexGetCoordinateSection(), DMPlexGetCoordinateVec()
8263*552f7358SJed Brown @*/
8264*552f7358SJed Brown PetscErrorCode DMPlexComputeCellGeometry(DM dm, PetscInt cell, PetscReal *v0, PetscReal *J, PetscReal *invJ, PetscReal *detJ) {
8265*552f7358SJed Brown   PetscInt       dim, maxConeSize;
8266*552f7358SJed Brown   PetscErrorCode ierr;
8267*552f7358SJed Brown 
8268*552f7358SJed Brown   PetscFunctionBegin;
8269*552f7358SJed Brown   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
8270*552f7358SJed Brown   ierr = DMPlexGetMaxSizes(dm, &maxConeSize, PETSC_NULL);CHKERRQ(ierr);
8271*552f7358SJed Brown   switch(dim) {
8272*552f7358SJed Brown   case 2:
8273*552f7358SJed Brown     switch(maxConeSize) {
8274*552f7358SJed Brown     case 3:
8275*552f7358SJed Brown       ierr = DMPlexComputeTriangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr);
8276*552f7358SJed Brown       break;
8277*552f7358SJed Brown     case 4:
8278*552f7358SJed Brown       ierr = DMPlexComputeRectangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr);
8279*552f7358SJed Brown       break;
8280*552f7358SJed Brown     default:
8281*552f7358SJed Brown       SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of cell vertices %D for element geometry computation", maxConeSize);
8282*552f7358SJed Brown     }
8283*552f7358SJed Brown     break;
8284*552f7358SJed Brown   case 3:
8285*552f7358SJed Brown     switch(maxConeSize) {
8286*552f7358SJed Brown     case 4:
8287*552f7358SJed Brown       ierr = DMPlexComputeTetrahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr);
8288*552f7358SJed Brown       break;
8289*552f7358SJed Brown     case 8:
8290*552f7358SJed Brown       ierr = DMPlexComputeHexahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr);
8291*552f7358SJed Brown       break;
8292*552f7358SJed Brown     default:
8293*552f7358SJed Brown       SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of cell vertices %D for element geometry computation", maxConeSize);
8294*552f7358SJed Brown     }
8295*552f7358SJed Brown     break;
8296*552f7358SJed Brown   default:
8297*552f7358SJed Brown     SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported dimension %D for element geometry computation", dim);
8298*552f7358SJed Brown   }
8299*552f7358SJed Brown   PetscFunctionReturn(0);
8300*552f7358SJed Brown }
8301*552f7358SJed Brown 
8302*552f7358SJed Brown #undef __FUNCT__
8303*552f7358SJed Brown #define __FUNCT__ "DMPlexGetFaceOrientation"
8304*552f7358SJed Brown PetscErrorCode DMPlexGetFaceOrientation(DM dm, PetscInt cell, PetscInt numCorners, PetscInt indices[], PetscInt oppositeVertex, PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) {
8305*552f7358SJed Brown   MPI_Comm       comm      = ((PetscObject) dm)->comm;
8306*552f7358SJed Brown   PetscBool      posOrient = PETSC_FALSE;
8307*552f7358SJed Brown   const PetscInt debug     = 0;
8308*552f7358SJed Brown   PetscInt       cellDim, faceSize, f;
8309*552f7358SJed Brown   PetscErrorCode ierr;
8310*552f7358SJed Brown 
8311*552f7358SJed Brown   ierr = DMPlexGetDimension(dm, &cellDim);CHKERRQ(ierr);
8312*552f7358SJed Brown   if (debug) {PetscPrintf(comm, "cellDim: %d numCorners: %d\n", cellDim, numCorners);CHKERRQ(ierr);}
8313*552f7358SJed Brown 
8314*552f7358SJed Brown   if (cellDim == numCorners-1) {
8315*552f7358SJed Brown     /* Simplices */
8316*552f7358SJed Brown     faceSize  = numCorners-1;
8317*552f7358SJed Brown     posOrient = !(oppositeVertex%2) ? PETSC_TRUE : PETSC_FALSE;
8318*552f7358SJed Brown   } else if (cellDim == 1 && numCorners == 3) {
8319*552f7358SJed Brown     /* Quadratic line */
8320*552f7358SJed Brown     faceSize  = 1;
8321*552f7358SJed Brown     posOrient = PETSC_TRUE;
8322*552f7358SJed Brown   } else if (cellDim == 2 && numCorners == 4) {
8323*552f7358SJed Brown     /* Quads */
8324*552f7358SJed Brown     faceSize  = 2;
8325*552f7358SJed Brown     if ((indices[1] > indices[0]) && (indices[1] - indices[0] == 1)) {
8326*552f7358SJed Brown       posOrient = PETSC_TRUE;
8327*552f7358SJed Brown     } else if ((indices[0] == 3) && (indices[1] == 0)) {
8328*552f7358SJed Brown       posOrient = PETSC_TRUE;
8329*552f7358SJed Brown     } else {
8330*552f7358SJed Brown       if (((indices[0] > indices[1]) && (indices[0] - indices[1] == 1)) || ((indices[0] == 0) && (indices[1] == 3))) {
8331*552f7358SJed Brown         posOrient = PETSC_FALSE;
8332*552f7358SJed Brown       } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossedge");
8333*552f7358SJed Brown     }
8334*552f7358SJed Brown   } else if (cellDim == 2 && numCorners == 6) {
8335*552f7358SJed Brown     /* Quadratic triangle (I hate this) */
8336*552f7358SJed Brown     /* Edges are determined by the first 2 vertices (corners of edges) */
8337*552f7358SJed Brown     const PetscInt faceSizeTri = 3;
8338*552f7358SJed Brown     PetscInt  sortedIndices[3], i, iFace;
8339*552f7358SJed Brown     PetscBool found = PETSC_FALSE;
8340*552f7358SJed Brown     PetscInt  faceVerticesTriSorted[9] = {
8341*552f7358SJed Brown       0, 3,  4, /* bottom */
8342*552f7358SJed Brown       1, 4,  5, /* right */
8343*552f7358SJed Brown       2, 3,  5, /* left */
8344*552f7358SJed Brown     };
8345*552f7358SJed Brown     PetscInt  faceVerticesTri[9] = {
8346*552f7358SJed Brown       0, 3,  4, /* bottom */
8347*552f7358SJed Brown       1, 4,  5, /* right */
8348*552f7358SJed Brown       2, 5,  3, /* left */
8349*552f7358SJed Brown     };
8350*552f7358SJed Brown 
8351*552f7358SJed Brown     faceSize = faceSizeTri;
8352*552f7358SJed Brown     for (i = 0; i < faceSizeTri; ++i) sortedIndices[i] = indices[i];
8353*552f7358SJed Brown     ierr = PetscSortInt(faceSizeTri, sortedIndices);CHKERRQ(ierr);
8354*552f7358SJed Brown     for (iFace = 0; iFace < 3; ++iFace) {
8355*552f7358SJed Brown       const PetscInt ii = iFace*faceSizeTri;
8356*552f7358SJed Brown       PetscInt       fVertex, cVertex;
8357*552f7358SJed Brown 
8358*552f7358SJed Brown       if ((sortedIndices[0] == faceVerticesTriSorted[ii+0]) &&
8359*552f7358SJed Brown           (sortedIndices[1] == faceVerticesTriSorted[ii+1])) {
8360*552f7358SJed Brown         for (fVertex = 0; fVertex < faceSizeTri; ++fVertex) {
8361*552f7358SJed Brown           for (cVertex = 0; cVertex < faceSizeTri; ++cVertex) {
8362*552f7358SJed Brown             if (indices[cVertex] == faceVerticesTri[ii+fVertex]) {
8363*552f7358SJed Brown               faceVertices[fVertex] = origVertices[cVertex];
8364*552f7358SJed Brown               break;
8365*552f7358SJed Brown             }
8366*552f7358SJed Brown           }
8367*552f7358SJed Brown         }
8368*552f7358SJed Brown         found = PETSC_TRUE;
8369*552f7358SJed Brown         break;
8370*552f7358SJed Brown       }
8371*552f7358SJed Brown     }
8372*552f7358SJed Brown     if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid tri crossface");
8373*552f7358SJed Brown     if (posOriented) {*posOriented = PETSC_TRUE;}
8374*552f7358SJed Brown     PetscFunctionReturn(0);
8375*552f7358SJed Brown   } else if (cellDim == 2 && numCorners == 9) {
8376*552f7358SJed Brown     /* Quadratic quad (I hate this) */
8377*552f7358SJed Brown     /* Edges are determined by the first 2 vertices (corners of edges) */
8378*552f7358SJed Brown     const PetscInt faceSizeQuad = 3;
8379*552f7358SJed Brown     PetscInt  sortedIndices[3], i, iFace;
8380*552f7358SJed Brown     PetscBool found = PETSC_FALSE;
8381*552f7358SJed Brown     PetscInt  faceVerticesQuadSorted[12] = {
8382*552f7358SJed Brown       0, 1,  4, /* bottom */
8383*552f7358SJed Brown       1, 2,  5, /* right */
8384*552f7358SJed Brown       2, 3,  6, /* top */
8385*552f7358SJed Brown       0, 3,  7, /* left */
8386*552f7358SJed Brown     };
8387*552f7358SJed Brown     PetscInt  faceVerticesQuad[12] = {
8388*552f7358SJed Brown       0, 1,  4, /* bottom */
8389*552f7358SJed Brown       1, 2,  5, /* right */
8390*552f7358SJed Brown       2, 3,  6, /* top */
8391*552f7358SJed Brown       3, 0,  7, /* left */
8392*552f7358SJed Brown     };
8393*552f7358SJed Brown 
8394*552f7358SJed Brown     faceSize = faceSizeQuad;
8395*552f7358SJed Brown     for (i = 0; i < faceSizeQuad; ++i) sortedIndices[i] = indices[i];
8396*552f7358SJed Brown     ierr = PetscSortInt(faceSizeQuad, sortedIndices);CHKERRQ(ierr);
8397*552f7358SJed Brown     for (iFace = 0; iFace < 4; ++iFace) {
8398*552f7358SJed Brown       const PetscInt ii = iFace*faceSizeQuad;
8399*552f7358SJed Brown       PetscInt       fVertex, cVertex;
8400*552f7358SJed Brown 
8401*552f7358SJed Brown       if ((sortedIndices[0] == faceVerticesQuadSorted[ii+0]) &&
8402*552f7358SJed Brown           (sortedIndices[1] == faceVerticesQuadSorted[ii+1])) {
8403*552f7358SJed Brown         for (fVertex = 0; fVertex < faceSizeQuad; ++fVertex) {
8404*552f7358SJed Brown           for (cVertex = 0; cVertex < faceSizeQuad; ++cVertex) {
8405*552f7358SJed Brown             if (indices[cVertex] == faceVerticesQuad[ii+fVertex]) {
8406*552f7358SJed Brown               faceVertices[fVertex] = origVertices[cVertex];
8407*552f7358SJed Brown               break;
8408*552f7358SJed Brown             }
8409*552f7358SJed Brown           }
8410*552f7358SJed Brown         }
8411*552f7358SJed Brown         found = PETSC_TRUE;
8412*552f7358SJed Brown         break;
8413*552f7358SJed Brown       }
8414*552f7358SJed Brown     }
8415*552f7358SJed Brown     if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossface");
8416*552f7358SJed Brown     if (posOriented) {*posOriented = PETSC_TRUE;}
8417*552f7358SJed Brown     PetscFunctionReturn(0);
8418*552f7358SJed Brown   } else if (cellDim == 3 && numCorners == 8) {
8419*552f7358SJed Brown     /* Hexes
8420*552f7358SJed Brown        A hex is two oriented quads with the normal of the first
8421*552f7358SJed Brown        pointing up at the second.
8422*552f7358SJed Brown 
8423*552f7358SJed Brown           7---6
8424*552f7358SJed Brown          /|  /|
8425*552f7358SJed Brown         4---5 |
8426*552f7358SJed Brown         | 3-|-2
8427*552f7358SJed Brown         |/  |/
8428*552f7358SJed Brown         0---1
8429*552f7358SJed Brown 
8430*552f7358SJed Brown         Faces are determined by the first 4 vertices (corners of faces) */
8431*552f7358SJed Brown     const PetscInt faceSizeHex = 4;
8432*552f7358SJed Brown     PetscInt  sortedIndices[4], i, iFace;
8433*552f7358SJed Brown     PetscBool found = PETSC_FALSE;
8434*552f7358SJed Brown     PetscInt faceVerticesHexSorted[24] = {
8435*552f7358SJed Brown       0, 1, 2, 3,  /* bottom */
8436*552f7358SJed Brown       4, 5, 6, 7,  /* top */
8437*552f7358SJed Brown       0, 1, 4, 5,  /* front */
8438*552f7358SJed Brown       1, 2, 5, 6,  /* right */
8439*552f7358SJed Brown       2, 3, 6, 7,  /* back */
8440*552f7358SJed Brown       0, 3, 4, 7,  /* left */
8441*552f7358SJed Brown     };
8442*552f7358SJed Brown     PetscInt faceVerticesHex[24] = {
8443*552f7358SJed Brown       3, 2, 1, 0,  /* bottom */
8444*552f7358SJed Brown       4, 5, 6, 7,  /* top */
8445*552f7358SJed Brown       0, 1, 5, 4,  /* front */
8446*552f7358SJed Brown       1, 2, 6, 5,  /* right */
8447*552f7358SJed Brown       2, 3, 7, 6,  /* back */
8448*552f7358SJed Brown       3, 0, 4, 7,  /* left */
8449*552f7358SJed Brown     };
8450*552f7358SJed Brown 
8451*552f7358SJed Brown     faceSize = faceSizeHex;
8452*552f7358SJed Brown     for (i = 0; i < faceSizeHex; ++i) sortedIndices[i] = indices[i];
8453*552f7358SJed Brown     ierr = PetscSortInt(faceSizeHex, sortedIndices);CHKERRQ(ierr);
8454*552f7358SJed Brown     for (iFace = 0; iFace < 6; ++iFace) {
8455*552f7358SJed Brown       const PetscInt ii = iFace*faceSizeHex;
8456*552f7358SJed Brown       PetscInt       fVertex, cVertex;
8457*552f7358SJed Brown 
8458*552f7358SJed Brown       if ((sortedIndices[0] == faceVerticesHexSorted[ii+0]) &&
8459*552f7358SJed Brown           (sortedIndices[1] == faceVerticesHexSorted[ii+1]) &&
8460*552f7358SJed Brown           (sortedIndices[2] == faceVerticesHexSorted[ii+2]) &&
8461*552f7358SJed Brown           (sortedIndices[3] == faceVerticesHexSorted[ii+3])) {
8462*552f7358SJed Brown         for (fVertex = 0; fVertex < faceSizeHex; ++fVertex) {
8463*552f7358SJed Brown           for (cVertex = 0; cVertex < faceSizeHex; ++cVertex) {
8464*552f7358SJed Brown             if (indices[cVertex] == faceVerticesHex[ii+fVertex]) {
8465*552f7358SJed Brown               faceVertices[fVertex] = origVertices[cVertex];
8466*552f7358SJed Brown               break;
8467*552f7358SJed Brown             }
8468*552f7358SJed Brown           }
8469*552f7358SJed Brown         }
8470*552f7358SJed Brown         found = PETSC_TRUE;
8471*552f7358SJed Brown         break;
8472*552f7358SJed Brown       }
8473*552f7358SJed Brown     }
8474*552f7358SJed Brown     if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface");
8475*552f7358SJed Brown     if (posOriented) {*posOriented = PETSC_TRUE;}
8476*552f7358SJed Brown     PetscFunctionReturn(0);
8477*552f7358SJed Brown   } else if (cellDim == 3 && numCorners == 10) {
8478*552f7358SJed Brown     /* Quadratic tet */
8479*552f7358SJed Brown     /* Faces are determined by the first 3 vertices (corners of faces) */
8480*552f7358SJed Brown     const PetscInt faceSizeTet = 6;
8481*552f7358SJed Brown     PetscInt  sortedIndices[6], i, iFace;
8482*552f7358SJed Brown     PetscBool found = PETSC_FALSE;
8483*552f7358SJed Brown     PetscInt faceVerticesTetSorted[24] = {
8484*552f7358SJed Brown       0, 1, 2,  6, 7, 8, /* bottom */
8485*552f7358SJed Brown       0, 3, 4,  6, 7, 9,  /* front */
8486*552f7358SJed Brown       1, 4, 5,  7, 8, 9,  /* right */
8487*552f7358SJed Brown       2, 3, 5,  6, 8, 9,  /* left */
8488*552f7358SJed Brown     };
8489*552f7358SJed Brown     PetscInt faceVerticesTet[24] = {
8490*552f7358SJed Brown       0, 1, 2,  6, 7, 8, /* bottom */
8491*552f7358SJed Brown       0, 4, 3,  6, 7, 9,  /* front */
8492*552f7358SJed Brown       1, 5, 4,  7, 8, 9,  /* right */
8493*552f7358SJed Brown       2, 3, 5,  8, 6, 9,  /* left */
8494*552f7358SJed Brown     };
8495*552f7358SJed Brown 
8496*552f7358SJed Brown     faceSize = faceSizeTet;
8497*552f7358SJed Brown     for (i = 0; i < faceSizeTet; ++i) sortedIndices[i] = indices[i];
8498*552f7358SJed Brown     ierr = PetscSortInt(faceSizeTet, sortedIndices);CHKERRQ(ierr);
8499*552f7358SJed Brown     for (iFace=0; iFace < 4; ++iFace) {
8500*552f7358SJed Brown       const PetscInt ii = iFace*faceSizeTet;
8501*552f7358SJed Brown       PetscInt       fVertex, cVertex;
8502*552f7358SJed Brown 
8503*552f7358SJed Brown       if ((sortedIndices[0] == faceVerticesTetSorted[ii+0]) &&
8504*552f7358SJed Brown           (sortedIndices[1] == faceVerticesTetSorted[ii+1]) &&
8505*552f7358SJed Brown           (sortedIndices[2] == faceVerticesTetSorted[ii+2]) &&
8506*552f7358SJed Brown           (sortedIndices[3] == faceVerticesTetSorted[ii+3])) {
8507*552f7358SJed Brown         for (fVertex = 0; fVertex < faceSizeTet; ++fVertex) {
8508*552f7358SJed Brown           for (cVertex = 0; cVertex < faceSizeTet; ++cVertex) {
8509*552f7358SJed Brown             if (indices[cVertex] == faceVerticesTet[ii+fVertex]) {
8510*552f7358SJed Brown               faceVertices[fVertex] = origVertices[cVertex];
8511*552f7358SJed Brown               break;
8512*552f7358SJed Brown             }
8513*552f7358SJed Brown           }
8514*552f7358SJed Brown         }
8515*552f7358SJed Brown         found = PETSC_TRUE;
8516*552f7358SJed Brown         break;
8517*552f7358SJed Brown       }
8518*552f7358SJed Brown     }
8519*552f7358SJed Brown     if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid tet crossface");
8520*552f7358SJed Brown     if (posOriented) {*posOriented = PETSC_TRUE;}
8521*552f7358SJed Brown     PetscFunctionReturn(0);
8522*552f7358SJed Brown   } else if (cellDim == 3 && numCorners == 27) {
8523*552f7358SJed Brown     /* Quadratic hexes (I hate this)
8524*552f7358SJed Brown        A hex is two oriented quads with the normal of the first
8525*552f7358SJed Brown        pointing up at the second.
8526*552f7358SJed Brown 
8527*552f7358SJed Brown          7---6
8528*552f7358SJed Brown         /|  /|
8529*552f7358SJed Brown        4---5 |
8530*552f7358SJed Brown        | 3-|-2
8531*552f7358SJed Brown        |/  |/
8532*552f7358SJed Brown        0---1
8533*552f7358SJed Brown 
8534*552f7358SJed Brown        Faces are determined by the first 4 vertices (corners of faces) */
8535*552f7358SJed Brown     const PetscInt faceSizeQuadHex = 9;
8536*552f7358SJed Brown     PetscInt  sortedIndices[9], i, iFace;
8537*552f7358SJed Brown     PetscBool found = PETSC_FALSE;
8538*552f7358SJed Brown     PetscInt faceVerticesQuadHexSorted[54] = {
8539*552f7358SJed Brown       0, 1, 2, 3,  8, 9, 10, 11,  24, /* bottom */
8540*552f7358SJed Brown       4, 5, 6, 7,  12, 13, 14, 15,  25, /* top */
8541*552f7358SJed Brown       0, 1, 4, 5,  8, 12, 16, 17,  22, /* front */
8542*552f7358SJed Brown       1, 2, 5, 6,  9, 13, 17, 18,  21, /* right */
8543*552f7358SJed Brown       2, 3, 6, 7,  10, 14, 18, 19,  23, /* back */
8544*552f7358SJed Brown       0, 3, 4, 7,  11, 15, 16, 19,  20, /* left */
8545*552f7358SJed Brown     };
8546*552f7358SJed Brown     PetscInt faceVerticesQuadHex[54] = {
8547*552f7358SJed Brown       3, 2, 1, 0,  10, 9, 8, 11,  24, /* bottom */
8548*552f7358SJed Brown       4, 5, 6, 7,  12, 13, 14, 15,  25, /* top */
8549*552f7358SJed Brown       0, 1, 5, 4,  8, 17, 12, 16,  22, /* front */
8550*552f7358SJed Brown       1, 2, 6, 5,  9, 18, 13, 17,  21, /* right */
8551*552f7358SJed Brown       2, 3, 7, 6,  10, 19, 14, 18,  23, /* back */
8552*552f7358SJed Brown       3, 0, 4, 7,  11, 16, 15, 19,  20 /* left */
8553*552f7358SJed Brown     };
8554*552f7358SJed Brown 
8555*552f7358SJed Brown     faceSize = faceSizeQuadHex;
8556*552f7358SJed Brown     for (i = 0; i < faceSizeQuadHex; ++i) sortedIndices[i] = indices[i];
8557*552f7358SJed Brown     ierr = PetscSortInt(faceSizeQuadHex, sortedIndices);CHKERRQ(ierr);
8558*552f7358SJed Brown     for (iFace = 0; iFace < 6; ++iFace) {
8559*552f7358SJed Brown       const PetscInt ii = iFace*faceSizeQuadHex;
8560*552f7358SJed Brown       PetscInt       fVertex, cVertex;
8561*552f7358SJed Brown 
8562*552f7358SJed Brown       if ((sortedIndices[0] == faceVerticesQuadHexSorted[ii+0]) &&
8563*552f7358SJed Brown           (sortedIndices[1] == faceVerticesQuadHexSorted[ii+1]) &&
8564*552f7358SJed Brown           (sortedIndices[2] == faceVerticesQuadHexSorted[ii+2]) &&
8565*552f7358SJed Brown           (sortedIndices[3] == faceVerticesQuadHexSorted[ii+3])) {
8566*552f7358SJed Brown         for (fVertex = 0; fVertex < faceSizeQuadHex; ++fVertex) {
8567*552f7358SJed Brown           for (cVertex = 0; cVertex < faceSizeQuadHex; ++cVertex) {
8568*552f7358SJed Brown             if (indices[cVertex] == faceVerticesQuadHex[ii+fVertex]) {
8569*552f7358SJed Brown               faceVertices[fVertex] = origVertices[cVertex];
8570*552f7358SJed Brown               break;
8571*552f7358SJed Brown             }
8572*552f7358SJed Brown           }
8573*552f7358SJed Brown         }
8574*552f7358SJed Brown         found = PETSC_TRUE;
8575*552f7358SJed Brown         break;
8576*552f7358SJed Brown       }
8577*552f7358SJed Brown     }
8578*552f7358SJed Brown     if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface");
8579*552f7358SJed Brown     if (posOriented) {*posOriented = PETSC_TRUE;}
8580*552f7358SJed Brown     PetscFunctionReturn(0);
8581*552f7358SJed Brown   } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Unknown cell type for faceOrientation().");
8582*552f7358SJed Brown   if (!posOrient) {
8583*552f7358SJed Brown     if (debug) {ierr = PetscPrintf(comm, "  Reversing initial face orientation\n");CHKERRQ(ierr);}
8584*552f7358SJed Brown     for (f = 0; f < faceSize; ++f) {
8585*552f7358SJed Brown       faceVertices[f] = origVertices[faceSize-1 - f];
8586*552f7358SJed Brown     }
8587*552f7358SJed Brown   } else {
8588*552f7358SJed Brown     if (debug) {ierr = PetscPrintf(comm, "  Keeping initial face orientation\n");CHKERRQ(ierr);}
8589*552f7358SJed Brown     for (f = 0; f < faceSize; ++f) {
8590*552f7358SJed Brown       faceVertices[f] = origVertices[f];
8591*552f7358SJed Brown     }
8592*552f7358SJed Brown   }
8593*552f7358SJed Brown   if (posOriented) {*posOriented = posOrient;}
8594*552f7358SJed Brown   PetscFunctionReturn(0);
8595*552f7358SJed Brown }
8596*552f7358SJed Brown 
8597*552f7358SJed Brown #undef __FUNCT__
8598*552f7358SJed Brown #define __FUNCT__ "DMPlexGetOrientedFace"
8599*552f7358SJed Brown /*
8600*552f7358SJed Brown     Given a cell and a face, as a set of vertices,
8601*552f7358SJed Brown       return the oriented face, as a set of vertices, in faceVertices
8602*552f7358SJed Brown     The orientation is such that the face normal points out of the cell
8603*552f7358SJed Brown */
8604*552f7358SJed Brown PetscErrorCode DMPlexGetOrientedFace(DM dm, PetscInt cell, PetscInt faceSize, const PetscInt face[], PetscInt numCorners, PetscInt indices[], PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented)
8605*552f7358SJed Brown {
8606*552f7358SJed Brown   const PetscInt *cone = PETSC_NULL;
8607*552f7358SJed Brown   PetscInt        coneSize, v, f, v2;
8608*552f7358SJed Brown   PetscInt        oppositeVertex = -1;
8609*552f7358SJed Brown   PetscErrorCode  ierr;
8610*552f7358SJed Brown 
8611*552f7358SJed Brown   PetscFunctionBegin;
8612*552f7358SJed Brown   ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr);
8613*552f7358SJed Brown   ierr = DMPlexGetCone(dm, cell, &cone);CHKERRQ(ierr);
8614*552f7358SJed Brown   for (v = 0, v2 = 0; v < coneSize; ++v) {
8615*552f7358SJed Brown     PetscBool found  = PETSC_FALSE;
8616*552f7358SJed Brown 
8617*552f7358SJed Brown     for (f = 0; f < faceSize; ++f) {
8618*552f7358SJed Brown       if (face[f] == cone[v]) {found = PETSC_TRUE; break;}
8619*552f7358SJed Brown     }
8620*552f7358SJed Brown     if (found) {
8621*552f7358SJed Brown       indices[v2]      = v;
8622*552f7358SJed Brown       origVertices[v2] = cone[v];
8623*552f7358SJed Brown       ++v2;
8624*552f7358SJed Brown     } else {
8625*552f7358SJed Brown       oppositeVertex = v;
8626*552f7358SJed Brown     }
8627*552f7358SJed Brown   }
8628*552f7358SJed Brown   ierr = DMPlexGetFaceOrientation(dm, cell, numCorners, indices, oppositeVertex, origVertices, faceVertices, posOriented);CHKERRQ(ierr);
8629*552f7358SJed Brown   PetscFunctionReturn(0);
8630*552f7358SJed Brown }
8631*552f7358SJed Brown 
8632*552f7358SJed Brown PETSC_STATIC_INLINE PetscInt epsilon(PetscInt i, PetscInt j, PetscInt k)
8633*552f7358SJed Brown {
8634*552f7358SJed Brown   switch(i) {
8635*552f7358SJed Brown   case 0:
8636*552f7358SJed Brown     switch(j) {
8637*552f7358SJed Brown     case 0: return 0;
8638*552f7358SJed Brown     case 1:
8639*552f7358SJed Brown       switch(k) {
8640*552f7358SJed Brown       case 0: return 0;
8641*552f7358SJed Brown       case 1: return 0;
8642*552f7358SJed Brown       case 2: return 1;
8643*552f7358SJed Brown       }
8644*552f7358SJed Brown     case 2:
8645*552f7358SJed Brown       switch(k) {
8646*552f7358SJed Brown       case 0: return 0;
8647*552f7358SJed Brown       case 1: return -1;
8648*552f7358SJed Brown       case 2: return 0;
8649*552f7358SJed Brown       }
8650*552f7358SJed Brown     }
8651*552f7358SJed Brown   case 1:
8652*552f7358SJed Brown     switch(j) {
8653*552f7358SJed Brown     case 0:
8654*552f7358SJed Brown       switch(k) {
8655*552f7358SJed Brown       case 0: return 0;
8656*552f7358SJed Brown       case 1: return 0;
8657*552f7358SJed Brown       case 2: return -1;
8658*552f7358SJed Brown       }
8659*552f7358SJed Brown     case 1: return 0;
8660*552f7358SJed Brown     case 2:
8661*552f7358SJed Brown       switch(k) {
8662*552f7358SJed Brown       case 0: return 1;
8663*552f7358SJed Brown       case 1: return 0;
8664*552f7358SJed Brown       case 2: return 0;
8665*552f7358SJed Brown       }
8666*552f7358SJed Brown     }
8667*552f7358SJed Brown   case 2:
8668*552f7358SJed Brown     switch(j) {
8669*552f7358SJed Brown     case 0:
8670*552f7358SJed Brown       switch(k) {
8671*552f7358SJed Brown       case 0: return 0;
8672*552f7358SJed Brown       case 1: return 1;
8673*552f7358SJed Brown       case 2: return 0;
8674*552f7358SJed Brown       }
8675*552f7358SJed Brown     case 1:
8676*552f7358SJed Brown       switch(k) {
8677*552f7358SJed Brown       case 0: return -1;
8678*552f7358SJed Brown       case 1: return 0;
8679*552f7358SJed Brown       case 2: return 0;
8680*552f7358SJed Brown       }
8681*552f7358SJed Brown     case 2: return 0;
8682*552f7358SJed Brown     }
8683*552f7358SJed Brown   }
8684*552f7358SJed Brown   return 0;
8685*552f7358SJed Brown }
8686*552f7358SJed Brown 
8687*552f7358SJed Brown #undef __FUNCT__
8688*552f7358SJed Brown #define __FUNCT__ "DMPlexCreateRigidBody"
8689*552f7358SJed Brown /*@C
8690*552f7358SJed Brown   DMPlexCreateRigidBody - create rigid body modes from coordinates
8691*552f7358SJed Brown 
8692*552f7358SJed Brown   Collective on DM
8693*552f7358SJed Brown 
8694*552f7358SJed Brown   Input Arguments:
8695*552f7358SJed Brown + dm - the DM
8696*552f7358SJed Brown . section - the local section associated with the rigid field, or PETSC_NULL for the default section
8697*552f7358SJed Brown - globalSection - the global section associated with the rigid field, or PETSC_NULL for the default section
8698*552f7358SJed Brown 
8699*552f7358SJed Brown   Output Argument:
8700*552f7358SJed Brown . sp - the null space
8701*552f7358SJed Brown 
8702*552f7358SJed Brown   Note: This is necessary to take account of Dirichlet conditions on the displacements
8703*552f7358SJed Brown 
8704*552f7358SJed Brown   Level: advanced
8705*552f7358SJed Brown 
8706*552f7358SJed Brown .seealso: MatNullSpaceCreate()
8707*552f7358SJed Brown @*/
8708*552f7358SJed Brown PetscErrorCode DMPlexCreateRigidBody(DM dm, PetscSection section, PetscSection globalSection, MatNullSpace *sp)
8709*552f7358SJed Brown {
8710*552f7358SJed Brown   MPI_Comm       comm = ((PetscObject) dm)->comm;
8711*552f7358SJed Brown   Vec            coordinates, localMode, mode[6];
8712*552f7358SJed Brown   PetscSection   coordSection;
8713*552f7358SJed Brown   PetscScalar   *coords;
8714*552f7358SJed Brown   PetscInt       dim, vStart, vEnd, v, n, m, d, i, j;
8715*552f7358SJed Brown   PetscErrorCode ierr;
8716*552f7358SJed Brown 
8717*552f7358SJed Brown   PetscFunctionBegin;
8718*552f7358SJed Brown   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
8719*552f7358SJed Brown   if (dim == 1) {
8720*552f7358SJed Brown     ierr = MatNullSpaceCreate(comm, PETSC_TRUE, 0, PETSC_NULL, sp);CHKERRQ(ierr);
8721*552f7358SJed Brown     PetscFunctionReturn(0);
8722*552f7358SJed Brown   }
8723*552f7358SJed Brown   if (!section)       {ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);}
8724*552f7358SJed Brown   if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);}
8725*552f7358SJed Brown   ierr = PetscSectionGetConstrainedStorageSize(globalSection, &n);CHKERRQ(ierr);
8726*552f7358SJed Brown   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
8727*552f7358SJed Brown   ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr);
8728*552f7358SJed Brown   ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
8729*552f7358SJed Brown   m    = (dim*(dim+1))/2;
8730*552f7358SJed Brown   ierr = VecCreate(comm, &mode[0]);CHKERRQ(ierr);
8731*552f7358SJed Brown   ierr = VecSetSizes(mode[0], n, PETSC_DETERMINE);CHKERRQ(ierr);
8732*552f7358SJed Brown   ierr = VecSetUp(mode[0]);CHKERRQ(ierr);
8733*552f7358SJed Brown   for (i = 1; i < m; ++i) {ierr = VecDuplicate(mode[0], &mode[i]);CHKERRQ(ierr);}
8734*552f7358SJed Brown   /* Assume P1 */
8735*552f7358SJed Brown   ierr = DMGetLocalVector(dm, &localMode);CHKERRQ(ierr);
8736*552f7358SJed Brown   for (d = 0; d < dim; ++d) {
8737*552f7358SJed Brown     PetscScalar values[3] = {0.0, 0.0, 0.0};
8738*552f7358SJed Brown 
8739*552f7358SJed Brown     values[d] = 1.0;
8740*552f7358SJed Brown     ierr = VecSet(localMode, 0.0);CHKERRQ(ierr);
8741*552f7358SJed Brown     for (v = vStart; v < vEnd; ++v) {
8742*552f7358SJed Brown       ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr);
8743*552f7358SJed Brown     }
8744*552f7358SJed Brown     ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr);
8745*552f7358SJed Brown     ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr);
8746*552f7358SJed Brown   }
8747*552f7358SJed Brown   ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr);
8748*552f7358SJed Brown   for (d = dim; d < dim*(dim+1)/2; ++d) {
8749*552f7358SJed Brown     PetscInt i, j, k = dim > 2 ? d - dim : d;
8750*552f7358SJed Brown 
8751*552f7358SJed Brown     ierr = VecSet(localMode, 0.0);CHKERRQ(ierr);
8752*552f7358SJed Brown     for (v = vStart; v < vEnd; ++v) {
8753*552f7358SJed Brown       PetscScalar values[3] = {0.0, 0.0, 0.0};
8754*552f7358SJed Brown       PetscInt    off;
8755*552f7358SJed Brown 
8756*552f7358SJed Brown       ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr);
8757*552f7358SJed Brown       for (i = 0; i < dim; ++i) {
8758*552f7358SJed Brown         for (j = 0; j < dim; ++j) {
8759*552f7358SJed Brown           values[j] += epsilon(i, j, k)*PetscRealPart(coords[off+i]);
8760*552f7358SJed Brown         }
8761*552f7358SJed Brown       }
8762*552f7358SJed Brown       ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr);
8763*552f7358SJed Brown     }
8764*552f7358SJed Brown     ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr);
8765*552f7358SJed Brown     ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr);
8766*552f7358SJed Brown   }
8767*552f7358SJed Brown   ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr);
8768*552f7358SJed Brown   ierr = DMRestoreLocalVector(dm, &localMode);CHKERRQ(ierr);
8769*552f7358SJed Brown   for (i = 0; i < dim; ++i) {ierr = VecNormalize(mode[i], PETSC_NULL);CHKERRQ(ierr);}
8770*552f7358SJed Brown   /* Orthonormalize system */
8771*552f7358SJed Brown   for (i = dim; i < m; ++i) {
8772*552f7358SJed Brown     PetscScalar dots[6];
8773*552f7358SJed Brown 
8774*552f7358SJed Brown     ierr = VecMDot(mode[i], i, mode, dots);CHKERRQ(ierr);
8775*552f7358SJed Brown     for (j = 0; j < i; ++j) dots[j] *= -1.0;
8776*552f7358SJed Brown     ierr = VecMAXPY(mode[i], i, dots, mode);CHKERRQ(ierr);
8777*552f7358SJed Brown     ierr = VecNormalize(mode[i], PETSC_NULL);CHKERRQ(ierr);
8778*552f7358SJed Brown   }
8779*552f7358SJed Brown   ierr = MatNullSpaceCreate(comm, PETSC_FALSE, m, mode, sp);CHKERRQ(ierr);
8780*552f7358SJed Brown   for (i = 0; i< m; ++i) {ierr = VecDestroy(&mode[i]);CHKERRQ(ierr);}
8781*552f7358SJed Brown   PetscFunctionReturn(0);
8782*552f7358SJed Brown }
8783*552f7358SJed Brown 
8784*552f7358SJed Brown #undef __FUNCT__
8785*552f7358SJed Brown #define __FUNCT__ "DMPlexGetVTKBounds"
8786*552f7358SJed Brown PetscErrorCode DMPlexGetVTKBounds(DM dm, PetscInt *cMax, PetscInt *vMax)
8787*552f7358SJed Brown {
8788*552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *) dm->data;
8789*552f7358SJed Brown 
8790*552f7358SJed Brown   PetscFunctionBegin;
8791*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8792*552f7358SJed Brown   if (cMax) *cMax = mesh->vtkCellMax;
8793*552f7358SJed Brown   if (vMax) *vMax = mesh->vtkVertexMax;
8794*552f7358SJed Brown   PetscFunctionReturn(0);
8795*552f7358SJed Brown }
8796*552f7358SJed Brown 
8797*552f7358SJed Brown #undef __FUNCT__
8798*552f7358SJed Brown #define __FUNCT__ "DMPlexSetVTKBounds"
8799*552f7358SJed Brown PetscErrorCode DMPlexSetVTKBounds(DM dm, PetscInt cMax, PetscInt vMax)
8800*552f7358SJed Brown {
8801*552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *) dm->data;
8802*552f7358SJed Brown 
8803*552f7358SJed Brown   PetscFunctionBegin;
8804*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8805*552f7358SJed Brown   if (cMax >= 0) mesh->vtkCellMax   = cMax;
8806*552f7358SJed Brown   if (vMax >= 0) mesh->vtkVertexMax = vMax;
8807*552f7358SJed Brown   PetscFunctionReturn(0);
8808*552f7358SJed Brown }
8809*552f7358SJed Brown 
8810*552f7358SJed Brown #undef __FUNCT__
8811*552f7358SJed Brown #define __FUNCT__ "DMPlexGetVTKCellHeight"
8812*552f7358SJed Brown PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight)
8813*552f7358SJed Brown {
8814*552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *) dm->data;
8815*552f7358SJed Brown 
8816*552f7358SJed Brown   PetscFunctionBegin;
8817*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8818*552f7358SJed Brown   PetscValidPointer(cellHeight, 2);
8819*552f7358SJed Brown   *cellHeight = mesh->vtkCellHeight;
8820*552f7358SJed Brown   PetscFunctionReturn(0);
8821*552f7358SJed Brown }
8822*552f7358SJed Brown 
8823*552f7358SJed Brown #undef __FUNCT__
8824*552f7358SJed Brown #define __FUNCT__ "DMPlexSetVTKCellHeight"
8825*552f7358SJed Brown PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight)
8826*552f7358SJed Brown {
8827*552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *) dm->data;
8828*552f7358SJed Brown 
8829*552f7358SJed Brown   PetscFunctionBegin;
8830*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8831*552f7358SJed Brown   mesh->vtkCellHeight = cellHeight;
8832*552f7358SJed Brown   PetscFunctionReturn(0);
8833*552f7358SJed Brown }
8834*552f7358SJed Brown 
8835*552f7358SJed Brown #undef __FUNCT__
8836*552f7358SJed Brown #define __FUNCT__ "DMPlexInsertFace_Private"
8837*552f7358SJed Brown /*
8838*552f7358SJed Brown   DMPlexInsertFace_Private - Puts a face into the mesh
8839*552f7358SJed Brown 
8840*552f7358SJed Brown   Not collective
8841*552f7358SJed Brown 
8842*552f7358SJed Brown   Input Parameters:
8843*552f7358SJed Brown   + dm              - The DMPlex
8844*552f7358SJed Brown   . numFaceVertex   - The number of vertices in the face
8845*552f7358SJed Brown   . faceVertices    - The vertices in the face for dm
8846*552f7358SJed Brown   . subfaceVertices - The vertices in the face for subdm
8847*552f7358SJed Brown   . numCorners      - The number of vertices in the cell
8848*552f7358SJed Brown   . cell            - A cell in dm containing the face
8849*552f7358SJed Brown   . subcell         - A cell in subdm containing the face
8850*552f7358SJed Brown   . firstFace       - First face in the mesh
8851*552f7358SJed Brown   - newFacePoint    - Next face in the mesh
8852*552f7358SJed Brown 
8853*552f7358SJed Brown   Output Parameters:
8854*552f7358SJed Brown   . newFacePoint - Contains next face point number on input, updated on output
8855*552f7358SJed Brown 
8856*552f7358SJed Brown   Level: developer
8857*552f7358SJed Brown */
8858*552f7358SJed Brown PetscErrorCode DMPlexInsertFace_Private(DM dm, DM subdm, PetscInt numFaceVertices, const PetscInt faceVertices[], const PetscInt subfaceVertices[], PetscInt numCorners, PetscInt cell, PetscInt subcell, PetscInt firstFace, PetscInt *newFacePoint)
8859*552f7358SJed Brown {
8860*552f7358SJed Brown   MPI_Comm        comm    = ((PetscObject) dm)->comm;
8861*552f7358SJed Brown   DM_Plex     *submesh = (DM_Plex *) subdm->data;
8862*552f7358SJed Brown   const PetscInt *faces;
8863*552f7358SJed Brown   PetscInt        numFaces, coneSize;
8864*552f7358SJed Brown   PetscErrorCode  ierr;
8865*552f7358SJed Brown 
8866*552f7358SJed Brown   PetscFunctionBegin;
8867*552f7358SJed Brown   ierr = DMPlexGetConeSize(subdm, subcell, &coneSize);CHKERRQ(ierr);
8868*552f7358SJed Brown   if (coneSize != 1) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size of cell %d is %d != 1", cell, coneSize);
8869*552f7358SJed Brown #if 0
8870*552f7358SJed Brown   /* Cannot use this because support() has not been constructed yet */
8871*552f7358SJed Brown   ierr = DMPlexGetJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces);CHKERRQ(ierr);
8872*552f7358SJed Brown #else
8873*552f7358SJed Brown   {
8874*552f7358SJed Brown     PetscInt f;
8875*552f7358SJed Brown 
8876*552f7358SJed Brown     numFaces = 0;
8877*552f7358SJed Brown     ierr = DMGetWorkArray(subdm, 1, PETSC_INT, (void **) &faces);CHKERRQ(ierr);
8878*552f7358SJed Brown     for(f = firstFace; f < *newFacePoint; ++f) {
8879*552f7358SJed Brown       PetscInt dof, off, d;
8880*552f7358SJed Brown 
8881*552f7358SJed Brown       ierr = PetscSectionGetDof(submesh->coneSection, f, &dof);CHKERRQ(ierr);
8882*552f7358SJed Brown       ierr = PetscSectionGetOffset(submesh->coneSection, f, &off);CHKERRQ(ierr);
8883*552f7358SJed Brown       /* Yes, I know this is quadratic, but I expect the sizes to be <5 */
8884*552f7358SJed Brown       for(d = 0; d < dof; ++d) {
8885*552f7358SJed Brown         const PetscInt p = submesh->cones[off+d];
8886*552f7358SJed Brown         PetscInt       v;
8887*552f7358SJed Brown 
8888*552f7358SJed Brown         for(v = 0; v < numFaceVertices; ++v) {
8889*552f7358SJed Brown           if (subfaceVertices[v] == p) break;
8890*552f7358SJed Brown         }
8891*552f7358SJed Brown         if (v == numFaceVertices) break;
8892*552f7358SJed Brown       }
8893*552f7358SJed Brown       if (d == dof) {
8894*552f7358SJed Brown         numFaces = 1;
8895*552f7358SJed Brown         ((PetscInt *) faces)[0] = f;
8896*552f7358SJed Brown       }
8897*552f7358SJed Brown     }
8898*552f7358SJed Brown   }
8899*552f7358SJed Brown #endif
8900*552f7358SJed Brown   if (numFaces > 1) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Vertex set had %d faces, not one", numFaces);
8901*552f7358SJed Brown   else if (numFaces == 1) {
8902*552f7358SJed Brown     /* Add the other cell neighbor for this face */
8903*552f7358SJed Brown     ierr = DMPlexSetCone(subdm, cell, faces);CHKERRQ(ierr);
8904*552f7358SJed Brown   } else {
8905*552f7358SJed Brown     PetscInt *indices, *origVertices, *orientedVertices, *orientedSubVertices, v, ov;
8906*552f7358SJed Brown     PetscBool posOriented;
8907*552f7358SJed Brown 
8908*552f7358SJed Brown     ierr = DMGetWorkArray(subdm, 4*numFaceVertices * sizeof(PetscInt), PETSC_INT, &orientedVertices);CHKERRQ(ierr);
8909*552f7358SJed Brown     origVertices = &orientedVertices[numFaceVertices];
8910*552f7358SJed Brown     indices      = &orientedVertices[numFaceVertices*2];
8911*552f7358SJed Brown     orientedSubVertices = &orientedVertices[numFaceVertices*3];
8912*552f7358SJed Brown     ierr = DMPlexGetOrientedFace(dm, cell, numFaceVertices, faceVertices, numCorners, indices, origVertices, orientedVertices, &posOriented);CHKERRQ(ierr);
8913*552f7358SJed Brown     /* TODO: I know that routine should return a permutation, not the indices */
8914*552f7358SJed Brown     for(v = 0; v < numFaceVertices; ++v) {
8915*552f7358SJed Brown       const PetscInt vertex = faceVertices[v], subvertex = subfaceVertices[v];
8916*552f7358SJed Brown       for(ov = 0; ov < numFaceVertices; ++ov) {
8917*552f7358SJed Brown         if (orientedVertices[ov] == vertex) {
8918*552f7358SJed Brown           orientedSubVertices[ov] = subvertex;
8919*552f7358SJed Brown           break;
8920*552f7358SJed Brown         }
8921*552f7358SJed Brown       }
8922*552f7358SJed Brown       if (ov == numFaceVertices) SETERRQ1(comm, PETSC_ERR_PLIB, "Could not find face vertex %d in orientated set", vertex);
8923*552f7358SJed Brown     }
8924*552f7358SJed Brown     ierr = DMPlexSetCone(subdm, *newFacePoint, orientedSubVertices);CHKERRQ(ierr);
8925*552f7358SJed Brown     ierr = DMPlexSetCone(subdm, subcell, newFacePoint);CHKERRQ(ierr);
8926*552f7358SJed Brown     ierr = DMRestoreWorkArray(subdm, 4*numFaceVertices * sizeof(PetscInt), PETSC_INT, &orientedVertices);CHKERRQ(ierr);
8927*552f7358SJed Brown     ++(*newFacePoint);
8928*552f7358SJed Brown   }
8929*552f7358SJed Brown   ierr = DMPlexRestoreJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces);CHKERRQ(ierr);
8930*552f7358SJed Brown   PetscFunctionReturn(0);
8931*552f7358SJed Brown }
8932*552f7358SJed Brown 
8933*552f7358SJed Brown #undef __FUNCT__
8934*552f7358SJed Brown #define __FUNCT__ "DMPlexCreateSubmesh"
8935*552f7358SJed Brown PetscErrorCode DMPlexCreateSubmesh(DM dm, const char label[], DM *subdm)
8936*552f7358SJed Brown {
8937*552f7358SJed Brown   MPI_Comm        comm = ((PetscObject) dm)->comm;
8938*552f7358SJed Brown   DM_Plex     *submesh;
8939*552f7358SJed Brown   PetscBool       boundaryFaces = PETSC_FALSE;
8940*552f7358SJed Brown   PetscSection    coordSection, subCoordSection;
8941*552f7358SJed Brown   Vec             coordinates, subCoordinates;
8942*552f7358SJed Brown   PetscScalar    *coords, *subCoords;
8943*552f7358SJed Brown   IS              labelIS;
8944*552f7358SJed Brown   const PetscInt *subVertices;
8945*552f7358SJed Brown   PetscInt       *subVerticesActive, *tmpPoints;
8946*552f7358SJed Brown   PetscInt       *subCells = PETSC_NULL;
8947*552f7358SJed Brown   PetscInt        numSubVertices, numSubVerticesActive, firstSubVertex, numSubCells = 0, maxSubCells = 0, numOldSubCells;
8948*552f7358SJed Brown   PetscInt       *face, *subface, maxConeSize, numSubFaces = 0, firstSubFace, newFacePoint, nFV = 0, coordSize;
8949*552f7358SJed Brown   PetscInt        dim; /* Right now, do not specify dimension */
8950*552f7358SJed Brown   PetscInt        cStart, cEnd, cMax, c, vStart, vEnd, vMax, v, p, corner, i, d, f;
8951*552f7358SJed Brown   PetscErrorCode  ierr;
8952*552f7358SJed Brown 
8953*552f7358SJed Brown   PetscFunctionBegin;
8954*552f7358SJed Brown   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
8955*552f7358SJed Brown   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
8956*552f7358SJed Brown   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
8957*552f7358SJed Brown   ierr = DMPlexGetMaxSizes(dm, &maxConeSize, PETSC_NULL);CHKERRQ(ierr);
8958*552f7358SJed Brown   ierr = DMPlexGetVTKBounds(dm, &cMax, &vMax);CHKERRQ(ierr);
8959*552f7358SJed Brown   if (cMax >= 0) {cEnd = PetscMin(cEnd, cMax);}
8960*552f7358SJed Brown   if (vMax >= 0) {vEnd = PetscMin(vEnd, vMax);}
8961*552f7358SJed Brown   ierr = DMGetWorkArray(dm, 2*maxConeSize, PETSC_INT, &face);CHKERRQ(ierr);
8962*552f7358SJed Brown   subface = &face[maxConeSize];
8963*552f7358SJed Brown   ierr = DMCreate(comm, subdm);CHKERRQ(ierr);
8964*552f7358SJed Brown   ierr = DMSetType(*subdm, DMPLEX);CHKERRQ(ierr);
8965*552f7358SJed Brown   ierr = DMPlexSetDimension(*subdm, dim-1);CHKERRQ(ierr);
8966*552f7358SJed Brown   ierr = DMPlexGetStratumIS(dm, label, 1, &labelIS);CHKERRQ(ierr);
8967*552f7358SJed Brown   ierr = ISGetSize(labelIS, &numSubVertices);CHKERRQ(ierr);
8968*552f7358SJed Brown   ierr = ISGetIndices(labelIS, &subVertices);CHKERRQ(ierr);
8969*552f7358SJed Brown   maxSubCells = numSubVertices;
8970*552f7358SJed Brown   ierr = PetscMalloc(maxSubCells * sizeof(PetscInt), &subCells);CHKERRQ(ierr);
8971*552f7358SJed Brown   ierr = PetscMalloc(numSubVertices * sizeof(PetscInt), &subVerticesActive);CHKERRQ(ierr);
8972*552f7358SJed Brown   ierr = PetscMemzero(subVerticesActive, numSubVertices * sizeof(PetscInt));CHKERRQ(ierr);
8973*552f7358SJed Brown   for(v = 0; v < numSubVertices; ++v) {
8974*552f7358SJed Brown     const PetscInt vertex = subVertices[v];
8975*552f7358SJed Brown     PetscInt *star = PETSC_NULL;
8976*552f7358SJed Brown     PetscInt  starSize, numCells = 0;
8977*552f7358SJed Brown 
8978*552f7358SJed Brown     ierr = DMPlexGetTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr);
8979*552f7358SJed Brown     for(p = 0; p < starSize*2; p += 2) {
8980*552f7358SJed Brown       const PetscInt point = star[p];
8981*552f7358SJed Brown       if ((point >= cStart) && (point < cEnd)) {
8982*552f7358SJed Brown         star[numCells++] = point;
8983*552f7358SJed Brown       }
8984*552f7358SJed Brown     }
8985*552f7358SJed Brown     numOldSubCells = numSubCells;
8986*552f7358SJed Brown     for(c = 0; c < numCells; ++c) {
8987*552f7358SJed Brown       const PetscInt cell    = star[c];
8988*552f7358SJed Brown       PetscInt      *closure = PETSC_NULL;
8989*552f7358SJed Brown       PetscInt       closureSize, numCorners = 0, faceSize = 0;
8990*552f7358SJed Brown       PetscInt       cellLoc;
8991*552f7358SJed Brown 
8992*552f7358SJed Brown       ierr = PetscFindInt(cell, numOldSubCells, subCells, &cellLoc);CHKERRQ(ierr);
8993*552f7358SJed Brown       if (cellLoc >= 0) continue;
8994*552f7358SJed Brown       ierr = DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
8995*552f7358SJed Brown       for(p = 0; p < closureSize*2; p += 2) {
8996*552f7358SJed Brown         const PetscInt point = closure[p];
8997*552f7358SJed Brown         if ((point >= vStart) && (point < vEnd)) {
8998*552f7358SJed Brown           closure[numCorners++] = point;
8999*552f7358SJed Brown         }
9000*552f7358SJed Brown       }
9001*552f7358SJed Brown       if (!nFV) {ierr = DMPlexGetNumFaceVertices(dm, numCorners, &nFV);CHKERRQ(ierr);}
9002*552f7358SJed Brown       for(corner = 0; corner < numCorners; ++corner) {
9003*552f7358SJed Brown         const PetscInt cellVertex = closure[corner];
9004*552f7358SJed Brown         PetscInt       subVertex;
9005*552f7358SJed Brown 
9006*552f7358SJed Brown         ierr = PetscFindInt(cellVertex, numSubVertices, subVertices, &subVertex);CHKERRQ(ierr);
9007*552f7358SJed Brown         if (subVertex >= 0) { /* contains submesh vertex */
9008*552f7358SJed Brown           for(i = 0; i < faceSize; ++i) {if (cellVertex == face[i]) break;}
9009*552f7358SJed Brown           if (i == faceSize) {
9010*552f7358SJed Brown             if (faceSize >= maxConeSize) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of vertices in face %d should not exceed %d", faceSize+1, maxConeSize);
9011*552f7358SJed Brown             face[faceSize]    = cellVertex;
9012*552f7358SJed Brown             subface[faceSize] = subVertex;
9013*552f7358SJed Brown             ++faceSize;
9014*552f7358SJed Brown           }
9015*552f7358SJed Brown         }
9016*552f7358SJed Brown       }
9017*552f7358SJed Brown       ierr = DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
9018*552f7358SJed Brown       if (faceSize >= nFV) {
9019*552f7358SJed Brown         if (faceSize > nFV && !boundaryFaces) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %d of an element on the surface", faceSize);
9020*552f7358SJed Brown         if (numSubCells >= maxSubCells) {
9021*552f7358SJed Brown           PetscInt *tmpCells;
9022*552f7358SJed Brown           maxSubCells *= 2;
9023*552f7358SJed Brown           ierr = PetscMalloc(maxSubCells * sizeof(PetscInt), &tmpCells);CHKERRQ(ierr);
9024*552f7358SJed Brown           ierr = PetscMemcpy(tmpCells, subCells, numSubCells * sizeof(PetscInt));CHKERRQ(ierr);
9025*552f7358SJed Brown           ierr = PetscFree(subCells);CHKERRQ(ierr);
9026*552f7358SJed Brown           subCells = tmpCells;
9027*552f7358SJed Brown         }
9028*552f7358SJed Brown         /* TOOD: Maybe overestimate then squeeze out empty faces */
9029*552f7358SJed Brown         if (faceSize > nFV) {
9030*552f7358SJed Brown           /* TODO: This is tricky. Maybe just add all faces */
9031*552f7358SJed Brown           numSubFaces++;
9032*552f7358SJed Brown         } else {
9033*552f7358SJed Brown           numSubFaces++;
9034*552f7358SJed Brown         }
9035*552f7358SJed Brown         for(f = 0; f < faceSize; ++f) {
9036*552f7358SJed Brown           subVerticesActive[subface[f]] = 1;
9037*552f7358SJed Brown         }
9038*552f7358SJed Brown         subCells[numSubCells++] = cell;
9039*552f7358SJed Brown       }
9040*552f7358SJed Brown     }
9041*552f7358SJed Brown     ierr = DMPlexRestoreTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr);
9042*552f7358SJed Brown     ierr = PetscSortRemoveDupsInt(&numSubCells, subCells);CHKERRQ(ierr);
9043*552f7358SJed Brown   }
9044*552f7358SJed Brown   /* Pick out active subvertices */
9045*552f7358SJed Brown   for(v = 0, numSubVerticesActive = 0; v < numSubVertices; ++v) {
9046*552f7358SJed Brown     if (subVerticesActive[v]) {
9047*552f7358SJed Brown       subVerticesActive[numSubVerticesActive++] = subVertices[v];
9048*552f7358SJed Brown     }
9049*552f7358SJed Brown   }
9050*552f7358SJed Brown   ierr = DMPlexSetChart(*subdm, 0, numSubCells+numSubFaces+numSubVerticesActive);CHKERRQ(ierr);
9051*552f7358SJed Brown   /* Set cone sizes */
9052*552f7358SJed Brown   firstSubVertex = numSubCells;
9053*552f7358SJed Brown   firstSubFace   = numSubCells+numSubVerticesActive;
9054*552f7358SJed Brown   newFacePoint   = firstSubFace;
9055*552f7358SJed Brown   for(c = 0; c < numSubCells; ++c) {
9056*552f7358SJed Brown     ierr = DMPlexSetConeSize(*subdm, c, 1);CHKERRQ(ierr);
9057*552f7358SJed Brown   }
9058*552f7358SJed Brown   for(f = firstSubFace; f < firstSubFace+numSubFaces; ++f) {
9059*552f7358SJed Brown     ierr = DMPlexSetConeSize(*subdm, f, nFV);CHKERRQ(ierr);
9060*552f7358SJed Brown   }
9061*552f7358SJed Brown   ierr = DMSetUp(*subdm);CHKERRQ(ierr);
9062*552f7358SJed Brown   /* Create face cones */
9063*552f7358SJed Brown   for(c = 0; c < numSubCells; ++c) {
9064*552f7358SJed Brown     const PetscInt cell    = subCells[c];
9065*552f7358SJed Brown     PetscInt      *closure = PETSC_NULL;
9066*552f7358SJed Brown     PetscInt       closureSize, numCorners = 0, faceSize = 0;
9067*552f7358SJed Brown 
9068*552f7358SJed Brown     ierr = DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
9069*552f7358SJed Brown     for(p = 0; p < closureSize*2; p += 2) {
9070*552f7358SJed Brown       const PetscInt point = closure[p];
9071*552f7358SJed Brown       if ((point >= vStart) && (point < vEnd)) {
9072*552f7358SJed Brown         closure[numCorners++] = point;
9073*552f7358SJed Brown       }
9074*552f7358SJed Brown     }
9075*552f7358SJed Brown     for(corner = 0; corner < numCorners; ++corner) {
9076*552f7358SJed Brown       const PetscInt cellVertex = closure[corner];
9077*552f7358SJed Brown       PetscInt       subVertex;
9078*552f7358SJed Brown 
9079*552f7358SJed Brown       ierr = PetscFindInt(cellVertex, numSubVerticesActive, subVerticesActive, &subVertex);CHKERRQ(ierr);
9080*552f7358SJed Brown       if (subVertex >= 0) { /* contains submesh vertex */
9081*552f7358SJed Brown         for(i = 0; i < faceSize; ++i) {if (cellVertex == face[i]) break;}
9082*552f7358SJed Brown         if (i == faceSize) {
9083*552f7358SJed Brown           face[faceSize]    = cellVertex;
9084*552f7358SJed Brown           subface[faceSize] = numSubCells+subVertex;
9085*552f7358SJed Brown           ++faceSize;
9086*552f7358SJed Brown         }
9087*552f7358SJed Brown       }
9088*552f7358SJed Brown     }
9089*552f7358SJed Brown     ierr = DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
9090*552f7358SJed Brown     if (faceSize >= nFV) {
9091*552f7358SJed Brown       if (faceSize > nFV && !boundaryFaces) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %d of an element on the surface", faceSize);
9092*552f7358SJed Brown       // Here we allow a set of vertices to lie completely on a boundary cell (like a corner tetrahedron)
9093*552f7358SJed Brown       //   We have to take all the faces, and discard those in the interior
9094*552f7358SJed Brown       //   We check the join of the face vertices, which produces 2 cells if in the interior
9095*552f7358SJed Brown #if 0
9096*552f7358SJed Brown       // This object just calls insert on each face that comes from subsets()
9097*552f7358SJed Brown       // In fact, we can just always acll subsets(), since when we pass a single face it is a single call
9098*552f7358SJed Brown       FaceInserterV<FlexMesh::sieve_type> inserter(mesh, sieve, subSieve, f, *c_iter, numCorners, indices, &origVertices, &faceVertices, &submeshCells);
9099*552f7358SJed Brown       PointArray                          faceVec(face->begin(), face->end());
9100*552f7358SJed Brown 
9101*552f7358SJed Brown       subsets(faceVec, nFV, inserter);
9102*552f7358SJed Brown #endif
9103*552f7358SJed Brown       ierr = DMPlexInsertFace_Private(dm, *subdm, faceSize, face, subface, numCorners, cell, c, firstSubFace, &newFacePoint);CHKERRQ(ierr);
9104*552f7358SJed Brown     }
9105*552f7358SJed Brown   }
9106*552f7358SJed Brown   ierr = DMPlexSymmetrize(*subdm);CHKERRQ(ierr);
9107*552f7358SJed Brown   ierr = DMPlexStratify(*subdm);CHKERRQ(ierr);
9108*552f7358SJed Brown   /* Build coordinates */
9109*552f7358SJed Brown   ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr);
9110*552f7358SJed Brown   ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
9111*552f7358SJed Brown   ierr = DMPlexGetCoordinateSection(*subdm, &subCoordSection);CHKERRQ(ierr);
9112*552f7358SJed Brown   ierr = PetscSectionSetChart(subCoordSection, firstSubVertex, firstSubVertex+numSubVerticesActive);CHKERRQ(ierr);
9113*552f7358SJed Brown   for (v = firstSubVertex; v < firstSubVertex+numSubVerticesActive; ++v) {
9114*552f7358SJed Brown     ierr = PetscSectionSetDof(subCoordSection, v, dim);CHKERRQ(ierr);
9115*552f7358SJed Brown   }
9116*552f7358SJed Brown   ierr = PetscSectionSetUp(subCoordSection);CHKERRQ(ierr);
9117*552f7358SJed Brown   ierr = PetscSectionGetStorageSize(subCoordSection, &coordSize);CHKERRQ(ierr);
9118*552f7358SJed Brown   ierr = VecCreate(((PetscObject) dm)->comm, &subCoordinates);CHKERRQ(ierr);
9119*552f7358SJed Brown   ierr = VecSetSizes(subCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr);
9120*552f7358SJed Brown   ierr = VecSetFromOptions(subCoordinates);CHKERRQ(ierr);
9121*552f7358SJed Brown   ierr = VecGetArray(coordinates,    &coords);CHKERRQ(ierr);
9122*552f7358SJed Brown   ierr = VecGetArray(subCoordinates, &subCoords);CHKERRQ(ierr);
9123*552f7358SJed Brown   for(v = 0; v < numSubVerticesActive; ++v) {
9124*552f7358SJed Brown     const PetscInt vertex    = subVerticesActive[v];
9125*552f7358SJed Brown     const PetscInt subVertex = firstSubVertex+v;
9126*552f7358SJed Brown     PetscInt dof, off, sdof, soff;
9127*552f7358SJed Brown 
9128*552f7358SJed Brown     ierr = PetscSectionGetDof(coordSection, vertex, &dof);CHKERRQ(ierr);
9129*552f7358SJed Brown     ierr = PetscSectionGetOffset(coordSection, vertex, &off);CHKERRQ(ierr);
9130*552f7358SJed Brown     ierr = PetscSectionGetDof(subCoordSection, subVertex, &sdof);CHKERRQ(ierr);
9131*552f7358SJed Brown     ierr = PetscSectionGetOffset(subCoordSection, subVertex, &soff);CHKERRQ(ierr);
9132*552f7358SJed Brown     if (dof != sdof) SETERRQ4(comm, PETSC_ERR_PLIB, "Coordinate dimension %d on subvertex %d, vertex %d should be %d", sdof, subVertex, vertex, dof);
9133*552f7358SJed Brown     for(d = 0; d < dof; ++d) {
9134*552f7358SJed Brown       subCoords[soff+d] = coords[off+d];
9135*552f7358SJed Brown     }
9136*552f7358SJed Brown   }
9137*552f7358SJed Brown   ierr = VecRestoreArray(coordinates,    &coords);CHKERRQ(ierr);
9138*552f7358SJed Brown   ierr = VecRestoreArray(subCoordinates, &subCoords);CHKERRQ(ierr);
9139*552f7358SJed Brown   ierr = DMSetCoordinatesLocal(*subdm, subCoordinates);CHKERRQ(ierr);
9140*552f7358SJed Brown   ierr = VecDestroy(&subCoordinates);CHKERRQ(ierr);
9141*552f7358SJed Brown 
9142*552f7358SJed Brown   ierr = DMPlexSetVTKCellHeight(*subdm, 1);CHKERRQ(ierr);
9143*552f7358SJed Brown   /* Create map from submesh points to original mesh points */
9144*552f7358SJed Brown   submesh = (DM_Plex *) (*subdm)->data;
9145*552f7358SJed Brown   ierr = PetscMalloc((numSubCells+numSubVerticesActive) * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr);
9146*552f7358SJed Brown   for(c = 0; c < numSubCells; ++c) {
9147*552f7358SJed Brown     tmpPoints[c] = subCells[c];
9148*552f7358SJed Brown   }
9149*552f7358SJed Brown   for(v = numSubCells; v < numSubCells+numSubVerticesActive; ++v) {
9150*552f7358SJed Brown     tmpPoints[v] = subVerticesActive[v-numSubCells];
9151*552f7358SJed Brown   }
9152*552f7358SJed Brown   ierr = ISCreateGeneral(comm, numSubCells+numSubVerticesActive, tmpPoints, PETSC_OWN_POINTER, &submesh->subpointMap);CHKERRQ(ierr);
9153*552f7358SJed Brown 
9154*552f7358SJed Brown   ierr = PetscFree(subCells);CHKERRQ(ierr);
9155*552f7358SJed Brown   ierr = PetscFree(subVerticesActive);CHKERRQ(ierr);
9156*552f7358SJed Brown   ierr = ISRestoreIndices(labelIS, &subVertices);CHKERRQ(ierr);
9157*552f7358SJed Brown   ierr = ISDestroy(&labelIS);CHKERRQ(ierr);
9158*552f7358SJed Brown   ierr = DMRestoreWorkArray(dm, 2*maxConeSize, PETSC_INT, &face);CHKERRQ(ierr);
9159*552f7358SJed Brown   PetscFunctionReturn(0);
9160*552f7358SJed Brown }
9161*552f7358SJed Brown 
9162*552f7358SJed Brown #undef __FUNCT__
9163*552f7358SJed Brown #define __FUNCT__ "DMPlexCreateNumbering_Private"
9164*552f7358SJed Brown /* We can easily have a form that takes an IS instead */
9165*552f7358SJed Brown PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscSF sf, IS *numbering)
9166*552f7358SJed Brown {
9167*552f7358SJed Brown   PetscSection   section, globalSection;
9168*552f7358SJed Brown   PetscInt      *numbers, p;
9169*552f7358SJed Brown   PetscErrorCode ierr;
9170*552f7358SJed Brown 
9171*552f7358SJed Brown   PetscFunctionBegin;
9172*552f7358SJed Brown   ierr = PetscSectionCreate(((PetscObject) dm)->comm, &section);CHKERRQ(ierr);
9173*552f7358SJed Brown   ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr);
9174*552f7358SJed Brown   for(p = pStart; p < pEnd; ++p) {
9175*552f7358SJed Brown     ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr);
9176*552f7358SJed Brown   }
9177*552f7358SJed Brown   ierr = PetscSectionSetUp(section);CHKERRQ(ierr);
9178*552f7358SJed Brown   ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr);
9179*552f7358SJed Brown   ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &numbers);CHKERRQ(ierr);
9180*552f7358SJed Brown   for(p = pStart; p < pEnd; ++p) {
9181*552f7358SJed Brown     ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr);
9182*552f7358SJed Brown   }
9183*552f7358SJed Brown   ierr = ISCreateGeneral(((PetscObject) dm)->comm, pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr);
9184*552f7358SJed Brown   ierr = PetscSectionDestroy(&section);CHKERRQ(ierr);
9185*552f7358SJed Brown   ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr);
9186*552f7358SJed Brown   PetscFunctionReturn(0);
9187*552f7358SJed Brown }
9188*552f7358SJed Brown 
9189*552f7358SJed Brown #undef __FUNCT__
9190*552f7358SJed Brown #define __FUNCT__ "DMPlexGetCellNumbering"
9191*552f7358SJed Brown PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers)
9192*552f7358SJed Brown {
9193*552f7358SJed Brown   DM_Plex    *mesh = (DM_Plex *) dm->data;
9194*552f7358SJed Brown   PetscInt       cellHeight, cStart, cEnd, cMax;
9195*552f7358SJed Brown   PetscErrorCode ierr;
9196*552f7358SJed Brown 
9197*552f7358SJed Brown   PetscFunctionBegin;
9198*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9199*552f7358SJed Brown   if (!mesh->globalCellNumbers) {
9200*552f7358SJed Brown     ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr);
9201*552f7358SJed Brown     ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);
9202*552f7358SJed Brown     ierr = DMPlexGetVTKBounds(dm, &cMax, PETSC_NULL);CHKERRQ(ierr);
9203*552f7358SJed Brown     if (cMax >= 0) {cEnd = PetscMin(cEnd, cMax);}
9204*552f7358SJed Brown     ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr);
9205*552f7358SJed Brown   }
9206*552f7358SJed Brown   *globalCellNumbers = mesh->globalCellNumbers;
9207*552f7358SJed Brown   PetscFunctionReturn(0);
9208*552f7358SJed Brown }
9209*552f7358SJed Brown 
9210*552f7358SJed Brown #undef __FUNCT__
9211*552f7358SJed Brown #define __FUNCT__ "DMPlexGetVertexNumbering"
9212*552f7358SJed Brown PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers)
9213*552f7358SJed Brown {
9214*552f7358SJed Brown   DM_Plex    *mesh = (DM_Plex *) dm->data;
9215*552f7358SJed Brown   PetscInt       vStart, vEnd, vMax;
9216*552f7358SJed Brown   PetscErrorCode ierr;
9217*552f7358SJed Brown 
9218*552f7358SJed Brown   PetscFunctionBegin;
9219*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9220*552f7358SJed Brown   if (!mesh->globalVertexNumbers) {
9221*552f7358SJed Brown     ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
9222*552f7358SJed Brown     ierr = DMPlexGetVTKBounds(dm, PETSC_NULL, &vMax);CHKERRQ(ierr);
9223*552f7358SJed Brown     if (vMax >= 0) {vEnd = PetscMin(vEnd, vMax);}
9224*552f7358SJed Brown     ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr);
9225*552f7358SJed Brown   }
9226*552f7358SJed Brown   *globalVertexNumbers = mesh->globalVertexNumbers;
9227*552f7358SJed Brown   PetscFunctionReturn(0);
9228*552f7358SJed Brown }
9229*552f7358SJed Brown 
9230*552f7358SJed Brown #undef __FUNCT__
9231*552f7358SJed Brown #define __FUNCT__ "DMPlexGetSubpointMap"
9232*552f7358SJed Brown PetscErrorCode DMPlexGetSubpointMap(DM dm, IS *subpointMap)
9233*552f7358SJed Brown {
9234*552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *) dm->data;
9235*552f7358SJed Brown 
9236*552f7358SJed Brown   PetscFunctionBegin;
9237*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9238*552f7358SJed Brown   PetscValidPointer(subpointMap, 2);
9239*552f7358SJed Brown   *subpointMap = mesh->subpointMap;
9240*552f7358SJed Brown   PetscFunctionReturn(0);
9241*552f7358SJed Brown }
9242*552f7358SJed Brown 
9243*552f7358SJed Brown #undef __FUNCT__
9244*552f7358SJed Brown #define __FUNCT__ "DMPlexSetSubpointMap"
9245*552f7358SJed Brown /* Note: Should normally not be called by the user, since it is set in DMPlexCreateSubmesh() */
9246*552f7358SJed Brown PetscErrorCode DMPlexSetSubpointMap(DM dm, IS subpointMap)
9247*552f7358SJed Brown {
9248*552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *) dm->data;
9249*552f7358SJed Brown 
9250*552f7358SJed Brown   PetscFunctionBegin;
9251*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9252*552f7358SJed Brown   PetscValidHeaderSpecific(subpointMap, IS_CLASSID, 2);
9253*552f7358SJed Brown   mesh->subpointMap = subpointMap;
9254*552f7358SJed Brown   PetscFunctionReturn(0);
9255*552f7358SJed Brown }
9256*552f7358SJed Brown 
9257*552f7358SJed Brown #undef __FUNCT__
9258*552f7358SJed Brown #define __FUNCT__ "DMPlexGetScale"
9259*552f7358SJed Brown PetscErrorCode DMPlexGetScale(DM dm, PetscUnit unit, PetscReal *scale)
9260*552f7358SJed Brown {
9261*552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *) dm->data;
9262*552f7358SJed Brown 
9263*552f7358SJed Brown   PetscFunctionBegin;
9264*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9265*552f7358SJed Brown   PetscValidPointer(scale, 3);
9266*552f7358SJed Brown   *scale = mesh->scale[unit];
9267*552f7358SJed Brown   PetscFunctionReturn(0);
9268*552f7358SJed Brown }
9269*552f7358SJed Brown 
9270*552f7358SJed Brown #undef __FUNCT__
9271*552f7358SJed Brown #define __FUNCT__ "DMPlexSetScale"
9272*552f7358SJed Brown PetscErrorCode DMPlexSetScale(DM dm, PetscUnit unit, PetscReal scale)
9273*552f7358SJed Brown {
9274*552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *) dm->data;
9275*552f7358SJed Brown 
9276*552f7358SJed Brown   PetscFunctionBegin;
9277*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9278*552f7358SJed Brown   mesh->scale[unit] = scale;
9279*552f7358SJed Brown   PetscFunctionReturn(0);
9280*552f7358SJed Brown }
9281*552f7358SJed Brown 
9282*552f7358SJed Brown 
9283*552f7358SJed Brown /*******************************************************************************
9284*552f7358SJed Brown This should be in a separate Discretization object, but I am not sure how to lay
9285*552f7358SJed Brown it out yet, so I am stuffing things here while I experiment.
9286*552f7358SJed Brown *******************************************************************************/
9287*552f7358SJed Brown #undef __FUNCT__
9288*552f7358SJed Brown #define __FUNCT__ "DMPlexSetFEMIntegration"
9289*552f7358SJed Brown PetscErrorCode DMPlexSetFEMIntegration(DM dm,
9290*552f7358SJed Brown                                           PetscErrorCode (*integrateResidualFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[],
9291*552f7358SJed Brown                                                                                  const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[],
9292*552f7358SJed Brown                                                                                  void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]),
9293*552f7358SJed Brown                                                                                  void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]),
9294*552f7358SJed Brown                                           PetscErrorCode (*integrateJacobianActionFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], const PetscScalar[],
9295*552f7358SJed Brown                                                                                        const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[],
9296*552f7358SJed Brown                                                                                        void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]),
9297*552f7358SJed Brown                                                                                        void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]),
9298*552f7358SJed Brown                                                                                        void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]),
9299*552f7358SJed Brown                                                                                        void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]),
9300*552f7358SJed Brown                                           PetscErrorCode (*integrateJacobianFEM)(PetscInt, PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[],
9301*552f7358SJed Brown                                                                                  const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[],
9302*552f7358SJed Brown                                                                                  void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]),
9303*552f7358SJed Brown                                                                                  void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]),
9304*552f7358SJed Brown                                                                                  void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]),
9305*552f7358SJed Brown                                                                                  void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]))
9306*552f7358SJed Brown {
9307*552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *) dm->data;
9308*552f7358SJed Brown 
9309*552f7358SJed Brown   PetscFunctionBegin;
9310*552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9311*552f7358SJed Brown   mesh->integrateResidualFEM       = integrateResidualFEM;
9312*552f7358SJed Brown   mesh->integrateJacobianActionFEM = integrateJacobianActionFEM;
9313*552f7358SJed Brown   mesh->integrateJacobianFEM       = integrateJacobianFEM;
9314*552f7358SJed Brown   PetscFunctionReturn(0);
9315*552f7358SJed Brown }
9316*552f7358SJed Brown 
9317*552f7358SJed Brown #undef __FUNCT__
9318*552f7358SJed Brown #define __FUNCT__ "DMPlexProjectFunctionLocal"
9319*552f7358SJed Brown PetscErrorCode DMPlexProjectFunctionLocal(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec localX)
9320*552f7358SJed Brown {
9321*552f7358SJed Brown   Vec            coordinates;
9322*552f7358SJed Brown   PetscSection   section, cSection;
9323*552f7358SJed Brown   PetscInt       dim, vStart, vEnd, v, c, d;
9324*552f7358SJed Brown   PetscScalar   *values, *cArray;
9325*552f7358SJed Brown   PetscReal     *coords;
9326*552f7358SJed Brown   PetscErrorCode ierr;
9327*552f7358SJed Brown 
9328*552f7358SJed Brown   PetscFunctionBegin;
9329*552f7358SJed Brown   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
9330*552f7358SJed Brown   ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
9331*552f7358SJed Brown   ierr = DMPlexGetCoordinateSection(dm, &cSection);CHKERRQ(ierr);
9332*552f7358SJed Brown   ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
9333*552f7358SJed Brown   ierr = PetscMalloc(numComp * sizeof(PetscScalar), &values);CHKERRQ(ierr);
9334*552f7358SJed Brown   ierr = VecGetArray(coordinates, &cArray);CHKERRQ(ierr);
9335*552f7358SJed Brown   ierr = PetscSectionGetDof(cSection, vStart, &dim);CHKERRQ(ierr);
9336*552f7358SJed Brown   ierr = PetscMalloc(dim * sizeof(PetscReal),&coords);CHKERRQ(ierr);
9337*552f7358SJed Brown   for (v = vStart; v < vEnd; ++v) {
9338*552f7358SJed Brown     PetscInt dof, off;
9339*552f7358SJed Brown 
9340*552f7358SJed Brown     ierr = PetscSectionGetDof(cSection, v, &dof);CHKERRQ(ierr);
9341*552f7358SJed Brown     ierr = PetscSectionGetOffset(cSection, v, &off);CHKERRQ(ierr);
9342*552f7358SJed Brown     if (dof > dim) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Cannot have more coordinates %d then dimensions %d", dof, dim);
9343*552f7358SJed Brown     for(d = 0; d < dof; ++d) {
9344*552f7358SJed Brown       coords[d] = PetscRealPart(cArray[off+d]);
9345*552f7358SJed Brown     }
9346*552f7358SJed Brown     for(c = 0; c < numComp; ++c) {
9347*552f7358SJed Brown       values[c] = (*funcs[c])(coords);
9348*552f7358SJed Brown     }
9349*552f7358SJed Brown     ierr = VecSetValuesSection(localX, section, v, values, mode);CHKERRQ(ierr);
9350*552f7358SJed Brown   }
9351*552f7358SJed Brown   ierr = VecRestoreArray(coordinates, &cArray);CHKERRQ(ierr);
9352*552f7358SJed Brown   /* Temporary, must be replaced by a projection on the finite element basis */
9353*552f7358SJed Brown   {
9354*552f7358SJed Brown     PetscInt eStart = 0, eEnd = 0, e, depth;
9355*552f7358SJed Brown 
9356*552f7358SJed Brown     ierr = DMPlexGetLabelSize(dm, "depth", &depth);CHKERRQ(ierr);
9357*552f7358SJed Brown     --depth;
9358*552f7358SJed Brown     if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);}
9359*552f7358SJed Brown     for (e = eStart; e < eEnd; ++e) {
9360*552f7358SJed Brown       const PetscInt *cone = PETSC_NULL;
9361*552f7358SJed Brown       PetscInt        coneSize, d;
9362*552f7358SJed Brown       PetscScalar    *coordsA, *coordsB;
9363*552f7358SJed Brown 
9364*552f7358SJed Brown       ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr);
9365*552f7358SJed Brown       ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr);
9366*552f7358SJed Brown       if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_SIZ, "Cone size %d for point %d should be 2", coneSize, e);
9367*552f7358SJed Brown       ierr = VecGetValuesSection(coordinates, cSection, cone[0], &coordsA);CHKERRQ(ierr);
9368*552f7358SJed Brown       ierr = VecGetValuesSection(coordinates, cSection, cone[1], &coordsB);CHKERRQ(ierr);
9369*552f7358SJed Brown       for (d = 0; d < dim; ++d) {
9370*552f7358SJed Brown         coords[d] = 0.5*(PetscRealPart(coordsA[d]) + PetscRealPart(coordsB[d]));
9371*552f7358SJed Brown       }
9372*552f7358SJed Brown       for (c = 0; c < numComp; ++c) {
9373*552f7358SJed Brown         values[c] = (*funcs[c])(coords);
9374*552f7358SJed Brown       }
9375*552f7358SJed Brown       ierr = VecSetValuesSection(localX, section, e, values, mode);CHKERRQ(ierr);
9376*552f7358SJed Brown     }
9377*552f7358SJed Brown   }
9378*552f7358SJed Brown 
9379*552f7358SJed Brown   ierr = PetscFree(coords);CHKERRQ(ierr);
9380*552f7358SJed Brown   ierr = PetscFree(values);CHKERRQ(ierr);
9381*552f7358SJed Brown #if 0
9382*552f7358SJed Brown   const PetscInt localDof = this->_mesh->sizeWithBC(s, *cells->begin());
9383*552f7358SJed Brown   PetscReal      detJ;
9384*552f7358SJed Brown 
9385*552f7358SJed Brown   ierr = PetscMalloc(localDof * sizeof(PetscScalar), &values);CHKERRQ(ierr);
9386*552f7358SJed Brown   ierr = PetscMalloc2(dim,PetscReal,&v0,dim*dim,PetscReal,&J);CHKERRQ(ierr);
9387*552f7358SJed Brown   ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type> pV((int) pow(this->_mesh->getSieve()->getMaxConeSize(), dim+1)+1, true);
9388*552f7358SJed Brown 
9389*552f7358SJed Brown   for (PetscInt c = cStart; c < cEnd; ++c) {
9390*552f7358SJed Brown     ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*this->_mesh->getSieve(), c, pV);
9391*552f7358SJed Brown     const PETSC_MESH_TYPE::point_type *oPoints = pV.getPoints();
9392*552f7358SJed Brown     const int                          oSize   = pV.getSize();
9393*552f7358SJed Brown     int                                v       = 0;
9394*552f7358SJed Brown 
9395*552f7358SJed Brown     ierr = DMPlexComputeCellGeometry(dm, c, v0, J, PETSC_NULL, &detJ);CHKERRQ(ierr);
9396*552f7358SJed Brown     for (PetscInt cl = 0; cl < oSize; ++cl) {
9397*552f7358SJed Brown       const PetscInt fDim;
9398*552f7358SJed Brown 
9399*552f7358SJed Brown       ierr = PetscSectionGetDof(oPoints[cl], &fDim);CHKERRQ(ierr);
9400*552f7358SJed Brown       if (pointDim) {
9401*552f7358SJed Brown         for (PetscInt d = 0; d < fDim; ++d, ++v) {
9402*552f7358SJed Brown           values[v] = (*this->_options.integrate)(v0, J, v, initFunc);
9403*552f7358SJed Brown         }
9404*552f7358SJed Brown       }
9405*552f7358SJed Brown     }
9406*552f7358SJed Brown     ierr = DMPlexVecSetClosure(dm, PETSC_NULL, localX, c, values);CHKERRQ(ierr);
9407*552f7358SJed Brown     pV.clear();
9408*552f7358SJed Brown   }
9409*552f7358SJed Brown   ierr = PetscFree2(v0,J);CHKERRQ(ierr);
9410*552f7358SJed Brown   ierr = PetscFree(values);CHKERRQ(ierr);
9411*552f7358SJed Brown #endif
9412*552f7358SJed Brown   PetscFunctionReturn(0);
9413*552f7358SJed Brown }
9414*552f7358SJed Brown 
9415*552f7358SJed Brown #undef __FUNCT__
9416*552f7358SJed Brown #define __FUNCT__ "DMPlexProjectFunction"
9417*552f7358SJed Brown /*@C
9418*552f7358SJed Brown   DMPlexProjectFunction - This projects the given function into the function space provided.
9419*552f7358SJed Brown 
9420*552f7358SJed Brown   Input Parameters:
9421*552f7358SJed Brown + dm      - The DM
9422*552f7358SJed Brown . numComp - The number of components (functions)
9423*552f7358SJed Brown . funcs   - The coordinate functions to evaluate
9424*552f7358SJed Brown - mode    - The insertion mode for values
9425*552f7358SJed Brown 
9426*552f7358SJed Brown   Output Parameter:
9427*552f7358SJed Brown . X - vector
9428*552f7358SJed Brown 
9429*552f7358SJed Brown   Level: developer
9430*552f7358SJed Brown 
9431*552f7358SJed Brown   Note:
9432*552f7358SJed Brown   This currently just calls the function with the coordinates of each vertex and edge midpoint, and stores the result in a vector.
9433*552f7358SJed Brown   We will eventually fix it.
9434*552f7358SJed Brown 
9435*552f7358SJed Brown ,seealso: DMPlexComputeL2Diff()
9436*552f7358SJed Brown */
9437*552f7358SJed Brown PetscErrorCode DMPlexProjectFunction(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec X)
9438*552f7358SJed Brown {
9439*552f7358SJed Brown   Vec            localX;
9440*552f7358SJed Brown   PetscErrorCode ierr;
9441*552f7358SJed Brown 
9442*552f7358SJed Brown   PetscFunctionBegin;
9443*552f7358SJed Brown   ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr);
9444*552f7358SJed Brown   ierr = DMPlexProjectFunctionLocal(dm, numComp, funcs, mode, localX);CHKERRQ(ierr);
9445*552f7358SJed Brown   ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr);
9446*552f7358SJed Brown   ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr);
9447*552f7358SJed Brown   ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr);
9448*552f7358SJed Brown   PetscFunctionReturn(0);
9449*552f7358SJed Brown }
9450*552f7358SJed Brown 
9451*552f7358SJed Brown #undef __FUNCT__
9452*552f7358SJed Brown #define __FUNCT__ "DMPlexComputeL2Diff"
9453*552f7358SJed Brown /*@C
9454*552f7358SJed Brown   DMPlexComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h.
9455*552f7358SJed Brown 
9456*552f7358SJed Brown   Input Parameters:
9457*552f7358SJed Brown + dm    - The DM
9458*552f7358SJed Brown . quad  - The PetscQuadrature object for each field
9459*552f7358SJed Brown . funcs - The functions to evaluate for each field component
9460*552f7358SJed Brown - X     - The coefficient vector u_h
9461*552f7358SJed Brown 
9462*552f7358SJed Brown   Output Parameter:
9463*552f7358SJed Brown . diff - The diff ||u - u_h||_2
9464*552f7358SJed Brown 
9465*552f7358SJed Brown   Level: developer
9466*552f7358SJed Brown 
9467*552f7358SJed Brown .seealso: DMPlexProjectFunction()
9468*552f7358SJed Brown */
9469*552f7358SJed Brown PetscErrorCode DMPlexComputeL2Diff(DM dm, PetscQuadrature quad[], PetscScalar (**funcs)(const PetscReal []), Vec X, PetscReal *diff) {
9470*552f7358SJed Brown   const PetscInt   debug = 0;
9471*552f7358SJed Brown   PetscSection     section;
9472*552f7358SJed Brown   Vec              localX;
9473*552f7358SJed Brown   PetscReal       *coords, *v0, *J, *invJ, detJ;
9474*552f7358SJed Brown   PetscReal        localDiff = 0.0;
9475*552f7358SJed Brown   PetscInt         dim, numFields, numComponents = 0, cStart, cEnd, c, field, fieldOffset, comp;
9476*552f7358SJed Brown   PetscErrorCode   ierr;
9477*552f7358SJed Brown 
9478*552f7358SJed Brown   PetscFunctionBegin;
9479*552f7358SJed Brown   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
9480*552f7358SJed Brown   ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
9481*552f7358SJed Brown   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
9482*552f7358SJed Brown   ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr);
9483*552f7358SJed Brown   ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr);
9484*552f7358SJed Brown   ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr);
9485*552f7358SJed Brown   for (field = 0; field < numFields; ++field) {
9486*552f7358SJed Brown     numComponents += quad[field].numComponents;
9487*552f7358SJed Brown   }
9488*552f7358SJed Brown   ierr = DMPlexProjectFunctionLocal(dm, numComponents, funcs, INSERT_BC_VALUES, localX);CHKERRQ(ierr);
9489*552f7358SJed Brown   ierr = PetscMalloc4(dim,PetscReal,&coords,dim,PetscReal,&v0,dim*dim,PetscReal,&J,dim*dim,PetscReal,&invJ);CHKERRQ(ierr);
9490*552f7358SJed Brown   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
9491*552f7358SJed Brown   for (c = cStart; c < cEnd; ++c) {
9492*552f7358SJed Brown     const PetscScalar *x;
9493*552f7358SJed Brown     PetscReal          elemDiff = 0.0;
9494*552f7358SJed Brown 
9495*552f7358SJed Brown     ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr);
9496*552f7358SJed Brown     if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c);
9497*552f7358SJed Brown     ierr = DMPlexVecGetClosure(dm, PETSC_NULL, localX, c, PETSC_NULL, &x);CHKERRQ(ierr);
9498*552f7358SJed Brown 
9499*552f7358SJed Brown     for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) {
9500*552f7358SJed Brown       const PetscInt   numQuadPoints = quad[field].numQuadPoints;
9501*552f7358SJed Brown       const PetscReal *quadPoints    = quad[field].quadPoints;
9502*552f7358SJed Brown       const PetscReal *quadWeights   = quad[field].quadWeights;
9503*552f7358SJed Brown       const PetscInt   numBasisFuncs = quad[field].numBasisFuncs;
9504*552f7358SJed Brown       const PetscInt   numBasisComps = quad[field].numComponents;
9505*552f7358SJed Brown       const PetscReal *basis         = quad[field].basis;
9506*552f7358SJed Brown       PetscInt         q, d, e, fc, f;
9507*552f7358SJed Brown 
9508*552f7358SJed Brown       if (debug) {
9509*552f7358SJed Brown         char title[1024];
9510*552f7358SJed Brown         ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr);
9511*552f7358SJed Brown         ierr = DMPrintCellVector(c, title, numBasisFuncs*numBasisComps, &x[fieldOffset]);CHKERRQ(ierr);
9512*552f7358SJed Brown       }
9513*552f7358SJed Brown       for (q = 0; q < numQuadPoints; ++q) {
9514*552f7358SJed Brown         for (d = 0; d < dim; d++) {
9515*552f7358SJed Brown           coords[d] = v0[d];
9516*552f7358SJed Brown           for (e = 0; e < dim; e++) {
9517*552f7358SJed Brown             coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0);
9518*552f7358SJed Brown           }
9519*552f7358SJed Brown         }
9520*552f7358SJed Brown         for (fc = 0; fc < numBasisComps; ++fc) {
9521*552f7358SJed Brown           const PetscReal funcVal     = PetscRealPart((*funcs[comp+fc])(coords));
9522*552f7358SJed Brown           PetscReal       interpolant = 0.0;
9523*552f7358SJed Brown           for (f = 0; f < numBasisFuncs; ++f) {
9524*552f7358SJed Brown             const PetscInt fidx = f*numBasisComps+fc;
9525*552f7358SJed Brown             interpolant += PetscRealPart(x[fieldOffset+fidx])*basis[q*numBasisFuncs*numBasisComps+fidx];
9526*552f7358SJed Brown           }
9527*552f7358SJed Brown           if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, "    elem %d field %d diff %g\n", c, field, PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ);CHKERRQ(ierr);}
9528*552f7358SJed Brown           elemDiff += PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ;
9529*552f7358SJed Brown         }
9530*552f7358SJed Brown       }
9531*552f7358SJed Brown       comp        += numBasisComps;
9532*552f7358SJed Brown       fieldOffset += numBasisFuncs*numBasisComps;
9533*552f7358SJed Brown     }
9534*552f7358SJed Brown     ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, localX, c, PETSC_NULL, &x);CHKERRQ(ierr);
9535*552f7358SJed Brown     if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, "  elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);}
9536*552f7358SJed Brown     localDiff += elemDiff;
9537*552f7358SJed Brown   }
9538*552f7358SJed Brown   ierr = PetscFree4(coords,v0,J,invJ);CHKERRQ(ierr);
9539*552f7358SJed Brown   ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr);
9540*552f7358SJed Brown   ierr = MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD);CHKERRQ(ierr);
9541*552f7358SJed Brown   *diff = PetscSqrtReal(*diff);
9542*552f7358SJed Brown   PetscFunctionReturn(0);
9543*552f7358SJed Brown }
9544*552f7358SJed Brown 
9545*552f7358SJed Brown #undef __FUNCT__
9546*552f7358SJed Brown #define __FUNCT__ "DMPlexComputeResidualFEM"
9547*552f7358SJed Brown /*@
9548*552f7358SJed Brown   DMPlexComputeResidualFEM - Form the local residual F from the local input X using pointwise functions specified by the user
9549*552f7358SJed Brown 
9550*552f7358SJed Brown   Input Parameters:
9551*552f7358SJed Brown + dm - The mesh
9552*552f7358SJed Brown . X  - Local input vector
9553*552f7358SJed Brown - user - The user context
9554*552f7358SJed Brown 
9555*552f7358SJed Brown   Output Parameter:
9556*552f7358SJed Brown . F  - Local output vector
9557*552f7358SJed Brown 
9558*552f7358SJed Brown   Note:
9559*552f7358SJed Brown   The second member of the user context must be an FEMContext.
9560*552f7358SJed Brown 
9561*552f7358SJed Brown   We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator,
9562*552f7358SJed Brown   like a GPU, or vectorize on a multicore machine.
9563*552f7358SJed Brown 
9564*552f7358SJed Brown .seealso: DMPlexComputeJacobianActionFEM()
9565*552f7358SJed Brown */
9566*552f7358SJed Brown PetscErrorCode DMPlexComputeResidualFEM(DM dm, Vec X, Vec F, void *user)
9567*552f7358SJed Brown {
9568*552f7358SJed Brown   DM_Plex      *mesh = (DM_Plex *) dm->data;
9569*552f7358SJed Brown   PetscFEM        *fem  = (PetscFEM *) &((DM *) user)[1];
9570*552f7358SJed Brown   PetscQuadrature *quad = fem->quad;
9571*552f7358SJed Brown   PetscSection     section;
9572*552f7358SJed Brown   PetscReal       *v0, *J, *invJ, *detJ;
9573*552f7358SJed Brown   PetscScalar     *elemVec, *u;
9574*552f7358SJed Brown   PetscInt         dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c;
9575*552f7358SJed Brown   PetscInt         cellDof = 0, numComponents = 0;
9576*552f7358SJed Brown   PetscErrorCode   ierr;
9577*552f7358SJed Brown 
9578*552f7358SJed Brown   PetscFunctionBegin;
9579*552f7358SJed Brown   /* ierr = PetscLogEventBegin(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */
9580*552f7358SJed Brown   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
9581*552f7358SJed Brown   ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
9582*552f7358SJed Brown   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
9583*552f7358SJed Brown   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
9584*552f7358SJed Brown   numCells = cEnd - cStart;
9585*552f7358SJed Brown   for (field = 0; field < numFields; ++field) {
9586*552f7358SJed Brown     cellDof += quad[field].numBasisFuncs*quad[field].numComponents;
9587*552f7358SJed Brown     numComponents += quad[field].numComponents;
9588*552f7358SJed Brown   }
9589*552f7358SJed Brown   ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr);
9590*552f7358SJed Brown   ierr = VecSet(F, 0.0);CHKERRQ(ierr);
9591*552f7358SJed Brown   ierr = PetscMalloc6(numCells*cellDof,PetscScalar,&u,numCells*dim,PetscReal,&v0,numCells*dim*dim,PetscReal,&J,numCells*dim*dim,PetscReal,&invJ,numCells,PetscReal,&detJ,numCells*cellDof,PetscScalar,&elemVec);CHKERRQ(ierr);
9592*552f7358SJed Brown   for (c = cStart; c < cEnd; ++c) {
9593*552f7358SJed Brown     const PetscScalar *x;
9594*552f7358SJed Brown     PetscInt           i;
9595*552f7358SJed Brown 
9596*552f7358SJed Brown     ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr);
9597*552f7358SJed Brown     if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c);
9598*552f7358SJed Brown     ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr);
9599*552f7358SJed Brown 
9600*552f7358SJed Brown     for (i = 0; i < cellDof; ++i) {
9601*552f7358SJed Brown       u[c*cellDof+i] = x[i];
9602*552f7358SJed Brown     }
9603*552f7358SJed Brown     ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr);
9604*552f7358SJed Brown   }
9605*552f7358SJed Brown   for (field = 0; field < numFields; ++field) {
9606*552f7358SJed Brown     const PetscInt numQuadPoints = quad[field].numQuadPoints;
9607*552f7358SJed Brown     const PetscInt numBasisFuncs = quad[field].numBasisFuncs;
9608*552f7358SJed Brown     void (*f0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f0[]) = fem->f0Funcs[field];
9609*552f7358SJed Brown     void (*f1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f1[]) = fem->f1Funcs[field];
9610*552f7358SJed Brown     /* Conforming batches */
9611*552f7358SJed Brown     PetscInt blockSize  = numBasisFuncs*numQuadPoints;
9612*552f7358SJed Brown     PetscInt numBlocks  = 1;
9613*552f7358SJed Brown     PetscInt batchSize  = numBlocks * blockSize;
9614*552f7358SJed Brown     PetscInt numBatches = numBatchesTmp;
9615*552f7358SJed Brown     PetscInt numChunks  = numCells / (numBatches*batchSize);
9616*552f7358SJed Brown     /* Remainder */
9617*552f7358SJed Brown     PetscInt numRemainder = numCells % (numBatches * batchSize);
9618*552f7358SJed Brown     PetscInt offset       = numCells - numRemainder;
9619*552f7358SJed Brown 
9620*552f7358SJed Brown     ierr = (*mesh->integrateResidualFEM)(numChunks*numBatches*batchSize, numFields, field, quad, u, v0, J, invJ, detJ, f0, f1, elemVec);CHKERRQ(ierr);
9621*552f7358SJed Brown     ierr = (*mesh->integrateResidualFEM)(numRemainder, numFields, field, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset],
9622*552f7358SJed Brown                                          f0, f1, &elemVec[offset*cellDof]);CHKERRQ(ierr);
9623*552f7358SJed Brown   }
9624*552f7358SJed Brown   for (c = cStart; c < cEnd; ++c) {
9625*552f7358SJed Brown     if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Residual", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);}
9626*552f7358SJed Brown     ierr = DMPlexVecSetClosure(dm, PETSC_NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr);
9627*552f7358SJed Brown   }
9628*552f7358SJed Brown   ierr = PetscFree6(u,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr);
9629*552f7358SJed Brown   if (mesh->printFEM) {
9630*552f7358SJed Brown     PetscMPIInt rank, numProcs;
9631*552f7358SJed Brown     PetscInt    p;
9632*552f7358SJed Brown 
9633*552f7358SJed Brown     ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr);
9634*552f7358SJed Brown     ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr);
9635*552f7358SJed Brown     ierr = PetscPrintf(PETSC_COMM_WORLD, "Residual:\n");CHKERRQ(ierr);
9636*552f7358SJed Brown     for (p = 0; p < numProcs; ++p) {
9637*552f7358SJed Brown       if (p == rank) {
9638*552f7358SJed Brown         Vec f;
9639*552f7358SJed Brown 
9640*552f7358SJed Brown         ierr = VecDuplicate(F, &f);CHKERRQ(ierr);
9641*552f7358SJed Brown         ierr = VecCopy(F, f);CHKERRQ(ierr);
9642*552f7358SJed Brown         ierr = VecChop(f, 1.0e-10);CHKERRQ(ierr);
9643*552f7358SJed Brown         ierr = VecView(f, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
9644*552f7358SJed Brown         ierr = VecDestroy(&f);CHKERRQ(ierr);
9645*552f7358SJed Brown         ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);
9646*552f7358SJed Brown       }
9647*552f7358SJed Brown       ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr);
9648*552f7358SJed Brown     }
9649*552f7358SJed Brown   }
9650*552f7358SJed Brown   /* ierr = PetscLogEventEnd(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */
9651*552f7358SJed Brown   PetscFunctionReturn(0);
9652*552f7358SJed Brown }
9653*552f7358SJed Brown 
9654*552f7358SJed Brown #undef __FUNCT__
9655*552f7358SJed Brown #define __FUNCT__ "DMPlexComputeJacobianActionFEM"
9656*552f7358SJed Brown /*@C
9657*552f7358SJed Brown   DMPlexComputeJacobianActionFEM - Form the local action of Jacobian J(u) on the local input X using pointwise functions specified by the user
9658*552f7358SJed Brown 
9659*552f7358SJed Brown   Input Parameters:
9660*552f7358SJed Brown + dm - The mesh
9661*552f7358SJed Brown . J  - The Jacobian shell matrix
9662*552f7358SJed Brown . X  - Local input vector
9663*552f7358SJed Brown - user - The user context
9664*552f7358SJed Brown 
9665*552f7358SJed Brown   Output Parameter:
9666*552f7358SJed Brown . F  - Local output vector
9667*552f7358SJed Brown 
9668*552f7358SJed Brown   Note:
9669*552f7358SJed Brown   The second member of the user context must be an FEMContext.
9670*552f7358SJed Brown 
9671*552f7358SJed Brown   We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator,
9672*552f7358SJed Brown   like a GPU, or vectorize on a multicore machine.
9673*552f7358SJed Brown 
9674*552f7358SJed Brown .seealso: DMPlexComputeResidualFEM()
9675*552f7358SJed Brown */
9676*552f7358SJed Brown PetscErrorCode DMPlexComputeJacobianActionFEM(DM dm, Mat Jac, Vec X, Vec F, void *user)
9677*552f7358SJed Brown {
9678*552f7358SJed Brown   DM_Plex      *mesh = (DM_Plex *) dm->data;
9679*552f7358SJed Brown   PetscFEM        *fem  = (PetscFEM *) &((DM *) user)[1];
9680*552f7358SJed Brown   PetscQuadrature *quad = fem->quad;
9681*552f7358SJed Brown   PetscSection     section;
9682*552f7358SJed Brown   JacActionCtx    *jctx;
9683*552f7358SJed Brown   PetscReal       *v0, *J, *invJ, *detJ;
9684*552f7358SJed Brown   PetscScalar     *elemVec, *u, *a;
9685*552f7358SJed Brown   PetscInt         dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c;
9686*552f7358SJed Brown   PetscInt         cellDof = 0;
9687*552f7358SJed Brown   PetscErrorCode   ierr;
9688*552f7358SJed Brown 
9689*552f7358SJed Brown   PetscFunctionBegin;
9690*552f7358SJed Brown   /* ierr = PetscLogEventBegin(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */
9691*552f7358SJed Brown   ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr);
9692*552f7358SJed Brown   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
9693*552f7358SJed Brown   ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
9694*552f7358SJed Brown   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
9695*552f7358SJed Brown   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
9696*552f7358SJed Brown   numCells = cEnd - cStart;
9697*552f7358SJed Brown   for (field = 0; field < numFields; ++field) {
9698*552f7358SJed Brown     cellDof += quad[field].numBasisFuncs*quad[field].numComponents;
9699*552f7358SJed Brown   }
9700*552f7358SJed Brown   ierr = VecSet(F, 0.0);CHKERRQ(ierr);
9701*552f7358SJed Brown   ierr = PetscMalloc7(numCells*cellDof,PetscScalar,&u,numCells*cellDof,PetscScalar,&a,numCells*dim,PetscReal,&v0,numCells*dim*dim,PetscReal,&J,numCells*dim*dim,PetscReal,&invJ,numCells,PetscReal,&detJ,numCells*cellDof,PetscScalar,&elemVec);CHKERRQ(ierr);
9702*552f7358SJed Brown   for (c = cStart; c < cEnd; ++c) {
9703*552f7358SJed Brown     const PetscScalar *x;
9704*552f7358SJed Brown     PetscInt           i;
9705*552f7358SJed Brown 
9706*552f7358SJed Brown     ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr);
9707*552f7358SJed Brown     if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c);
9708*552f7358SJed Brown     ierr = DMPlexVecGetClosure(dm, PETSC_NULL, jctx->u, c, PETSC_NULL, &x);CHKERRQ(ierr);
9709*552f7358SJed Brown     for (i = 0; i < cellDof; ++i) {
9710*552f7358SJed Brown       u[c*cellDof+i] = x[i];
9711*552f7358SJed Brown     }
9712*552f7358SJed Brown     ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, jctx->u, c, PETSC_NULL, &x);CHKERRQ(ierr);
9713*552f7358SJed Brown     ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr);
9714*552f7358SJed Brown     for (i = 0; i < cellDof; ++i) {
9715*552f7358SJed Brown       a[c*cellDof+i] = x[i];
9716*552f7358SJed Brown     }
9717*552f7358SJed Brown     ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr);
9718*552f7358SJed Brown   }
9719*552f7358SJed Brown   for (field = 0; field < numFields; ++field) {
9720*552f7358SJed Brown     const PetscInt numQuadPoints = quad[field].numQuadPoints;
9721*552f7358SJed Brown     const PetscInt numBasisFuncs = quad[field].numBasisFuncs;
9722*552f7358SJed Brown     /* Conforming batches */
9723*552f7358SJed Brown     PetscInt blockSize  = numBasisFuncs*numQuadPoints;
9724*552f7358SJed Brown     PetscInt numBlocks  = 1;
9725*552f7358SJed Brown     PetscInt batchSize  = numBlocks * blockSize;
9726*552f7358SJed Brown     PetscInt numBatches = numBatchesTmp;
9727*552f7358SJed Brown     PetscInt numChunks  = numCells / (numBatches*batchSize);
9728*552f7358SJed Brown     /* Remainder */
9729*552f7358SJed Brown     PetscInt numRemainder = numCells % (numBatches * batchSize);
9730*552f7358SJed Brown     PetscInt offset       = numCells - numRemainder;
9731*552f7358SJed Brown 
9732*552f7358SJed Brown     ierr = (*mesh->integrateJacobianActionFEM)(numChunks*numBatches*batchSize, numFields, field, quad, u, a, v0, J, invJ, detJ, fem->g0Funcs, fem->g1Funcs, fem->g2Funcs, fem->g3Funcs, elemVec);CHKERRQ(ierr);
9733*552f7358SJed Brown     ierr = (*mesh->integrateJacobianActionFEM)(numRemainder, numFields, field, quad, &u[offset*cellDof], &a[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset],
9734*552f7358SJed Brown                                                fem->g0Funcs, fem->g1Funcs, fem->g2Funcs, fem->g3Funcs, &elemVec[offset*cellDof]);CHKERRQ(ierr);
9735*552f7358SJed Brown   }
9736*552f7358SJed Brown   for (c = cStart; c < cEnd; ++c) {
9737*552f7358SJed Brown     if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Jacobian Action", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);}
9738*552f7358SJed Brown     ierr = DMPlexVecSetClosure(dm, PETSC_NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr);
9739*552f7358SJed Brown   }
9740*552f7358SJed Brown   ierr = PetscFree7(u,a,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr);
9741*552f7358SJed Brown   if (mesh->printFEM) {
9742*552f7358SJed Brown     PetscMPIInt rank, numProcs;
9743*552f7358SJed Brown     PetscInt    p;
9744*552f7358SJed Brown 
9745*552f7358SJed Brown     ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr);
9746*552f7358SJed Brown     ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr);
9747*552f7358SJed Brown     ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian Action:\n");CHKERRQ(ierr);
9748*552f7358SJed Brown     for (p = 0; p < numProcs; ++p) {
9749*552f7358SJed Brown       if (p == rank) {ierr = VecView(F, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);}
9750*552f7358SJed Brown       ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr);
9751*552f7358SJed Brown     }
9752*552f7358SJed Brown   }
9753*552f7358SJed Brown   /* ierr = PetscLogEventEnd(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */
9754*552f7358SJed Brown   PetscFunctionReturn(0);
9755*552f7358SJed Brown }
9756*552f7358SJed Brown 
9757*552f7358SJed Brown #undef __FUNCT__
9758*552f7358SJed Brown #define __FUNCT__ "DMPlexComputeJacobianFEM"
9759*552f7358SJed Brown /*@
9760*552f7358SJed Brown   DMPlexComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user.
9761*552f7358SJed Brown 
9762*552f7358SJed Brown   Input Parameters:
9763*552f7358SJed Brown + dm - The mesh
9764*552f7358SJed Brown . X  - Local input vector
9765*552f7358SJed Brown - user - The user context
9766*552f7358SJed Brown 
9767*552f7358SJed Brown   Output Parameter:
9768*552f7358SJed Brown . Jac  - Jacobian matrix
9769*552f7358SJed Brown 
9770*552f7358SJed Brown   Note:
9771*552f7358SJed Brown   The second member of the user context must be an FEMContext.
9772*552f7358SJed Brown 
9773*552f7358SJed Brown   We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator,
9774*552f7358SJed Brown   like a GPU, or vectorize on a multicore machine.
9775*552f7358SJed Brown 
9776*552f7358SJed Brown .seealso: FormFunctionLocal()
9777*552f7358SJed Brown */
9778*552f7358SJed Brown PetscErrorCode DMPlexComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP, MatStructure *str,void *user)
9779*552f7358SJed Brown {
9780*552f7358SJed Brown   DM_Plex      *mesh = (DM_Plex *) dm->data;
9781*552f7358SJed Brown   PetscFEM        *fem  = (PetscFEM *) &((DM *) user)[1];
9782*552f7358SJed Brown   PetscQuadrature *quad = fem->quad;
9783*552f7358SJed Brown   PetscSection     section;
9784*552f7358SJed Brown   PetscReal       *v0, *J, *invJ, *detJ;
9785*552f7358SJed Brown   PetscScalar     *elemMat, *u;
9786*552f7358SJed Brown   PetscInt         dim, numFields, field, fieldI, numBatchesTmp = 1, numCells, cStart, cEnd, c;
9787*552f7358SJed Brown   PetscInt         cellDof = 0, numComponents = 0;
9788*552f7358SJed Brown   PetscBool        isShell;
9789*552f7358SJed Brown   PetscErrorCode   ierr;
9790*552f7358SJed Brown 
9791*552f7358SJed Brown   PetscFunctionBegin;
9792*552f7358SJed Brown   /* ierr = PetscLogEventBegin(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */
9793*552f7358SJed Brown   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
9794*552f7358SJed Brown   ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
9795*552f7358SJed Brown   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
9796*552f7358SJed Brown   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
9797*552f7358SJed Brown   numCells = cEnd - cStart;
9798*552f7358SJed Brown   for (field = 0; field < numFields; ++field) {
9799*552f7358SJed Brown     cellDof += quad[field].numBasisFuncs*quad[field].numComponents;
9800*552f7358SJed Brown     numComponents += quad[field].numComponents;
9801*552f7358SJed Brown   }
9802*552f7358SJed Brown   ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr);
9803*552f7358SJed Brown   ierr = MatZeroEntries(JacP);CHKERRQ(ierr);
9804*552f7358SJed Brown   ierr = PetscMalloc6(numCells*cellDof,PetscScalar,&u,numCells*dim,PetscReal,&v0,numCells*dim*dim,PetscReal,&J,numCells*dim*dim,PetscReal,&invJ,numCells,PetscReal,&detJ,numCells*cellDof*cellDof,PetscScalar,&elemMat);CHKERRQ(ierr);
9805*552f7358SJed Brown   for (c = cStart; c < cEnd; ++c) {
9806*552f7358SJed Brown     const PetscScalar *x;
9807*552f7358SJed Brown     PetscInt           i;
9808*552f7358SJed Brown 
9809*552f7358SJed Brown     ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr);
9810*552f7358SJed Brown     if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c);
9811*552f7358SJed Brown     ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr);
9812*552f7358SJed Brown 
9813*552f7358SJed Brown     for (i = 0; i < cellDof; ++i) {
9814*552f7358SJed Brown       u[c*cellDof+i] = x[i];
9815*552f7358SJed Brown     }
9816*552f7358SJed Brown     ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr);
9817*552f7358SJed Brown   }
9818*552f7358SJed Brown   ierr = PetscMemzero(elemMat, numCells*cellDof*cellDof * sizeof(PetscScalar));CHKERRQ(ierr);
9819*552f7358SJed Brown   for (fieldI = 0; fieldI < numFields; ++fieldI) {
9820*552f7358SJed Brown     const PetscInt numQuadPoints = quad[fieldI].numQuadPoints;
9821*552f7358SJed Brown     const PetscInt numBasisFuncs = quad[fieldI].numBasisFuncs;
9822*552f7358SJed Brown     PetscInt       fieldJ;
9823*552f7358SJed Brown 
9824*552f7358SJed Brown     for (fieldJ = 0; fieldJ < numFields; ++fieldJ) {
9825*552f7358SJed Brown       void (*g0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g0[]) = fem->g0Funcs[fieldI*numFields+fieldJ];
9826*552f7358SJed Brown       void (*g1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g1[]) = fem->g1Funcs[fieldI*numFields+fieldJ];
9827*552f7358SJed Brown       void (*g2)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g2[]) = fem->g2Funcs[fieldI*numFields+fieldJ];
9828*552f7358SJed Brown       void (*g3)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g3[]) = fem->g3Funcs[fieldI*numFields+fieldJ];
9829*552f7358SJed Brown       /* Conforming batches */
9830*552f7358SJed Brown       PetscInt blockSize  = numBasisFuncs*numQuadPoints;
9831*552f7358SJed Brown       PetscInt numBlocks  = 1;
9832*552f7358SJed Brown       PetscInt batchSize  = numBlocks * blockSize;
9833*552f7358SJed Brown       PetscInt numBatches = numBatchesTmp;
9834*552f7358SJed Brown       PetscInt numChunks  = numCells / (numBatches*batchSize);
9835*552f7358SJed Brown       /* Remainder */
9836*552f7358SJed Brown       PetscInt numRemainder = numCells % (numBatches * batchSize);
9837*552f7358SJed Brown       PetscInt offset       = numCells - numRemainder;
9838*552f7358SJed Brown 
9839*552f7358SJed Brown       ierr = (*mesh->integrateJacobianFEM)(numChunks*numBatches*batchSize, numFields, fieldI, fieldJ, quad, u, v0, J, invJ, detJ, g0, g1, g2, g3, elemMat);CHKERRQ(ierr);
9840*552f7358SJed Brown       ierr = (*mesh->integrateJacobianFEM)(numRemainder, numFields, fieldI, fieldJ, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset],
9841*552f7358SJed Brown                                            g0, g1, g2, g3, &elemMat[offset*cellDof*cellDof]);CHKERRQ(ierr);
9842*552f7358SJed Brown     }
9843*552f7358SJed Brown   }
9844*552f7358SJed Brown   for (c = cStart; c < cEnd; ++c) {
9845*552f7358SJed Brown     if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(c, "Jacobian", cellDof, cellDof, &elemMat[c*cellDof*cellDof]);CHKERRQ(ierr);}
9846*552f7358SJed Brown     ierr = DMPlexMatSetClosure(dm, PETSC_NULL, PETSC_NULL, JacP, c, &elemMat[c*cellDof*cellDof], ADD_VALUES);CHKERRQ(ierr);
9847*552f7358SJed Brown   }
9848*552f7358SJed Brown   ierr = PetscFree6(u,v0,J,invJ,detJ,elemMat);CHKERRQ(ierr);
9849*552f7358SJed Brown 
9850*552f7358SJed Brown   /* Assemble matrix, using the 2-step process:
9851*552f7358SJed Brown        MatAssemblyBegin(), MatAssemblyEnd(). */
9852*552f7358SJed Brown   ierr = MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
9853*552f7358SJed Brown   ierr = MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
9854*552f7358SJed Brown 
9855*552f7358SJed Brown   if (mesh->printFEM) {
9856*552f7358SJed Brown     ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian:\n");CHKERRQ(ierr);
9857*552f7358SJed Brown     ierr = MatChop(JacP, 1.0e-10);CHKERRQ(ierr);
9858*552f7358SJed Brown     ierr = MatView(JacP, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
9859*552f7358SJed Brown   }
9860*552f7358SJed Brown   /* ierr = PetscLogEventEnd(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */
9861*552f7358SJed Brown   ierr = PetscObjectTypeCompare((PetscObject)Jac, MATSHELL, &isShell);CHKERRQ(ierr);
9862*552f7358SJed Brown   if (isShell) {
9863*552f7358SJed Brown     JacActionCtx *jctx;
9864*552f7358SJed Brown 
9865*552f7358SJed Brown     ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr);
9866*552f7358SJed Brown     ierr = VecCopy(X, jctx->u);CHKERRQ(ierr);
9867*552f7358SJed Brown   }
9868*552f7358SJed Brown   *str = SAME_NONZERO_PATTERN;
9869*552f7358SJed Brown   PetscFunctionReturn(0);
9870*552f7358SJed Brown }
9871*552f7358SJed Brown 
9872*552f7358SJed Brown 
9873*552f7358SJed Brown #undef __FUNCT__
9874*552f7358SJed Brown #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel"
9875*552f7358SJed Brown /*@C
9876*552f7358SJed Brown   PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using
9877*552f7358SJed Brown   the local section and an SF describing the section point overlap.
9878*552f7358SJed Brown 
9879*552f7358SJed Brown   Input Parameters:
9880*552f7358SJed Brown   + s - The PetscSection for the local field layout
9881*552f7358SJed Brown   . sf - The SF describing parallel layout of the section points
9882*552f7358SJed Brown   . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs
9883*552f7358SJed Brown   . label - The label specifying the points
9884*552f7358SJed Brown   - labelValue - The label stratum specifying the points
9885*552f7358SJed Brown 
9886*552f7358SJed Brown   Output Parameter:
9887*552f7358SJed Brown   . gsection - The PetscSection for the global field layout
9888*552f7358SJed Brown 
9889*552f7358SJed Brown   Note: This gives negative sizes and offsets to points not owned by this process
9890*552f7358SJed Brown 
9891*552f7358SJed Brown   Level: developer
9892*552f7358SJed Brown 
9893*552f7358SJed Brown .seealso: PetscSectionCreate()
9894*552f7358SJed Brown @*/
9895*552f7358SJed Brown PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection)
9896*552f7358SJed Brown {
9897*552f7358SJed Brown   PetscInt      *neg;
9898*552f7358SJed Brown   PetscInt       pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots;
9899*552f7358SJed Brown   PetscErrorCode ierr;
9900*552f7358SJed Brown 
9901*552f7358SJed Brown   PetscFunctionBegin;
9902*552f7358SJed Brown   ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr);
9903*552f7358SJed Brown   ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr);
9904*552f7358SJed Brown   ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr);
9905*552f7358SJed Brown   ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &neg);CHKERRQ(ierr);
9906*552f7358SJed Brown   /* Mark ghost points with negative dof */
9907*552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
9908*552f7358SJed Brown     PetscInt value;
9909*552f7358SJed Brown 
9910*552f7358SJed Brown     ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr);
9911*552f7358SJed Brown     if (value != labelValue) continue;
9912*552f7358SJed Brown     ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr);
9913*552f7358SJed Brown     ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr);
9914*552f7358SJed Brown     ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr);
9915*552f7358SJed Brown     if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);}
9916*552f7358SJed Brown     neg[p-pStart] = -(dof+1);
9917*552f7358SJed Brown   }
9918*552f7358SJed Brown   ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr);
9919*552f7358SJed Brown   ierr = PetscSFGetGraph(sf, &nroots, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr);
9920*552f7358SJed Brown   if (nroots >= 0) {
9921*552f7358SJed Brown     if (nroots > pEnd - pStart) {
9922*552f7358SJed Brown       PetscInt *tmpDof;
9923*552f7358SJed Brown       /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */
9924*552f7358SJed Brown       ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpDof);CHKERRQ(ierr);
9925*552f7358SJed Brown       ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr);
9926*552f7358SJed Brown       ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr);
9927*552f7358SJed Brown       for (p = pStart; p < pEnd; ++p) {
9928*552f7358SJed Brown         if (tmpDof[p] < 0) {(*gsection)->atlasDof[p-pStart] = tmpDof[p];}
9929*552f7358SJed Brown       }
9930*552f7358SJed Brown       ierr = PetscFree(tmpDof);CHKERRQ(ierr);
9931*552f7358SJed Brown     } else {
9932*552f7358SJed Brown       ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr);
9933*552f7358SJed Brown       ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr);
9934*552f7358SJed Brown     }
9935*552f7358SJed Brown   }
9936*552f7358SJed Brown   /* Calculate new sizes, get proccess offset, and calculate point offsets */
9937*552f7358SJed Brown   for (p = 0, off = 0; p < pEnd-pStart; ++p) {
9938*552f7358SJed Brown     cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0;
9939*552f7358SJed Brown     (*gsection)->atlasOff[p] = off;
9940*552f7358SJed Brown     off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0;
9941*552f7358SJed Brown   }
9942*552f7358SJed Brown   ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr);
9943*552f7358SJed Brown   globalOff -= off;
9944*552f7358SJed Brown   for (p = 0, off = 0; p < pEnd-pStart; ++p) {
9945*552f7358SJed Brown     (*gsection)->atlasOff[p] += globalOff;
9946*552f7358SJed Brown     neg[p] = -((*gsection)->atlasOff[p]+1);
9947*552f7358SJed Brown   }
9948*552f7358SJed Brown   /* Put in negative offsets for ghost points */
9949*552f7358SJed Brown   if (nroots >= 0) {
9950*552f7358SJed Brown     if (nroots > pEnd - pStart) {
9951*552f7358SJed Brown       PetscInt *tmpOff;
9952*552f7358SJed Brown       /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */
9953*552f7358SJed Brown       ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpOff);CHKERRQ(ierr);
9954*552f7358SJed Brown       ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr);
9955*552f7358SJed Brown       ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr);
9956*552f7358SJed Brown       for (p = pStart; p < pEnd; ++p) {
9957*552f7358SJed Brown         if (tmpOff[p] < 0) {(*gsection)->atlasOff[p-pStart] = tmpOff[p];}
9958*552f7358SJed Brown       }
9959*552f7358SJed Brown       ierr = PetscFree(tmpOff);CHKERRQ(ierr);
9960*552f7358SJed Brown     } else {
9961*552f7358SJed Brown       ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr);
9962*552f7358SJed Brown       ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr);
9963*552f7358SJed Brown     }
9964*552f7358SJed Brown   }
9965*552f7358SJed Brown   ierr = PetscFree(neg);CHKERRQ(ierr);
9966*552f7358SJed Brown   PetscFunctionReturn(0);
9967*552f7358SJed Brown }
9968