xref: /petsc/src/dm/impls/plex/plex.c (revision 13048561641ef7eff4572e9d6024b84800bf9a8c)
134541f0dSBarry Smith #include <petsc-private/dmpleximpl.h>   /*I      "petscdmplex.h"   I*/
2552f7358SJed Brown #include <../src/sys/utils/hash.h>
3d53a3d6fSBarry Smith #include <petsc-private/isimpl.h>
40c312b8eSJed Brown #include <petscsf.h>
5552f7358SJed Brown 
6552f7358SJed Brown /* Logging support */
71337e6e5SMatthew G. Knepley PetscLogEvent DMPLEX_Interpolate, DMPLEX_Partition, DMPLEX_Distribute, DMPLEX_DistributeCones, DMPLEX_DistributeLabels, DMPLEX_DistributeSF, DMPLEX_DistributeField, DMPLEX_DistributeData, DMPLEX_Stratify, DMPLEX_Preallocate, DMPLEX_ResidualFEM, DMPLEX_JacobianFEM;
8552f7358SJed Brown 
95a576424SJed Brown PETSC_EXTERN PetscErrorCode VecView_Seq(Vec, PetscViewer);
105a576424SJed Brown PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer);
11552f7358SJed Brown 
12552f7358SJed Brown #undef __FUNCT__
13552f7358SJed Brown #define __FUNCT__ "VecView_Plex_Local"
14552f7358SJed Brown PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer)
15552f7358SJed Brown {
16552f7358SJed Brown   DM             dm;
17552f7358SJed Brown   PetscBool      isvtk;
18552f7358SJed Brown   PetscErrorCode ierr;
19552f7358SJed Brown 
20552f7358SJed Brown   PetscFunctionBegin;
21552f7358SJed Brown   ierr = VecGetDM(v, &dm);CHKERRQ(ierr);
2282f516ccSBarry Smith   if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
23552f7358SJed Brown   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr);
24552f7358SJed Brown   if (isvtk) {
25552f7358SJed Brown     PetscViewerVTKFieldType ft = PETSC_VTK_POINT_FIELD;
26552f7358SJed Brown     PetscSection            section;
27552f7358SJed Brown     PetscInt                dim, pStart, pEnd, cStart, fStart, vStart, cdof = 0, fdof = 0, vdof = 0;
28552f7358SJed Brown 
29552f7358SJed Brown     ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
30552f7358SJed Brown     ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
310298fd71SBarry Smith     ierr = DMPlexGetHeightStratum(dm, 0, &cStart, NULL);CHKERRQ(ierr);
320298fd71SBarry Smith     ierr = DMPlexGetHeightStratum(dm, 1, &fStart, NULL);CHKERRQ(ierr);
330298fd71SBarry Smith     ierr = DMPlexGetDepthStratum(dm, 0, &vStart, NULL);CHKERRQ(ierr);
34552f7358SJed Brown     ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr);
35552f7358SJed Brown     /* Assumes that numer of dofs per point of each stratum is constant, natural for VTK */
36552f7358SJed Brown     if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetDof(section, cStart, &cdof);CHKERRQ(ierr);}
37552f7358SJed Brown     if ((fStart >= pStart) && (fStart < pEnd)) {ierr = PetscSectionGetDof(section, fStart, &fdof);CHKERRQ(ierr);}
38552f7358SJed Brown     if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetDof(section, vStart, &vdof);CHKERRQ(ierr);}
39552f7358SJed Brown     if (cdof && fdof && vdof) { /* Actually Q2 or some such, but visualize as Q1 */
40552f7358SJed Brown       ft = (cdof == dim) ? PETSC_VTK_POINT_VECTOR_FIELD : PETSC_VTK_POINT_FIELD;
41552f7358SJed Brown     } else if (cdof && vdof) {
42ce94432eSBarry Smith       SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"No support for viewing mixed space with dofs at both vertices and cells");
43552f7358SJed Brown     } else if (cdof) {
44552f7358SJed Brown       /* TODO: This assumption should be removed when there is a way of identifying whether a space is conceptually a
45552f7358SJed Brown        * vector or just happens to have the same number of dofs as the dimension. */
46552f7358SJed Brown       if (cdof == dim) {
47552f7358SJed Brown         ft = PETSC_VTK_CELL_VECTOR_FIELD;
48552f7358SJed Brown       } else {
49552f7358SJed Brown         ft = PETSC_VTK_CELL_FIELD;
50552f7358SJed Brown       }
51552f7358SJed Brown     } else if (vdof) {
52552f7358SJed Brown       if (vdof == dim) {
53552f7358SJed Brown         ft = PETSC_VTK_POINT_VECTOR_FIELD;
54552f7358SJed Brown       } else {
55552f7358SJed Brown         ft = PETSC_VTK_POINT_FIELD;
56552f7358SJed Brown       }
5782f516ccSBarry Smith     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Could not classify input Vec for VTK");
58552f7358SJed Brown 
59552f7358SJed Brown     ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); /* viewer drops reference */
60552f7358SJed Brown     ierr = PetscObjectReference((PetscObject) v);CHKERRQ(ierr);  /* viewer drops reference */
61552f7358SJed Brown     ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, ft, (PetscObject) v);CHKERRQ(ierr);
62552f7358SJed Brown   } else {
63552f7358SJed Brown     PetscBool isseq;
64552f7358SJed Brown 
65552f7358SJed Brown     ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr);
66552f7358SJed Brown     if (isseq) {
67552f7358SJed Brown       ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);
68552f7358SJed Brown     } else {
69552f7358SJed Brown       ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);
70552f7358SJed Brown     }
71552f7358SJed Brown   }
72552f7358SJed Brown   PetscFunctionReturn(0);
73552f7358SJed Brown }
74552f7358SJed Brown 
75552f7358SJed Brown #undef __FUNCT__
76552f7358SJed Brown #define __FUNCT__ "VecView_Plex"
77552f7358SJed Brown PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer)
78552f7358SJed Brown {
79552f7358SJed Brown   DM             dm;
80552f7358SJed Brown   PetscBool      isvtk;
81552f7358SJed Brown   PetscErrorCode ierr;
82552f7358SJed Brown 
83552f7358SJed Brown   PetscFunctionBegin;
84552f7358SJed Brown   ierr = VecGetDM(v, &dm);CHKERRQ(ierr);
8582f516ccSBarry Smith   if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
86552f7358SJed Brown   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr);
87552f7358SJed Brown   if (isvtk) {
88552f7358SJed Brown     Vec         locv;
89552f7358SJed Brown     const char *name;
90552f7358SJed Brown 
91552f7358SJed Brown     ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr);
92552f7358SJed Brown     ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr);
93552f7358SJed Brown     ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr);
94552f7358SJed Brown     ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr);
95552f7358SJed Brown     ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr);
96552f7358SJed Brown     ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr);
97552f7358SJed Brown     ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr);
98552f7358SJed Brown   } else {
99552f7358SJed Brown     PetscBool isseq;
100552f7358SJed Brown 
101552f7358SJed Brown     ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr);
102552f7358SJed Brown     if (isseq) {
103552f7358SJed Brown       ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);
104552f7358SJed Brown     } else {
105552f7358SJed Brown       ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);
106552f7358SJed Brown     }
107552f7358SJed Brown   }
108552f7358SJed Brown   PetscFunctionReturn(0);
109552f7358SJed Brown }
110552f7358SJed Brown 
111552f7358SJed Brown #undef __FUNCT__
112552f7358SJed Brown #define __FUNCT__ "DMPlexView_Ascii"
113552f7358SJed Brown PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer)
114552f7358SJed Brown {
115552f7358SJed Brown   DM_Plex          *mesh = (DM_Plex*) dm->data;
116552f7358SJed Brown   DM                cdm;
117552f7358SJed Brown   DMLabel           markers;
118552f7358SJed Brown   PetscSection      coordSection;
119552f7358SJed Brown   Vec               coordinates;
120552f7358SJed Brown   PetscViewerFormat format;
121552f7358SJed Brown   PetscErrorCode    ierr;
122552f7358SJed Brown 
123552f7358SJed Brown   PetscFunctionBegin;
124552f7358SJed Brown   ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
125552f7358SJed Brown   ierr = DMGetDefaultSection(cdm, &coordSection);CHKERRQ(ierr);
126552f7358SJed Brown   ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
127552f7358SJed Brown   ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr);
128552f7358SJed Brown   if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
129552f7358SJed Brown     const char *name;
130552f7358SJed Brown     PetscInt    maxConeSize, maxSupportSize;
131552f7358SJed Brown     PetscInt    pStart, pEnd, p;
132552f7358SJed Brown     PetscMPIInt rank, size;
133552f7358SJed Brown 
13482f516ccSBarry Smith     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr);
13582f516ccSBarry Smith     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr);
136552f7358SJed Brown     ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr);
137552f7358SJed Brown     ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
138552f7358SJed Brown     ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr);
139552f7358SJed Brown     ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr);
140552f7358SJed Brown     ierr = PetscViewerASCIIPrintf(viewer, "Mesh '%s':\n", name);CHKERRQ(ierr);
141552f7358SJed Brown     ierr = PetscViewerASCIISynchronizedPrintf(viewer, "Max sizes cone: %D support: %D\n", maxConeSize, maxSupportSize);CHKERRQ(ierr);
142552f7358SJed Brown     ierr = PetscViewerASCIIPrintf(viewer, "orientation is missing\n", name);CHKERRQ(ierr);
143552f7358SJed Brown     ierr = PetscViewerASCIIPrintf(viewer, "cap --> base:\n", name);CHKERRQ(ierr);
144552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
145552f7358SJed Brown       PetscInt dof, off, s;
146552f7358SJed Brown 
147552f7358SJed Brown       ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr);
148552f7358SJed Brown       ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr);
149552f7358SJed Brown       for (s = off; s < off+dof; ++s) {
150552f7358SJed Brown         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr);
151552f7358SJed Brown       }
152552f7358SJed Brown     }
153552f7358SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
154552f7358SJed Brown     ierr = PetscViewerASCIIPrintf(viewer, "base <-- cap:\n", name);CHKERRQ(ierr);
155552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
156552f7358SJed Brown       PetscInt dof, off, c;
157552f7358SJed Brown 
158552f7358SJed Brown       ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr);
159552f7358SJed Brown       ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr);
160552f7358SJed Brown       for (c = off; c < off+dof; ++c) {
161552f7358SJed Brown         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr);
162552f7358SJed Brown       }
163552f7358SJed Brown     }
164552f7358SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1650298fd71SBarry Smith     ierr = PetscSectionGetChart(coordSection, &pStart, NULL);CHKERRQ(ierr);
166552f7358SJed Brown     if (pStart >= 0) {ierr = PetscSectionVecView(coordSection, coordinates, viewer);CHKERRQ(ierr);}
167552f7358SJed Brown     ierr = DMPlexGetLabel(dm, "marker", &markers);CHKERRQ(ierr);
168552f7358SJed Brown     ierr = DMLabelView(markers,viewer);CHKERRQ(ierr);
169552f7358SJed Brown     if (size > 1) {
170552f7358SJed Brown       PetscSF sf;
171552f7358SJed Brown 
172552f7358SJed Brown       ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr);
173552f7358SJed Brown       ierr = PetscSFView(sf, viewer);CHKERRQ(ierr);
174552f7358SJed Brown     }
175552f7358SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
176552f7358SJed Brown   } else if (format == PETSC_VIEWER_ASCII_LATEX) {
177552f7358SJed Brown     const char  *name;
178552f7358SJed Brown     const char  *colors[3] = {"red", "blue", "green"};
179552f7358SJed Brown     const int    numColors  = 3;
180552f7358SJed Brown     PetscReal    scale      = 2.0;
181552f7358SJed Brown     PetscScalar *coords;
182552f7358SJed Brown     PetscInt     depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p;
183552f7358SJed Brown     PetscMPIInt  rank, size;
184552f7358SJed Brown 
185552f7358SJed Brown     ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
18682f516ccSBarry Smith     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr);
18782f516ccSBarry Smith     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr);
188552f7358SJed Brown     ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr);
189552f7358SJed Brown     ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr);
190770b213bSMatthew G Knepley     ierr = PetscViewerASCIIPrintf(viewer, "\
191770b213bSMatthew G Knepley \\documentclass[crop,multi=false]{standalone}\n\n\
192552f7358SJed Brown \\usepackage{tikz}\n\
193552f7358SJed Brown \\usepackage{pgflibraryshapes}\n\
194552f7358SJed Brown \\usetikzlibrary{backgrounds}\n\
195552f7358SJed Brown \\usetikzlibrary{arrows}\n\
196552f7358SJed Brown \\begin{document}\n\
197552f7358SJed Brown \\section{%s}\n\
198770b213bSMatthew G Knepley \\begin{center}\n", name, 8.0/scale);CHKERRQ(ierr);
199770b213bSMatthew G Knepley     ierr = PetscViewerASCIIPrintf(viewer, "Mesh for process ");CHKERRQ(ierr);
200770b213bSMatthew G Knepley     for (p = 0; p < size; ++p) {
201770b213bSMatthew G Knepley       if (p > 0 && p == size-1) {
202770b213bSMatthew G Knepley         ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr);
203770b213bSMatthew G Knepley       } else if (p > 0) {
204770b213bSMatthew G Knepley         ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr);
205770b213bSMatthew G Knepley       }
206770b213bSMatthew G Knepley       ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr);
207770b213bSMatthew G Knepley     }
208770b213bSMatthew G Knepley     ierr = PetscViewerASCIIPrintf(viewer, ".\n\n\n\
209770b213bSMatthew G Knepley \\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n");CHKERRQ(ierr);
210552f7358SJed Brown     /* Plot vertices */
211552f7358SJed Brown     ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
212552f7358SJed Brown     ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr);
213552f7358SJed Brown     ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr);
214552f7358SJed Brown     for (v = vStart; v < vEnd; ++v) {
215552f7358SJed Brown       PetscInt off, dof, d;
216552f7358SJed Brown 
217552f7358SJed Brown       ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr);
218552f7358SJed Brown       ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr);
219552f7358SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr);
220552f7358SJed Brown       for (d = 0; d < dof; ++d) {
221552f7358SJed Brown         if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);}
2226712e2f1SBarry Smith         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)(scale*PetscRealPart(coords[off+d])));CHKERRQ(ierr);
223552f7358SJed Brown       }
224552f7358SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", v, rank, colors[rank%numColors], v);CHKERRQ(ierr);
225552f7358SJed Brown     }
226552f7358SJed Brown     ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr);
227552f7358SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
228552f7358SJed Brown     ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr);
229552f7358SJed Brown     /* Plot edges */
230552f7358SJed Brown     ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr);
231552f7358SJed Brown     ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr);
232552f7358SJed Brown     if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);}
233552f7358SJed Brown     for (e = eStart; e < eEnd; ++e) {
234552f7358SJed Brown       const PetscInt *cone;
235552f7358SJed Brown       PetscInt        coneSize, offA, offB, dof, d;
236552f7358SJed Brown 
237552f7358SJed Brown       ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr);
23882f516ccSBarry Smith       if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %d cone should have two vertices, not %d", e, coneSize);
239552f7358SJed Brown       ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr);
240552f7358SJed Brown       ierr = PetscSectionGetDof(coordSection, cone[0], &dof);CHKERRQ(ierr);
241552f7358SJed Brown       ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr);
242552f7358SJed Brown       ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr);
243552f7358SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr);
244552f7358SJed Brown       for (d = 0; d < dof; ++d) {
245552f7358SJed Brown         if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);}
2466712e2f1SBarry Smith         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)(scale*0.5*PetscRealPart(coords[offA+d]+coords[offB+d])));CHKERRQ(ierr);
247552f7358SJed Brown       }
248552f7358SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", e, rank, colors[rank%numColors], e);CHKERRQ(ierr);
249552f7358SJed Brown     }
250552f7358SJed Brown     ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr);
251552f7358SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
252552f7358SJed Brown     ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr);
253552f7358SJed Brown     /* Plot cells */
254552f7358SJed Brown     ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
255552f7358SJed Brown     for (c = cStart; c < cEnd; ++c) {
2560298fd71SBarry Smith       PetscInt *closure = NULL;
257552f7358SJed Brown       PetscInt  closureSize, firstPoint = -1;
258552f7358SJed Brown 
259552f7358SJed Brown       ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
260552f7358SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]);CHKERRQ(ierr);
261552f7358SJed Brown       for (p = 0; p < closureSize*2; p += 2) {
262552f7358SJed Brown         const PetscInt point = closure[p];
263552f7358SJed Brown 
264552f7358SJed Brown         if ((point < vStart) || (point >= vEnd)) continue;
265552f7358SJed Brown         if (firstPoint >= 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- ");CHKERRQ(ierr);}
266552f7358SJed Brown         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%D)", point, rank);CHKERRQ(ierr);
267552f7358SJed Brown         if (firstPoint < 0) firstPoint = point;
268552f7358SJed Brown       }
269552f7358SJed Brown       /* Why doesn't this work? ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- cycle;\n");CHKERRQ(ierr); */
270552f7358SJed Brown       ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%D);\n", firstPoint, rank);CHKERRQ(ierr);
271552f7358SJed Brown       ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
272552f7358SJed Brown     }
273552f7358SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
274552f7358SJed Brown     ierr = PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n\\end{center}\n");CHKERRQ(ierr);
275770b213bSMatthew G Knepley     ierr = PetscViewerASCIIPrintf(viewer, "\\end{document}\n", name);CHKERRQ(ierr);
276552f7358SJed Brown   } else {
27782f516ccSBarry Smith     MPI_Comm    comm;
278834065abSMatthew G. Knepley     PetscInt   *sizes, *hybsizes;
279834065abSMatthew G. Knepley     PetscInt    locDepth, depth, dim, d, pMax[4];
280552f7358SJed Brown     PetscInt    pStart, pEnd, p;
281a57dd577SMatthew G Knepley     PetscInt    numLabels, l;
2821143a3c0SMatthew G. Knepley     const char *name;
283552f7358SJed Brown     PetscMPIInt size;
284552f7358SJed Brown 
28582f516ccSBarry Smith     ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
286552f7358SJed Brown     ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
287552f7358SJed Brown     ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
2885f64d76eSMatthew G. Knepley     ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr);
2891143a3c0SMatthew G. Knepley     if (name) {ierr = PetscViewerASCIIPrintf(viewer, "%s in %D dimensions:\n", name, dim);CHKERRQ(ierr);}
2901143a3c0SMatthew G. Knepley     else      {ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimensions:\n", dim);CHKERRQ(ierr);}
291552f7358SJed Brown     ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr);
292552f7358SJed Brown     ierr = MPI_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr);
293834065abSMatthew G. Knepley     ierr = DMPlexGetHybridBounds(dm, &pMax[depth], &pMax[depth-1], &pMax[1], &pMax[0]);CHKERRQ(ierr);
294dcca6d9dSJed Brown     ierr = PetscMalloc2(size,&sizes,size,&hybsizes);CHKERRQ(ierr);
295552f7358SJed Brown     if (depth == 1) {
296552f7358SJed Brown       ierr = DMPlexGetDepthStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr);
297552f7358SJed Brown       pEnd = pEnd - pStart;
298552f7358SJed Brown       ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr);
299552f7358SJed Brown       ierr = PetscViewerASCIIPrintf(viewer, "  %D-cells:", 0);CHKERRQ(ierr);
300552f7358SJed Brown       for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);}
301552f7358SJed Brown       ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr);
302552f7358SJed Brown       ierr = DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr);
303552f7358SJed Brown       pEnd = pEnd - pStart;
304552f7358SJed Brown       ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr);
305552f7358SJed Brown       ierr = PetscViewerASCIIPrintf(viewer, "  %D-cells:", dim);CHKERRQ(ierr);
306552f7358SJed Brown       for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);}
307552f7358SJed Brown       ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr);
308552f7358SJed Brown     } else {
309552f7358SJed Brown       for (d = 0; d <= dim; d++) {
310552f7358SJed Brown         ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr);
311834065abSMatthew G. Knepley         pEnd    -= pStart;
312834065abSMatthew G. Knepley         pMax[d] -= pStart;
313552f7358SJed Brown         ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr);
314834065abSMatthew G. Knepley         ierr = MPI_Gather(&pMax[d], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr);
315552f7358SJed Brown         ierr = PetscViewerASCIIPrintf(viewer, "  %D-cells:", d);CHKERRQ(ierr);
316834065abSMatthew G. Knepley         for (p = 0; p < size; ++p) {
317834065abSMatthew G. Knepley           if (hybsizes[p] >= 0) {ierr = PetscViewerASCIIPrintf(viewer, " %D (%D)", sizes[p], sizes[p] - hybsizes[p]);CHKERRQ(ierr);}
318834065abSMatthew G. Knepley           else                  {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);}
319834065abSMatthew G. Knepley         }
320552f7358SJed Brown         ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr);
321552f7358SJed Brown       }
322552f7358SJed Brown     }
323834065abSMatthew G. Knepley     ierr = PetscFree2(sizes,hybsizes);CHKERRQ(ierr);
324a57dd577SMatthew G Knepley     ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr);
325a57dd577SMatthew G Knepley     if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Labels:\n");CHKERRQ(ierr);}
326a57dd577SMatthew G Knepley     for (l = 0; l < numLabels; ++l) {
327a57dd577SMatthew G Knepley       DMLabel         label;
328a57dd577SMatthew G Knepley       const char     *name;
329a57dd577SMatthew G Knepley       IS              valueIS;
330a57dd577SMatthew G Knepley       const PetscInt *values;
331a57dd577SMatthew G Knepley       PetscInt        numValues, v;
332a57dd577SMatthew G Knepley 
333a57dd577SMatthew G Knepley       ierr = DMPlexGetLabelName(dm, l, &name);CHKERRQ(ierr);
334a57dd577SMatthew G Knepley       ierr = DMPlexGetLabel(dm, name, &label);CHKERRQ(ierr);
335a57dd577SMatthew G Knepley       ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr);
336a57dd577SMatthew G Knepley       ierr = PetscViewerASCIIPrintf(viewer, "  %s: %d strata of sizes (", name, numValues);CHKERRQ(ierr);
337a57dd577SMatthew G Knepley       ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr);
338a57dd577SMatthew G Knepley       ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr);
339a57dd577SMatthew G Knepley       for (v = 0; v < numValues; ++v) {
340a57dd577SMatthew G Knepley         PetscInt size;
341a57dd577SMatthew G Knepley 
342a57dd577SMatthew G Knepley         ierr = DMLabelGetStratumSize(label, values[v], &size);CHKERRQ(ierr);
343a57dd577SMatthew G Knepley         if (v > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);}
344a57dd577SMatthew G Knepley         ierr = PetscViewerASCIIPrintf(viewer, "%d", size);CHKERRQ(ierr);
345a57dd577SMatthew G Knepley       }
346a57dd577SMatthew G Knepley       ierr = PetscViewerASCIIPrintf(viewer, ")\n");CHKERRQ(ierr);
347a57dd577SMatthew G Knepley       ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr);
3484d41221fSMatthew G Knepley       ierr = ISDestroy(&valueIS);CHKERRQ(ierr);
349a57dd577SMatthew G Knepley     }
350552f7358SJed Brown   }
351552f7358SJed Brown   PetscFunctionReturn(0);
352552f7358SJed Brown }
353552f7358SJed Brown 
354552f7358SJed Brown #undef __FUNCT__
355552f7358SJed Brown #define __FUNCT__ "DMView_Plex"
356552f7358SJed Brown PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer)
357552f7358SJed Brown {
358552f7358SJed Brown   PetscBool      iascii, isbinary;
359552f7358SJed Brown   PetscErrorCode ierr;
360552f7358SJed Brown 
361552f7358SJed Brown   PetscFunctionBegin;
362552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
363552f7358SJed Brown   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
364552f7358SJed Brown   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
365552f7358SJed Brown   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERBINARY, &isbinary);CHKERRQ(ierr);
366552f7358SJed Brown   if (iascii) {
367552f7358SJed Brown     ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr);
368552f7358SJed Brown #if 0
369552f7358SJed Brown   } else if (isbinary) {
370552f7358SJed Brown     ierr = DMPlexView_Binary(dm, viewer);CHKERRQ(ierr);
371552f7358SJed Brown #endif
37211aeaf0aSBarry Smith   }
373552f7358SJed Brown   PetscFunctionReturn(0);
374552f7358SJed Brown }
375552f7358SJed Brown 
376552f7358SJed Brown #undef __FUNCT__
377552f7358SJed Brown #define __FUNCT__ "DMDestroy_Plex"
378552f7358SJed Brown PetscErrorCode DMDestroy_Plex(DM dm)
379552f7358SJed Brown {
380552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
381552f7358SJed Brown   DMLabel        next  = mesh->labels;
382552f7358SJed Brown   PetscErrorCode ierr;
383552f7358SJed Brown 
384552f7358SJed Brown   PetscFunctionBegin;
3850d644c17SKarl Rupp   if (--mesh->refct > 0) PetscFunctionReturn(0);
386552f7358SJed Brown   ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr);
387552f7358SJed Brown   ierr = PetscFree(mesh->cones);CHKERRQ(ierr);
388552f7358SJed Brown   ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr);
389552f7358SJed Brown   ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr);
390552f7358SJed Brown   ierr = PetscFree(mesh->supports);CHKERRQ(ierr);
391552f7358SJed Brown   ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr);
392552f7358SJed Brown   while (next) {
393552f7358SJed Brown     DMLabel tmp = next->next;
394552f7358SJed Brown 
395552f7358SJed Brown     ierr = DMLabelDestroy(&next);CHKERRQ(ierr);
396552f7358SJed Brown     next = tmp;
397552f7358SJed Brown   }
398a89082eeSMatthew G Knepley   ierr = DMLabelDestroy(&mesh->subpointMap);CHKERRQ(ierr);
399552f7358SJed Brown   ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr);
400552f7358SJed Brown   ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr);
401552f7358SJed Brown   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
402552f7358SJed Brown   ierr = PetscFree(mesh);CHKERRQ(ierr);
403552f7358SJed Brown   PetscFunctionReturn(0);
404552f7358SJed Brown }
405552f7358SJed Brown 
406552f7358SJed Brown #undef __FUNCT__
407552f7358SJed Brown #define __FUNCT__ "DMCreateMatrix_Plex"
408b412c318SBarry Smith PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J)
409552f7358SJed Brown {
410552f7358SJed Brown   PetscSection   section, sectionGlobal;
411552f7358SJed Brown   PetscInt       bs = -1;
412552f7358SJed Brown   PetscInt       localSize;
41389545effSMatthew G. Knepley   PetscBool      isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock;
414552f7358SJed Brown   PetscErrorCode ierr;
415b412c318SBarry Smith   MatType        mtype;
416552f7358SJed Brown 
417552f7358SJed Brown   PetscFunctionBegin;
418607a6623SBarry Smith   ierr = MatInitializePackage();CHKERRQ(ierr);
419b412c318SBarry Smith   mtype = dm->mattype;
420552f7358SJed Brown   ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);
421552f7358SJed Brown   ierr = DMGetDefaultGlobalSection(dm, &sectionGlobal);CHKERRQ(ierr);
422552f7358SJed Brown   /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */
423552f7358SJed Brown   ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr);
42482f516ccSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)dm), J);CHKERRQ(ierr);
425552f7358SJed Brown   ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
426552f7358SJed Brown   ierr = MatSetType(*J, mtype);CHKERRQ(ierr);
427552f7358SJed Brown   ierr = MatSetFromOptions(*J);CHKERRQ(ierr);
428552f7358SJed Brown   ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr);
429552f7358SJed Brown   ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr);
430552f7358SJed Brown   ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr);
431552f7358SJed Brown   ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr);
432552f7358SJed Brown   ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr);
433552f7358SJed Brown   ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr);
434552f7358SJed Brown   ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr);
435552f7358SJed Brown   if (!isShell) {
436552f7358SJed Brown     PetscBool fillMatrix = (PetscBool) !dm->prealloc_only;
4372a28c762SMatthew G Knepley     PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal, bsMax, bsMin;
438552f7358SJed Brown 
439552f7358SJed Brown     if (bs < 0) {
440552f7358SJed Brown       if (isBlock || isSeqBlock || isMPIBlock || isSymBlock || isSymSeqBlock || isSymMPIBlock) {
441fad22124SMatthew G Knepley         PetscInt pStart, pEnd, p, dof, cdof;
442552f7358SJed Brown 
443552f7358SJed Brown         ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr);
444552f7358SJed Brown         for (p = pStart; p < pEnd; ++p) {
445552f7358SJed Brown           ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr);
446fad22124SMatthew G Knepley           ierr = PetscSectionGetConstraintDof(sectionGlobal, p, &cdof);CHKERRQ(ierr);
447fad22124SMatthew G Knepley           if (dof-cdof) {
4482a28c762SMatthew G Knepley             if (bs < 0) {
449fad22124SMatthew G Knepley               bs = dof-cdof;
450fad22124SMatthew G Knepley             } else if (bs != dof-cdof) {
4512a28c762SMatthew G Knepley               /* Layout does not admit a pointwise block size */
4522a28c762SMatthew G Knepley               bs = 1;
453552f7358SJed Brown               break;
454552f7358SJed Brown             }
455552f7358SJed Brown           }
4562a28c762SMatthew G Knepley         }
4572a28c762SMatthew G Knepley         /* Must have same blocksize on all procs (some might have no points) */
4582a28c762SMatthew G Knepley         bsLocal = bs;
45982f516ccSBarry Smith         ierr = MPI_Allreduce(&bsLocal, &bsMax, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);
4602a28c762SMatthew G Knepley         bsLocal = bs < 0 ? bsMax : bs;
46182f516ccSBarry Smith         ierr = MPI_Allreduce(&bsLocal, &bsMin, 1, MPIU_INT, MPI_MIN, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);
4622a28c762SMatthew G Knepley         if (bsMin != bsMax) {
4632a28c762SMatthew G Knepley           bs = 1;
4642a28c762SMatthew G Knepley         } else {
4652a28c762SMatthew G Knepley           bs = bsMax;
4662a28c762SMatthew G Knepley         }
467552f7358SJed Brown       } else {
468552f7358SJed Brown         bs = 1;
469552f7358SJed Brown       }
470552f7358SJed Brown     }
4711795a4d1SJed Brown     ierr = PetscCalloc4(localSize/bs, &dnz, localSize/bs, &onz, localSize/bs, &dnzu, localSize/bs, &onzu);CHKERRQ(ierr);
472552f7358SJed Brown     ierr = DMPlexPreallocateOperator(dm, bs, section, sectionGlobal, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr);
473552f7358SJed Brown     ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr);
474552f7358SJed Brown   }
475552f7358SJed Brown   PetscFunctionReturn(0);
476552f7358SJed Brown }
477552f7358SJed Brown 
478552f7358SJed Brown #undef __FUNCT__
479552f7358SJed Brown #define __FUNCT__ "DMPlexGetDimension"
480552f7358SJed Brown /*@
481552f7358SJed Brown   DMPlexGetDimension - Return the topological mesh dimension
482552f7358SJed Brown 
483552f7358SJed Brown   Not collective
484552f7358SJed Brown 
485552f7358SJed Brown   Input Parameter:
486552f7358SJed Brown . mesh - The DMPlex
487552f7358SJed Brown 
488552f7358SJed Brown   Output Parameter:
489552f7358SJed Brown . dim - The topological mesh dimension
490552f7358SJed Brown 
491552f7358SJed Brown   Level: beginner
492552f7358SJed Brown 
493552f7358SJed Brown .seealso: DMPlexCreate()
494552f7358SJed Brown @*/
495552f7358SJed Brown PetscErrorCode DMPlexGetDimension(DM dm, PetscInt *dim)
496552f7358SJed Brown {
497552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
498552f7358SJed Brown 
499552f7358SJed Brown   PetscFunctionBegin;
500552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
501552f7358SJed Brown   PetscValidPointer(dim, 2);
502552f7358SJed Brown   *dim = mesh->dim;
503552f7358SJed Brown   PetscFunctionReturn(0);
504552f7358SJed Brown }
505552f7358SJed Brown 
506552f7358SJed Brown #undef __FUNCT__
507552f7358SJed Brown #define __FUNCT__ "DMPlexSetDimension"
508552f7358SJed Brown /*@
509552f7358SJed Brown   DMPlexSetDimension - Set the topological mesh dimension
510552f7358SJed Brown 
511552f7358SJed Brown   Collective on mesh
512552f7358SJed Brown 
513552f7358SJed Brown   Input Parameters:
514552f7358SJed Brown + mesh - The DMPlex
515552f7358SJed Brown - dim - The topological mesh dimension
516552f7358SJed Brown 
517552f7358SJed Brown   Level: beginner
518552f7358SJed Brown 
519552f7358SJed Brown .seealso: DMPlexCreate()
520552f7358SJed Brown @*/
521552f7358SJed Brown PetscErrorCode DMPlexSetDimension(DM dm, PetscInt dim)
522552f7358SJed Brown {
523552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
524552f7358SJed Brown 
525552f7358SJed Brown   PetscFunctionBegin;
526552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
527552f7358SJed Brown   PetscValidLogicalCollectiveInt(dm, dim, 2);
528552f7358SJed Brown   mesh->dim               = dim;
529552f7358SJed Brown   mesh->preallocCenterDim = dim;
530552f7358SJed Brown   PetscFunctionReturn(0);
531552f7358SJed Brown }
532552f7358SJed Brown 
533552f7358SJed Brown #undef __FUNCT__
534552f7358SJed Brown #define __FUNCT__ "DMPlexGetChart"
535552f7358SJed Brown /*@
536552f7358SJed Brown   DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd)
537552f7358SJed Brown 
538552f7358SJed Brown   Not collective
539552f7358SJed Brown 
540552f7358SJed Brown   Input Parameter:
541552f7358SJed Brown . mesh - The DMPlex
542552f7358SJed Brown 
543552f7358SJed Brown   Output Parameters:
544552f7358SJed Brown + pStart - The first mesh point
545552f7358SJed Brown - pEnd   - The upper bound for mesh points
546552f7358SJed Brown 
547552f7358SJed Brown   Level: beginner
548552f7358SJed Brown 
549552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetChart()
550552f7358SJed Brown @*/
551552f7358SJed Brown PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd)
552552f7358SJed Brown {
553552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
554552f7358SJed Brown   PetscErrorCode ierr;
555552f7358SJed Brown 
556552f7358SJed Brown   PetscFunctionBegin;
557552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
558552f7358SJed Brown   ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr);
559552f7358SJed Brown   PetscFunctionReturn(0);
560552f7358SJed Brown }
561552f7358SJed Brown 
562552f7358SJed Brown #undef __FUNCT__
563552f7358SJed Brown #define __FUNCT__ "DMPlexSetChart"
564552f7358SJed Brown /*@
565552f7358SJed Brown   DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd)
566552f7358SJed Brown 
567552f7358SJed Brown   Not collective
568552f7358SJed Brown 
569552f7358SJed Brown   Input Parameters:
570552f7358SJed Brown + mesh - The DMPlex
571552f7358SJed Brown . pStart - The first mesh point
572552f7358SJed Brown - pEnd   - The upper bound for mesh points
573552f7358SJed Brown 
574552f7358SJed Brown   Output Parameters:
575552f7358SJed Brown 
576552f7358SJed Brown   Level: beginner
577552f7358SJed Brown 
578552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetChart()
579552f7358SJed Brown @*/
580552f7358SJed Brown PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd)
581552f7358SJed Brown {
582552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
583552f7358SJed Brown   PetscErrorCode ierr;
584552f7358SJed Brown 
585552f7358SJed Brown   PetscFunctionBegin;
586552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
587552f7358SJed Brown   ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr);
588552f7358SJed Brown   ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr);
589552f7358SJed Brown   PetscFunctionReturn(0);
590552f7358SJed Brown }
591552f7358SJed Brown 
592552f7358SJed Brown #undef __FUNCT__
593552f7358SJed Brown #define __FUNCT__ "DMPlexGetConeSize"
594552f7358SJed Brown /*@
595552f7358SJed Brown   DMPlexGetConeSize - Return the number of in-edges for this point in the Sieve DAG
596552f7358SJed Brown 
597552f7358SJed Brown   Not collective
598552f7358SJed Brown 
599552f7358SJed Brown   Input Parameters:
600552f7358SJed Brown + mesh - The DMPlex
601552f7358SJed Brown - p - The Sieve point, which must lie in the chart set with DMPlexSetChart()
602552f7358SJed Brown 
603552f7358SJed Brown   Output Parameter:
604552f7358SJed Brown . size - The cone size for point p
605552f7358SJed Brown 
606552f7358SJed Brown   Level: beginner
607552f7358SJed Brown 
608552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart()
609552f7358SJed Brown @*/
610552f7358SJed Brown PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size)
611552f7358SJed Brown {
612552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
613552f7358SJed Brown   PetscErrorCode ierr;
614552f7358SJed Brown 
615552f7358SJed Brown   PetscFunctionBegin;
616552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
617552f7358SJed Brown   PetscValidPointer(size, 3);
618552f7358SJed Brown   ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr);
619552f7358SJed Brown   PetscFunctionReturn(0);
620552f7358SJed Brown }
621552f7358SJed Brown 
622552f7358SJed Brown #undef __FUNCT__
623552f7358SJed Brown #define __FUNCT__ "DMPlexSetConeSize"
624552f7358SJed Brown /*@
625552f7358SJed Brown   DMPlexSetConeSize - Set the number of in-edges for this point in the Sieve DAG
626552f7358SJed Brown 
627552f7358SJed Brown   Not collective
628552f7358SJed Brown 
629552f7358SJed Brown   Input Parameters:
630552f7358SJed Brown + mesh - The DMPlex
631552f7358SJed Brown . p - The Sieve point, which must lie in the chart set with DMPlexSetChart()
632552f7358SJed Brown - size - The cone size for point p
633552f7358SJed Brown 
634552f7358SJed Brown   Output Parameter:
635552f7358SJed Brown 
636552f7358SJed Brown   Note:
637552f7358SJed Brown   This should be called after DMPlexSetChart().
638552f7358SJed Brown 
639552f7358SJed Brown   Level: beginner
640552f7358SJed Brown 
641552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart()
642552f7358SJed Brown @*/
643552f7358SJed Brown PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size)
644552f7358SJed Brown {
645552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
646552f7358SJed Brown   PetscErrorCode ierr;
647552f7358SJed Brown 
648552f7358SJed Brown   PetscFunctionBegin;
649552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
650552f7358SJed Brown   ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr);
6510d644c17SKarl Rupp 
652552f7358SJed Brown   mesh->maxConeSize = PetscMax(mesh->maxConeSize, size);
653552f7358SJed Brown   PetscFunctionReturn(0);
654552f7358SJed Brown }
655552f7358SJed Brown 
656552f7358SJed Brown #undef __FUNCT__
657552f7358SJed Brown #define __FUNCT__ "DMPlexGetCone"
658552f7358SJed Brown /*@C
659552f7358SJed Brown   DMPlexGetCone - Return the points on the in-edges for this point in the Sieve DAG
660552f7358SJed Brown 
661552f7358SJed Brown   Not collective
662552f7358SJed Brown 
663552f7358SJed Brown   Input Parameters:
664552f7358SJed Brown + mesh - The DMPlex
665552f7358SJed Brown - p - The Sieve point, which must lie in the chart set with DMPlexSetChart()
666552f7358SJed Brown 
667552f7358SJed Brown   Output Parameter:
668552f7358SJed Brown . cone - An array of points which are on the in-edges for point p
669552f7358SJed Brown 
670552f7358SJed Brown   Level: beginner
671552f7358SJed Brown 
6723813dfbdSMatthew G Knepley   Fortran Notes:
6733813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
6743813dfbdSMatthew G Knepley   include petsc.h90 in your code.
6753813dfbdSMatthew G Knepley 
6763813dfbdSMatthew G Knepley   You must also call DMPlexRestoreCone() after you finish using the returned array.
677552f7358SJed Brown 
678552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart()
679552f7358SJed Brown @*/
680552f7358SJed Brown PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[])
681552f7358SJed Brown {
682552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
683552f7358SJed Brown   PetscInt       off;
684552f7358SJed Brown   PetscErrorCode ierr;
685552f7358SJed Brown 
686552f7358SJed Brown   PetscFunctionBegin;
687552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
688552f7358SJed Brown   PetscValidPointer(cone, 3);
689552f7358SJed Brown   ierr  = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr);
690552f7358SJed Brown   *cone = &mesh->cones[off];
691552f7358SJed Brown   PetscFunctionReturn(0);
692552f7358SJed Brown }
693552f7358SJed Brown 
694552f7358SJed Brown #undef __FUNCT__
695552f7358SJed Brown #define __FUNCT__ "DMPlexSetCone"
696552f7358SJed Brown /*@
697552f7358SJed Brown   DMPlexSetCone - Set the points on the in-edges for this point in the Sieve DAG
698552f7358SJed Brown 
699552f7358SJed Brown   Not collective
700552f7358SJed Brown 
701552f7358SJed Brown   Input Parameters:
702552f7358SJed Brown + mesh - The DMPlex
703552f7358SJed Brown . p - The Sieve point, which must lie in the chart set with DMPlexSetChart()
704552f7358SJed Brown - cone - An array of points which are on the in-edges for point p
705552f7358SJed Brown 
706552f7358SJed Brown   Output Parameter:
707552f7358SJed Brown 
708552f7358SJed Brown   Note:
709552f7358SJed Brown   This should be called after all calls to DMPlexSetConeSize() and DMSetUp().
710552f7358SJed Brown 
711552f7358SJed Brown   Level: beginner
712552f7358SJed Brown 
713552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp()
714552f7358SJed Brown @*/
715552f7358SJed Brown PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[])
716552f7358SJed Brown {
717552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
718552f7358SJed Brown   PetscInt       pStart, pEnd;
719552f7358SJed Brown   PetscInt       dof, off, c;
720552f7358SJed Brown   PetscErrorCode ierr;
721552f7358SJed Brown 
722552f7358SJed Brown   PetscFunctionBegin;
723552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
724552f7358SJed Brown   ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr);
725552f7358SJed Brown   ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr);
726552f7358SJed Brown   if (dof) PetscValidPointer(cone, 3);
727552f7358SJed Brown   ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr);
72882f516ccSBarry Smith   if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd);
729552f7358SJed Brown   for (c = 0; c < dof; ++c) {
73082f516ccSBarry Smith     if ((cone[c] < pStart) || (cone[c] >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", cone[c], pStart, pEnd);
731552f7358SJed Brown     mesh->cones[off+c] = cone[c];
732552f7358SJed Brown   }
733552f7358SJed Brown   PetscFunctionReturn(0);
734552f7358SJed Brown }
735552f7358SJed Brown 
736552f7358SJed Brown #undef __FUNCT__
737552f7358SJed Brown #define __FUNCT__ "DMPlexGetConeOrientation"
738552f7358SJed Brown /*@C
739552f7358SJed Brown   DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the Sieve DAG
740552f7358SJed Brown 
741552f7358SJed Brown   Not collective
742552f7358SJed Brown 
743552f7358SJed Brown   Input Parameters:
744552f7358SJed Brown + mesh - The DMPlex
745552f7358SJed Brown - p - The Sieve point, which must lie in the chart set with DMPlexSetChart()
746552f7358SJed Brown 
747552f7358SJed Brown   Output Parameter:
748552f7358SJed Brown . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an
749552f7358SJed Brown                     integer giving the prescription for cone traversal. If it is negative, the cone is
750552f7358SJed Brown                     traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives
751552f7358SJed Brown                     the index of the cone point on which to start.
752552f7358SJed Brown 
753552f7358SJed Brown   Level: beginner
754552f7358SJed Brown 
7553813dfbdSMatthew G Knepley   Fortran Notes:
7563813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
7573813dfbdSMatthew G Knepley   include petsc.h90 in your code.
7583813dfbdSMatthew G Knepley 
7593813dfbdSMatthew G Knepley   You must also call DMPlexRestoreConeOrientation() after you finish using the returned array.
760552f7358SJed Brown 
761552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart()
762552f7358SJed Brown @*/
763552f7358SJed Brown PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[])
764552f7358SJed Brown {
765552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
766552f7358SJed Brown   PetscInt       off;
767552f7358SJed Brown   PetscErrorCode ierr;
768552f7358SJed Brown 
769552f7358SJed Brown   PetscFunctionBegin;
770552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
771552f7358SJed Brown #if defined(PETSC_USE_DEBUG)
772552f7358SJed Brown   {
773552f7358SJed Brown     PetscInt dof;
774552f7358SJed Brown     ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr);
775552f7358SJed Brown     if (dof) PetscValidPointer(coneOrientation, 3);
776552f7358SJed Brown   }
777552f7358SJed Brown #endif
778552f7358SJed Brown   ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr);
7790d644c17SKarl Rupp 
780552f7358SJed Brown   *coneOrientation = &mesh->coneOrientations[off];
781552f7358SJed Brown   PetscFunctionReturn(0);
782552f7358SJed Brown }
783552f7358SJed Brown 
784552f7358SJed Brown #undef __FUNCT__
785552f7358SJed Brown #define __FUNCT__ "DMPlexSetConeOrientation"
786552f7358SJed Brown /*@
787552f7358SJed Brown   DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the Sieve DAG
788552f7358SJed Brown 
789552f7358SJed Brown   Not collective
790552f7358SJed Brown 
791552f7358SJed Brown   Input Parameters:
792552f7358SJed Brown + mesh - The DMPlex
793552f7358SJed Brown . p - The Sieve point, which must lie in the chart set with DMPlexSetChart()
794552f7358SJed Brown - coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an
795552f7358SJed Brown                     integer giving the prescription for cone traversal. If it is negative, the cone is
796552f7358SJed Brown                     traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives
797552f7358SJed Brown                     the index of the cone point on which to start.
798552f7358SJed Brown 
799552f7358SJed Brown   Output Parameter:
800552f7358SJed Brown 
801552f7358SJed Brown   Note:
802552f7358SJed Brown   This should be called after all calls to DMPlexSetConeSize() and DMSetUp().
803552f7358SJed Brown 
804552f7358SJed Brown   Level: beginner
805552f7358SJed Brown 
806552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp()
807552f7358SJed Brown @*/
808552f7358SJed Brown PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[])
809552f7358SJed Brown {
810552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
811552f7358SJed Brown   PetscInt       pStart, pEnd;
812552f7358SJed Brown   PetscInt       dof, off, c;
813552f7358SJed Brown   PetscErrorCode ierr;
814552f7358SJed Brown 
815552f7358SJed Brown   PetscFunctionBegin;
816552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
817552f7358SJed Brown   ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr);
818552f7358SJed Brown   ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr);
819552f7358SJed Brown   if (dof) PetscValidPointer(coneOrientation, 3);
820552f7358SJed Brown   ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr);
82182f516ccSBarry Smith   if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd);
822552f7358SJed Brown   for (c = 0; c < dof; ++c) {
823552f7358SJed Brown     PetscInt cdof, o = coneOrientation[c];
824552f7358SJed Brown 
825552f7358SJed Brown     ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr);
82682f516ccSBarry Smith     if (o && ((o < -(cdof+1)) || (o >= cdof))) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone orientation %D is not in the valid range [%D. %D)", o, -(cdof+1), cdof);
827552f7358SJed Brown     mesh->coneOrientations[off+c] = o;
828552f7358SJed Brown   }
829552f7358SJed Brown   PetscFunctionReturn(0);
830552f7358SJed Brown }
831552f7358SJed Brown 
832552f7358SJed Brown #undef __FUNCT__
833552f7358SJed Brown #define __FUNCT__ "DMPlexInsertCone"
834552f7358SJed Brown PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint)
835552f7358SJed Brown {
836552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
837552f7358SJed Brown   PetscInt       pStart, pEnd;
838552f7358SJed Brown   PetscInt       dof, off;
839552f7358SJed Brown   PetscErrorCode ierr;
840552f7358SJed Brown 
841552f7358SJed Brown   PetscFunctionBegin;
842552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
843552f7358SJed Brown   ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr);
84482f516ccSBarry Smith   if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd);
84582f516ccSBarry Smith   if ((conePoint < pStart) || (conePoint >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", conePoint, pStart, pEnd);
84677c88f5bSMatthew G Knepley   ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr);
84777c88f5bSMatthew G Knepley   ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr);
84877c88f5bSMatthew G Knepley   if ((conePos < 0) || (conePos >= dof)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %D of point %D is not in the valid range [0, %D)", conePos, p, dof);
849552f7358SJed Brown   mesh->cones[off+conePos] = conePoint;
850552f7358SJed Brown   PetscFunctionReturn(0);
851552f7358SJed Brown }
852552f7358SJed Brown 
853552f7358SJed Brown #undef __FUNCT__
85477c88f5bSMatthew G Knepley #define __FUNCT__ "DMPlexInsertConeOrientation"
85577c88f5bSMatthew G Knepley PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation)
85677c88f5bSMatthew G Knepley {
85777c88f5bSMatthew G Knepley   DM_Plex       *mesh = (DM_Plex*) dm->data;
85877c88f5bSMatthew G Knepley   PetscInt       pStart, pEnd;
85977c88f5bSMatthew G Knepley   PetscInt       dof, off;
86077c88f5bSMatthew G Knepley   PetscErrorCode ierr;
86177c88f5bSMatthew G Knepley 
86277c88f5bSMatthew G Knepley   PetscFunctionBegin;
86377c88f5bSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
86477c88f5bSMatthew G Knepley   ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr);
86577c88f5bSMatthew G Knepley   if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd);
86677c88f5bSMatthew G Knepley   ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr);
86777c88f5bSMatthew G Knepley   ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr);
86877c88f5bSMatthew G Knepley   if ((conePos < 0) || (conePos >= dof)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %D of point %D is not in the valid range [0, %D)", conePos, p, dof);
86977c88f5bSMatthew G Knepley   mesh->coneOrientations[off+conePos] = coneOrientation;
87077c88f5bSMatthew G Knepley   PetscFunctionReturn(0);
87177c88f5bSMatthew G Knepley }
87277c88f5bSMatthew G Knepley 
87377c88f5bSMatthew G Knepley #undef __FUNCT__
874552f7358SJed Brown #define __FUNCT__ "DMPlexGetSupportSize"
875552f7358SJed Brown /*@
876552f7358SJed Brown   DMPlexGetSupportSize - Return the number of out-edges for this point in the Sieve DAG
877552f7358SJed Brown 
878552f7358SJed Brown   Not collective
879552f7358SJed Brown 
880552f7358SJed Brown   Input Parameters:
881552f7358SJed Brown + mesh - The DMPlex
882552f7358SJed Brown - p - The Sieve point, which must lie in the chart set with DMPlexSetChart()
883552f7358SJed Brown 
884552f7358SJed Brown   Output Parameter:
885552f7358SJed Brown . size - The support size for point p
886552f7358SJed Brown 
887552f7358SJed Brown   Level: beginner
888552f7358SJed Brown 
889552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize()
890552f7358SJed Brown @*/
891552f7358SJed Brown PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size)
892552f7358SJed Brown {
893552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
894552f7358SJed Brown   PetscErrorCode ierr;
895552f7358SJed Brown 
896552f7358SJed Brown   PetscFunctionBegin;
897552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
898552f7358SJed Brown   PetscValidPointer(size, 3);
899552f7358SJed Brown   ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr);
900552f7358SJed Brown   PetscFunctionReturn(0);
901552f7358SJed Brown }
902552f7358SJed Brown 
903552f7358SJed Brown #undef __FUNCT__
904552f7358SJed Brown #define __FUNCT__ "DMPlexSetSupportSize"
905552f7358SJed Brown /*@
906552f7358SJed Brown   DMPlexSetSupportSize - Set the number of out-edges for this point in the Sieve DAG
907552f7358SJed Brown 
908552f7358SJed Brown   Not collective
909552f7358SJed Brown 
910552f7358SJed Brown   Input Parameters:
911552f7358SJed Brown + mesh - The DMPlex
912552f7358SJed Brown . p - The Sieve point, which must lie in the chart set with DMPlexSetChart()
913552f7358SJed Brown - size - The support size for point p
914552f7358SJed Brown 
915552f7358SJed Brown   Output Parameter:
916552f7358SJed Brown 
917552f7358SJed Brown   Note:
918552f7358SJed Brown   This should be called after DMPlexSetChart().
919552f7358SJed Brown 
920552f7358SJed Brown   Level: beginner
921552f7358SJed Brown 
922552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart()
923552f7358SJed Brown @*/
924552f7358SJed Brown PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size)
925552f7358SJed Brown {
926552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
927552f7358SJed Brown   PetscErrorCode ierr;
928552f7358SJed Brown 
929552f7358SJed Brown   PetscFunctionBegin;
930552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
931552f7358SJed Brown   ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr);
9320d644c17SKarl Rupp 
933552f7358SJed Brown   mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size);
934552f7358SJed Brown   PetscFunctionReturn(0);
935552f7358SJed Brown }
936552f7358SJed Brown 
937552f7358SJed Brown #undef __FUNCT__
938552f7358SJed Brown #define __FUNCT__ "DMPlexGetSupport"
939552f7358SJed Brown /*@C
940552f7358SJed Brown   DMPlexGetSupport - Return the points on the out-edges for this point in the Sieve DAG
941552f7358SJed Brown 
942552f7358SJed Brown   Not collective
943552f7358SJed Brown 
944552f7358SJed Brown   Input Parameters:
945552f7358SJed Brown + mesh - The DMPlex
946552f7358SJed Brown - p - The Sieve point, which must lie in the chart set with DMPlexSetChart()
947552f7358SJed Brown 
948552f7358SJed Brown   Output Parameter:
949552f7358SJed Brown . support - An array of points which are on the out-edges for point p
950552f7358SJed Brown 
951552f7358SJed Brown   Level: beginner
952552f7358SJed Brown 
9533813dfbdSMatthew G Knepley   Fortran Notes:
9543813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
9553813dfbdSMatthew G Knepley   include petsc.h90 in your code.
9563813dfbdSMatthew G Knepley 
9573813dfbdSMatthew G Knepley   You must also call DMPlexRestoreSupport() after you finish using the returned array.
9583813dfbdSMatthew G Knepley 
959552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone()
960552f7358SJed Brown @*/
961552f7358SJed Brown PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[])
962552f7358SJed Brown {
963552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
964552f7358SJed Brown   PetscInt       off;
965552f7358SJed Brown   PetscErrorCode ierr;
966552f7358SJed Brown 
967552f7358SJed Brown   PetscFunctionBegin;
968552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
969552f7358SJed Brown   PetscValidPointer(support, 3);
970552f7358SJed Brown   ierr     = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr);
971552f7358SJed Brown   *support = &mesh->supports[off];
972552f7358SJed Brown   PetscFunctionReturn(0);
973552f7358SJed Brown }
974552f7358SJed Brown 
975552f7358SJed Brown #undef __FUNCT__
976552f7358SJed Brown #define __FUNCT__ "DMPlexSetSupport"
977552f7358SJed Brown /*@
978552f7358SJed Brown   DMPlexSetSupport - Set the points on the out-edges for this point in the Sieve DAG
979552f7358SJed Brown 
980552f7358SJed Brown   Not collective
981552f7358SJed Brown 
982552f7358SJed Brown   Input Parameters:
983552f7358SJed Brown + mesh - The DMPlex
984552f7358SJed Brown . p - The Sieve point, which must lie in the chart set with DMPlexSetChart()
985552f7358SJed Brown - support - An array of points which are on the in-edges for point p
986552f7358SJed Brown 
987552f7358SJed Brown   Output Parameter:
988552f7358SJed Brown 
989552f7358SJed Brown   Note:
990552f7358SJed Brown   This should be called after all calls to DMPlexSetSupportSize() and DMSetUp().
991552f7358SJed Brown 
992552f7358SJed Brown   Level: beginner
993552f7358SJed Brown 
994552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp()
995552f7358SJed Brown @*/
996552f7358SJed Brown PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[])
997552f7358SJed Brown {
998552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
999552f7358SJed Brown   PetscInt       pStart, pEnd;
1000552f7358SJed Brown   PetscInt       dof, off, c;
1001552f7358SJed Brown   PetscErrorCode ierr;
1002552f7358SJed Brown 
1003552f7358SJed Brown   PetscFunctionBegin;
1004552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1005552f7358SJed Brown   ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr);
1006552f7358SJed Brown   ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr);
1007552f7358SJed Brown   if (dof) PetscValidPointer(support, 3);
1008552f7358SJed Brown   ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr);
100982f516ccSBarry Smith   if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd);
1010552f7358SJed Brown   for (c = 0; c < dof; ++c) {
101182f516ccSBarry Smith     if ((support[c] < pStart) || (support[c] >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", support[c], pStart, pEnd);
1012552f7358SJed Brown     mesh->supports[off+c] = support[c];
1013552f7358SJed Brown   }
1014552f7358SJed Brown   PetscFunctionReturn(0);
1015552f7358SJed Brown }
1016552f7358SJed Brown 
1017552f7358SJed Brown #undef __FUNCT__
1018552f7358SJed Brown #define __FUNCT__ "DMPlexInsertSupport"
1019552f7358SJed Brown PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint)
1020552f7358SJed Brown {
1021552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
1022552f7358SJed Brown   PetscInt       pStart, pEnd;
1023552f7358SJed Brown   PetscInt       dof, off;
1024552f7358SJed Brown   PetscErrorCode ierr;
1025552f7358SJed Brown 
1026552f7358SJed Brown   PetscFunctionBegin;
1027552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1028552f7358SJed Brown   ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr);
1029552f7358SJed Brown   ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr);
1030552f7358SJed Brown   ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr);
103182f516ccSBarry Smith   if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd);
103282f516ccSBarry Smith   if ((supportPoint < pStart) || (supportPoint >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", supportPoint, pStart, pEnd);
103382f516ccSBarry Smith   if (supportPos >= dof) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support position %D of point %D is not in the valid range [0, %D)", supportPos, p, dof);
1034552f7358SJed Brown   mesh->supports[off+supportPos] = supportPoint;
1035552f7358SJed Brown   PetscFunctionReturn(0);
1036552f7358SJed Brown }
1037552f7358SJed Brown 
1038552f7358SJed Brown #undef __FUNCT__
1039552f7358SJed Brown #define __FUNCT__ "DMPlexGetTransitiveClosure"
1040552f7358SJed Brown /*@C
1041552f7358SJed Brown   DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG
1042552f7358SJed Brown 
1043552f7358SJed Brown   Not collective
1044552f7358SJed Brown 
1045552f7358SJed Brown   Input Parameters:
1046552f7358SJed Brown + mesh - The DMPlex
1047552f7358SJed Brown . p - The Sieve point, which must lie in the chart set with DMPlexSetChart()
1048552f7358SJed Brown . useCone - PETSC_TRUE for in-edges,  otherwise use out-edges
10490298fd71SBarry Smith - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used
1050552f7358SJed Brown 
1051552f7358SJed Brown   Output Parameters:
1052552f7358SJed Brown + numPoints - The number of points in the closure, so points[] is of size 2*numPoints
1053552f7358SJed Brown - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]
1054552f7358SJed Brown 
1055552f7358SJed Brown   Note:
10560298fd71SBarry Smith   If using internal storage (points is NULL on input), each call overwrites the last output.
1057552f7358SJed Brown 
10583813dfbdSMatthew G Knepley   Fortran Notes:
10593813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
10603813dfbdSMatthew G Knepley   include petsc.h90 in your code.
10613813dfbdSMatthew G Knepley 
10623813dfbdSMatthew G Knepley   The numPoints argument is not present in the Fortran 90 binding since it is internal to the array.
10633813dfbdSMatthew G Knepley 
1064552f7358SJed Brown   Level: beginner
1065552f7358SJed Brown 
1066552f7358SJed Brown .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone()
1067552f7358SJed Brown @*/
1068552f7358SJed Brown PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
1069552f7358SJed Brown {
1070552f7358SJed Brown   DM_Plex        *mesh = (DM_Plex*) dm->data;
1071552f7358SJed Brown   PetscInt       *closure, *fifo;
10720298fd71SBarry Smith   const PetscInt *tmp = NULL, *tmpO = NULL;
1073552f7358SJed Brown   PetscInt        tmpSize, t;
1074552f7358SJed Brown   PetscInt        depth       = 0, maxSize;
1075552f7358SJed Brown   PetscInt        closureSize = 2, fifoSize = 0, fifoStart = 0;
1076552f7358SJed Brown   PetscErrorCode  ierr;
1077552f7358SJed Brown 
1078552f7358SJed Brown   PetscFunctionBegin;
1079552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1080552f7358SJed Brown   ierr    = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
1081552f7358SJed Brown   /* This is only 1-level */
1082552f7358SJed Brown   if (useCone) {
1083552f7358SJed Brown     ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr);
1084552f7358SJed Brown     ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr);
1085552f7358SJed Brown     ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr);
1086552f7358SJed Brown   } else {
1087552f7358SJed Brown     ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr);
1088552f7358SJed Brown     ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr);
1089552f7358SJed Brown   }
1090bfbcdd7aSMatthew G. Knepley   if (depth == 1) {
1091bfbcdd7aSMatthew G. Knepley     if (*points) {
1092bfbcdd7aSMatthew G. Knepley       closure = *points;
1093bfbcdd7aSMatthew G. Knepley     } else {
1094bfbcdd7aSMatthew G. Knepley       maxSize = 2*(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)+1);
1095bfbcdd7aSMatthew G. Knepley       ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &closure);CHKERRQ(ierr);
1096bfbcdd7aSMatthew G. Knepley     }
1097bfbcdd7aSMatthew G. Knepley     closure[0] = p; closure[1] = 0;
1098bfbcdd7aSMatthew G. Knepley     for (t = 0; t < tmpSize; ++t, closureSize += 2) {
1099bfbcdd7aSMatthew G. Knepley       closure[closureSize]   = tmp[t];
1100bfbcdd7aSMatthew G. Knepley       closure[closureSize+1] = tmpO ? tmpO[t] : 0;
1101bfbcdd7aSMatthew G. Knepley     }
1102bfbcdd7aSMatthew G. Knepley     if (numPoints) *numPoints = closureSize/2;
1103bfbcdd7aSMatthew G. Knepley     if (points)    *points    = closure;
1104bfbcdd7aSMatthew G. Knepley     PetscFunctionReturn(0);
1105bfbcdd7aSMatthew G. Knepley   }
1106bfbcdd7aSMatthew G. Knepley   maxSize = 2*PetscMax(PetscMax(PetscPowInt(mesh->maxConeSize,depth+1),PetscPowInt(mesh->maxSupportSize,depth+1)),depth+1);
1107bfbcdd7aSMatthew G. Knepley   ierr    = DMGetWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr);
1108bfbcdd7aSMatthew G. Knepley   if (*points) {
1109bfbcdd7aSMatthew G. Knepley     closure = *points;
1110bfbcdd7aSMatthew G. Knepley   } else {
1111bfbcdd7aSMatthew G. Knepley     ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &closure);CHKERRQ(ierr);
1112bfbcdd7aSMatthew G. Knepley   }
1113bfbcdd7aSMatthew G. Knepley   closure[0] = p; closure[1] = 0;
1114552f7358SJed Brown   for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) {
1115552f7358SJed Brown     const PetscInt cp = tmp[t];
1116552f7358SJed Brown     const PetscInt co = tmpO ? tmpO[t] : 0;
1117552f7358SJed Brown 
1118552f7358SJed Brown     closure[closureSize]   = cp;
1119552f7358SJed Brown     closure[closureSize+1] = co;
1120552f7358SJed Brown     fifo[fifoSize]         = cp;
1121552f7358SJed Brown     fifo[fifoSize+1]       = co;
1122552f7358SJed Brown   }
1123bfbcdd7aSMatthew G. Knepley   /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */
1124552f7358SJed Brown   while (fifoSize - fifoStart) {
1125552f7358SJed Brown     const PetscInt q   = fifo[fifoStart];
1126552f7358SJed Brown     const PetscInt o   = fifo[fifoStart+1];
1127552f7358SJed Brown     const PetscInt rev = o >= 0 ? 0 : 1;
1128552f7358SJed Brown     const PetscInt off = rev ? -(o+1) : o;
1129552f7358SJed Brown 
1130552f7358SJed Brown     if (useCone) {
1131552f7358SJed Brown       ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr);
1132552f7358SJed Brown       ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr);
1133552f7358SJed Brown       ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr);
1134552f7358SJed Brown     } else {
1135552f7358SJed Brown       ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr);
1136552f7358SJed Brown       ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr);
11370298fd71SBarry Smith       tmpO = NULL;
1138552f7358SJed Brown     }
1139552f7358SJed Brown     for (t = 0; t < tmpSize; ++t) {
1140552f7358SJed Brown       const PetscInt i  = ((rev ? tmpSize-t : t) + off)%tmpSize;
1141552f7358SJed Brown       const PetscInt cp = tmp[i];
11422e1b13c2SMatthew G. Knepley       /* Must propogate orientation: When we reverse orientation, we both reverse the direction of iteration and start at the other end of the chain. */
11432e1b13c2SMatthew G. Knepley       /* HACK: It is worse to get the size here, than to change the interpretation of -(*+1)
11442e1b13c2SMatthew G. Knepley        const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; */
11452e1b13c2SMatthew G. Knepley       PetscInt       co = tmpO ? tmpO[i] : 0;
1146552f7358SJed Brown       PetscInt       c;
1147552f7358SJed Brown 
11482e1b13c2SMatthew G. Knepley       if (rev) {
11492e1b13c2SMatthew G. Knepley         PetscInt childSize, coff;
11502e1b13c2SMatthew G. Knepley         ierr = DMPlexGetConeSize(dm, cp, &childSize);CHKERRQ(ierr);
11512e1b13c2SMatthew G. Knepley         coff = tmpO[i] < 0 ? -(tmpO[i]+1) : tmpO[i];
11522e1b13c2SMatthew G. Knepley         co   = childSize ? -(((coff+childSize-1)%childSize)+1) : 0;
11532e1b13c2SMatthew G. Knepley       }
1154552f7358SJed Brown       /* Check for duplicate */
1155552f7358SJed Brown       for (c = 0; c < closureSize; c += 2) {
1156552f7358SJed Brown         if (closure[c] == cp) break;
1157552f7358SJed Brown       }
1158552f7358SJed Brown       if (c == closureSize) {
1159552f7358SJed Brown         closure[closureSize]   = cp;
1160552f7358SJed Brown         closure[closureSize+1] = co;
1161552f7358SJed Brown         fifo[fifoSize]         = cp;
1162552f7358SJed Brown         fifo[fifoSize+1]       = co;
1163552f7358SJed Brown         closureSize           += 2;
1164552f7358SJed Brown         fifoSize              += 2;
1165552f7358SJed Brown       }
1166552f7358SJed Brown     }
1167552f7358SJed Brown     fifoStart += 2;
1168552f7358SJed Brown   }
1169552f7358SJed Brown   if (numPoints) *numPoints = closureSize/2;
1170552f7358SJed Brown   if (points)    *points    = closure;
1171552f7358SJed Brown   ierr = DMRestoreWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr);
1172552f7358SJed Brown   PetscFunctionReturn(0);
1173552f7358SJed Brown }
1174552f7358SJed Brown 
1175552f7358SJed Brown #undef __FUNCT__
11769bf0dad6SMatthew G. Knepley #define __FUNCT__ "DMPlexGetTransitiveClosure_Internal"
11779bf0dad6SMatthew G. Knepley /*@C
11789bf0dad6SMatthew G. Knepley   DMPlexGetTransitiveClosure_Internal - Return the points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG with a specified initial orientation
11799bf0dad6SMatthew G. Knepley 
11809bf0dad6SMatthew G. Knepley   Not collective
11819bf0dad6SMatthew G. Knepley 
11829bf0dad6SMatthew G. Knepley   Input Parameters:
11839bf0dad6SMatthew G. Knepley + mesh - The DMPlex
11849bf0dad6SMatthew G. Knepley . p - The Sieve point, which must lie in the chart set with DMPlexSetChart()
11859bf0dad6SMatthew G. Knepley . orientation - The orientation of the point
11869bf0dad6SMatthew G. Knepley . useCone - PETSC_TRUE for in-edges,  otherwise use out-edges
11879bf0dad6SMatthew G. Knepley - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used
11889bf0dad6SMatthew G. Knepley 
11899bf0dad6SMatthew G. Knepley   Output Parameters:
11909bf0dad6SMatthew G. Knepley + numPoints - The number of points in the closure, so points[] is of size 2*numPoints
11919bf0dad6SMatthew G. Knepley - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]
11929bf0dad6SMatthew G. Knepley 
11939bf0dad6SMatthew G. Knepley   Note:
11949bf0dad6SMatthew G. Knepley   If using internal storage (points is NULL on input), each call overwrites the last output.
11959bf0dad6SMatthew G. Knepley 
11969bf0dad6SMatthew G. Knepley   Fortran Notes:
11979bf0dad6SMatthew G. Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
11989bf0dad6SMatthew G. Knepley   include petsc.h90 in your code.
11999bf0dad6SMatthew G. Knepley 
12009bf0dad6SMatthew G. Knepley   The numPoints argument is not present in the Fortran 90 binding since it is internal to the array.
12019bf0dad6SMatthew G. Knepley 
12029bf0dad6SMatthew G. Knepley   Level: beginner
12039bf0dad6SMatthew G. Knepley 
12049bf0dad6SMatthew G. Knepley .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone()
12059bf0dad6SMatthew G. Knepley @*/
12069bf0dad6SMatthew G. Knepley PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
12079bf0dad6SMatthew G. Knepley {
12089bf0dad6SMatthew G. Knepley   DM_Plex        *mesh = (DM_Plex*) dm->data;
12099bf0dad6SMatthew G. Knepley   PetscInt       *closure, *fifo;
12109bf0dad6SMatthew G. Knepley   const PetscInt *tmp = NULL, *tmpO = NULL;
12119bf0dad6SMatthew G. Knepley   PetscInt        tmpSize, t;
12129bf0dad6SMatthew G. Knepley   PetscInt        depth       = 0, maxSize;
12139bf0dad6SMatthew G. Knepley   PetscInt        closureSize = 2, fifoSize = 0, fifoStart = 0;
12149bf0dad6SMatthew G. Knepley   PetscErrorCode  ierr;
12159bf0dad6SMatthew G. Knepley 
12169bf0dad6SMatthew G. Knepley   PetscFunctionBegin;
12179bf0dad6SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
12189bf0dad6SMatthew G. Knepley   ierr    = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
12199bf0dad6SMatthew G. Knepley   /* This is only 1-level */
12209bf0dad6SMatthew G. Knepley   if (useCone) {
12219bf0dad6SMatthew G. Knepley     ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr);
12229bf0dad6SMatthew G. Knepley     ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr);
12239bf0dad6SMatthew G. Knepley     ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr);
12249bf0dad6SMatthew G. Knepley   } else {
12259bf0dad6SMatthew G. Knepley     ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr);
12269bf0dad6SMatthew G. Knepley     ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr);
12279bf0dad6SMatthew G. Knepley   }
12289bf0dad6SMatthew G. Knepley   if (depth == 1) {
12299bf0dad6SMatthew G. Knepley     if (*points) {
12309bf0dad6SMatthew G. Knepley       closure = *points;
12319bf0dad6SMatthew G. Knepley     } else {
12329bf0dad6SMatthew G. Knepley       maxSize = 2*(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)+1);
12339bf0dad6SMatthew G. Knepley       ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &closure);CHKERRQ(ierr);
12349bf0dad6SMatthew G. Knepley     }
12359bf0dad6SMatthew G. Knepley     closure[0] = p; closure[1] = ornt;
12369bf0dad6SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t, closureSize += 2) {
12379bf0dad6SMatthew G. Knepley       const PetscInt i = ornt >= 0 ? (t+ornt)%tmpSize : (-(ornt+1) + tmpSize-t)%tmpSize;
12389bf0dad6SMatthew G. Knepley       closure[closureSize]   = tmp[i];
12399bf0dad6SMatthew G. Knepley       closure[closureSize+1] = tmpO ? tmpO[i] : 0;
12409bf0dad6SMatthew G. Knepley     }
12419bf0dad6SMatthew G. Knepley     if (numPoints) *numPoints = closureSize/2;
12429bf0dad6SMatthew G. Knepley     if (points)    *points    = closure;
12439bf0dad6SMatthew G. Knepley     PetscFunctionReturn(0);
12449bf0dad6SMatthew G. Knepley   }
12459bf0dad6SMatthew G. Knepley   maxSize = 2*PetscMax(PetscMax(PetscPowInt(mesh->maxConeSize,depth+1),PetscPowInt(mesh->maxSupportSize,depth+1)),depth+1);
12469bf0dad6SMatthew G. Knepley   ierr    = DMGetWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr);
12479bf0dad6SMatthew G. Knepley   if (*points) {
12489bf0dad6SMatthew G. Knepley     closure = *points;
12499bf0dad6SMatthew G. Knepley   } else {
12509bf0dad6SMatthew G. Knepley     ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &closure);CHKERRQ(ierr);
12519bf0dad6SMatthew G. Knepley   }
12529bf0dad6SMatthew G. Knepley   closure[0] = p; closure[1] = ornt;
12539bf0dad6SMatthew G. Knepley   for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) {
12549bf0dad6SMatthew G. Knepley     const PetscInt i  = ornt >= 0 ? (t+ornt)%tmpSize : (-(ornt+1) + tmpSize-t)%tmpSize;
12559bf0dad6SMatthew G. Knepley     const PetscInt cp = tmp[i];
12569bf0dad6SMatthew G. Knepley     PetscInt       co = tmpO ? tmpO[i] : 0;
12579bf0dad6SMatthew G. Knepley 
12589bf0dad6SMatthew G. Knepley     if (ornt < 0) {
12599bf0dad6SMatthew G. Knepley       PetscInt childSize, coff;
12609bf0dad6SMatthew G. Knepley       ierr = DMPlexGetConeSize(dm, cp, &childSize);CHKERRQ(ierr);
12619bf0dad6SMatthew G. Knepley       coff = tmpO[i] < 0 ? -(tmpO[i]+1) : tmpO[i];
12629bf0dad6SMatthew G. Knepley       co   = childSize ? -(((coff+childSize-1)%childSize)+1) : 0;
12639bf0dad6SMatthew G. Knepley     }
12649bf0dad6SMatthew G. Knepley     closure[closureSize]   = cp;
12659bf0dad6SMatthew G. Knepley     closure[closureSize+1] = co;
12669bf0dad6SMatthew G. Knepley     fifo[fifoSize]         = cp;
12679bf0dad6SMatthew G. Knepley     fifo[fifoSize+1]       = co;
12689bf0dad6SMatthew G. Knepley   }
12699bf0dad6SMatthew G. Knepley   /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */
12709bf0dad6SMatthew G. Knepley   while (fifoSize - fifoStart) {
12719bf0dad6SMatthew G. Knepley     const PetscInt q   = fifo[fifoStart];
12729bf0dad6SMatthew G. Knepley     const PetscInt o   = fifo[fifoStart+1];
12739bf0dad6SMatthew G. Knepley     const PetscInt rev = o >= 0 ? 0 : 1;
12749bf0dad6SMatthew G. Knepley     const PetscInt off = rev ? -(o+1) : o;
12759bf0dad6SMatthew G. Knepley 
12769bf0dad6SMatthew G. Knepley     if (useCone) {
12779bf0dad6SMatthew G. Knepley       ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr);
12789bf0dad6SMatthew G. Knepley       ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr);
12799bf0dad6SMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr);
12809bf0dad6SMatthew G. Knepley     } else {
12819bf0dad6SMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr);
12829bf0dad6SMatthew G. Knepley       ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr);
12839bf0dad6SMatthew G. Knepley       tmpO = NULL;
12849bf0dad6SMatthew G. Knepley     }
12859bf0dad6SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
12869bf0dad6SMatthew G. Knepley       const PetscInt i  = ((rev ? tmpSize-t : t) + off)%tmpSize;
12879bf0dad6SMatthew G. Knepley       const PetscInt cp = tmp[i];
12889bf0dad6SMatthew G. Knepley       /* Must propogate orientation: When we reverse orientation, we both reverse the direction of iteration and start at the other end of the chain. */
12899bf0dad6SMatthew G. Knepley       /* HACK: It is worse to get the size here, than to change the interpretation of -(*+1)
12909bf0dad6SMatthew G. Knepley        const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; */
12919bf0dad6SMatthew G. Knepley       PetscInt       co = tmpO ? tmpO[i] : 0;
12929bf0dad6SMatthew G. Knepley       PetscInt       c;
12939bf0dad6SMatthew G. Knepley 
12949bf0dad6SMatthew G. Knepley       if (rev) {
12959bf0dad6SMatthew G. Knepley         PetscInt childSize, coff;
12969bf0dad6SMatthew G. Knepley         ierr = DMPlexGetConeSize(dm, cp, &childSize);CHKERRQ(ierr);
12979bf0dad6SMatthew G. Knepley         coff = tmpO[i] < 0 ? -(tmpO[i]+1) : tmpO[i];
12989bf0dad6SMatthew G. Knepley         co   = childSize ? -(((coff+childSize-1)%childSize)+1) : 0;
12999bf0dad6SMatthew G. Knepley       }
13009bf0dad6SMatthew G. Knepley       /* Check for duplicate */
13019bf0dad6SMatthew G. Knepley       for (c = 0; c < closureSize; c += 2) {
13029bf0dad6SMatthew G. Knepley         if (closure[c] == cp) break;
13039bf0dad6SMatthew G. Knepley       }
13049bf0dad6SMatthew G. Knepley       if (c == closureSize) {
13059bf0dad6SMatthew G. Knepley         closure[closureSize]   = cp;
13069bf0dad6SMatthew G. Knepley         closure[closureSize+1] = co;
13079bf0dad6SMatthew G. Knepley         fifo[fifoSize]         = cp;
13089bf0dad6SMatthew G. Knepley         fifo[fifoSize+1]       = co;
13099bf0dad6SMatthew G. Knepley         closureSize           += 2;
13109bf0dad6SMatthew G. Knepley         fifoSize              += 2;
13119bf0dad6SMatthew G. Knepley       }
13129bf0dad6SMatthew G. Knepley     }
13139bf0dad6SMatthew G. Knepley     fifoStart += 2;
13149bf0dad6SMatthew G. Knepley   }
13159bf0dad6SMatthew G. Knepley   if (numPoints) *numPoints = closureSize/2;
13169bf0dad6SMatthew G. Knepley   if (points)    *points    = closure;
13179bf0dad6SMatthew G. Knepley   ierr = DMRestoreWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr);
13189bf0dad6SMatthew G. Knepley   PetscFunctionReturn(0);
13199bf0dad6SMatthew G. Knepley }
13209bf0dad6SMatthew G. Knepley 
13219bf0dad6SMatthew G. Knepley #undef __FUNCT__
1322552f7358SJed Brown #define __FUNCT__ "DMPlexRestoreTransitiveClosure"
1323552f7358SJed Brown /*@C
1324552f7358SJed 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
1325552f7358SJed Brown 
1326552f7358SJed Brown   Not collective
1327552f7358SJed Brown 
1328552f7358SJed Brown   Input Parameters:
1329552f7358SJed Brown + mesh - The DMPlex
1330552f7358SJed Brown . p - The Sieve point, which must lie in the chart set with DMPlexSetChart()
1331552f7358SJed Brown . useCone - PETSC_TRUE for in-edges,  otherwise use out-edges
1332e5c84f05SJed Brown . numPoints - The number of points in the closure, so points[] is of size 2*numPoints, zeroed on exit
1333e5c84f05SJed Brown - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...], zeroed on exit
1334552f7358SJed Brown 
1335552f7358SJed Brown   Note:
13360298fd71SBarry Smith   If not using internal storage (points is not NULL on input), this call is unnecessary
1337552f7358SJed Brown 
13383813dfbdSMatthew G Knepley   Fortran Notes:
13393813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
13403813dfbdSMatthew G Knepley   include petsc.h90 in your code.
13413813dfbdSMatthew G Knepley 
13423813dfbdSMatthew G Knepley   The numPoints argument is not present in the Fortran 90 binding since it is internal to the array.
13433813dfbdSMatthew G Knepley 
1344552f7358SJed Brown   Level: beginner
1345552f7358SJed Brown 
1346552f7358SJed Brown .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone()
1347552f7358SJed Brown @*/
1348552f7358SJed Brown PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
1349552f7358SJed Brown {
1350552f7358SJed Brown   PetscErrorCode ierr;
1351552f7358SJed Brown 
1352552f7358SJed Brown   PetscFunctionBegin;
1353552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1354e5c84f05SJed Brown   if (numPoints) PetscValidIntPointer(numPoints,4);
1355e5c84f05SJed Brown   if (points) PetscValidPointer(points,5);
1356552f7358SJed Brown   ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, points);CHKERRQ(ierr);
13574ff43b2cSJed Brown   if (numPoints) *numPoints = 0;
1358552f7358SJed Brown   PetscFunctionReturn(0);
1359552f7358SJed Brown }
1360552f7358SJed Brown 
1361552f7358SJed Brown #undef __FUNCT__
1362552f7358SJed Brown #define __FUNCT__ "DMPlexGetMaxSizes"
1363552f7358SJed Brown /*@
1364552f7358SJed Brown   DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the Sieve DAG
1365552f7358SJed Brown 
1366552f7358SJed Brown   Not collective
1367552f7358SJed Brown 
1368552f7358SJed Brown   Input Parameter:
1369552f7358SJed Brown . mesh - The DMPlex
1370552f7358SJed Brown 
1371552f7358SJed Brown   Output Parameters:
1372552f7358SJed Brown + maxConeSize - The maximum number of in-edges
1373552f7358SJed Brown - maxSupportSize - The maximum number of out-edges
1374552f7358SJed Brown 
1375552f7358SJed Brown   Level: beginner
1376552f7358SJed Brown 
1377552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart()
1378552f7358SJed Brown @*/
1379552f7358SJed Brown PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize)
1380552f7358SJed Brown {
1381552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
1382552f7358SJed Brown 
1383552f7358SJed Brown   PetscFunctionBegin;
1384552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1385552f7358SJed Brown   if (maxConeSize)    *maxConeSize    = mesh->maxConeSize;
1386552f7358SJed Brown   if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize;
1387552f7358SJed Brown   PetscFunctionReturn(0);
1388552f7358SJed Brown }
1389552f7358SJed Brown 
1390552f7358SJed Brown #undef __FUNCT__
1391552f7358SJed Brown #define __FUNCT__ "DMSetUp_Plex"
1392552f7358SJed Brown PetscErrorCode DMSetUp_Plex(DM dm)
1393552f7358SJed Brown {
1394552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
1395552f7358SJed Brown   PetscInt       size;
1396552f7358SJed Brown   PetscErrorCode ierr;
1397552f7358SJed Brown 
1398552f7358SJed Brown   PetscFunctionBegin;
1399552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1400552f7358SJed Brown   ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr);
1401552f7358SJed Brown   ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr);
14021795a4d1SJed Brown   ierr = PetscMalloc1(size, &mesh->cones);CHKERRQ(ierr);
14031795a4d1SJed Brown   ierr = PetscCalloc1(size, &mesh->coneOrientations);CHKERRQ(ierr);
1404552f7358SJed Brown   if (mesh->maxSupportSize) {
1405552f7358SJed Brown     ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr);
1406552f7358SJed Brown     ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr);
14071795a4d1SJed Brown     ierr = PetscMalloc1(size, &mesh->supports);CHKERRQ(ierr);
1408552f7358SJed Brown   }
1409552f7358SJed Brown   PetscFunctionReturn(0);
1410552f7358SJed Brown }
1411552f7358SJed Brown 
1412552f7358SJed Brown #undef __FUNCT__
1413552f7358SJed Brown #define __FUNCT__ "DMCreateSubDM_Plex"
1414552f7358SJed Brown PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm)
1415552f7358SJed Brown {
1416552f7358SJed Brown   PetscErrorCode ierr;
1417552f7358SJed Brown 
1418552f7358SJed Brown   PetscFunctionBegin;
14194d9407bcSMatthew G. Knepley   if (subdm) {ierr = DMClone(dm, subdm);CHKERRQ(ierr);}
14204d9407bcSMatthew G. Knepley   ierr = DMCreateSubDM_Section_Private(dm, numFields, fields, is, subdm);CHKERRQ(ierr);
1421552f7358SJed Brown   PetscFunctionReturn(0);
1422552f7358SJed Brown }
1423552f7358SJed Brown 
1424552f7358SJed Brown #undef __FUNCT__
1425552f7358SJed Brown #define __FUNCT__ "DMPlexSymmetrize"
1426552f7358SJed Brown /*@
1427552f7358SJed Brown   DMPlexSymmetrize - Creates support (out-edge) information from cone (in-edge) inoformation
1428552f7358SJed Brown 
1429552f7358SJed Brown   Not collective
1430552f7358SJed Brown 
1431552f7358SJed Brown   Input Parameter:
1432552f7358SJed Brown . mesh - The DMPlex
1433552f7358SJed Brown 
1434552f7358SJed Brown   Output Parameter:
1435552f7358SJed Brown 
1436552f7358SJed Brown   Note:
1437552f7358SJed Brown   This should be called after all calls to DMPlexSetCone()
1438552f7358SJed Brown 
1439552f7358SJed Brown   Level: beginner
1440552f7358SJed Brown 
1441552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone()
1442552f7358SJed Brown @*/
1443552f7358SJed Brown PetscErrorCode DMPlexSymmetrize(DM dm)
1444552f7358SJed Brown {
1445552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
1446552f7358SJed Brown   PetscInt      *offsets;
1447552f7358SJed Brown   PetscInt       supportSize;
1448552f7358SJed Brown   PetscInt       pStart, pEnd, p;
1449552f7358SJed Brown   PetscErrorCode ierr;
1450552f7358SJed Brown 
1451552f7358SJed Brown   PetscFunctionBegin;
1452552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
145382f516ccSBarry Smith   if (mesh->supports) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex");
1454552f7358SJed Brown   /* Calculate support sizes */
1455552f7358SJed Brown   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
1456552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
1457552f7358SJed Brown     PetscInt dof, off, c;
1458552f7358SJed Brown 
1459552f7358SJed Brown     ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr);
1460552f7358SJed Brown     ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr);
1461552f7358SJed Brown     for (c = off; c < off+dof; ++c) {
1462552f7358SJed Brown       ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr);
1463552f7358SJed Brown     }
1464552f7358SJed Brown   }
1465552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
1466552f7358SJed Brown     PetscInt dof;
1467552f7358SJed Brown 
1468552f7358SJed Brown     ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr);
14690d644c17SKarl Rupp 
1470552f7358SJed Brown     mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof);
1471552f7358SJed Brown   }
1472552f7358SJed Brown   ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr);
1473552f7358SJed Brown   /* Calculate supports */
1474552f7358SJed Brown   ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr);
14751795a4d1SJed Brown   ierr = PetscMalloc1(supportSize, &mesh->supports);CHKERRQ(ierr);
14761795a4d1SJed Brown   ierr = PetscCalloc1(pEnd - pStart, &offsets);CHKERRQ(ierr);
1477552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
1478552f7358SJed Brown     PetscInt dof, off, c;
1479552f7358SJed Brown 
1480552f7358SJed Brown     ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr);
1481552f7358SJed Brown     ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr);
1482552f7358SJed Brown     for (c = off; c < off+dof; ++c) {
1483552f7358SJed Brown       const PetscInt q = mesh->cones[c];
1484552f7358SJed Brown       PetscInt       offS;
1485552f7358SJed Brown 
1486552f7358SJed Brown       ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr);
14870d644c17SKarl Rupp 
1488552f7358SJed Brown       mesh->supports[offS+offsets[q]] = p;
1489552f7358SJed Brown       ++offsets[q];
1490552f7358SJed Brown     }
1491552f7358SJed Brown   }
1492552f7358SJed Brown   ierr = PetscFree(offsets);CHKERRQ(ierr);
1493552f7358SJed Brown   PetscFunctionReturn(0);
1494552f7358SJed Brown }
1495552f7358SJed Brown 
1496552f7358SJed Brown #undef __FUNCT__
1497552f7358SJed Brown #define __FUNCT__ "DMPlexStratify"
1498552f7358SJed Brown /*@
1499552f7358SJed Brown   DMPlexStratify - The Sieve DAG for most topologies is a graded poset (http://en.wikipedia.org/wiki/Graded_poset), and
1500552f7358SJed Brown   can be illustrated by Hasse Diagram (a http://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the
1501552f7358SJed Brown   same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in
1502552f7358SJed Brown   the DAG.
1503552f7358SJed Brown 
1504552f7358SJed Brown   Not collective
1505552f7358SJed Brown 
1506552f7358SJed Brown   Input Parameter:
1507552f7358SJed Brown . mesh - The DMPlex
1508552f7358SJed Brown 
1509552f7358SJed Brown   Output Parameter:
1510552f7358SJed Brown 
1511552f7358SJed Brown   Notes:
1512552f7358SJed Brown   The normal association for the point grade is element dimension (or co-dimension). For instance, all vertices would
1513552f7358SJed Brown   have depth 0, and all edges depth 1. Likewise, all cells heights would have height 0, and all faces height 1.
1514552f7358SJed Brown 
1515552f7358SJed Brown   This should be called after all calls to DMPlexSymmetrize()
1516552f7358SJed Brown 
1517552f7358SJed Brown   Level: beginner
1518552f7358SJed Brown 
1519552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSymmetrize()
1520552f7358SJed Brown @*/
1521552f7358SJed Brown PetscErrorCode DMPlexStratify(DM dm)
1522552f7358SJed Brown {
1523aa50250dSMatthew G. Knepley   DMLabel        label;
1524552f7358SJed Brown   PetscInt       pStart, pEnd, p;
1525552f7358SJed Brown   PetscInt       numRoots = 0, numLeaves = 0;
1526552f7358SJed Brown   PetscErrorCode ierr;
1527552f7358SJed Brown 
1528552f7358SJed Brown   PetscFunctionBegin;
1529552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1530552f7358SJed Brown   ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr);
1531552f7358SJed Brown   /* Calculate depth */
1532aa50250dSMatthew G. Knepley   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
1533aa50250dSMatthew G. Knepley   ierr = DMPlexCreateLabel(dm, "depth");CHKERRQ(ierr);
1534aa50250dSMatthew G. Knepley   ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr);
1535552f7358SJed Brown   /* Initialize roots and count leaves */
1536552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
1537552f7358SJed Brown     PetscInt coneSize, supportSize;
1538552f7358SJed Brown 
1539552f7358SJed Brown     ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
1540552f7358SJed Brown     ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr);
1541552f7358SJed Brown     if (!coneSize && supportSize) {
1542552f7358SJed Brown       ++numRoots;
1543aa50250dSMatthew G. Knepley       ierr = DMLabelSetValue(label, p, 0);CHKERRQ(ierr);
1544552f7358SJed Brown     } else if (!supportSize && coneSize) {
1545552f7358SJed Brown       ++numLeaves;
1546552f7358SJed Brown     } else if (!supportSize && !coneSize) {
1547552f7358SJed Brown       /* Isolated points */
1548aa50250dSMatthew G. Knepley       ierr = DMLabelSetValue(label, p, 0);CHKERRQ(ierr);
1549552f7358SJed Brown     }
1550552f7358SJed Brown   }
1551552f7358SJed Brown   if (numRoots + numLeaves == (pEnd - pStart)) {
1552552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
1553552f7358SJed Brown       PetscInt coneSize, supportSize;
1554552f7358SJed Brown 
1555552f7358SJed Brown       ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
1556552f7358SJed Brown       ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr);
1557552f7358SJed Brown       if (!supportSize && coneSize) {
1558aa50250dSMatthew G. Knepley         ierr = DMLabelSetValue(label, p, 1);CHKERRQ(ierr);
1559552f7358SJed Brown       }
1560552f7358SJed Brown     }
1561552f7358SJed Brown   } else {
156274ef644bSMatthew G. Knepley     IS       pointIS;
156374ef644bSMatthew G. Knepley     PetscInt numPoints = 0, level = 0;
1564552f7358SJed Brown 
156574ef644bSMatthew G. Knepley     ierr = DMLabelGetStratumIS(label, level, &pointIS);CHKERRQ(ierr);
156674ef644bSMatthew G. Knepley     if (pointIS) {ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr);}
156774ef644bSMatthew G. Knepley     while (numPoints) {
156874ef644bSMatthew G. Knepley       const PetscInt *points;
156974ef644bSMatthew G. Knepley       const PetscInt  newLevel = level+1;
157074ef644bSMatthew G. Knepley 
157174ef644bSMatthew G. Knepley       ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr);
157274ef644bSMatthew G. Knepley       for (p = 0; p < numPoints; ++p) {
157374ef644bSMatthew G. Knepley         const PetscInt  point = points[p];
157474ef644bSMatthew G. Knepley         const PetscInt *support;
157574ef644bSMatthew G. Knepley         PetscInt        supportSize, s;
157674ef644bSMatthew G. Knepley 
157774ef644bSMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, point, &supportSize);CHKERRQ(ierr);
157874ef644bSMatthew G. Knepley         ierr = DMPlexGetSupport(dm, point, &support);CHKERRQ(ierr);
157974ef644bSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
158074ef644bSMatthew G. Knepley           ierr = DMLabelSetValue(label, support[s], newLevel);CHKERRQ(ierr);
1581552f7358SJed Brown         }
1582552f7358SJed Brown       }
15835edfc765SMatthew G. Knepley       ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr);
158474ef644bSMatthew G. Knepley       ++level;
158574ef644bSMatthew G. Knepley       ierr = ISDestroy(&pointIS);CHKERRQ(ierr);
158674ef644bSMatthew G. Knepley       ierr = DMLabelGetStratumIS(label, level, &pointIS);CHKERRQ(ierr);
158774ef644bSMatthew G. Knepley       if (pointIS) {ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr);}
158874ef644bSMatthew G. Knepley       else         {numPoints = 0;}
158974ef644bSMatthew G. Knepley     }
159074ef644bSMatthew G. Knepley     ierr = ISDestroy(&pointIS);CHKERRQ(ierr);
159174ef644bSMatthew G. Knepley   }
1592552f7358SJed Brown   ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr);
1593552f7358SJed Brown   PetscFunctionReturn(0);
1594552f7358SJed Brown }
1595552f7358SJed Brown 
1596552f7358SJed Brown #undef __FUNCT__
1597552f7358SJed Brown #define __FUNCT__ "DMPlexGetJoin"
1598552f7358SJed Brown /*@C
1599552f7358SJed Brown   DMPlexGetJoin - Get an array for the join of the set of points
1600552f7358SJed Brown 
1601552f7358SJed Brown   Not Collective
1602552f7358SJed Brown 
1603552f7358SJed Brown   Input Parameters:
1604552f7358SJed Brown + dm - The DMPlex object
1605552f7358SJed Brown . numPoints - The number of input points for the join
1606552f7358SJed Brown - points - The input points
1607552f7358SJed Brown 
1608552f7358SJed Brown   Output Parameters:
1609552f7358SJed Brown + numCoveredPoints - The number of points in the join
1610552f7358SJed Brown - coveredPoints - The points in the join
1611552f7358SJed Brown 
1612552f7358SJed Brown   Level: intermediate
1613552f7358SJed Brown 
1614552f7358SJed Brown   Note: Currently, this is restricted to a single level join
1615552f7358SJed Brown 
16163813dfbdSMatthew G Knepley   Fortran Notes:
16173813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
16183813dfbdSMatthew G Knepley   include petsc.h90 in your code.
16193813dfbdSMatthew G Knepley 
16203813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
16213813dfbdSMatthew G Knepley 
1622552f7358SJed Brown .keywords: mesh
1623552f7358SJed Brown .seealso: DMPlexRestoreJoin(), DMPlexGetMeet()
1624552f7358SJed Brown @*/
1625552f7358SJed Brown PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
1626552f7358SJed Brown {
1627552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
1628552f7358SJed Brown   PetscInt      *join[2];
1629552f7358SJed Brown   PetscInt       joinSize, i = 0;
1630552f7358SJed Brown   PetscInt       dof, off, p, c, m;
1631552f7358SJed Brown   PetscErrorCode ierr;
1632552f7358SJed Brown 
1633552f7358SJed Brown   PetscFunctionBegin;
1634552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1635552f7358SJed Brown   PetscValidPointer(points, 2);
1636552f7358SJed Brown   PetscValidPointer(numCoveredPoints, 3);
1637552f7358SJed Brown   PetscValidPointer(coveredPoints, 4);
1638552f7358SJed Brown   ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[0]);CHKERRQ(ierr);
1639552f7358SJed Brown   ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1]);CHKERRQ(ierr);
1640552f7358SJed Brown   /* Copy in support of first point */
1641552f7358SJed Brown   ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr);
1642552f7358SJed Brown   ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr);
1643552f7358SJed Brown   for (joinSize = 0; joinSize < dof; ++joinSize) {
1644552f7358SJed Brown     join[i][joinSize] = mesh->supports[off+joinSize];
1645552f7358SJed Brown   }
1646552f7358SJed Brown   /* Check each successive support */
1647552f7358SJed Brown   for (p = 1; p < numPoints; ++p) {
1648552f7358SJed Brown     PetscInt newJoinSize = 0;
1649552f7358SJed Brown 
1650552f7358SJed Brown     ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr);
1651552f7358SJed Brown     ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr);
1652552f7358SJed Brown     for (c = 0; c < dof; ++c) {
1653552f7358SJed Brown       const PetscInt point = mesh->supports[off+c];
1654552f7358SJed Brown 
1655552f7358SJed Brown       for (m = 0; m < joinSize; ++m) {
1656552f7358SJed Brown         if (point == join[i][m]) {
1657552f7358SJed Brown           join[1-i][newJoinSize++] = point;
1658552f7358SJed Brown           break;
1659552f7358SJed Brown         }
1660552f7358SJed Brown       }
1661552f7358SJed Brown     }
1662552f7358SJed Brown     joinSize = newJoinSize;
1663552f7358SJed Brown     i        = 1-i;
1664552f7358SJed Brown   }
1665552f7358SJed Brown   *numCoveredPoints = joinSize;
1666552f7358SJed Brown   *coveredPoints    = join[i];
1667552f7358SJed Brown   ierr              = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr);
1668552f7358SJed Brown   PetscFunctionReturn(0);
1669552f7358SJed Brown }
1670552f7358SJed Brown 
1671552f7358SJed Brown #undef __FUNCT__
1672552f7358SJed Brown #define __FUNCT__ "DMPlexRestoreJoin"
1673552f7358SJed Brown /*@C
1674552f7358SJed Brown   DMPlexRestoreJoin - Restore an array for the join of the set of points
1675552f7358SJed Brown 
1676552f7358SJed Brown   Not Collective
1677552f7358SJed Brown 
1678552f7358SJed Brown   Input Parameters:
1679552f7358SJed Brown + dm - The DMPlex object
1680552f7358SJed Brown . numPoints - The number of input points for the join
1681552f7358SJed Brown - points - The input points
1682552f7358SJed Brown 
1683552f7358SJed Brown   Output Parameters:
1684552f7358SJed Brown + numCoveredPoints - The number of points in the join
1685552f7358SJed Brown - coveredPoints - The points in the join
1686552f7358SJed Brown 
16873813dfbdSMatthew G Knepley   Fortran Notes:
16883813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
16893813dfbdSMatthew G Knepley   include petsc.h90 in your code.
16903813dfbdSMatthew G Knepley 
16913813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
16923813dfbdSMatthew G Knepley 
1693552f7358SJed Brown   Level: intermediate
1694552f7358SJed Brown 
1695552f7358SJed Brown .keywords: mesh
1696552f7358SJed Brown .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet()
1697552f7358SJed Brown @*/
1698552f7358SJed Brown PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
1699552f7358SJed Brown {
1700552f7358SJed Brown   PetscErrorCode ierr;
1701552f7358SJed Brown 
1702552f7358SJed Brown   PetscFunctionBegin;
1703552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1704d7902bd2SMatthew G. Knepley   if (points) PetscValidIntPointer(points,3);
1705d7902bd2SMatthew G. Knepley   if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4);
1706d7902bd2SMatthew G. Knepley   PetscValidPointer(coveredPoints, 5);
1707552f7358SJed Brown   ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr);
1708d7902bd2SMatthew G. Knepley   if (numCoveredPoints) *numCoveredPoints = 0;
1709552f7358SJed Brown   PetscFunctionReturn(0);
1710552f7358SJed Brown }
1711552f7358SJed Brown 
1712552f7358SJed Brown #undef __FUNCT__
1713552f7358SJed Brown #define __FUNCT__ "DMPlexGetFullJoin"
1714552f7358SJed Brown /*@C
1715552f7358SJed Brown   DMPlexGetFullJoin - Get an array for the join of the set of points
1716552f7358SJed Brown 
1717552f7358SJed Brown   Not Collective
1718552f7358SJed Brown 
1719552f7358SJed Brown   Input Parameters:
1720552f7358SJed Brown + dm - The DMPlex object
1721552f7358SJed Brown . numPoints - The number of input points for the join
1722552f7358SJed Brown - points - The input points
1723552f7358SJed Brown 
1724552f7358SJed Brown   Output Parameters:
1725552f7358SJed Brown + numCoveredPoints - The number of points in the join
1726552f7358SJed Brown - coveredPoints - The points in the join
1727552f7358SJed Brown 
17283813dfbdSMatthew G Knepley   Fortran Notes:
17293813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
17303813dfbdSMatthew G Knepley   include petsc.h90 in your code.
17313813dfbdSMatthew G Knepley 
17323813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
17333813dfbdSMatthew G Knepley 
1734552f7358SJed Brown   Level: intermediate
1735552f7358SJed Brown 
1736552f7358SJed Brown .keywords: mesh
1737552f7358SJed Brown .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet()
1738552f7358SJed Brown @*/
1739552f7358SJed Brown PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
1740552f7358SJed Brown {
1741552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
1742552f7358SJed Brown   PetscInt      *offsets, **closures;
1743552f7358SJed Brown   PetscInt      *join[2];
1744552f7358SJed Brown   PetscInt       depth = 0, maxSize, joinSize = 0, i = 0;
1745552f7358SJed Brown   PetscInt       p, d, c, m;
1746552f7358SJed Brown   PetscErrorCode ierr;
1747552f7358SJed Brown 
1748552f7358SJed Brown   PetscFunctionBegin;
1749552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1750552f7358SJed Brown   PetscValidPointer(points, 2);
1751552f7358SJed Brown   PetscValidPointer(numCoveredPoints, 3);
1752552f7358SJed Brown   PetscValidPointer(coveredPoints, 4);
1753552f7358SJed Brown 
1754552f7358SJed Brown   ierr    = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
17551795a4d1SJed Brown   ierr    = PetscCalloc1(numPoints, &closures);CHKERRQ(ierr);
1756552f7358SJed Brown   ierr    = DMGetWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr);
1757e7b80042SMatthew G. Knepley   maxSize = PetscPowInt(mesh->maxSupportSize,depth+1);
1758552f7358SJed Brown   ierr    = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[0]);CHKERRQ(ierr);
1759552f7358SJed Brown   ierr    = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[1]);CHKERRQ(ierr);
1760552f7358SJed Brown 
1761552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
1762552f7358SJed Brown     PetscInt closureSize;
1763552f7358SJed Brown 
1764552f7358SJed Brown     ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr);
17650d644c17SKarl Rupp 
1766552f7358SJed Brown     offsets[p*(depth+2)+0] = 0;
1767552f7358SJed Brown     for (d = 0; d < depth+1; ++d) {
1768552f7358SJed Brown       PetscInt pStart, pEnd, i;
1769552f7358SJed Brown 
1770552f7358SJed Brown       ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr);
1771552f7358SJed Brown       for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) {
1772552f7358SJed Brown         if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) {
1773552f7358SJed Brown           offsets[p*(depth+2)+d+1] = i;
1774552f7358SJed Brown           break;
1775552f7358SJed Brown         }
1776552f7358SJed Brown       }
1777552f7358SJed Brown       if (i == closureSize) offsets[p*(depth+2)+d+1] = i;
1778552f7358SJed Brown     }
177982f516ccSBarry Smith     if (offsets[p*(depth+2)+depth+1] != closureSize) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(depth+2)+depth+1], closureSize);
1780552f7358SJed Brown   }
1781552f7358SJed Brown   for (d = 0; d < depth+1; ++d) {
1782552f7358SJed Brown     PetscInt dof;
1783552f7358SJed Brown 
1784552f7358SJed Brown     /* Copy in support of first point */
1785552f7358SJed Brown     dof = offsets[d+1] - offsets[d];
1786552f7358SJed Brown     for (joinSize = 0; joinSize < dof; ++joinSize) {
1787552f7358SJed Brown       join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2];
1788552f7358SJed Brown     }
1789552f7358SJed Brown     /* Check each successive cone */
1790552f7358SJed Brown     for (p = 1; p < numPoints && joinSize; ++p) {
1791552f7358SJed Brown       PetscInt newJoinSize = 0;
1792552f7358SJed Brown 
1793552f7358SJed Brown       dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d];
1794552f7358SJed Brown       for (c = 0; c < dof; ++c) {
1795552f7358SJed Brown         const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2];
1796552f7358SJed Brown 
1797552f7358SJed Brown         for (m = 0; m < joinSize; ++m) {
1798552f7358SJed Brown           if (point == join[i][m]) {
1799552f7358SJed Brown             join[1-i][newJoinSize++] = point;
1800552f7358SJed Brown             break;
1801552f7358SJed Brown           }
1802552f7358SJed Brown         }
1803552f7358SJed Brown       }
1804552f7358SJed Brown       joinSize = newJoinSize;
1805552f7358SJed Brown       i        = 1-i;
1806552f7358SJed Brown     }
1807552f7358SJed Brown     if (joinSize) break;
1808552f7358SJed Brown   }
1809552f7358SJed Brown   *numCoveredPoints = joinSize;
1810552f7358SJed Brown   *coveredPoints    = join[i];
1811552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
18120298fd71SBarry Smith     ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]);CHKERRQ(ierr);
1813552f7358SJed Brown   }
1814552f7358SJed Brown   ierr = PetscFree(closures);CHKERRQ(ierr);
1815552f7358SJed Brown   ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr);
1816552f7358SJed Brown   ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr);
1817552f7358SJed Brown   PetscFunctionReturn(0);
1818552f7358SJed Brown }
1819552f7358SJed Brown 
1820552f7358SJed Brown #undef __FUNCT__
1821552f7358SJed Brown #define __FUNCT__ "DMPlexGetMeet"
1822552f7358SJed Brown /*@C
1823552f7358SJed Brown   DMPlexGetMeet - Get an array for the meet of the set of points
1824552f7358SJed Brown 
1825552f7358SJed Brown   Not Collective
1826552f7358SJed Brown 
1827552f7358SJed Brown   Input Parameters:
1828552f7358SJed Brown + dm - The DMPlex object
1829552f7358SJed Brown . numPoints - The number of input points for the meet
1830552f7358SJed Brown - points - The input points
1831552f7358SJed Brown 
1832552f7358SJed Brown   Output Parameters:
1833552f7358SJed Brown + numCoveredPoints - The number of points in the meet
1834552f7358SJed Brown - coveredPoints - The points in the meet
1835552f7358SJed Brown 
1836552f7358SJed Brown   Level: intermediate
1837552f7358SJed Brown 
1838552f7358SJed Brown   Note: Currently, this is restricted to a single level meet
1839552f7358SJed Brown 
18403813dfbdSMatthew G Knepley   Fortran Notes:
18413813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
18423813dfbdSMatthew G Knepley   include petsc.h90 in your code.
18433813dfbdSMatthew G Knepley 
18443813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
18453813dfbdSMatthew G Knepley 
1846552f7358SJed Brown .keywords: mesh
1847552f7358SJed Brown .seealso: DMPlexRestoreMeet(), DMPlexGetJoin()
1848552f7358SJed Brown @*/
1849552f7358SJed Brown PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints)
1850552f7358SJed Brown {
1851552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
1852552f7358SJed Brown   PetscInt      *meet[2];
1853552f7358SJed Brown   PetscInt       meetSize, i = 0;
1854552f7358SJed Brown   PetscInt       dof, off, p, c, m;
1855552f7358SJed Brown   PetscErrorCode ierr;
1856552f7358SJed Brown 
1857552f7358SJed Brown   PetscFunctionBegin;
1858552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1859552f7358SJed Brown   PetscValidPointer(points, 2);
1860552f7358SJed Brown   PetscValidPointer(numCoveringPoints, 3);
1861552f7358SJed Brown   PetscValidPointer(coveringPoints, 4);
1862552f7358SJed Brown   ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[0]);CHKERRQ(ierr);
1863552f7358SJed Brown   ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1]);CHKERRQ(ierr);
1864552f7358SJed Brown   /* Copy in cone of first point */
1865552f7358SJed Brown   ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr);
1866552f7358SJed Brown   ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr);
1867552f7358SJed Brown   for (meetSize = 0; meetSize < dof; ++meetSize) {
1868552f7358SJed Brown     meet[i][meetSize] = mesh->cones[off+meetSize];
1869552f7358SJed Brown   }
1870552f7358SJed Brown   /* Check each successive cone */
1871552f7358SJed Brown   for (p = 1; p < numPoints; ++p) {
1872552f7358SJed Brown     PetscInt newMeetSize = 0;
1873552f7358SJed Brown 
1874552f7358SJed Brown     ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr);
1875552f7358SJed Brown     ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr);
1876552f7358SJed Brown     for (c = 0; c < dof; ++c) {
1877552f7358SJed Brown       const PetscInt point = mesh->cones[off+c];
1878552f7358SJed Brown 
1879552f7358SJed Brown       for (m = 0; m < meetSize; ++m) {
1880552f7358SJed Brown         if (point == meet[i][m]) {
1881552f7358SJed Brown           meet[1-i][newMeetSize++] = point;
1882552f7358SJed Brown           break;
1883552f7358SJed Brown         }
1884552f7358SJed Brown       }
1885552f7358SJed Brown     }
1886552f7358SJed Brown     meetSize = newMeetSize;
1887552f7358SJed Brown     i        = 1-i;
1888552f7358SJed Brown   }
1889552f7358SJed Brown   *numCoveringPoints = meetSize;
1890552f7358SJed Brown   *coveringPoints    = meet[i];
1891552f7358SJed Brown   ierr               = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr);
1892552f7358SJed Brown   PetscFunctionReturn(0);
1893552f7358SJed Brown }
1894552f7358SJed Brown 
1895552f7358SJed Brown #undef __FUNCT__
1896552f7358SJed Brown #define __FUNCT__ "DMPlexRestoreMeet"
1897552f7358SJed Brown /*@C
1898552f7358SJed Brown   DMPlexRestoreMeet - Restore an array for the meet of the set of points
1899552f7358SJed Brown 
1900552f7358SJed Brown   Not Collective
1901552f7358SJed Brown 
1902552f7358SJed Brown   Input Parameters:
1903552f7358SJed Brown + dm - The DMPlex object
1904552f7358SJed Brown . numPoints - The number of input points for the meet
1905552f7358SJed Brown - points - The input points
1906552f7358SJed Brown 
1907552f7358SJed Brown   Output Parameters:
1908552f7358SJed Brown + numCoveredPoints - The number of points in the meet
1909552f7358SJed Brown - coveredPoints - The points in the meet
1910552f7358SJed Brown 
1911552f7358SJed Brown   Level: intermediate
1912552f7358SJed Brown 
19133813dfbdSMatthew G Knepley   Fortran Notes:
19143813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
19153813dfbdSMatthew G Knepley   include petsc.h90 in your code.
19163813dfbdSMatthew G Knepley 
19173813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
19183813dfbdSMatthew G Knepley 
1919552f7358SJed Brown .keywords: mesh
1920552f7358SJed Brown .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin()
1921552f7358SJed Brown @*/
1922552f7358SJed Brown PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
1923552f7358SJed Brown {
1924552f7358SJed Brown   PetscErrorCode ierr;
1925552f7358SJed Brown 
1926552f7358SJed Brown   PetscFunctionBegin;
1927552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1928d7902bd2SMatthew G. Knepley   if (points) PetscValidIntPointer(points,3);
1929d7902bd2SMatthew G. Knepley   if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4);
1930d7902bd2SMatthew G. Knepley   PetscValidPointer(coveredPoints,5);
1931552f7358SJed Brown   ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr);
1932d7902bd2SMatthew G. Knepley   if (numCoveredPoints) *numCoveredPoints = 0;
1933552f7358SJed Brown   PetscFunctionReturn(0);
1934552f7358SJed Brown }
1935552f7358SJed Brown 
1936552f7358SJed Brown #undef __FUNCT__
1937552f7358SJed Brown #define __FUNCT__ "DMPlexGetFullMeet"
1938552f7358SJed Brown /*@C
1939552f7358SJed Brown   DMPlexGetFullMeet - Get an array for the meet of the set of points
1940552f7358SJed Brown 
1941552f7358SJed Brown   Not Collective
1942552f7358SJed Brown 
1943552f7358SJed Brown   Input Parameters:
1944552f7358SJed Brown + dm - The DMPlex object
1945552f7358SJed Brown . numPoints - The number of input points for the meet
1946552f7358SJed Brown - points - The input points
1947552f7358SJed Brown 
1948552f7358SJed Brown   Output Parameters:
1949552f7358SJed Brown + numCoveredPoints - The number of points in the meet
1950552f7358SJed Brown - coveredPoints - The points in the meet
1951552f7358SJed Brown 
1952552f7358SJed Brown   Level: intermediate
1953552f7358SJed Brown 
19543813dfbdSMatthew G Knepley   Fortran Notes:
19553813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
19563813dfbdSMatthew G Knepley   include petsc.h90 in your code.
19573813dfbdSMatthew G Knepley 
19583813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
19593813dfbdSMatthew G Knepley 
1960552f7358SJed Brown .keywords: mesh
1961552f7358SJed Brown .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin()
1962552f7358SJed Brown @*/
1963552f7358SJed Brown PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
1964552f7358SJed Brown {
1965552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
1966552f7358SJed Brown   PetscInt      *offsets, **closures;
1967552f7358SJed Brown   PetscInt      *meet[2];
1968552f7358SJed Brown   PetscInt       height = 0, maxSize, meetSize = 0, i = 0;
1969552f7358SJed Brown   PetscInt       p, h, c, m;
1970552f7358SJed Brown   PetscErrorCode ierr;
1971552f7358SJed Brown 
1972552f7358SJed Brown   PetscFunctionBegin;
1973552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1974552f7358SJed Brown   PetscValidPointer(points, 2);
1975552f7358SJed Brown   PetscValidPointer(numCoveredPoints, 3);
1976552f7358SJed Brown   PetscValidPointer(coveredPoints, 4);
1977552f7358SJed Brown 
1978552f7358SJed Brown   ierr    = DMPlexGetDepth(dm, &height);CHKERRQ(ierr);
1979785e854fSJed Brown   ierr    = PetscMalloc1(numPoints, &closures);CHKERRQ(ierr);
1980552f7358SJed Brown   ierr    = DMGetWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr);
1981e7b80042SMatthew G. Knepley   maxSize = PetscPowInt(mesh->maxConeSize,height+1);
1982552f7358SJed Brown   ierr    = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[0]);CHKERRQ(ierr);
1983552f7358SJed Brown   ierr    = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[1]);CHKERRQ(ierr);
1984552f7358SJed Brown 
1985552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
1986552f7358SJed Brown     PetscInt closureSize;
1987552f7358SJed Brown 
1988552f7358SJed Brown     ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr);
19890d644c17SKarl Rupp 
1990552f7358SJed Brown     offsets[p*(height+2)+0] = 0;
1991552f7358SJed Brown     for (h = 0; h < height+1; ++h) {
1992552f7358SJed Brown       PetscInt pStart, pEnd, i;
1993552f7358SJed Brown 
1994552f7358SJed Brown       ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr);
1995552f7358SJed Brown       for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) {
1996552f7358SJed Brown         if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) {
1997552f7358SJed Brown           offsets[p*(height+2)+h+1] = i;
1998552f7358SJed Brown           break;
1999552f7358SJed Brown         }
2000552f7358SJed Brown       }
2001552f7358SJed Brown       if (i == closureSize) offsets[p*(height+2)+h+1] = i;
2002552f7358SJed Brown     }
200382f516ccSBarry Smith     if (offsets[p*(height+2)+height+1] != closureSize) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(height+2)+height+1], closureSize);
2004552f7358SJed Brown   }
2005552f7358SJed Brown   for (h = 0; h < height+1; ++h) {
2006552f7358SJed Brown     PetscInt dof;
2007552f7358SJed Brown 
2008552f7358SJed Brown     /* Copy in cone of first point */
2009552f7358SJed Brown     dof = offsets[h+1] - offsets[h];
2010552f7358SJed Brown     for (meetSize = 0; meetSize < dof; ++meetSize) {
2011552f7358SJed Brown       meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2];
2012552f7358SJed Brown     }
2013552f7358SJed Brown     /* Check each successive cone */
2014552f7358SJed Brown     for (p = 1; p < numPoints && meetSize; ++p) {
2015552f7358SJed Brown       PetscInt newMeetSize = 0;
2016552f7358SJed Brown 
2017552f7358SJed Brown       dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h];
2018552f7358SJed Brown       for (c = 0; c < dof; ++c) {
2019552f7358SJed Brown         const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2];
2020552f7358SJed Brown 
2021552f7358SJed Brown         for (m = 0; m < meetSize; ++m) {
2022552f7358SJed Brown           if (point == meet[i][m]) {
2023552f7358SJed Brown             meet[1-i][newMeetSize++] = point;
2024552f7358SJed Brown             break;
2025552f7358SJed Brown           }
2026552f7358SJed Brown         }
2027552f7358SJed Brown       }
2028552f7358SJed Brown       meetSize = newMeetSize;
2029552f7358SJed Brown       i        = 1-i;
2030552f7358SJed Brown     }
2031552f7358SJed Brown     if (meetSize) break;
2032552f7358SJed Brown   }
2033552f7358SJed Brown   *numCoveredPoints = meetSize;
2034552f7358SJed Brown   *coveredPoints    = meet[i];
2035552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
20360298fd71SBarry Smith     ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]);CHKERRQ(ierr);
2037552f7358SJed Brown   }
2038552f7358SJed Brown   ierr = PetscFree(closures);CHKERRQ(ierr);
2039552f7358SJed Brown   ierr = DMRestoreWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr);
2040552f7358SJed Brown   ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr);
2041552f7358SJed Brown   PetscFunctionReturn(0);
2042552f7358SJed Brown }
2043552f7358SJed Brown 
2044552f7358SJed Brown #undef __FUNCT__
20454e3744c5SMatthew G. Knepley #define __FUNCT__ "DMPlexEqual"
20464e3744c5SMatthew G. Knepley /*@C
20474e3744c5SMatthew G. Knepley   DMPlexEqual - Determine if two DMs have the same topology
20484e3744c5SMatthew G. Knepley 
20494e3744c5SMatthew G. Knepley   Not Collective
20504e3744c5SMatthew G. Knepley 
20514e3744c5SMatthew G. Knepley   Input Parameters:
20524e3744c5SMatthew G. Knepley + dmA - A DMPlex object
20534e3744c5SMatthew G. Knepley - dmB - A DMPlex object
20544e3744c5SMatthew G. Knepley 
20554e3744c5SMatthew G. Knepley   Output Parameters:
20564e3744c5SMatthew G. Knepley . equal - PETSC_TRUE if the topologies are identical
20574e3744c5SMatthew G. Knepley 
20584e3744c5SMatthew G. Knepley   Level: intermediate
20594e3744c5SMatthew G. Knepley 
20604e3744c5SMatthew G. Knepley   Notes:
20614e3744c5SMatthew G. Knepley   We are not solving graph isomorphism, so we do not permutation.
20624e3744c5SMatthew G. Knepley 
20634e3744c5SMatthew G. Knepley .keywords: mesh
20644e3744c5SMatthew G. Knepley .seealso: DMPlexGetCone()
20654e3744c5SMatthew G. Knepley @*/
20664e3744c5SMatthew G. Knepley PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal)
20674e3744c5SMatthew G. Knepley {
20684e3744c5SMatthew G. Knepley   PetscInt       depth, depthB, pStart, pEnd, pStartB, pEndB, p;
20694e3744c5SMatthew G. Knepley   PetscErrorCode ierr;
20704e3744c5SMatthew G. Knepley 
20714e3744c5SMatthew G. Knepley   PetscFunctionBegin;
20724e3744c5SMatthew G. Knepley   PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
20734e3744c5SMatthew G. Knepley   PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
20744e3744c5SMatthew G. Knepley   PetscValidPointer(equal, 3);
20754e3744c5SMatthew G. Knepley 
20764e3744c5SMatthew G. Knepley   *equal = PETSC_FALSE;
20774e3744c5SMatthew G. Knepley   ierr = DMPlexGetDepth(dmA, &depth);CHKERRQ(ierr);
20784e3744c5SMatthew G. Knepley   ierr = DMPlexGetDepth(dmB, &depthB);CHKERRQ(ierr);
20794e3744c5SMatthew G. Knepley   if (depth != depthB) PetscFunctionReturn(0);
20804e3744c5SMatthew G. Knepley   ierr = DMPlexGetChart(dmA, &pStart,  &pEnd);CHKERRQ(ierr);
20814e3744c5SMatthew G. Knepley   ierr = DMPlexGetChart(dmB, &pStartB, &pEndB);CHKERRQ(ierr);
20824e3744c5SMatthew G. Knepley   if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(0);
20834e3744c5SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
20844e3744c5SMatthew G. Knepley     const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB;
20854e3744c5SMatthew G. Knepley     PetscInt        coneSize, coneSizeB, c, supportSize, supportSizeB, s;
20864e3744c5SMatthew G. Knepley 
20874e3744c5SMatthew G. Knepley     ierr = DMPlexGetConeSize(dmA, p, &coneSize);CHKERRQ(ierr);
20884e3744c5SMatthew G. Knepley     ierr = DMPlexGetCone(dmA, p, &cone);CHKERRQ(ierr);
20894e3744c5SMatthew G. Knepley     ierr = DMPlexGetConeOrientation(dmA, p, &ornt);CHKERRQ(ierr);
20904e3744c5SMatthew G. Knepley     ierr = DMPlexGetConeSize(dmB, p, &coneSizeB);CHKERRQ(ierr);
20914e3744c5SMatthew G. Knepley     ierr = DMPlexGetCone(dmB, p, &coneB);CHKERRQ(ierr);
20924e3744c5SMatthew G. Knepley     ierr = DMPlexGetConeOrientation(dmB, p, &orntB);CHKERRQ(ierr);
20934e3744c5SMatthew G. Knepley     if (coneSize != coneSizeB) PetscFunctionReturn(0);
20944e3744c5SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
20954e3744c5SMatthew G. Knepley       if (cone[c] != coneB[c]) PetscFunctionReturn(0);
20964e3744c5SMatthew G. Knepley       if (ornt[c] != orntB[c]) PetscFunctionReturn(0);
20974e3744c5SMatthew G. Knepley     }
20984e3744c5SMatthew G. Knepley     ierr = DMPlexGetSupportSize(dmA, p, &supportSize);CHKERRQ(ierr);
20994e3744c5SMatthew G. Knepley     ierr = DMPlexGetSupport(dmA, p, &support);CHKERRQ(ierr);
21004e3744c5SMatthew G. Knepley     ierr = DMPlexGetSupportSize(dmB, p, &supportSizeB);CHKERRQ(ierr);
21014e3744c5SMatthew G. Knepley     ierr = DMPlexGetSupport(dmB, p, &supportB);CHKERRQ(ierr);
21024e3744c5SMatthew G. Knepley     if (supportSize != supportSizeB) PetscFunctionReturn(0);
21034e3744c5SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
21044e3744c5SMatthew G. Knepley       if (support[s] != supportB[s]) PetscFunctionReturn(0);
21054e3744c5SMatthew G. Knepley     }
21064e3744c5SMatthew G. Knepley   }
21074e3744c5SMatthew G. Knepley   *equal = PETSC_TRUE;
21084e3744c5SMatthew G. Knepley   PetscFunctionReturn(0);
21094e3744c5SMatthew G. Knepley }
21104e3744c5SMatthew G. Knepley 
21114e3744c5SMatthew G. Knepley #undef __FUNCT__
211218ad9376SMatthew G. Knepley #define __FUNCT__ "DMPlexGetNumFaceVertices"
211318ad9376SMatthew G. Knepley PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices)
2114a6dfd86eSKarl Rupp {
211582f516ccSBarry Smith   MPI_Comm       comm;
2116552f7358SJed Brown   PetscErrorCode ierr;
2117552f7358SJed Brown 
2118552f7358SJed Brown   PetscFunctionBegin;
211982f516ccSBarry Smith   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
2120552f7358SJed Brown   PetscValidPointer(numFaceVertices,3);
2121552f7358SJed Brown   switch (cellDim) {
2122552f7358SJed Brown   case 0:
2123552f7358SJed Brown     *numFaceVertices = 0;
2124552f7358SJed Brown     break;
2125552f7358SJed Brown   case 1:
2126552f7358SJed Brown     *numFaceVertices = 1;
2127552f7358SJed Brown     break;
2128552f7358SJed Brown   case 2:
2129552f7358SJed Brown     switch (numCorners) {
213019436ca2SJed Brown     case 3: /* triangle */
213119436ca2SJed Brown       *numFaceVertices = 2; /* Edge has 2 vertices */
2132552f7358SJed Brown       break;
213319436ca2SJed Brown     case 4: /* quadrilateral */
213419436ca2SJed Brown       *numFaceVertices = 2; /* Edge has 2 vertices */
2135552f7358SJed Brown       break;
213619436ca2SJed Brown     case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */
213719436ca2SJed Brown       *numFaceVertices = 3; /* Edge has 3 vertices */
2138552f7358SJed Brown       break;
213919436ca2SJed Brown     case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */
214019436ca2SJed Brown       *numFaceVertices = 3; /* Edge has 3 vertices */
2141552f7358SJed Brown       break;
2142552f7358SJed Brown     default:
2143552f7358SJed Brown       SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim);
2144552f7358SJed Brown     }
2145552f7358SJed Brown     break;
2146552f7358SJed Brown   case 3:
2147552f7358SJed Brown     switch (numCorners) {
214819436ca2SJed Brown     case 4: /* tetradehdron */
214919436ca2SJed Brown       *numFaceVertices = 3; /* Face has 3 vertices */
2150552f7358SJed Brown       break;
215119436ca2SJed Brown     case 6: /* tet cohesive cells */
215219436ca2SJed Brown       *numFaceVertices = 4; /* Face has 4 vertices */
2153552f7358SJed Brown       break;
215419436ca2SJed Brown     case 8: /* hexahedron */
215519436ca2SJed Brown       *numFaceVertices = 4; /* Face has 4 vertices */
2156552f7358SJed Brown       break;
215719436ca2SJed Brown     case 9: /* tet cohesive Lagrange cells */
215819436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
2159552f7358SJed Brown       break;
216019436ca2SJed Brown     case 10: /* quadratic tetrahedron */
216119436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
2162552f7358SJed Brown       break;
216319436ca2SJed Brown     case 12: /* hex cohesive Lagrange cells */
216419436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
2165552f7358SJed Brown       break;
216619436ca2SJed Brown     case 18: /* quadratic tet cohesive Lagrange cells */
216719436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
2168552f7358SJed Brown       break;
216919436ca2SJed Brown     case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */
217019436ca2SJed Brown       *numFaceVertices = 9; /* Face has 9 vertices */
2171552f7358SJed Brown       break;
2172552f7358SJed Brown     default:
2173552f7358SJed Brown       SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim);
2174552f7358SJed Brown     }
2175552f7358SJed Brown     break;
2176552f7358SJed Brown   default:
2177552f7358SJed Brown     SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %d", cellDim);
2178552f7358SJed Brown   }
2179552f7358SJed Brown   PetscFunctionReturn(0);
2180552f7358SJed Brown }
2181552f7358SJed Brown 
2182552f7358SJed Brown #undef __FUNCT__
2183d27a0f52SMatthew G. Knepley #define __FUNCT__ "DMPlexOrient"
2184d27a0f52SMatthew G. Knepley /* Trys to give the mesh a consistent orientation */
2185d27a0f52SMatthew G. Knepley PetscErrorCode DMPlexOrient(DM dm)
2186d27a0f52SMatthew G. Knepley {
2187a1b4d4a2SMatthew G. Knepley   PetscBT        seenCells, flippedCells, seenFaces;
2188a1b4d4a2SMatthew G. Knepley   PetscInt      *faceFIFO, fTop, fBottom;
2189a1b4d4a2SMatthew G. Knepley   PetscInt       dim, h, cStart, cEnd, c, fStart, fEnd, face, maxConeSize, *revcone, *revconeO;
2190d27a0f52SMatthew G. Knepley   PetscErrorCode ierr;
2191d27a0f52SMatthew G. Knepley 
2192d27a0f52SMatthew G. Knepley   PetscFunctionBegin;
2193d27a0f52SMatthew G. Knepley   /* Truth Table
2194d27a0f52SMatthew G. Knepley      mismatch    flips   do action   mismatch   flipA ^ flipB   action
2195d27a0f52SMatthew G. Knepley          F       0 flips     no         F             F           F
2196d27a0f52SMatthew G. Knepley          F       1 flip      yes        F             T           T
2197d27a0f52SMatthew G. Knepley          F       2 flips     no         T             F           T
2198d27a0f52SMatthew G. Knepley          T       0 flips     yes        T             T           F
2199d27a0f52SMatthew G. Knepley          T       1 flip      no
2200d27a0f52SMatthew G. Knepley          T       2 flips     yes
2201d27a0f52SMatthew G. Knepley   */
2202a1b4d4a2SMatthew G. Knepley   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
2203d27a0f52SMatthew G. Knepley   ierr = DMPlexGetVTKCellHeight(dm, &h);CHKERRQ(ierr);
2204a1b4d4a2SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, h,   &cStart, &cEnd);CHKERRQ(ierr);
2205d27a0f52SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, h+1, &fStart, &fEnd);CHKERRQ(ierr);
2206a1b4d4a2SMatthew G. Knepley   ierr = PetscBTCreate(cEnd - cStart, &seenCells);CHKERRQ(ierr);
2207a1b4d4a2SMatthew G. Knepley   ierr = PetscBTMemzero(cEnd - cStart, seenCells);CHKERRQ(ierr);
2208a1b4d4a2SMatthew G. Knepley   ierr = PetscBTCreate(cEnd - cStart, &flippedCells);CHKERRQ(ierr);
2209a1b4d4a2SMatthew G. Knepley   ierr = PetscBTMemzero(cEnd - cStart, flippedCells);CHKERRQ(ierr);
2210a1b4d4a2SMatthew G. Knepley   ierr = PetscBTCreate(fEnd - fStart, &seenFaces);CHKERRQ(ierr);
2211a1b4d4a2SMatthew G. Knepley   ierr = PetscBTMemzero(fEnd - fStart, seenFaces);CHKERRQ(ierr);
2212785e854fSJed Brown   ierr = PetscMalloc1((fEnd - fStart), &faceFIFO);CHKERRQ(ierr);
2213a1b4d4a2SMatthew G. Knepley   fTop = fBottom = 0;
2214a1b4d4a2SMatthew G. Knepley   /* Initialize FIFO with first cell */
2215defeeaeaSMatthew G. Knepley   if (cEnd > cStart) {
2216a1b4d4a2SMatthew G. Knepley     const PetscInt *cone;
2217a1b4d4a2SMatthew G. Knepley     PetscInt        coneSize;
2218a1b4d4a2SMatthew G. Knepley 
2219a1b4d4a2SMatthew G. Knepley     ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr);
2220a1b4d4a2SMatthew G. Knepley     ierr = DMPlexGetCone(dm, cStart, &cone);CHKERRQ(ierr);
2221a1b4d4a2SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
2222a1b4d4a2SMatthew G. Knepley       faceFIFO[fBottom++] = cone[c];
2223a1b4d4a2SMatthew G. Knepley       ierr = PetscBTSet(seenFaces, cone[c]-fStart);CHKERRQ(ierr);
2224a1b4d4a2SMatthew G. Knepley     }
2225a1b4d4a2SMatthew G. Knepley   }
2226a1b4d4a2SMatthew G. Knepley   /* Consider each face in FIFO */
2227a1b4d4a2SMatthew G. Knepley   while (fTop < fBottom) {
2228d27a0f52SMatthew G. Knepley     const PetscInt *support, *coneA, *coneB, *coneOA, *coneOB;
2229a1b4d4a2SMatthew G. Knepley     PetscInt        supportSize, coneSizeA, coneSizeB, posA = -1, posB = -1;
2230d27a0f52SMatthew G. Knepley     PetscInt        seenA, flippedA, seenB, flippedB, mismatch;
2231d27a0f52SMatthew G. Knepley 
2232a1b4d4a2SMatthew G. Knepley     face = faceFIFO[fTop++];
2233a1b4d4a2SMatthew G. Knepley     ierr = DMPlexGetSupportSize(dm, face, &supportSize);CHKERRQ(ierr);
2234a1b4d4a2SMatthew G. Knepley     ierr = DMPlexGetSupport(dm, face, &support);CHKERRQ(ierr);
2235d27a0f52SMatthew G. Knepley     if (supportSize < 2) continue;
2236d27a0f52SMatthew G. Knepley     if (supportSize != 2) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Faces should separate only two cells, not %d", supportSize);
2237a1b4d4a2SMatthew G. Knepley     seenA    = PetscBTLookup(seenCells,    support[0]-cStart);
223886cff514SMatthew G. Knepley     flippedA = PetscBTLookup(flippedCells, support[0]-cStart) ? 1 : 0;
2239a1b4d4a2SMatthew G. Knepley     seenB    = PetscBTLookup(seenCells,    support[1]-cStart);
224086cff514SMatthew G. Knepley     flippedB = PetscBTLookup(flippedCells, support[1]-cStart) ? 1 : 0;
2241d27a0f52SMatthew G. Knepley 
2242d27a0f52SMatthew G. Knepley     ierr = DMPlexGetConeSize(dm, support[0], &coneSizeA);CHKERRQ(ierr);
2243d27a0f52SMatthew G. Knepley     ierr = DMPlexGetConeSize(dm, support[1], &coneSizeB);CHKERRQ(ierr);
2244d27a0f52SMatthew G. Knepley     ierr = DMPlexGetCone(dm, support[0], &coneA);CHKERRQ(ierr);
2245d27a0f52SMatthew G. Knepley     ierr = DMPlexGetCone(dm, support[1], &coneB);CHKERRQ(ierr);
2246d27a0f52SMatthew G. Knepley     ierr = DMPlexGetConeOrientation(dm, support[0], &coneOA);CHKERRQ(ierr);
2247d27a0f52SMatthew G. Knepley     ierr = DMPlexGetConeOrientation(dm, support[1], &coneOB);CHKERRQ(ierr);
2248a1b4d4a2SMatthew G. Knepley     for (c = 0; c < coneSizeA; ++c) {
2249a1b4d4a2SMatthew G. Knepley       if (!PetscBTLookup(seenFaces, coneA[c]-fStart)) {
2250a1b4d4a2SMatthew G. Knepley         faceFIFO[fBottom++] = coneA[c];
2251a1b4d4a2SMatthew G. Knepley         ierr = PetscBTSet(seenFaces, coneA[c]-fStart);CHKERRQ(ierr);
2252a1b4d4a2SMatthew G. Knepley       }
2253a1b4d4a2SMatthew G. Knepley       if (coneA[c] == face) posA = c;
2254a1b4d4a2SMatthew G. Knepley       if (fBottom > fEnd-fStart) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Face %d was pushed exceeding capacity %d > %d", coneA[c], fBottom, fEnd-fStart);
2255a1b4d4a2SMatthew G. Knepley     }
2256a1b4d4a2SMatthew G. Knepley     if (posA < 0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %d could not be located in cell %d", face, support[0]);
2257a1b4d4a2SMatthew G. Knepley     for (c = 0; c < coneSizeB; ++c) {
2258a1b4d4a2SMatthew G. Knepley       if (!PetscBTLookup(seenFaces, coneB[c]-fStart)) {
2259a1b4d4a2SMatthew G. Knepley         faceFIFO[fBottom++] = coneB[c];
2260a1b4d4a2SMatthew G. Knepley         ierr = PetscBTSet(seenFaces, coneB[c]-fStart);CHKERRQ(ierr);
2261a1b4d4a2SMatthew G. Knepley       }
2262a1b4d4a2SMatthew G. Knepley       if (coneB[c] == face) posB = c;
2263a1b4d4a2SMatthew G. Knepley       if (fBottom > fEnd-fStart) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Face %d was pushed exceeding capacity %d > %d", coneA[c], fBottom, fEnd-fStart);
2264a1b4d4a2SMatthew G. Knepley     }
2265a1b4d4a2SMatthew G. Knepley     if (posB < 0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %d could not be located in cell %d", face, support[1]);
2266d27a0f52SMatthew G. Knepley 
2267d27a0f52SMatthew G. Knepley     if (dim == 1) {
2268d27a0f52SMatthew G. Knepley       mismatch = posA == posB;
2269d27a0f52SMatthew G. Knepley     } else {
2270d27a0f52SMatthew G. Knepley       mismatch = coneOA[posA] == coneOB[posB];
2271d27a0f52SMatthew G. Knepley     }
2272d27a0f52SMatthew G. Knepley 
2273d27a0f52SMatthew G. Knepley     if (mismatch ^ (flippedA ^ flippedB)) {
2274d27a0f52SMatthew G. Knepley       if (seenA && seenB) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Previously seen cells %d and %d do not match: Fault mesh is non-orientable", support[0], support[1]);
2275d27a0f52SMatthew G. Knepley       if (!seenA && !flippedA) {
2276a1b4d4a2SMatthew G. Knepley         ierr = PetscBTSet(flippedCells, support[0]-cStart);CHKERRQ(ierr);
2277d27a0f52SMatthew G. Knepley       } else if (!seenB && !flippedB) {
2278a1b4d4a2SMatthew G. Knepley         ierr = PetscBTSet(flippedCells, support[1]-cStart);CHKERRQ(ierr);
2279d27a0f52SMatthew G. Knepley       } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Inconsistent mesh orientation: Fault mesh is non-orientable");
228086cff514SMatthew G. Knepley     } else if (mismatch && flippedA && flippedB) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Attempt to flip already flipped cell: Fault mesh is non-orientable");
2281a1b4d4a2SMatthew G. Knepley     ierr = PetscBTSet(seenCells, support[0]-cStart);CHKERRQ(ierr);
2282a1b4d4a2SMatthew G. Knepley     ierr = PetscBTSet(seenCells, support[1]-cStart);CHKERRQ(ierr);
2283d27a0f52SMatthew G. Knepley   }
2284fedde076SMatthew G. Knepley   /* Now all subdomains are oriented, but we need a consistent parallel orientation */
2285fedde076SMatthew G. Knepley   {
2286fedde076SMatthew G. Knepley     /* Find a representative face (edge) separating pairs of procs */
2287fedde076SMatthew G. Knepley     PetscSF            sf;
2288fedde076SMatthew G. Knepley     const PetscInt    *lpoints;
2289fedde076SMatthew G. Knepley     const PetscSFNode *rpoints;
2290*13048561SMatthew G. Knepley     PetscInt          *neighbors, *nranks;
2291fedde076SMatthew G. Knepley     PetscInt           numLeaves, numRoots, numNeighbors = 0, l, n;
2292a1b4d4a2SMatthew G. Knepley 
2293fedde076SMatthew G. Knepley     ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr);
2294fedde076SMatthew G. Knepley     ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &lpoints, &rpoints);CHKERRQ(ierr);
2295fedde076SMatthew G. Knepley     if (numLeaves >= 0) {
229662ad4a6aSMatthew G. Knepley       const PetscInt *cone, *ornt, *support;
229762ad4a6aSMatthew G. Knepley       PetscInt        coneSize, supportSize;
229862ad4a6aSMatthew G. Knepley       int            *rornt, *lornt; /* PetscSF cannot handle smaller than int */
2299*13048561SMatthew G. Knepley       PetscBool      *match, flipped = PETSC_FALSE;
230062ad4a6aSMatthew G. Knepley 
2301fedde076SMatthew G. Knepley       ierr = PetscMalloc1(numLeaves,&neighbors);CHKERRQ(ierr);
2302fedde076SMatthew G. Knepley       /* I know this is p^2 time in general, but for bounded degree its alright */
2303fedde076SMatthew G. Knepley       for (l = 0; l < numLeaves; ++l) {
2304fedde076SMatthew G. Knepley         const PetscInt face = lpoints[l];
2305fedde076SMatthew G. Knepley         if ((face >= fStart) && (face < fEnd)) {
2306fedde076SMatthew G. Knepley           const PetscInt rank = rpoints[l].rank;
2307fedde076SMatthew G. Knepley           for (n = 0; n < numNeighbors; ++n) if (rank == rpoints[neighbors[n]].rank) break;
2308fedde076SMatthew G. Knepley           if (n >= numNeighbors) {
2309fedde076SMatthew G. Knepley             PetscInt supportSize;
2310fedde076SMatthew G. Knepley             ierr = DMPlexGetSupportSize(dm, face, &supportSize);CHKERRQ(ierr);
2311fedde076SMatthew G. Knepley             if (supportSize != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Boundary faces should see one cell, not %d", supportSize);
2312fedde076SMatthew G. Knepley             neighbors[numNeighbors++] = l;
2313fedde076SMatthew G. Knepley           }
2314fedde076SMatthew G. Knepley         }
2315fedde076SMatthew G. Knepley       }
2316*13048561SMatthew G. Knepley       ierr = PetscCalloc4(numNeighbors,&match,numNeighbors,&nranks,numRoots,&rornt,numRoots,&lornt);CHKERRQ(ierr);
2317fedde076SMatthew G. Knepley       for (face = fStart; face < fEnd; ++face) {
2318fedde076SMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, face, &supportSize);CHKERRQ(ierr);
2319fedde076SMatthew G. Knepley         if (supportSize != 1) continue;
2320fedde076SMatthew G. Knepley         ierr = DMPlexGetSupport(dm, face, &support);CHKERRQ(ierr);
2321fedde076SMatthew G. Knepley 
2322fedde076SMatthew G. Knepley         ierr = DMPlexGetCone(dm, support[0], &cone);CHKERRQ(ierr);
232362ad4a6aSMatthew G. Knepley         ierr = DMPlexGetConeSize(dm, support[0], &coneSize);CHKERRQ(ierr);
2324fedde076SMatthew G. Knepley         ierr = DMPlexGetConeOrientation(dm, support[0], &ornt);CHKERRQ(ierr);
2325fedde076SMatthew G. Knepley         for (c = 0; c < coneSize; ++c) if (cone[c] == face) break;
23265b7033fcSMatthew G. Knepley         if (dim == 1) {
23275b7033fcSMatthew G. Knepley           /* Use cone position instead, shifted to -1 or 1 */
23285b7033fcSMatthew G. Knepley           rornt[face] = c*2-1;
23295b7033fcSMatthew G. Knepley         } else {
2330fedde076SMatthew G. Knepley           if (PetscBTLookup(flippedCells, support[0]-cStart)) rornt[face] = ornt[c] < 0 ? -1 :  1;
2331fedde076SMatthew G. Knepley           else                                                rornt[face] = ornt[c] < 0 ?  1 : -1;
2332fedde076SMatthew G. Knepley         }
23335b7033fcSMatthew G. Knepley       }
2334fedde076SMatthew G. Knepley       /* Mark each edge with match or nomatch */
2335fedde076SMatthew G. Knepley       ierr = PetscSFBcastBegin(sf, MPI_INT, rornt, lornt);CHKERRQ(ierr);
2336fedde076SMatthew G. Knepley       ierr = PetscSFBcastEnd(sf, MPI_INT, rornt, lornt);CHKERRQ(ierr);
2337fedde076SMatthew G. Knepley       for (n = 0; n < numNeighbors; ++n) {
2338fedde076SMatthew G. Knepley         const PetscInt face = lpoints[neighbors[n]];
2339fedde076SMatthew G. Knepley 
2340*13048561SMatthew G. Knepley         if (rornt[face]*lornt[face] < 0) match[n] = PETSC_TRUE;
2341*13048561SMatthew G. Knepley         else                             match[n] = PETSC_FALSE;
2342*13048561SMatthew G. Knepley         nranks[n] = rpoints[neighbors[n]].rank;
2343fedde076SMatthew G. Knepley       }
2344*13048561SMatthew G. Knepley       /* Collect the graph on 0 */
2345*13048561SMatthew G. Knepley       {
2346*13048561SMatthew G. Knepley         MPI_Comm     comm = PetscObjectComm((PetscObject) sf);
2347*13048561SMatthew G. Knepley         PetscBT      seenProcs, flippedProcs;
2348*13048561SMatthew G. Knepley         PetscInt    *procFIFO, pTop, pBottom;
2349*13048561SMatthew G. Knepley         PetscInt    *adj = NULL;
2350*13048561SMatthew G. Knepley         PetscBool   *val = NULL;
2351*13048561SMatthew G. Knepley         PetscMPIInt *recvcounts = NULL, *displs = NULL, p;
2352*13048561SMatthew G. Knepley         PetscMPIInt  N = numNeighbors, numProcs = 0, rank;
2353*13048561SMatthew G. Knepley         PetscInt     debug = 0;
2354*13048561SMatthew G. Knepley 
2355*13048561SMatthew G. Knepley         ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
2356*13048561SMatthew G. Knepley         if (!rank) {ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr);}
2357*13048561SMatthew G. Knepley         ierr = PetscCalloc2(numProcs,&recvcounts,numProcs+1,&displs);CHKERRQ(ierr);
2358*13048561SMatthew G. Knepley         ierr = MPI_Gather(&N, 1, MPI_INT, recvcounts, 1, MPI_INT, 0, comm);CHKERRQ(ierr);
2359*13048561SMatthew G. Knepley         for (p = 0; p < numProcs; ++p) {
2360*13048561SMatthew G. Knepley           displs[p+1] = displs[p] + recvcounts[p];
2361*13048561SMatthew G. Knepley         }
2362*13048561SMatthew G. Knepley         if (!rank) {ierr = PetscMalloc2(displs[numProcs],&adj,displs[numProcs],&val);CHKERRQ(ierr);}
2363*13048561SMatthew G. Knepley         ierr = MPI_Gatherv(nranks, numNeighbors, MPIU_INT, adj, recvcounts, displs, MPIU_INT, 0, comm);CHKERRQ(ierr);
2364*13048561SMatthew G. Knepley         ierr = MPI_Gatherv(match, numNeighbors, MPIU_BOOL, val, recvcounts, displs, MPIU_BOOL, 0, comm);CHKERRQ(ierr);
2365*13048561SMatthew G. Knepley         if (debug) {
2366*13048561SMatthew G. Knepley           for (p = 0; p < numProcs; ++p) {
2367*13048561SMatthew G. Knepley             ierr = PetscPrintf(comm, "Proc %d:\n", p);
2368*13048561SMatthew G. Knepley             for (n = 0; n < recvcounts[p]; ++n) {
2369*13048561SMatthew G. Knepley               ierr = PetscPrintf(comm, "  edge %d (%d):\n", adj[displs[p]+n], val[displs[p]+n]);
2370*13048561SMatthew G. Knepley             }
2371*13048561SMatthew G. Knepley           }
2372*13048561SMatthew G. Knepley         }
2373*13048561SMatthew G. Knepley         ierr = PetscBTCreate(numProcs, &seenProcs);CHKERRQ(ierr);
2374*13048561SMatthew G. Knepley         ierr = PetscBTMemzero(numProcs, seenProcs);CHKERRQ(ierr);
2375*13048561SMatthew G. Knepley         ierr = PetscBTCreate(numProcs, &flippedProcs);CHKERRQ(ierr);
2376*13048561SMatthew G. Knepley         ierr = PetscBTMemzero(numProcs, flippedProcs);CHKERRQ(ierr);
2377*13048561SMatthew G. Knepley         ierr = PetscMalloc1(numProcs,&procFIFO);CHKERRQ(ierr);
2378*13048561SMatthew G. Knepley         pTop = pBottom = 0;
2379*13048561SMatthew G. Knepley         for (p = 0; p < numProcs; ++p) {
2380*13048561SMatthew G. Knepley           if (PetscBTLookup(seenProcs, p)) continue;
2381*13048561SMatthew G. Knepley           /* Initialize FIFO with next proc */
2382*13048561SMatthew G. Knepley           procFIFO[pBottom++] = p;
2383*13048561SMatthew G. Knepley           ierr = PetscBTSet(seenProcs, p);CHKERRQ(ierr);
2384*13048561SMatthew G. Knepley           /* Consider each proc in FIFO */
2385*13048561SMatthew G. Knepley           while (pTop < pBottom) {
2386*13048561SMatthew G. Knepley             PetscInt proc, nproc, seen, flippedA, flippedB, mismatch;
2387*13048561SMatthew G. Knepley 
2388*13048561SMatthew G. Knepley             proc     = procFIFO[pTop++];
2389*13048561SMatthew G. Knepley             flippedA = PetscBTLookup(flippedProcs, proc) ? 1 : 0;
2390*13048561SMatthew G. Knepley             /* Loop over neighboring procs */
2391*13048561SMatthew G. Knepley             for (n = 0; n < recvcounts[proc]; ++n) {
2392*13048561SMatthew G. Knepley               nproc    = adj[displs[proc]+n];
2393*13048561SMatthew G. Knepley               mismatch = val[displs[proc]+n] ? 0 : 1;
2394*13048561SMatthew G. Knepley               seen     = PetscBTLookup(seenProcs, nproc);
2395*13048561SMatthew G. Knepley               flippedB = PetscBTLookup(flippedProcs, nproc) ? 1 : 0;
2396*13048561SMatthew G. Knepley 
2397*13048561SMatthew G. Knepley               if (mismatch ^ (flippedA ^ flippedB)) {
2398*13048561SMatthew G. Knepley                 if (seen) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Previously seen procs %d and %d do not match: Fault mesh is non-orientable", proc, nproc);
2399*13048561SMatthew G. Knepley                 if (!flippedB) {
2400*13048561SMatthew G. Knepley                   ierr = PetscBTSet(flippedProcs, nproc);CHKERRQ(ierr);
2401*13048561SMatthew G. Knepley               } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Inconsistent mesh orientation: Fault mesh is non-orientable");
2402*13048561SMatthew G. Knepley               } else if (mismatch && flippedA && flippedB) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Attempt to flip already flipped cell: Fault mesh is non-orientable");
2403*13048561SMatthew G. Knepley               if (!seen) {
2404*13048561SMatthew G. Knepley                 procFIFO[pBottom++] = nproc;
2405*13048561SMatthew G. Knepley                 ierr = PetscBTSet(seenProcs, nproc);CHKERRQ(ierr);
2406*13048561SMatthew G. Knepley               }
2407*13048561SMatthew G. Knepley             }
2408*13048561SMatthew G. Knepley           }
2409*13048561SMatthew G. Knepley         }
2410*13048561SMatthew G. Knepley         ierr = PetscFree(procFIFO);CHKERRQ(ierr);
2411*13048561SMatthew G. Knepley 
2412*13048561SMatthew G. Knepley         ierr = PetscFree2(recvcounts,displs);CHKERRQ(ierr);
2413*13048561SMatthew G. Knepley         ierr = PetscFree2(adj,val);CHKERRQ(ierr);
2414*13048561SMatthew G. Knepley         {
2415*13048561SMatthew G. Knepley           PetscBool *flips;
2416*13048561SMatthew G. Knepley 
2417*13048561SMatthew G. Knepley           ierr = PetscMalloc1(numProcs,&flips);CHKERRQ(ierr);
2418*13048561SMatthew G. Knepley           for (p = 0; p < numProcs; ++p) {
2419*13048561SMatthew G. Knepley             flips[p] = PetscBTLookup(flippedProcs, p) ? PETSC_TRUE : PETSC_FALSE;
2420*13048561SMatthew G. Knepley             if (debug && flips[p]) {ierr = PetscPrintf(comm, "Flipping Proc %d:\n", p);}
2421*13048561SMatthew G. Knepley           }
2422*13048561SMatthew G. Knepley           ierr = MPI_Scatter(flips, 1, MPIU_BOOL, &flipped, 1, MPIU_BOOL, 0, comm);CHKERRQ(ierr);
2423*13048561SMatthew G. Knepley           ierr = PetscFree(flips);CHKERRQ(ierr);
2424*13048561SMatthew G. Knepley         }
2425*13048561SMatthew G. Knepley         ierr = PetscBTDestroy(&seenProcs);CHKERRQ(ierr);
2426*13048561SMatthew G. Knepley         ierr = PetscBTDestroy(&flippedProcs);CHKERRQ(ierr);
2427*13048561SMatthew G. Knepley       }
2428*13048561SMatthew G. Knepley       ierr = PetscFree4(match,nranks,rornt,lornt);CHKERRQ(ierr);
2429fedde076SMatthew G. Knepley       ierr = PetscFree(neighbors);CHKERRQ(ierr);
2430*13048561SMatthew G. Knepley       if (flipped) {for (c = cStart; c < cEnd; ++c) {ierr = PetscBTNegate(flippedCells, c-cStart);CHKERRQ(ierr);}}
2431fedde076SMatthew G. Knepley     }
2432fedde076SMatthew G. Knepley   }
2433fedde076SMatthew G. Knepley   /* Reverse flipped cells in the mesh */
2434d27a0f52SMatthew G. Knepley   ierr = DMPlexGetMaxSizes(dm, &maxConeSize, NULL);CHKERRQ(ierr);
2435d27a0f52SMatthew G. Knepley   ierr = DMGetWorkArray(dm, maxConeSize, PETSC_INT, &revcone);CHKERRQ(ierr);
2436d27a0f52SMatthew G. Knepley   ierr = DMGetWorkArray(dm, maxConeSize, PETSC_INT, &revconeO);CHKERRQ(ierr);
2437a1b4d4a2SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
2438f4e909fcSMatthew G. Knepley     const PetscInt *cone, *coneO, *support;
2439f4e909fcSMatthew G. Knepley     PetscInt        coneSize, supportSize, faceSize, cp, sp;
2440d27a0f52SMatthew G. Knepley 
2441a1b4d4a2SMatthew G. Knepley     if (!PetscBTLookup(flippedCells, c-cStart)) continue;
2442a1b4d4a2SMatthew G. Knepley     ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr);
2443a1b4d4a2SMatthew G. Knepley     ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
2444a1b4d4a2SMatthew G. Knepley     ierr = DMPlexGetConeOrientation(dm, c, &coneO);CHKERRQ(ierr);
2445a1b4d4a2SMatthew G. Knepley     for (cp = 0; cp < coneSize; ++cp) {
2446a1b4d4a2SMatthew G. Knepley       const PetscInt rcp = coneSize-cp-1;
2447a1b4d4a2SMatthew G. Knepley 
2448a1b4d4a2SMatthew G. Knepley       ierr = DMPlexGetConeSize(dm, cone[rcp], &faceSize);CHKERRQ(ierr);
2449a1b4d4a2SMatthew G. Knepley       revcone[cp]  = cone[rcp];
2450a1b4d4a2SMatthew G. Knepley       revconeO[cp] = coneO[rcp] >= 0 ? -(faceSize-coneO[rcp]) : faceSize+coneO[rcp];
2451d27a0f52SMatthew G. Knepley     }
2452a1b4d4a2SMatthew G. Knepley     ierr = DMPlexSetCone(dm, c, revcone);CHKERRQ(ierr);
2453a1b4d4a2SMatthew G. Knepley     ierr = DMPlexSetConeOrientation(dm, c, revconeO);CHKERRQ(ierr);
2454f4e909fcSMatthew G. Knepley     /* Reverse orientations of support */
2455f4e909fcSMatthew G. Knepley     faceSize = coneSize;
2456f4e909fcSMatthew G. Knepley     ierr = DMPlexGetSupportSize(dm, c, &supportSize);CHKERRQ(ierr);
2457f4e909fcSMatthew G. Knepley     ierr = DMPlexGetSupport(dm, c, &support);CHKERRQ(ierr);
2458f4e909fcSMatthew G. Knepley     for (sp = 0; sp < supportSize; ++sp) {
2459f4e909fcSMatthew G. Knepley       ierr = DMPlexGetConeSize(dm, support[sp], &coneSize);CHKERRQ(ierr);
2460f4e909fcSMatthew G. Knepley       ierr = DMPlexGetCone(dm, support[sp], &cone);CHKERRQ(ierr);
2461f4e909fcSMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, support[sp], &coneO);CHKERRQ(ierr);
2462f4e909fcSMatthew G. Knepley       for (cp = 0; cp < coneSize; ++cp) {
2463f4e909fcSMatthew G. Knepley         if (cone[cp] != c) continue;
2464f4e909fcSMatthew G. Knepley         ierr = DMPlexInsertConeOrientation(dm, support[sp], cp, coneO[cp] >= 0 ? -(faceSize-coneO[cp]) : faceSize+coneO[cp]);CHKERRQ(ierr);
2465f4e909fcSMatthew G. Knepley       }
2466f4e909fcSMatthew G. Knepley     }
2467d27a0f52SMatthew G. Knepley   }
2468d27a0f52SMatthew G. Knepley   ierr = DMRestoreWorkArray(dm, maxConeSize, PETSC_INT, &revcone);CHKERRQ(ierr);
2469d27a0f52SMatthew G. Knepley   ierr = DMRestoreWorkArray(dm, maxConeSize, PETSC_INT, &revconeO);CHKERRQ(ierr);
2470d27a0f52SMatthew G. Knepley   ierr = PetscBTDestroy(&seenCells);CHKERRQ(ierr);
2471a1b4d4a2SMatthew G. Knepley   ierr = PetscBTDestroy(&flippedCells);CHKERRQ(ierr);
2472a1b4d4a2SMatthew G. Knepley   ierr = PetscBTDestroy(&seenFaces);CHKERRQ(ierr);
2473a1b4d4a2SMatthew G. Knepley   ierr = PetscFree(faceFIFO);CHKERRQ(ierr);
2474d27a0f52SMatthew G. Knepley   PetscFunctionReturn(0);
2475d27a0f52SMatthew G. Knepley }
2476d27a0f52SMatthew G. Knepley 
2477d27a0f52SMatthew G. Knepley #undef __FUNCT__
2478cb1e1211SMatthew G Knepley #define __FUNCT__ "DMPlexGetAdjacencySingleLevel_Internal"
2479cb1e1211SMatthew G Knepley static PetscErrorCode DMPlexGetAdjacencySingleLevel_Internal(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[])
2480cb1e1211SMatthew G Knepley {
2481cb1e1211SMatthew G Knepley   const PetscInt *support = NULL;
2482cb1e1211SMatthew G Knepley   PetscInt        numAdj   = 0, maxAdjSize = *adjSize, supportSize, s;
2483cb1e1211SMatthew G Knepley   PetscErrorCode  ierr;
2484cb1e1211SMatthew G Knepley 
2485cb1e1211SMatthew G Knepley   PetscFunctionBegin;
2486cb1e1211SMatthew G Knepley   if (useClosure) {
2487cb1e1211SMatthew G Knepley     ierr = DMPlexGetConeSize(dm, p, &supportSize);CHKERRQ(ierr);
2488cb1e1211SMatthew G Knepley     ierr = DMPlexGetCone(dm, p, &support);CHKERRQ(ierr);
2489cb1e1211SMatthew G Knepley     for (s = 0; s < supportSize; ++s) {
2490cb1e1211SMatthew G Knepley       const PetscInt *cone = NULL;
2491cb1e1211SMatthew G Knepley       PetscInt        coneSize, c, q;
2492cb1e1211SMatthew G Knepley 
2493cb1e1211SMatthew G Knepley       ierr = DMPlexGetSupportSize(dm, support[s], &coneSize);CHKERRQ(ierr);
2494cb1e1211SMatthew G Knepley       ierr = DMPlexGetSupport(dm, support[s], &cone);CHKERRQ(ierr);
2495cb1e1211SMatthew G Knepley       for (c = 0; c < coneSize; ++c) {
2496cb1e1211SMatthew G Knepley         for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) {
2497cb1e1211SMatthew G Knepley           if (cone[c] == adj[q]) break;
2498cb1e1211SMatthew G Knepley         }
2499cb1e1211SMatthew G Knepley         if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize);
2500cb1e1211SMatthew G Knepley       }
2501cb1e1211SMatthew G Knepley     }
2502cb1e1211SMatthew G Knepley   } else {
2503cb1e1211SMatthew G Knepley     ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr);
2504cb1e1211SMatthew G Knepley     ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr);
2505cb1e1211SMatthew G Knepley     for (s = 0; s < supportSize; ++s) {
2506cb1e1211SMatthew G Knepley       const PetscInt *cone = NULL;
2507cb1e1211SMatthew G Knepley       PetscInt        coneSize, c, q;
2508cb1e1211SMatthew G Knepley 
2509cb1e1211SMatthew G Knepley       ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
2510cb1e1211SMatthew G Knepley       ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
2511cb1e1211SMatthew G Knepley       for (c = 0; c < coneSize; ++c) {
2512cb1e1211SMatthew G Knepley         for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) {
2513cb1e1211SMatthew G Knepley           if (cone[c] == adj[q]) break;
2514cb1e1211SMatthew G Knepley         }
2515cb1e1211SMatthew G Knepley         if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize);
2516cb1e1211SMatthew G Knepley       }
2517cb1e1211SMatthew G Knepley     }
2518cb1e1211SMatthew G Knepley   }
2519cb1e1211SMatthew G Knepley   *adjSize = numAdj;
2520cb1e1211SMatthew G Knepley   PetscFunctionReturn(0);
2521cb1e1211SMatthew G Knepley }
2522cb1e1211SMatthew G Knepley 
2523cb1e1211SMatthew G Knepley #undef __FUNCT__
2524552f7358SJed Brown #define __FUNCT__ "DMPlexCreateNeighborCSR"
252577c88f5bSMatthew G Knepley PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt cellHeight, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency)
25260adebc6cSBarry Smith {
2527552f7358SJed Brown   const PetscInt maxFaceCases = 30;
2528552f7358SJed Brown   PetscInt       numFaceCases = 0;
2529552f7358SJed Brown   PetscInt       numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */
2530552f7358SJed Brown   PetscInt      *off, *adj;
2531552f7358SJed Brown   PetscInt      *neighborCells, *tmpClosure;
2532552f7358SJed Brown   PetscInt       maxConeSize, maxSupportSize, maxClosure, maxNeighbors;
253377c88f5bSMatthew G Knepley   PetscInt       dim, cellDim, depth = 0, faceDepth, cStart, cEnd, c, numCells, cell;
2534552f7358SJed Brown   PetscErrorCode ierr;
2535552f7358SJed Brown 
2536552f7358SJed Brown   PetscFunctionBegin;
2537552f7358SJed Brown   /* For parallel partitioning, I think you have to communicate supports */
2538552f7358SJed Brown   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
253977c88f5bSMatthew G Knepley   cellDim = dim - cellHeight;
2540552f7358SJed Brown   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
254177c88f5bSMatthew G Knepley   ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);
2542552f7358SJed Brown   ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr);
2543552f7358SJed Brown   if (cEnd - cStart == 0) {
2544552f7358SJed Brown     if (numVertices) *numVertices = 0;
25450298fd71SBarry Smith     if (offsets)   *offsets   = NULL;
25460298fd71SBarry Smith     if (adjacency) *adjacency = NULL;
2547552f7358SJed Brown     PetscFunctionReturn(0);
2548552f7358SJed Brown   }
2549552f7358SJed Brown   numCells  = cEnd - cStart;
255077c88f5bSMatthew G Knepley   faceDepth = depth - cellHeight;
25510d957afbSMatthew G. Knepley   if (dim == depth) {
2552e430e843SMatthew G. Knepley     PetscInt f, fStart, fEnd;
2553e430e843SMatthew G. Knepley 
25541795a4d1SJed Brown     ierr = PetscCalloc1(numCells+1, &off);CHKERRQ(ierr);
2555e430e843SMatthew G. Knepley     /* Count neighboring cells */
2556e430e843SMatthew G. Knepley     ierr = DMPlexGetHeightStratum(dm, cellHeight+1, &fStart, &fEnd);CHKERRQ(ierr);
2557e430e843SMatthew G. Knepley     for (f = fStart; f < fEnd; ++f) {
2558e430e843SMatthew G. Knepley       const PetscInt *support;
2559e430e843SMatthew G. Knepley       PetscInt        supportSize;
2560e430e843SMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
2561e430e843SMatthew G. Knepley       ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
2562e430e843SMatthew G. Knepley       if (supportSize == 2) {
2563e430e843SMatthew G. Knepley         ++off[support[0]-cStart+1];
2564e430e843SMatthew G. Knepley         ++off[support[1]-cStart+1];
2565e430e843SMatthew G. Knepley       }
2566e430e843SMatthew G. Knepley     }
2567e430e843SMatthew G. Knepley     /* Prefix sum */
2568e430e843SMatthew G. Knepley     for (c = 1; c <= numCells; ++c) off[c] += off[c-1];
2569e430e843SMatthew G. Knepley     if (adjacency) {
2570e430e843SMatthew G. Knepley       PetscInt *tmp;
2571e430e843SMatthew G. Knepley 
2572785e854fSJed Brown       ierr = PetscMalloc1(off[numCells], &adj);CHKERRQ(ierr);
2573785e854fSJed Brown       ierr = PetscMalloc1((numCells+1), &tmp);CHKERRQ(ierr);
2574e430e843SMatthew G. Knepley       ierr = PetscMemcpy(tmp, off, (numCells+1) * sizeof(PetscInt));CHKERRQ(ierr);
2575e430e843SMatthew G. Knepley       /* Get neighboring cells */
2576e430e843SMatthew G. Knepley       for (f = fStart; f < fEnd; ++f) {
2577e430e843SMatthew G. Knepley         const PetscInt *support;
2578e430e843SMatthew G. Knepley         PetscInt        supportSize;
2579e430e843SMatthew G. Knepley         ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr);
2580e430e843SMatthew G. Knepley         ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr);
2581e430e843SMatthew G. Knepley         if (supportSize == 2) {
2582e430e843SMatthew G. Knepley           adj[tmp[support[0]-cStart]++] = support[1];
2583e430e843SMatthew G. Knepley           adj[tmp[support[1]-cStart]++] = support[0];
2584e430e843SMatthew G. Knepley         }
2585e430e843SMatthew G. Knepley       }
2586e430e843SMatthew G. Knepley #if defined(PETSC_USE_DEBUG)
25870d957afbSMatthew G. Knepley       for (c = 0; c < cEnd-cStart; ++c) if (tmp[c] != off[c+1]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Offset %d != %d for cell %d", tmp[c], off[c], c+cStart);
2588e430e843SMatthew G. Knepley #endif
2589e430e843SMatthew G. Knepley       ierr = PetscFree(tmp);CHKERRQ(ierr);
2590e430e843SMatthew G. Knepley     }
2591e430e843SMatthew G. Knepley     if (numVertices) *numVertices = numCells;
2592e430e843SMatthew G. Knepley     if (offsets)   *offsets   = off;
2593e430e843SMatthew G. Knepley     if (adjacency) *adjacency = adj;
2594e430e843SMatthew G. Knepley     PetscFunctionReturn(0);
2595e430e843SMatthew G. Knepley   }
2596552f7358SJed Brown   /* Setup face recognition */
259777c88f5bSMatthew G Knepley   if (faceDepth == 1) {
2598552f7358SJed 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 */
2599552f7358SJed Brown 
2600552f7358SJed Brown     for (c = cStart; c < cEnd; ++c) {
2601552f7358SJed Brown       PetscInt corners;
2602552f7358SJed Brown 
2603552f7358SJed Brown       ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr);
2604552f7358SJed Brown       if (!cornersSeen[corners]) {
2605552f7358SJed Brown         PetscInt nFV;
2606552f7358SJed Brown 
260782f516ccSBarry Smith         if (numFaceCases >= maxFaceCases) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases");
2608552f7358SJed Brown         cornersSeen[corners] = 1;
26090d644c17SKarl Rupp 
261018ad9376SMatthew G. Knepley         ierr = DMPlexGetNumFaceVertices(dm, cellDim, corners, &nFV);CHKERRQ(ierr);
26110d644c17SKarl Rupp 
2612552f7358SJed Brown         numFaceVertices[numFaceCases++] = nFV;
2613552f7358SJed Brown       }
2614552f7358SJed Brown     }
2615552f7358SJed Brown   }
2616e7b80042SMatthew G. Knepley   maxClosure   = 2*PetscMax(PetscPowInt(maxConeSize,depth+1),PetscPowInt(maxSupportSize,depth+1));
2617e7b80042SMatthew G. Knepley   maxNeighbors = PetscPowInt(maxConeSize,depth+1)*PetscPowInt(maxSupportSize,depth+1);
2618dcca6d9dSJed Brown   ierr         = PetscMalloc2(maxNeighbors,&neighborCells,maxClosure,&tmpClosure);CHKERRQ(ierr);
26191795a4d1SJed Brown   ierr         = PetscCalloc1(numCells+1, &off);CHKERRQ(ierr);
2620552f7358SJed Brown   /* Count neighboring cells */
2621552f7358SJed Brown   for (cell = cStart; cell < cEnd; ++cell) {
2622552f7358SJed Brown     PetscInt numNeighbors = maxNeighbors, n;
2623552f7358SJed Brown 
2624cb1e1211SMatthew G Knepley     ierr = DMPlexGetAdjacencySingleLevel_Internal(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr);
2625552f7358SJed Brown     /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */
2626552f7358SJed Brown     for (n = 0; n < numNeighbors; ++n) {
26274d25b1e8SKarl Rupp       PetscInt        cellPair[2];
262877c88f5bSMatthew G Knepley       PetscBool       found    = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE;
2629552f7358SJed Brown       PetscInt        meetSize = 0;
26300298fd71SBarry Smith       const PetscInt *meet    = NULL;
2631552f7358SJed Brown 
26324d25b1e8SKarl Rupp       cellPair[0] = cell; cellPair[1] = neighborCells[n];
2633552f7358SJed Brown       if (cellPair[0] == cellPair[1]) continue;
2634552f7358SJed Brown       if (!found) {
2635552f7358SJed Brown         ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr);
2636552f7358SJed Brown         if (meetSize) {
2637552f7358SJed Brown           PetscInt f;
2638552f7358SJed Brown 
2639552f7358SJed Brown           for (f = 0; f < numFaceCases; ++f) {
2640552f7358SJed Brown             if (numFaceVertices[f] == meetSize) {
2641552f7358SJed Brown               found = PETSC_TRUE;
2642552f7358SJed Brown               break;
2643552f7358SJed Brown             }
2644552f7358SJed Brown           }
2645552f7358SJed Brown         }
2646552f7358SJed Brown         ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr);
2647552f7358SJed Brown       }
26480d644c17SKarl Rupp       if (found) ++off[cell-cStart+1];
2649552f7358SJed Brown     }
2650552f7358SJed Brown   }
2651552f7358SJed Brown   /* Prefix sum */
26520d644c17SKarl Rupp   for (cell = 1; cell <= numCells; ++cell) off[cell] += off[cell-1];
26530d644c17SKarl Rupp 
2654552f7358SJed Brown   if (adjacency) {
2655785e854fSJed Brown     ierr = PetscMalloc1(off[numCells], &adj);CHKERRQ(ierr);
2656552f7358SJed Brown     /* Get neighboring cells */
2657552f7358SJed Brown     for (cell = cStart; cell < cEnd; ++cell) {
2658552f7358SJed Brown       PetscInt numNeighbors = maxNeighbors, n;
2659552f7358SJed Brown       PetscInt cellOffset   = 0;
2660552f7358SJed Brown 
2661cb1e1211SMatthew G Knepley       ierr = DMPlexGetAdjacencySingleLevel_Internal(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr);
2662552f7358SJed Brown       /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */
2663552f7358SJed Brown       for (n = 0; n < numNeighbors; ++n) {
26644d25b1e8SKarl Rupp         PetscInt        cellPair[2];
266577c88f5bSMatthew G Knepley         PetscBool       found    = faceDepth > 1 ? PETSC_TRUE : PETSC_FALSE;
2666552f7358SJed Brown         PetscInt        meetSize = 0;
26670298fd71SBarry Smith         const PetscInt *meet    = NULL;
2668552f7358SJed Brown 
26694d25b1e8SKarl Rupp         cellPair[0] = cell; cellPair[1] = neighborCells[n];
2670552f7358SJed Brown         if (cellPair[0] == cellPair[1]) continue;
2671552f7358SJed Brown         if (!found) {
2672552f7358SJed Brown           ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr);
2673552f7358SJed Brown           if (meetSize) {
2674552f7358SJed Brown             PetscInt f;
2675552f7358SJed Brown 
2676552f7358SJed Brown             for (f = 0; f < numFaceCases; ++f) {
2677552f7358SJed Brown               if (numFaceVertices[f] == meetSize) {
2678552f7358SJed Brown                 found = PETSC_TRUE;
2679552f7358SJed Brown                 break;
2680552f7358SJed Brown               }
2681552f7358SJed Brown             }
2682552f7358SJed Brown           }
2683552f7358SJed Brown           ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr);
2684552f7358SJed Brown         }
2685552f7358SJed Brown         if (found) {
2686552f7358SJed Brown           adj[off[cell-cStart]+cellOffset] = neighborCells[n];
2687552f7358SJed Brown           ++cellOffset;
2688552f7358SJed Brown         }
2689552f7358SJed Brown       }
2690552f7358SJed Brown     }
2691552f7358SJed Brown   }
2692552f7358SJed Brown   ierr = PetscFree2(neighborCells,tmpClosure);CHKERRQ(ierr);
2693552f7358SJed Brown   if (numVertices) *numVertices = numCells;
2694552f7358SJed Brown   if (offsets)   *offsets   = off;
2695552f7358SJed Brown   if (adjacency) *adjacency = adj;
2696552f7358SJed Brown   PetscFunctionReturn(0);
2697552f7358SJed Brown }
2698552f7358SJed Brown 
2699519f805aSKarl Rupp #if defined(PETSC_HAVE_CHACO)
2700519f805aSKarl Rupp #if defined(PETSC_HAVE_UNISTD_H)
2701552f7358SJed Brown #include <unistd.h>
2702552f7358SJed Brown #endif
2703552f7358SJed Brown /* Chaco does not have an include file */
270439d7646bSJed Brown PETSC_EXTERN int interface(int nvtxs, int *start, int *adjacency, int *vwgts,
2705552f7358SJed Brown                        float *ewgts, float *x, float *y, float *z, char *outassignname,
2706552f7358SJed Brown                        char *outfilename, short *assignment, int architecture, int ndims_tot,
2707552f7358SJed Brown                        int mesh_dims[3], double *goal, int global_method, int local_method,
2708552f7358SJed Brown                        int rqi_flag, int vmax, int ndims, double eigtol, long seed);
2709552f7358SJed Brown 
2710552f7358SJed Brown extern int FREE_GRAPH;
2711552f7358SJed Brown 
2712552f7358SJed Brown #undef __FUNCT__
2713552f7358SJed Brown #define __FUNCT__ "DMPlexPartition_Chaco"
2714552f7358SJed Brown PetscErrorCode DMPlexPartition_Chaco(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition)
2715552f7358SJed Brown {
2716552f7358SJed Brown   enum {DEFAULT_METHOD = 1, INERTIAL_METHOD = 3};
271782f516ccSBarry Smith   MPI_Comm       comm;
2718552f7358SJed Brown   int            nvtxs          = numVertices; /* number of vertices in full graph */
2719552f7358SJed Brown   int           *vwgts          = NULL;   /* weights for all vertices */
2720552f7358SJed Brown   float         *ewgts          = NULL;   /* weights for all edges */
2721552f7358SJed Brown   float         *x              = NULL, *y = NULL, *z = NULL; /* coordinates for inertial method */
2722552f7358SJed Brown   char          *outassignname  = NULL;   /*  name of assignment output file */
2723552f7358SJed Brown   char          *outfilename    = NULL;   /* output file name */
2724552f7358SJed Brown   int            architecture   = 1;      /* 0 => hypercube, d => d-dimensional mesh */
2725552f7358SJed Brown   int            ndims_tot      = 0;      /* total number of cube dimensions to divide */
2726552f7358SJed Brown   int            mesh_dims[3];            /* dimensions of mesh of processors */
2727552f7358SJed Brown   double        *goal          = NULL;    /* desired set sizes for each set */
2728552f7358SJed Brown   int            global_method = 1;       /* global partitioning algorithm */
2729552f7358SJed Brown   int            local_method  = 1;       /* local partitioning algorithm */
2730552f7358SJed Brown   int            rqi_flag      = 0;       /* should I use RQI/Symmlq eigensolver? */
2731552f7358SJed Brown   int            vmax          = 200;     /* how many vertices to coarsen down to? */
2732552f7358SJed Brown   int            ndims         = 1;       /* number of eigenvectors (2^d sets) */
2733552f7358SJed Brown   double         eigtol        = 0.001;   /* tolerance on eigenvectors */
2734552f7358SJed Brown   long           seed          = 123636512; /* for random graph mutations */
2735552f7358SJed Brown   short int     *assignment;              /* Output partition */
2736552f7358SJed Brown   int            fd_stdout, fd_pipe[2];
2737552f7358SJed Brown   PetscInt      *points;
2738552f7358SJed Brown   PetscMPIInt    commSize;
2739552f7358SJed Brown   int            i, v, p;
2740552f7358SJed Brown   PetscErrorCode ierr;
2741552f7358SJed Brown 
2742552f7358SJed Brown   PetscFunctionBegin;
274382f516ccSBarry Smith   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
2744552f7358SJed Brown   ierr = MPI_Comm_size(comm, &commSize);CHKERRQ(ierr);
2745552f7358SJed Brown   if (!numVertices) {
2746552f7358SJed Brown     ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr);
2747552f7358SJed Brown     ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr);
2748552f7358SJed Brown     ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr);
27490298fd71SBarry Smith     ierr = ISCreateGeneral(comm, 0, NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr);
2750552f7358SJed Brown     PetscFunctionReturn(0);
2751552f7358SJed Brown   }
2752552f7358SJed Brown   FREE_GRAPH = 0;                         /* Do not let Chaco free my memory */
27530d644c17SKarl Rupp   for (i = 0; i < start[numVertices]; ++i) ++adjacency[i];
27540d644c17SKarl Rupp 
2755552f7358SJed Brown   if (global_method == INERTIAL_METHOD) {
2756552f7358SJed Brown     /* manager.createCellCoordinates(nvtxs, &x, &y, &z); */
2757552f7358SJed Brown     SETERRQ(comm, PETSC_ERR_SUP, "Inertial partitioning not yet supported");
2758552f7358SJed Brown   }
2759552f7358SJed Brown   mesh_dims[0] = commSize;
2760552f7358SJed Brown   mesh_dims[1] = 1;
2761552f7358SJed Brown   mesh_dims[2] = 1;
2762785e854fSJed Brown   ierr = PetscMalloc1(nvtxs, &assignment);CHKERRQ(ierr);
2763552f7358SJed Brown   /* Chaco outputs to stdout. We redirect this to a buffer. */
2764552f7358SJed Brown   /* TODO: check error codes for UNIX calls */
2765519f805aSKarl Rupp #if defined(PETSC_HAVE_UNISTD_H)
2766552f7358SJed Brown   {
27677995c745SJed Brown     int piperet;
27687995c745SJed Brown     piperet = pipe(fd_pipe);
27697995c745SJed Brown     if (piperet) SETERRQ(comm,PETSC_ERR_SYS,"Could not create pipe");
2770552f7358SJed Brown     fd_stdout = dup(1);
2771552f7358SJed Brown     close(1);
2772552f7358SJed Brown     dup2(fd_pipe[1], 1);
2773552f7358SJed Brown   }
2774552f7358SJed Brown #endif
2775552f7358SJed Brown   ierr = interface(nvtxs, (int*) start, (int*) adjacency, vwgts, ewgts, x, y, z, outassignname, outfilename,
2776552f7358SJed Brown                    assignment, architecture, ndims_tot, mesh_dims, goal, global_method, local_method, rqi_flag,
2777552f7358SJed Brown                    vmax, ndims, eigtol, seed);
2778519f805aSKarl Rupp #if defined(PETSC_HAVE_UNISTD_H)
2779552f7358SJed Brown   {
2780552f7358SJed Brown     char msgLog[10000];
2781552f7358SJed Brown     int  count;
2782552f7358SJed Brown 
2783552f7358SJed Brown     fflush(stdout);
2784552f7358SJed Brown     count = read(fd_pipe[0], msgLog, (10000-1)*sizeof(char));
2785552f7358SJed Brown     if (count < 0) count = 0;
2786552f7358SJed Brown     msgLog[count] = 0;
2787552f7358SJed Brown     close(1);
2788552f7358SJed Brown     dup2(fd_stdout, 1);
2789552f7358SJed Brown     close(fd_stdout);
2790552f7358SJed Brown     close(fd_pipe[0]);
2791552f7358SJed Brown     close(fd_pipe[1]);
2792552f7358SJed Brown     if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", msgLog);
2793552f7358SJed Brown   }
2794552f7358SJed Brown #endif
2795552f7358SJed Brown   /* Convert to PetscSection+IS */
2796552f7358SJed Brown   ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr);
2797552f7358SJed Brown   ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr);
2798552f7358SJed Brown   for (v = 0; v < nvtxs; ++v) {
2799552f7358SJed Brown     ierr = PetscSectionAddDof(*partSection, assignment[v], 1);CHKERRQ(ierr);
2800552f7358SJed Brown   }
2801552f7358SJed Brown   ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr);
2802785e854fSJed Brown   ierr = PetscMalloc1(nvtxs, &points);CHKERRQ(ierr);
2803552f7358SJed Brown   for (p = 0, i = 0; p < commSize; ++p) {
2804552f7358SJed Brown     for (v = 0; v < nvtxs; ++v) {
2805552f7358SJed Brown       if (assignment[v] == p) points[i++] = v;
2806552f7358SJed Brown     }
2807552f7358SJed Brown   }
2808552f7358SJed Brown   if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs);
2809552f7358SJed Brown   ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr);
2810552f7358SJed Brown   if (global_method == INERTIAL_METHOD) {
2811552f7358SJed Brown     /* manager.destroyCellCoordinates(nvtxs, &x, &y, &z); */
2812552f7358SJed Brown   }
2813552f7358SJed Brown   ierr = PetscFree(assignment);CHKERRQ(ierr);
28140d644c17SKarl Rupp   for (i = 0; i < start[numVertices]; ++i) --adjacency[i];
2815552f7358SJed Brown   PetscFunctionReturn(0);
2816552f7358SJed Brown }
2817552f7358SJed Brown #endif
2818552f7358SJed Brown 
2819519f805aSKarl Rupp #if defined(PETSC_HAVE_PARMETIS)
282025cda350SMatthew G. Knepley #include <parmetis.h>
282125cda350SMatthew G. Knepley 
2822552f7358SJed Brown #undef __FUNCT__
2823552f7358SJed Brown #define __FUNCT__ "DMPlexPartition_ParMetis"
2824552f7358SJed Brown PetscErrorCode DMPlexPartition_ParMetis(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition)
2825552f7358SJed Brown {
282625cda350SMatthew G. Knepley   MPI_Comm       comm;
282754695375SMatthew G. Knepley   PetscInt       nvtxs      = numVertices; /* The number of vertices in full graph */
282854695375SMatthew G. Knepley   PetscInt      *vtxdist;                  /* Distribution of vertices across processes */
282954695375SMatthew G. Knepley   PetscInt      *xadj       = start;       /* Start of edge list for each vertex */
283054695375SMatthew G. Knepley   PetscInt      *adjncy     = adjacency;   /* Edge lists for all vertices */
283154695375SMatthew G. Knepley   PetscInt      *vwgt       = NULL;        /* Vertex weights */
283254695375SMatthew G. Knepley   PetscInt      *adjwgt     = NULL;        /* Edge weights */
283354695375SMatthew G. Knepley   PetscInt       wgtflag    = 0;           /* Indicates which weights are present */
283454695375SMatthew G. Knepley   PetscInt       numflag    = 0;           /* Indicates initial offset (0 or 1) */
283554695375SMatthew G. Knepley   PetscInt       ncon       = 1;           /* The number of weights per vertex */
283654695375SMatthew G. Knepley   PetscInt       nparts;                   /* The number of partitions */
283754695375SMatthew G. Knepley   PetscReal     *tpwgts;                   /* The fraction of vertex weights assigned to each partition */
283854695375SMatthew G. Knepley   PetscReal     *ubvec;                    /* The balance intolerance for vertex weights */
283954695375SMatthew G. Knepley   PetscInt       options[5];               /* Options */
284054695375SMatthew G. Knepley   /* Outputs */
284154695375SMatthew G. Knepley   PetscInt       edgeCut;                  /* The number of edges cut by the partition */
284225cda350SMatthew G. Knepley   PetscInt      *assignment, *points;
284325cda350SMatthew G. Knepley   PetscMPIInt    commSize, rank, p, v, i;
284425cda350SMatthew G. Knepley   PetscErrorCode ierr;
284525cda350SMatthew G. Knepley 
2846552f7358SJed Brown   PetscFunctionBegin;
284725cda350SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr);
284825cda350SMatthew G. Knepley   ierr = MPI_Comm_size(comm, &commSize);CHKERRQ(ierr);
284925cda350SMatthew G. Knepley   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
285025cda350SMatthew G. Knepley   nparts = commSize;
285125cda350SMatthew G. Knepley   options[0] = 0; /* Use all defaults */
285225cda350SMatthew G. Knepley   /* Calculate vertex distribution */
2853dcca6d9dSJed Brown   ierr = PetscMalloc4(nparts+1,&vtxdist,nparts*ncon,&tpwgts,ncon,&ubvec,nvtxs,&assignment);CHKERRQ(ierr);
285425cda350SMatthew G. Knepley   vtxdist[0] = 0;
285525cda350SMatthew G. Knepley   ierr = MPI_Allgather(&nvtxs, 1, MPIU_INT, &vtxdist[1], 1, MPIU_INT, comm);CHKERRQ(ierr);
285625cda350SMatthew G. Knepley   for (p = 2; p <= nparts; ++p) {
285725cda350SMatthew G. Knepley     vtxdist[p] += vtxdist[p-1];
285825cda350SMatthew G. Knepley   }
285925cda350SMatthew G. Knepley   /* Calculate weights */
286025cda350SMatthew G. Knepley   for (p = 0; p < nparts; ++p) {
286125cda350SMatthew G. Knepley     tpwgts[p] = 1.0/nparts;
286225cda350SMatthew G. Knepley   }
286325cda350SMatthew G. Knepley   ubvec[0] = 1.05;
286425cda350SMatthew G. Knepley 
286525cda350SMatthew G. Knepley   if (nparts == 1) {
286625cda350SMatthew G. Knepley     ierr = PetscMemzero(assignment, nvtxs * sizeof(PetscInt));
286725cda350SMatthew G. Knepley   } else {
286825cda350SMatthew G. Knepley     if (vtxdist[1] == vtxdist[nparts]) {
286925cda350SMatthew G. Knepley       if (!rank) {
2870e7ee2502SMatthew G. Knepley         PetscStackPush("METIS_PartGraphKway");
2871e7ee2502SMatthew G. Knepley         ierr = METIS_PartGraphKway(&nvtxs, &ncon, xadj, adjncy, vwgt, NULL, adjwgt, &nparts, tpwgts, ubvec, NULL, &edgeCut, assignment);
2872e7ee2502SMatthew G. Knepley         PetscStackPop;
2873e7ee2502SMatthew G. Knepley         if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in METIS_PartGraphKway()");
287425cda350SMatthew G. Knepley       }
287525cda350SMatthew G. Knepley     } else {
2876e7ee2502SMatthew G. Knepley       PetscStackPush("ParMETIS_V3_PartKway");
2877e7ee2502SMatthew G. Knepley       ierr = ParMETIS_V3_PartKway(vtxdist, xadj, adjncy, vwgt, adjwgt, &wgtflag, &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgeCut, assignment, &comm);
2878e7ee2502SMatthew G. Knepley       PetscStackPop;
2879e7ee2502SMatthew G. Knepley       if (ierr != METIS_OK) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in ParMETIS_V3_PartKway()");
288025cda350SMatthew G. Knepley     }
288125cda350SMatthew G. Knepley   }
288225cda350SMatthew G. Knepley   /* Convert to PetscSection+IS */
288325cda350SMatthew G. Knepley   ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr);
288425cda350SMatthew G. Knepley   ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr);
288525cda350SMatthew G. Knepley   for (v = 0; v < nvtxs; ++v) {
288625cda350SMatthew G. Knepley     ierr = PetscSectionAddDof(*partSection, assignment[v], 1);CHKERRQ(ierr);
288725cda350SMatthew G. Knepley   }
288825cda350SMatthew G. Knepley   ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr);
2889785e854fSJed Brown   ierr = PetscMalloc1(nvtxs, &points);CHKERRQ(ierr);
289025cda350SMatthew G. Knepley   for (p = 0, i = 0; p < commSize; ++p) {
289125cda350SMatthew G. Knepley     for (v = 0; v < nvtxs; ++v) {
289225cda350SMatthew G. Knepley       if (assignment[v] == p) points[i++] = v;
289325cda350SMatthew G. Knepley     }
289425cda350SMatthew G. Knepley   }
289525cda350SMatthew G. Knepley   if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs);
289625cda350SMatthew G. Knepley   ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr);
289725cda350SMatthew G. Knepley   ierr = PetscFree4(vtxdist,tpwgts,ubvec,assignment);CHKERRQ(ierr);
2898552f7358SJed Brown   PetscFunctionReturn(0);
2899552f7358SJed Brown }
2900552f7358SJed Brown #endif
2901552f7358SJed Brown 
2902552f7358SJed Brown #undef __FUNCT__
2903552f7358SJed Brown #define __FUNCT__ "DMPlexEnlargePartition"
2904552f7358SJed Brown /* Expand the partition by BFS on the adjacency graph */
2905a6dfd86eSKarl Rupp PetscErrorCode DMPlexEnlargePartition(DM dm, const PetscInt start[], const PetscInt adjacency[], PetscSection origPartSection, IS origPartition, PetscSection *partSection, IS *partition)
2906a6dfd86eSKarl Rupp {
2907552f7358SJed Brown   PetscHashI      h;
2908552f7358SJed Brown   const PetscInt *points;
2909552f7358SJed Brown   PetscInt      **tmpPoints, *newPoints, totPoints = 0;
2910552f7358SJed Brown   PetscInt        pStart, pEnd, part, q;
2911552f7358SJed Brown   PetscErrorCode  ierr;
2912552f7358SJed Brown 
2913552f7358SJed Brown   PetscFunctionBegin;
2914552f7358SJed Brown   PetscHashICreate(h);
291582f516ccSBarry Smith   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), partSection);CHKERRQ(ierr);
2916552f7358SJed Brown   ierr = PetscSectionGetChart(origPartSection, &pStart, &pEnd);CHKERRQ(ierr);
2917552f7358SJed Brown   ierr = PetscSectionSetChart(*partSection, pStart, pEnd);CHKERRQ(ierr);
2918552f7358SJed Brown   ierr = ISGetIndices(origPartition, &points);CHKERRQ(ierr);
2919785e854fSJed Brown   ierr = PetscMalloc1((pEnd - pStart), &tmpPoints);CHKERRQ(ierr);
2920552f7358SJed Brown   for (part = pStart; part < pEnd; ++part) {
2921552f7358SJed Brown     PetscInt numPoints, nP, numNewPoints, off, p, n = 0;
2922552f7358SJed Brown 
2923552f7358SJed Brown     PetscHashIClear(h);
2924552f7358SJed Brown     ierr = PetscSectionGetDof(origPartSection, part, &numPoints);CHKERRQ(ierr);
2925552f7358SJed Brown     ierr = PetscSectionGetOffset(origPartSection, part, &off);CHKERRQ(ierr);
2926552f7358SJed Brown     /* Add all existing points to h */
2927552f7358SJed Brown     for (p = 0; p < numPoints; ++p) {
2928552f7358SJed Brown       const PetscInt point = points[off+p];
2929552f7358SJed Brown       PetscHashIAdd(h, point, 1);
2930552f7358SJed Brown     }
2931552f7358SJed Brown     PetscHashISize(h, nP);
293282f516ccSBarry Smith     if (nP != numPoints) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Invalid partition has %d points, but only %d were unique", numPoints, nP);
2933552f7358SJed Brown     /* Add all points in next BFS level */
2934552f7358SJed Brown     /*   TODO We are brute forcing here, but could check the adjacency size to find the boundary */
2935552f7358SJed Brown     for (p = 0; p < numPoints; ++p) {
2936552f7358SJed Brown       const PetscInt point = points[off+p];
2937552f7358SJed Brown       PetscInt       s     = start[point], e = start[point+1], a;
2938552f7358SJed Brown 
29390d644c17SKarl Rupp       for (a = s; a < e; ++a) PetscHashIAdd(h, adjacency[a], 1);
2940552f7358SJed Brown     }
2941552f7358SJed Brown     PetscHashISize(h, numNewPoints);
2942552f7358SJed Brown     ierr = PetscSectionSetDof(*partSection, part, numNewPoints);CHKERRQ(ierr);
2943785e854fSJed Brown     ierr = PetscMalloc1(numNewPoints, &tmpPoints[part]);CHKERRQ(ierr);
2944c9fc7396SMatthew G. Knepley     ierr =  PetscHashIGetKeys(h, &n, tmpPoints[part]);CHKERRQ(ierr);
2945552f7358SJed Brown     totPoints += numNewPoints;
2946552f7358SJed Brown   }
2947552f7358SJed Brown   ierr = ISRestoreIndices(origPartition, &points);CHKERRQ(ierr);
2948552f7358SJed Brown   PetscHashIDestroy(h);
2949552f7358SJed Brown   ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr);
2950785e854fSJed Brown   ierr = PetscMalloc1(totPoints, &newPoints);CHKERRQ(ierr);
2951552f7358SJed Brown   for (part = pStart, q = 0; part < pEnd; ++part) {
2952552f7358SJed Brown     PetscInt numPoints, p;
2953552f7358SJed Brown 
2954552f7358SJed Brown     ierr = PetscSectionGetDof(*partSection, part, &numPoints);CHKERRQ(ierr);
29550d644c17SKarl Rupp     for (p = 0; p < numPoints; ++p, ++q) newPoints[q] = tmpPoints[part][p];
2956552f7358SJed Brown     ierr = PetscFree(tmpPoints[part]);CHKERRQ(ierr);
2957552f7358SJed Brown   }
2958552f7358SJed Brown   ierr = PetscFree(tmpPoints);CHKERRQ(ierr);
295982f516ccSBarry Smith   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), totPoints, newPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr);
2960552f7358SJed Brown   PetscFunctionReturn(0);
2961552f7358SJed Brown }
2962552f7358SJed Brown 
2963552f7358SJed Brown #undef __FUNCT__
2964552f7358SJed Brown #define __FUNCT__ "DMPlexCreatePartition"
2965552f7358SJed Brown /*
2966552f7358SJed Brown   DMPlexCreatePartition - Create a non-overlapping partition of the points at the given height
2967552f7358SJed Brown 
2968552f7358SJed Brown   Collective on DM
2969552f7358SJed Brown 
2970552f7358SJed Brown   Input Parameters:
2971552f7358SJed Brown   + dm - The DM
2972552f7358SJed Brown   . height - The height for points in the partition
2973552f7358SJed Brown   - enlarge - Expand each partition with neighbors
2974552f7358SJed Brown 
2975552f7358SJed Brown   Output Parameters:
2976552f7358SJed Brown   + partSection - The PetscSection giving the division of points by partition
2977552f7358SJed Brown   . partition - The list of points by partition
29780298fd71SBarry Smith   . origPartSection - If enlarge is true, the PetscSection giving the division of points before enlarging by partition, otherwise NULL
29790298fd71SBarry Smith   - origPartition - If enlarge is true, the list of points before enlarging by partition, otherwise NULL
2980552f7358SJed Brown 
2981552f7358SJed Brown   Level: developer
2982552f7358SJed Brown 
2983552f7358SJed Brown .seealso DMPlexDistribute()
2984552f7358SJed Brown */
2985ac17c9edSMatthew G. Knepley PetscErrorCode DMPlexCreatePartition(DM dm, const char name[], PetscInt height, PetscBool enlarge, PetscSection *partSection, IS *partition, PetscSection *origPartSection, IS *origPartition)
29860adebc6cSBarry Smith {
2987ac17c9edSMatthew G. Knepley   char           partname[1024];
2988ac17c9edSMatthew G. Knepley   PetscBool      isChaco = PETSC_FALSE, isMetis = PETSC_FALSE, flg;
2989552f7358SJed Brown   PetscMPIInt    size;
2990552f7358SJed Brown   PetscErrorCode ierr;
2991552f7358SJed Brown 
2992552f7358SJed Brown   PetscFunctionBegin;
299382f516ccSBarry Smith   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr);
29940d644c17SKarl Rupp 
29950298fd71SBarry Smith   *origPartSection = NULL;
29960298fd71SBarry Smith   *origPartition   = NULL;
2997552f7358SJed Brown   if (size == 1) {
2998552f7358SJed Brown     PetscInt *points;
2999552f7358SJed Brown     PetscInt  cStart, cEnd, c;
3000552f7358SJed Brown 
3001552f7358SJed Brown     ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
300282f516ccSBarry Smith     ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), partSection);CHKERRQ(ierr);
3003552f7358SJed Brown     ierr = PetscSectionSetChart(*partSection, 0, size);CHKERRQ(ierr);
3004552f7358SJed Brown     ierr = PetscSectionSetDof(*partSection, 0, cEnd-cStart);CHKERRQ(ierr);
3005552f7358SJed Brown     ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr);
3006785e854fSJed Brown     ierr = PetscMalloc1((cEnd - cStart), &points);CHKERRQ(ierr);
30070d644c17SKarl Rupp     for (c = cStart; c < cEnd; ++c) points[c] = c;
300882f516ccSBarry Smith     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr);
3009552f7358SJed Brown     PetscFunctionReturn(0);
3010552f7358SJed Brown   }
3011ac17c9edSMatthew G. Knepley   ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_partitioner", partname, 1024, &flg);CHKERRQ(ierr);
3012ac17c9edSMatthew G. Knepley   if (flg) name = partname;
3013ac17c9edSMatthew G. Knepley   if (name) {
3014ac17c9edSMatthew G. Knepley     ierr = PetscStrcmp(name, "chaco", &isChaco);CHKERRQ(ierr);
3015ac17c9edSMatthew G. Knepley     ierr = PetscStrcmp(name, "metis", &isMetis);CHKERRQ(ierr);
3016ac17c9edSMatthew G. Knepley   }
3017552f7358SJed Brown   if (height == 0) {
3018552f7358SJed Brown     PetscInt  numVertices;
30190298fd71SBarry Smith     PetscInt *start     = NULL;
30200298fd71SBarry Smith     PetscInt *adjacency = NULL;
3021552f7358SJed Brown 
302277c88f5bSMatthew G Knepley     ierr = DMPlexCreateNeighborCSR(dm, 0, &numVertices, &start, &adjacency);CHKERRQ(ierr);
3023ac17c9edSMatthew G. Knepley     if (!name || isChaco) {
3024519f805aSKarl Rupp #if defined(PETSC_HAVE_CHACO)
3025552f7358SJed Brown       ierr = DMPlexPartition_Chaco(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr);
3026ac17c9edSMatthew G. Knepley #else
3027ac17c9edSMatthew G. Knepley       SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Mesh partitioning needs external package support.\nPlease reconfigure with --download-chaco.");
3028552f7358SJed Brown #endif
3029ac17c9edSMatthew G. Knepley     } else if (isMetis) {
3030519f805aSKarl Rupp #if defined(PETSC_HAVE_PARMETIS)
3031552f7358SJed Brown       ierr = DMPlexPartition_ParMetis(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr);
3032552f7358SJed Brown #endif
3033ac17c9edSMatthew G. Knepley     } else SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Unknown mesh partitioning package %s", name);
3034552f7358SJed Brown     if (enlarge) {
3035552f7358SJed Brown       *origPartSection = *partSection;
3036552f7358SJed Brown       *origPartition   = *partition;
30370d644c17SKarl Rupp 
3038552f7358SJed Brown       ierr = DMPlexEnlargePartition(dm, start, adjacency, *origPartSection, *origPartition, partSection, partition);CHKERRQ(ierr);
3039552f7358SJed Brown     }
3040552f7358SJed Brown     ierr = PetscFree(start);CHKERRQ(ierr);
3041552f7358SJed Brown     ierr = PetscFree(adjacency);CHKERRQ(ierr);
3042552f7358SJed Brown # if 0
3043552f7358SJed Brown   } else if (height == 1) {
3044552f7358SJed Brown     /* Build the dual graph for faces and partition the hypergraph */
3045552f7358SJed Brown     PetscInt numEdges;
3046552f7358SJed Brown 
3047552f7358SJed Brown     buildFaceCSRV(mesh, mesh->getFactory()->getNumbering(mesh, mesh->depth()-1), &numEdges, &start, &adjacency, GraphPartitioner::zeroBase());
3048552f7358SJed Brown     GraphPartitioner().partition(numEdges, start, adjacency, partition, manager);
3049552f7358SJed Brown     destroyCSR(numEdges, start, adjacency);
3050552f7358SJed Brown #endif
305182f516ccSBarry Smith   } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid partition height %D", height);
3052552f7358SJed Brown   PetscFunctionReturn(0);
3053552f7358SJed Brown }
3054552f7358SJed Brown 
3055552f7358SJed Brown #undef __FUNCT__
3056552f7358SJed Brown #define __FUNCT__ "DMPlexCreatePartitionClosure"
30570adebc6cSBarry Smith PetscErrorCode DMPlexCreatePartitionClosure(DM dm, PetscSection pointSection, IS pointPartition, PetscSection *section, IS *partition)
30580adebc6cSBarry Smith {
3059552f7358SJed Brown   /* const PetscInt  height = 0; */
3060552f7358SJed Brown   const PetscInt *partArray;
3061cb3cb6d9SJed Brown   PetscInt       *allPoints, *packPoints;
3062cb3cb6d9SJed Brown   PetscInt        rStart, rEnd, rank, pStart, pEnd, newSize;
3063552f7358SJed Brown   PetscErrorCode  ierr;
3064cb3cb6d9SJed Brown   PetscBT         bt;
3065cb3cb6d9SJed Brown   PetscSegBuffer  segpack,segpart;
3066552f7358SJed Brown 
3067552f7358SJed Brown   PetscFunctionBegin;
3068552f7358SJed Brown   ierr = PetscSectionGetChart(pointSection, &rStart, &rEnd);CHKERRQ(ierr);
3069552f7358SJed Brown   ierr = ISGetIndices(pointPartition, &partArray);CHKERRQ(ierr);
307082f516ccSBarry Smith   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr);
3071552f7358SJed Brown   ierr = PetscSectionSetChart(*section, rStart, rEnd);CHKERRQ(ierr);
3072cb3cb6d9SJed Brown   ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr);
3073cb3cb6d9SJed Brown   ierr = PetscBTCreate(pEnd-pStart,&bt);CHKERRQ(ierr);
3074cb3cb6d9SJed Brown   ierr = PetscSegBufferCreate(sizeof(PetscInt),1000,&segpack);CHKERRQ(ierr);
3075cb3cb6d9SJed Brown   ierr = PetscSegBufferCreate(sizeof(PetscInt),1000,&segpart);CHKERRQ(ierr);
3076552f7358SJed Brown   for (rank = rStart; rank < rEnd; ++rank) {
3077471ecdacSJed Brown     PetscInt partSize = 0, numPoints, offset, p, *PETSC_RESTRICT placePoints;
3078552f7358SJed Brown 
3079552f7358SJed Brown     ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr);
3080552f7358SJed Brown     ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr);
3081552f7358SJed Brown     for (p = 0; p < numPoints; ++p) {
3082552f7358SJed Brown       PetscInt  point   = partArray[offset+p], closureSize, c;
30830298fd71SBarry Smith       PetscInt *closure = NULL;
3084552f7358SJed Brown 
3085552f7358SJed Brown       /* TODO Include support for height > 0 case */
3086552f7358SJed Brown       ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
3087cb3cb6d9SJed Brown       for (c=0; c<closureSize; c++) {
3088cb3cb6d9SJed Brown         PetscInt cpoint = closure[c*2];
3089cb3cb6d9SJed Brown         if (!PetscBTLookupSet(bt,cpoint-pStart)) {
3090471ecdacSJed Brown           PetscInt *PETSC_RESTRICT pt;
3091cb3cb6d9SJed Brown           partSize++;
3092471ecdacSJed Brown           ierr = PetscSegBufferGetInts(segpart,1,&pt);CHKERRQ(ierr);
3093cb3cb6d9SJed Brown           *pt = cpoint;
3094552f7358SJed Brown         }
3095cb3cb6d9SJed Brown       }
3096552f7358SJed Brown       ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
3097552f7358SJed Brown     }
3098552f7358SJed Brown     ierr = PetscSectionSetDof(*section, rank, partSize);CHKERRQ(ierr);
3099471ecdacSJed Brown     ierr = PetscSegBufferGetInts(segpack,partSize,&placePoints);CHKERRQ(ierr);
3100471ecdacSJed Brown     ierr = PetscSegBufferExtractTo(segpart,placePoints);CHKERRQ(ierr);
3101471ecdacSJed Brown     ierr = PetscSortInt(partSize,placePoints);CHKERRQ(ierr);
3102471ecdacSJed Brown     for (p=0; p<partSize; p++) {ierr = PetscBTClear(bt,placePoints[p]-pStart);CHKERRQ(ierr);}
3103552f7358SJed Brown   }
3104cb3cb6d9SJed Brown   ierr = PetscBTDestroy(&bt);CHKERRQ(ierr);
3105cb3cb6d9SJed Brown   ierr = PetscSegBufferDestroy(&segpart);CHKERRQ(ierr);
3106cb3cb6d9SJed Brown 
3107552f7358SJed Brown   ierr = PetscSectionSetUp(*section);CHKERRQ(ierr);
3108552f7358SJed Brown   ierr = PetscSectionGetStorageSize(*section, &newSize);CHKERRQ(ierr);
3109785e854fSJed Brown   ierr = PetscMalloc1(newSize, &allPoints);CHKERRQ(ierr);
3110552f7358SJed Brown 
3111137cf7b6SJed Brown   ierr = PetscSegBufferExtractInPlace(segpack,&packPoints);CHKERRQ(ierr);
3112552f7358SJed Brown   for (rank = rStart; rank < rEnd; ++rank) {
3113cb3cb6d9SJed Brown     PetscInt numPoints, offset;
3114552f7358SJed Brown 
3115cb3cb6d9SJed Brown     ierr = PetscSectionGetDof(*section, rank, &numPoints);CHKERRQ(ierr);
3116cb3cb6d9SJed Brown     ierr = PetscSectionGetOffset(*section, rank, &offset);CHKERRQ(ierr);
3117cb3cb6d9SJed Brown     ierr = PetscMemcpy(&allPoints[offset], packPoints, numPoints * sizeof(PetscInt));CHKERRQ(ierr);
3118cb3cb6d9SJed Brown     packPoints += numPoints;
3119552f7358SJed Brown   }
3120cb3cb6d9SJed Brown 
3121cb3cb6d9SJed Brown   ierr = PetscSegBufferDestroy(&segpack);CHKERRQ(ierr);
3122552f7358SJed Brown   ierr = ISRestoreIndices(pointPartition, &partArray);CHKERRQ(ierr);
312382f516ccSBarry Smith   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), newSize, allPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr);
3124552f7358SJed Brown   PetscFunctionReturn(0);
3125552f7358SJed Brown }
3126552f7358SJed Brown 
3127552f7358SJed Brown #undef __FUNCT__
3128552f7358SJed Brown #define __FUNCT__ "DMPlexDistributeField"
31291858a729SMatthew G. Knepley /*@
31301858a729SMatthew G. Knepley   DMPlexDistributeField - Distribute field data to match a given PetscSF, usually the SF from mesh distribution
31311858a729SMatthew G. Knepley 
31321858a729SMatthew G. Knepley   Collective on DM
31331858a729SMatthew G. Knepley 
3134552f7358SJed Brown   Input Parameters:
31351858a729SMatthew G. Knepley + dm - The DMPlex object
31361858a729SMatthew G. Knepley . pointSF - The PetscSF describing the communication pattern
31371858a729SMatthew G. Knepley . originalSection - The PetscSection for existing data layout
31381858a729SMatthew G. Knepley - originalVec - The existing data
3139552f7358SJed Brown 
3140552f7358SJed Brown   Output Parameters:
31411858a729SMatthew G. Knepley + newSection - The PetscSF describing the new data layout
31421858a729SMatthew G. Knepley - newVec - The new data
31431858a729SMatthew G. Knepley 
31441858a729SMatthew G. Knepley   Level: developer
31451858a729SMatthew G. Knepley 
31461858a729SMatthew G. Knepley .seealso: DMPlexDistribute(), DMPlexDistributeData()
31471858a729SMatthew G. Knepley @*/
3148552f7358SJed Brown PetscErrorCode DMPlexDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec)
3149552f7358SJed Brown {
3150552f7358SJed Brown   PetscSF        fieldSF;
3151552f7358SJed Brown   PetscInt      *remoteOffsets, fieldSize;
3152552f7358SJed Brown   PetscScalar   *originalValues, *newValues;
3153552f7358SJed Brown   PetscErrorCode ierr;
3154552f7358SJed Brown 
3155552f7358SJed Brown   PetscFunctionBegin;
31561337e6e5SMatthew G. Knepley   ierr = PetscLogEventBegin(DMPLEX_DistributeField,dm,0,0,0);CHKERRQ(ierr);
3157552f7358SJed Brown   ierr = PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection);CHKERRQ(ierr);
3158552f7358SJed Brown 
3159552f7358SJed Brown   ierr = PetscSectionGetStorageSize(newSection, &fieldSize);CHKERRQ(ierr);
3160552f7358SJed Brown   ierr = VecSetSizes(newVec, fieldSize, PETSC_DETERMINE);CHKERRQ(ierr);
3161c0dedaeaSBarry Smith   ierr = VecSetType(newVec,dm->vectype);CHKERRQ(ierr);
3162552f7358SJed Brown 
3163552f7358SJed Brown   ierr = VecGetArray(originalVec, &originalValues);CHKERRQ(ierr);
3164552f7358SJed Brown   ierr = VecGetArray(newVec, &newValues);CHKERRQ(ierr);
3165552f7358SJed Brown   ierr = PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF);CHKERRQ(ierr);
3166552f7358SJed Brown   ierr = PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr);
3167552f7358SJed Brown   ierr = PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr);
3168552f7358SJed Brown   ierr = PetscSFDestroy(&fieldSF);CHKERRQ(ierr);
3169552f7358SJed Brown   ierr = VecRestoreArray(newVec, &newValues);CHKERRQ(ierr);
3170552f7358SJed Brown   ierr = VecRestoreArray(originalVec, &originalValues);CHKERRQ(ierr);
31711337e6e5SMatthew G. Knepley   ierr = PetscLogEventEnd(DMPLEX_DistributeField,dm,0,0,0);CHKERRQ(ierr);
3172552f7358SJed Brown   PetscFunctionReturn(0);
3173552f7358SJed Brown }
3174552f7358SJed Brown 
3175552f7358SJed Brown #undef __FUNCT__
31761858a729SMatthew G. Knepley #define __FUNCT__ "DMPlexDistributeData"
31771858a729SMatthew G. Knepley /*@
31781858a729SMatthew G. Knepley   DMPlexDistributeData - Distribute field data to match a given PetscSF, usually the SF from mesh distribution
31791858a729SMatthew G. Knepley 
31801858a729SMatthew G. Knepley   Collective on DM
31811858a729SMatthew G. Knepley 
31821858a729SMatthew G. Knepley   Input Parameters:
31831858a729SMatthew G. Knepley + dm - The DMPlex object
31841858a729SMatthew G. Knepley . pointSF - The PetscSF describing the communication pattern
31851858a729SMatthew G. Knepley . originalSection - The PetscSection for existing data layout
31861858a729SMatthew G. Knepley . datatype - The type of data
31871858a729SMatthew G. Knepley - originalData - The existing data
31881858a729SMatthew G. Knepley 
31891858a729SMatthew G. Knepley   Output Parameters:
31901858a729SMatthew G. Knepley + newSection - The PetscSF describing the new data layout
31911858a729SMatthew G. Knepley - newData - The new data
31921858a729SMatthew G. Knepley 
31931858a729SMatthew G. Knepley   Level: developer
31941858a729SMatthew G. Knepley 
31951858a729SMatthew G. Knepley .seealso: DMPlexDistribute(), DMPlexDistributeField()
31961858a729SMatthew G. Knepley @*/
31971858a729SMatthew G. Knepley PetscErrorCode DMPlexDistributeData(DM dm, PetscSF pointSF, PetscSection originalSection, MPI_Datatype datatype, void *originalData, PetscSection newSection, void **newData)
31981858a729SMatthew G. Knepley {
31991858a729SMatthew G. Knepley   PetscSF        fieldSF;
32001858a729SMatthew G. Knepley   PetscInt      *remoteOffsets, fieldSize;
32011858a729SMatthew G. Knepley   PetscMPIInt    dataSize;
32021858a729SMatthew G. Knepley   PetscErrorCode ierr;
32031858a729SMatthew G. Knepley 
32041858a729SMatthew G. Knepley   PetscFunctionBegin;
32051337e6e5SMatthew G. Knepley   ierr = PetscLogEventBegin(DMPLEX_DistributeData,dm,0,0,0);CHKERRQ(ierr);
32061858a729SMatthew G. Knepley   ierr = PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection);CHKERRQ(ierr);
32071858a729SMatthew G. Knepley 
32081858a729SMatthew G. Knepley   ierr = PetscSectionGetStorageSize(newSection, &fieldSize);CHKERRQ(ierr);
32091858a729SMatthew G. Knepley   ierr = MPI_Type_size(datatype, &dataSize);CHKERRQ(ierr);
32101858a729SMatthew G. Knepley   ierr = PetscMalloc(fieldSize * dataSize, newData);CHKERRQ(ierr);
32111858a729SMatthew G. Knepley 
32121858a729SMatthew G. Knepley   ierr = PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF);CHKERRQ(ierr);
32131858a729SMatthew G. Knepley   ierr = PetscSFBcastBegin(fieldSF, datatype, originalData, *newData);CHKERRQ(ierr);
32141858a729SMatthew G. Knepley   ierr = PetscSFBcastEnd(fieldSF, datatype, originalData, *newData);CHKERRQ(ierr);
32151858a729SMatthew G. Knepley   ierr = PetscSFDestroy(&fieldSF);CHKERRQ(ierr);
32161337e6e5SMatthew G. Knepley   ierr = PetscLogEventEnd(DMPLEX_DistributeData,dm,0,0,0);CHKERRQ(ierr);
32171858a729SMatthew G. Knepley   PetscFunctionReturn(0);
32181858a729SMatthew G. Knepley }
32191858a729SMatthew G. Knepley 
32201858a729SMatthew G. Knepley #undef __FUNCT__
3221552f7358SJed Brown #define __FUNCT__ "DMPlexDistribute"
3222552f7358SJed Brown /*@C
3223552f7358SJed Brown   DMPlexDistribute - Distributes the mesh and any associated sections.
3224552f7358SJed Brown 
3225552f7358SJed Brown   Not Collective
3226552f7358SJed Brown 
3227552f7358SJed Brown   Input Parameter:
3228552f7358SJed Brown + dm  - The original DMPlex object
3229552f7358SJed Brown . partitioner - The partitioning package, or NULL for the default
3230552f7358SJed Brown - overlap - The overlap of partitions, 0 is the default
3231552f7358SJed Brown 
3232552f7358SJed Brown   Output Parameter:
3233e7ba9e7aSMatthew G. Knepley + sf - The PetscSF used for point distribution
3234e7ba9e7aSMatthew G. Knepley - parallelMesh - The distributed DMPlex object, or NULL
3235552f7358SJed Brown 
32360298fd71SBarry Smith   Note: If the mesh was not distributed, the return value is NULL
3237552f7358SJed Brown 
3238552f7358SJed Brown   Level: intermediate
3239552f7358SJed Brown 
3240552f7358SJed Brown .keywords: mesh, elements
3241552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexDistributeByFace()
3242552f7358SJed Brown @*/
3243e7ba9e7aSMatthew G. Knepley PetscErrorCode DMPlexDistribute(DM dm, const char partitioner[], PetscInt overlap, PetscSF *sf, DM *dmParallel)
3244552f7358SJed Brown {
3245552f7358SJed Brown   DM_Plex               *mesh   = (DM_Plex*) dm->data, *pmesh;
324682f516ccSBarry Smith   MPI_Comm               comm;
3247552f7358SJed Brown   const PetscInt         height = 0;
3248552f7358SJed Brown   PetscInt               dim, numRemoteRanks;
3249057e8d19SMichael Lange   IS                     origCellPart,        origPart,        cellPart,        part;
3250057e8d19SMichael Lange   PetscSection           origCellPartSection, origPartSection, cellPartSection, partSection;
3251552f7358SJed Brown   PetscSFNode           *remoteRanks;
3252552f7358SJed Brown   PetscSF                partSF, pointSF, coneSF;
3253552f7358SJed Brown   ISLocalToGlobalMapping renumbering;
3254552f7358SJed Brown   PetscSection           originalConeSection, newConeSection;
3255552f7358SJed Brown   PetscInt              *remoteOffsets;
3256552f7358SJed Brown   PetscInt              *cones, *newCones, newConesSize;
3257552f7358SJed Brown   PetscBool              flg;
3258552f7358SJed Brown   PetscMPIInt            rank, numProcs, p;
3259552f7358SJed Brown   PetscErrorCode         ierr;
3260552f7358SJed Brown 
3261552f7358SJed Brown   PetscFunctionBegin;
3262552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3263e7ba9e7aSMatthew G. Knepley   if (sf) PetscValidPointer(sf,4);
3264e7ba9e7aSMatthew G. Knepley   PetscValidPointer(dmParallel,5);
32650d644c17SKarl Rupp 
3266552f7358SJed Brown   ierr = PetscLogEventBegin(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr);
326782f516ccSBarry Smith   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
3268552f7358SJed Brown   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
3269552f7358SJed Brown   ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr);
32700d644c17SKarl Rupp 
32710298fd71SBarry Smith   *dmParallel = NULL;
3272552f7358SJed Brown   if (numProcs == 1) PetscFunctionReturn(0);
3273552f7358SJed Brown 
3274552f7358SJed Brown   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
3275552f7358SJed Brown   /* Create cell partition - We need to rewrite to use IS, use the MatPartition stuff */
3276b96ba592SMatthew G. Knepley   ierr = PetscLogEventBegin(DMPLEX_Partition,dm,0,0,0);CHKERRQ(ierr);
327782f516ccSBarry Smith   if (overlap > 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Overlap > 1 not yet implemented");
3278ac17c9edSMatthew G. Knepley   ierr = DMPlexCreatePartition(dm, partitioner, height, overlap > 0 ? PETSC_TRUE : PETSC_FALSE, &cellPartSection, &cellPart, &origCellPartSection, &origCellPart);CHKERRQ(ierr);
3279552f7358SJed Brown   /* Create SF assuming a serial partition for all processes: Could check for IS length here */
32800d644c17SKarl Rupp   if (!rank) numRemoteRanks = numProcs;
32810d644c17SKarl Rupp   else       numRemoteRanks = 0;
3282785e854fSJed Brown   ierr = PetscMalloc1(numRemoteRanks, &remoteRanks);CHKERRQ(ierr);
3283552f7358SJed Brown   for (p = 0; p < numRemoteRanks; ++p) {
3284552f7358SJed Brown     remoteRanks[p].rank  = p;
3285552f7358SJed Brown     remoteRanks[p].index = 0;
3286552f7358SJed Brown   }
3287552f7358SJed Brown   ierr = PetscSFCreate(comm, &partSF);CHKERRQ(ierr);
32880298fd71SBarry Smith   ierr = PetscSFSetGraph(partSF, 1, numRemoteRanks, NULL, PETSC_OWN_POINTER, remoteRanks, PETSC_OWN_POINTER);CHKERRQ(ierr);
3289552f7358SJed Brown   ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-partition_view", &flg);CHKERRQ(ierr);
3290552f7358SJed Brown   if (flg) {
3291552f7358SJed Brown     ierr = PetscPrintf(comm, "Cell Partition:\n");CHKERRQ(ierr);
3292552f7358SJed Brown     ierr = PetscSectionView(cellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
32930298fd71SBarry Smith     ierr = ISView(cellPart, NULL);CHKERRQ(ierr);
3294552f7358SJed Brown     if (origCellPart) {
3295552f7358SJed Brown       ierr = PetscPrintf(comm, "Original Cell Partition:\n");CHKERRQ(ierr);
3296552f7358SJed Brown       ierr = PetscSectionView(origCellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
32970298fd71SBarry Smith       ierr = ISView(origCellPart, NULL);CHKERRQ(ierr);
3298552f7358SJed Brown     }
32990298fd71SBarry Smith     ierr = PetscSFView(partSF, NULL);CHKERRQ(ierr);
3300552f7358SJed Brown   }
3301552f7358SJed Brown   /* Close the partition over the mesh */
3302552f7358SJed Brown   ierr = DMPlexCreatePartitionClosure(dm, cellPartSection, cellPart, &partSection, &part);CHKERRQ(ierr);
3303552f7358SJed Brown   ierr = ISDestroy(&cellPart);CHKERRQ(ierr);
3304552f7358SJed Brown   ierr = PetscSectionDestroy(&cellPartSection);CHKERRQ(ierr);
3305552f7358SJed Brown   /* Create new mesh */
3306552f7358SJed Brown   ierr  = DMPlexCreate(comm, dmParallel);CHKERRQ(ierr);
3307552f7358SJed Brown   ierr  = DMPlexSetDimension(*dmParallel, dim);CHKERRQ(ierr);
3308552f7358SJed Brown   ierr  = PetscObjectSetName((PetscObject) *dmParallel, "Parallel Mesh");CHKERRQ(ierr);
3309552f7358SJed Brown   pmesh = (DM_Plex*) (*dmParallel)->data;
3310552f7358SJed Brown   /* Distribute sieve points and the global point numbering (replaces creating remote bases) */
3311552f7358SJed Brown   ierr = PetscSFConvertPartition(partSF, partSection, part, &renumbering, &pointSF);CHKERRQ(ierr);
3312552f7358SJed Brown   if (flg) {
3313552f7358SJed Brown     ierr = PetscPrintf(comm, "Point Partition:\n");CHKERRQ(ierr);
3314552f7358SJed Brown     ierr = PetscSectionView(partSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
33150298fd71SBarry Smith     ierr = ISView(part, NULL);CHKERRQ(ierr);
33160298fd71SBarry Smith     ierr = PetscSFView(pointSF, NULL);CHKERRQ(ierr);
3317552f7358SJed Brown     ierr = PetscPrintf(comm, "Point Renumbering after partition:\n");CHKERRQ(ierr);
33180298fd71SBarry Smith     ierr = ISLocalToGlobalMappingView(renumbering, NULL);CHKERRQ(ierr);
3319552f7358SJed Brown   }
3320b96ba592SMatthew G. Knepley   ierr = PetscLogEventEnd(DMPLEX_Partition,dm,0,0,0);CHKERRQ(ierr);
33211337e6e5SMatthew G. Knepley   ierr = PetscLogEventBegin(DMPLEX_DistributeCones,dm,0,0,0);CHKERRQ(ierr);
3322552f7358SJed Brown   /* Distribute cone section */
3323552f7358SJed Brown   ierr = DMPlexGetConeSection(dm, &originalConeSection);CHKERRQ(ierr);
3324552f7358SJed Brown   ierr = DMPlexGetConeSection(*dmParallel, &newConeSection);CHKERRQ(ierr);
3325552f7358SJed Brown   ierr = PetscSFDistributeSection(pointSF, originalConeSection, &remoteOffsets, newConeSection);CHKERRQ(ierr);
3326552f7358SJed Brown   ierr = DMSetUp(*dmParallel);CHKERRQ(ierr);
3327552f7358SJed Brown   {
3328552f7358SJed Brown     PetscInt pStart, pEnd, p;
3329552f7358SJed Brown 
3330552f7358SJed Brown     ierr = PetscSectionGetChart(newConeSection, &pStart, &pEnd);CHKERRQ(ierr);
3331552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
3332552f7358SJed Brown       PetscInt coneSize;
3333552f7358SJed Brown       ierr               = PetscSectionGetDof(newConeSection, p, &coneSize);CHKERRQ(ierr);
3334552f7358SJed Brown       pmesh->maxConeSize = PetscMax(pmesh->maxConeSize, coneSize);
3335552f7358SJed Brown     }
3336552f7358SJed Brown   }
3337552f7358SJed Brown   /* Communicate and renumber cones */
3338552f7358SJed Brown   ierr = PetscSFCreateSectionSF(pointSF, originalConeSection, remoteOffsets, newConeSection, &coneSF);CHKERRQ(ierr);
3339552f7358SJed Brown   ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr);
3340552f7358SJed Brown   ierr = DMPlexGetCones(*dmParallel, &newCones);CHKERRQ(ierr);
3341552f7358SJed Brown   ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr);
3342552f7358SJed Brown   ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr);
3343552f7358SJed Brown   ierr = PetscSectionGetStorageSize(newConeSection, &newConesSize);CHKERRQ(ierr);
33440298fd71SBarry Smith   ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newConesSize, newCones, NULL, newCones);CHKERRQ(ierr);
3345552f7358SJed Brown   ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-cones_view", &flg);CHKERRQ(ierr);
3346552f7358SJed Brown   if (flg) {
3347552f7358SJed Brown     ierr = PetscPrintf(comm, "Serial Cone Section:\n");CHKERRQ(ierr);
3348552f7358SJed Brown     ierr = PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
3349552f7358SJed Brown     ierr = PetscPrintf(comm, "Parallel Cone Section:\n");CHKERRQ(ierr);
3350552f7358SJed Brown     ierr = PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
33510298fd71SBarry Smith     ierr = PetscSFView(coneSF, NULL);CHKERRQ(ierr);
3352552f7358SJed Brown   }
3353552f7358SJed Brown   ierr = DMPlexGetConeOrientations(dm, &cones);CHKERRQ(ierr);
3354552f7358SJed Brown   ierr = DMPlexGetConeOrientations(*dmParallel, &newCones);CHKERRQ(ierr);
3355552f7358SJed Brown   ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr);
3356552f7358SJed Brown   ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr);
3357552f7358SJed Brown   ierr = PetscSFDestroy(&coneSF);CHKERRQ(ierr);
33581337e6e5SMatthew G. Knepley   ierr = PetscLogEventEnd(DMPLEX_DistributeCones,dm,0,0,0);CHKERRQ(ierr);
3359552f7358SJed Brown   /* Create supports and stratify sieve */
3360552f7358SJed Brown   {
3361552f7358SJed Brown     PetscInt pStart, pEnd;
3362552f7358SJed Brown 
3363552f7358SJed Brown     ierr = PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr);
3364552f7358SJed Brown     ierr = PetscSectionSetChart(pmesh->supportSection, pStart, pEnd);CHKERRQ(ierr);
3365552f7358SJed Brown   }
3366552f7358SJed Brown   ierr = DMPlexSymmetrize(*dmParallel);CHKERRQ(ierr);
3367552f7358SJed Brown   ierr = DMPlexStratify(*dmParallel);CHKERRQ(ierr);
3368552f7358SJed Brown   /* Distribute Coordinates */
3369552f7358SJed Brown   {
3370552f7358SJed Brown     PetscSection originalCoordSection, newCoordSection;
3371552f7358SJed Brown     Vec          originalCoordinates, newCoordinates;
3372552f7358SJed Brown     const char  *name;
3373552f7358SJed Brown 
337469d8a9ceSMatthew G. Knepley     ierr = DMGetCoordinateSection(dm, &originalCoordSection);CHKERRQ(ierr);
337569d8a9ceSMatthew G. Knepley     ierr = DMGetCoordinateSection(*dmParallel, &newCoordSection);CHKERRQ(ierr);
3376552f7358SJed Brown     ierr = DMGetCoordinatesLocal(dm, &originalCoordinates);CHKERRQ(ierr);
3377552f7358SJed Brown     ierr = VecCreate(comm, &newCoordinates);CHKERRQ(ierr);
3378552f7358SJed Brown     ierr = PetscObjectGetName((PetscObject) originalCoordinates, &name);CHKERRQ(ierr);
3379552f7358SJed Brown     ierr = PetscObjectSetName((PetscObject) newCoordinates, name);CHKERRQ(ierr);
3380552f7358SJed Brown 
3381552f7358SJed Brown     ierr = DMPlexDistributeField(dm, pointSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates);CHKERRQ(ierr);
3382552f7358SJed Brown     ierr = DMSetCoordinatesLocal(*dmParallel, newCoordinates);CHKERRQ(ierr);
3383552f7358SJed Brown     ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr);
3384552f7358SJed Brown   }
3385552f7358SJed Brown   /* Distribute labels */
3386b96ba592SMatthew G. Knepley   ierr = PetscLogEventBegin(DMPLEX_DistributeLabels,dm,0,0,0);CHKERRQ(ierr);
3387552f7358SJed Brown   {
3388552f7358SJed Brown     DMLabel  next      = mesh->labels, newNext = pmesh->labels;
3389552f7358SJed Brown     PetscInt numLabels = 0, l;
3390552f7358SJed Brown 
3391552f7358SJed Brown     /* Bcast number of labels */
339220cb08bdSMatthew G. Knepley     while (next) {++numLabels; next = next->next;}
3393552f7358SJed Brown     ierr = MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm);CHKERRQ(ierr);
3394552f7358SJed Brown     next = mesh->labels;
3395552f7358SJed Brown     for (l = 0; l < numLabels; ++l) {
339620cb08bdSMatthew G. Knepley       DMLabel   labelNew;
3397552f7358SJed Brown       PetscBool isdepth;
3398552f7358SJed Brown 
339920cb08bdSMatthew G. Knepley       /* Skip "depth" because it is recreated */
340020cb08bdSMatthew G. Knepley       if (!rank) {ierr = PetscStrcmp(next->name, "depth", &isdepth);CHKERRQ(ierr);}
340120cb08bdSMatthew G. Knepley       ierr = MPI_Bcast(&isdepth, 1, MPIU_BOOL, 0, comm);CHKERRQ(ierr);
340220cb08bdSMatthew G. Knepley       if (isdepth) {if (!rank) next = next->next; continue;}
340320cb08bdSMatthew G. Knepley       ierr = DMLabelDistribute(next, partSection, part, renumbering, &labelNew);CHKERRQ(ierr);
3404552f7358SJed Brown       /* Insert into list */
340520cb08bdSMatthew G. Knepley       if (newNext) newNext->next = labelNew;
340620cb08bdSMatthew G. Knepley       else         pmesh->labels = labelNew;
340720cb08bdSMatthew G. Knepley       newNext = labelNew;
34080d644c17SKarl Rupp       if (!rank) next = next->next;
3409552f7358SJed Brown     }
3410552f7358SJed Brown   }
3411b96ba592SMatthew G. Knepley   ierr = PetscLogEventEnd(DMPLEX_DistributeLabels,dm,0,0,0);CHKERRQ(ierr);
34125a9d0af9SMatthew G. Knepley   /* Setup hybrid structure */
34135a9d0af9SMatthew G. Knepley   {
34145a9d0af9SMatthew G. Knepley     const PetscInt *gpoints;
34155a9d0af9SMatthew G. Knepley     PetscInt        depth, n, d;
34165a9d0af9SMatthew G. Knepley 
34175a9d0af9SMatthew G. Knepley     for (d = 0; d <= dim; ++d) {pmesh->hybridPointMax[d] = mesh->hybridPointMax[d];}
34185a9d0af9SMatthew G. Knepley     ierr = MPI_Bcast(pmesh->hybridPointMax, dim+1, MPIU_INT, 0, comm);CHKERRQ(ierr);
34195a9d0af9SMatthew G. Knepley     ierr = ISLocalToGlobalMappingGetSize(renumbering, &n);CHKERRQ(ierr);
34205a9d0af9SMatthew G. Knepley     ierr = ISLocalToGlobalMappingGetIndices(renumbering, &gpoints);CHKERRQ(ierr);
34215a9d0af9SMatthew G. Knepley     ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
34225a9d0af9SMatthew G. Knepley     for (d = 0; d <= dim; ++d) {
34235a9d0af9SMatthew G. Knepley       PetscInt pmax = pmesh->hybridPointMax[d], newmax = 0, pEnd, stratum[2], p;
34245a9d0af9SMatthew G. Knepley 
34255a9d0af9SMatthew G. Knepley       if (pmax < 0) continue;
34265a9d0af9SMatthew G. Knepley       ierr = DMPlexGetDepthStratum(dm, d > depth ? depth : d, &stratum[0], &stratum[1]);CHKERRQ(ierr);
34276dfbe1fcSMatthew G. Knepley       ierr = DMPlexGetDepthStratum(*dmParallel, d, NULL, &pEnd);CHKERRQ(ierr);
34285a9d0af9SMatthew G. Knepley       ierr = MPI_Bcast(stratum, 2, MPIU_INT, 0, comm);CHKERRQ(ierr);
34295a9d0af9SMatthew G. Knepley       for (p = 0; p < n; ++p) {
34305a9d0af9SMatthew G. Knepley         const PetscInt point = gpoints[p];
34315a9d0af9SMatthew G. Knepley 
34325a9d0af9SMatthew G. Knepley         if ((point >= stratum[0]) && (point < stratum[1]) && (point >= pmax)) ++newmax;
34335a9d0af9SMatthew G. Knepley       }
34345a9d0af9SMatthew G. Knepley       if (newmax > 0) pmesh->hybridPointMax[d] = pEnd - newmax;
34355a9d0af9SMatthew G. Knepley       else            pmesh->hybridPointMax[d] = -1;
34365a9d0af9SMatthew G. Knepley     }
34375a9d0af9SMatthew G. Knepley     ierr = ISLocalToGlobalMappingRestoreIndices(renumbering, &gpoints);CHKERRQ(ierr);
34385a9d0af9SMatthew G. Knepley   }
3439552f7358SJed Brown   /* Cleanup Partition */
3440552f7358SJed Brown   ierr = ISLocalToGlobalMappingDestroy(&renumbering);CHKERRQ(ierr);
3441552f7358SJed Brown   ierr = PetscSFDestroy(&partSF);CHKERRQ(ierr);
3442552f7358SJed Brown   ierr = PetscSectionDestroy(&partSection);CHKERRQ(ierr);
3443552f7358SJed Brown   ierr = ISDestroy(&part);CHKERRQ(ierr);
3444552f7358SJed Brown   /* Create point SF for parallel mesh */
3445b96ba592SMatthew G. Knepley   ierr = PetscLogEventBegin(DMPLEX_DistributeSF,dm,0,0,0);CHKERRQ(ierr);
3446552f7358SJed Brown   {
3447552f7358SJed Brown     const PetscInt *leaves;
3448552f7358SJed Brown     PetscSFNode    *remotePoints, *rowners, *lowners;
3449552f7358SJed Brown     PetscInt        numRoots, numLeaves, numGhostPoints = 0, p, gp, *ghostPoints;
3450552f7358SJed Brown     PetscInt        pStart, pEnd;
3451552f7358SJed Brown 
3452552f7358SJed Brown     ierr = DMPlexGetChart(*dmParallel, &pStart, &pEnd);CHKERRQ(ierr);
34530298fd71SBarry Smith     ierr = PetscSFGetGraph(pointSF, &numRoots, &numLeaves, &leaves, NULL);CHKERRQ(ierr);
3454dcca6d9dSJed Brown     ierr = PetscMalloc2(numRoots,&rowners,numLeaves,&lowners);CHKERRQ(ierr);
3455552f7358SJed Brown     for (p=0; p<numRoots; p++) {
3456552f7358SJed Brown       rowners[p].rank  = -1;
3457552f7358SJed Brown       rowners[p].index = -1;
3458552f7358SJed Brown     }
3459552f7358SJed Brown     if (origCellPart) {
3460057e8d19SMichael Lange       /* Make sure points in the original partition are not assigned to other procs */
3461057e8d19SMichael Lange       const PetscInt *origPoints;
3462552f7358SJed Brown 
3463057e8d19SMichael Lange       ierr = DMPlexCreatePartitionClosure(dm, origCellPartSection, origCellPart, &origPartSection, &origPart);CHKERRQ(ierr);
3464057e8d19SMichael Lange       ierr = ISGetIndices(origPart, &origPoints);CHKERRQ(ierr);
3465552f7358SJed Brown       for (p = 0; p < numProcs; ++p) {
3466552f7358SJed Brown         PetscInt dof, off, d;
3467552f7358SJed Brown 
3468057e8d19SMichael Lange         ierr = PetscSectionGetDof(origPartSection, p, &dof);CHKERRQ(ierr);
3469057e8d19SMichael Lange         ierr = PetscSectionGetOffset(origPartSection, p, &off);CHKERRQ(ierr);
3470552f7358SJed Brown         for (d = off; d < off+dof; ++d) {
3471057e8d19SMichael Lange           rowners[origPoints[d]].rank = p;
3472552f7358SJed Brown         }
3473552f7358SJed Brown       }
3474057e8d19SMichael Lange       ierr = ISRestoreIndices(origPart, &origPoints);CHKERRQ(ierr);
3475057e8d19SMichael Lange       ierr = ISDestroy(&origPart);CHKERRQ(ierr);
3476057e8d19SMichael Lange       ierr = PetscSectionDestroy(&origPartSection);CHKERRQ(ierr);
3477552f7358SJed Brown     }
3478552f7358SJed Brown     ierr = ISDestroy(&origCellPart);CHKERRQ(ierr);
3479552f7358SJed Brown     ierr = PetscSectionDestroy(&origCellPartSection);CHKERRQ(ierr);
3480552f7358SJed Brown 
3481552f7358SJed Brown     ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr);
3482552f7358SJed Brown     ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr);
3483552f7358SJed Brown     for (p = 0; p < numLeaves; ++p) {
3484552f7358SJed Brown       if (lowners[p].rank < 0 || lowners[p].rank == rank) { /* Either put in a bid or we know we own it */
3485552f7358SJed Brown         lowners[p].rank  = rank;
3486552f7358SJed Brown         lowners[p].index = leaves ? leaves[p] : p;
3487552f7358SJed Brown       } else if (lowners[p].rank >= 0) { /* Point already claimed so flag so that MAXLOC does not listen to us */
3488552f7358SJed Brown         lowners[p].rank  = -2;
3489552f7358SJed Brown         lowners[p].index = -2;
3490552f7358SJed Brown       }
3491552f7358SJed Brown     }
3492552f7358SJed Brown     for (p=0; p<numRoots; p++) { /* Root must not participate in the rediction, flag so that MAXLOC does not use */
3493552f7358SJed Brown       rowners[p].rank  = -3;
3494552f7358SJed Brown       rowners[p].index = -3;
3495552f7358SJed Brown     }
3496552f7358SJed Brown     ierr = PetscSFReduceBegin(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr);
3497552f7358SJed Brown     ierr = PetscSFReduceEnd(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr);
3498552f7358SJed Brown     ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr);
3499552f7358SJed Brown     ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr);
3500552f7358SJed Brown     for (p = 0; p < numLeaves; ++p) {
3501552f7358SJed Brown       if (lowners[p].rank < 0 || lowners[p].index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cell partition corrupt: point not claimed");
3502552f7358SJed Brown       if (lowners[p].rank != rank) ++numGhostPoints;
3503552f7358SJed Brown     }
3504785e854fSJed Brown     ierr = PetscMalloc1(numGhostPoints,    &ghostPoints);CHKERRQ(ierr);
3505785e854fSJed Brown     ierr = PetscMalloc1(numGhostPoints, &remotePoints);CHKERRQ(ierr);
3506552f7358SJed Brown     for (p = 0, gp = 0; p < numLeaves; ++p) {
3507552f7358SJed Brown       if (lowners[p].rank != rank) {
3508552f7358SJed Brown         ghostPoints[gp]        = leaves ? leaves[p] : p;
3509552f7358SJed Brown         remotePoints[gp].rank  = lowners[p].rank;
3510552f7358SJed Brown         remotePoints[gp].index = lowners[p].index;
3511552f7358SJed Brown         ++gp;
3512552f7358SJed Brown       }
3513552f7358SJed Brown     }
3514552f7358SJed Brown     ierr = PetscFree2(rowners,lowners);CHKERRQ(ierr);
3515552f7358SJed Brown     ierr = PetscSFSetGraph((*dmParallel)->sf, pEnd - pStart, numGhostPoints, ghostPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr);
3516552f7358SJed Brown     ierr = PetscSFSetFromOptions((*dmParallel)->sf);CHKERRQ(ierr);
3517552f7358SJed Brown   }
3518b96ba592SMatthew G. Knepley   ierr = PetscLogEventEnd(DMPLEX_DistributeSF,dm,0,0,0);CHKERRQ(ierr);
3519552f7358SJed Brown   /* Cleanup */
3520e7ba9e7aSMatthew G. Knepley   if (sf) {*sf = pointSF;}
3521e7ba9e7aSMatthew G. Knepley   else    {ierr = PetscSFDestroy(&pointSF);CHKERRQ(ierr);}
3522552f7358SJed Brown   ierr = DMSetFromOptions(*dmParallel);CHKERRQ(ierr);
3523552f7358SJed Brown   ierr = PetscLogEventEnd(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr);
3524552f7358SJed Brown   PetscFunctionReturn(0);
3525552f7358SJed Brown }
3526552f7358SJed Brown 
35272e1b13c2SMatthew G. Knepley #undef __FUNCT__
35289db3b87dSMatthew G. Knepley #define __FUNCT__ "DMPlexInvertCell"
35299db3b87dSMatthew G. Knepley /*@C
35309db3b87dSMatthew G. Knepley   DMPlexInvertCell - This flips tetrahedron and hexahedron orientation since Plex stores them internally with outward normals. Other cells are left untouched.
35319db3b87dSMatthew G. Knepley 
35329db3b87dSMatthew G. Knepley   Input Parameters:
35339db3b87dSMatthew G. Knepley + numCorners - The number of vertices in a cell
35349db3b87dSMatthew G. Knepley - cone - The incoming cone
35359db3b87dSMatthew G. Knepley 
35369db3b87dSMatthew G. Knepley   Output Parameter:
35379db3b87dSMatthew G. Knepley . cone - The inverted cone (in-place)
35389db3b87dSMatthew G. Knepley 
35399db3b87dSMatthew G. Knepley   Level: developer
35409db3b87dSMatthew G. Knepley 
35419db3b87dSMatthew G. Knepley .seealso: DMPlexGenerate()
35429db3b87dSMatthew G. Knepley @*/
35439db3b87dSMatthew G. Knepley PetscErrorCode DMPlexInvertCell(PetscInt dim, PetscInt numCorners, int cone[])
35442e1b13c2SMatthew G. Knepley {
35459db3b87dSMatthew G. Knepley   int tmpc;
35462e1b13c2SMatthew G. Knepley 
35472e1b13c2SMatthew G. Knepley   PetscFunctionBegin;
35489db3b87dSMatthew G. Knepley   if (dim != 3) PetscFunctionReturn(0);
35499db3b87dSMatthew G. Knepley   switch (numCorners) {
35509db3b87dSMatthew G. Knepley   case 4:
35511885f254SMatthew G. Knepley     tmpc    = cone[0];
35521885f254SMatthew G. Knepley     cone[0] = cone[1];
35531885f254SMatthew G. Knepley     cone[1] = tmpc;
35549db3b87dSMatthew G. Knepley     break;
35559db3b87dSMatthew G. Knepley   case 8:
35569db3b87dSMatthew G. Knepley     tmpc    = cone[1];
35579db3b87dSMatthew G. Knepley     cone[1] = cone[3];
35589db3b87dSMatthew G. Knepley     cone[3] = tmpc;
35599db3b87dSMatthew G. Knepley     break;
35609db3b87dSMatthew G. Knepley   default: break;
35619db3b87dSMatthew G. Knepley   }
35629db3b87dSMatthew G. Knepley   PetscFunctionReturn(0);
35639db3b87dSMatthew G. Knepley }
35649db3b87dSMatthew G. Knepley 
35659db3b87dSMatthew G. Knepley #undef __FUNCT__
35669db3b87dSMatthew G. Knepley #define __FUNCT__ "DMPlexInvertCells_Internal"
35679db3b87dSMatthew G. Knepley /* This is to fix the tetrahedron orientation from TetGen */
35689db3b87dSMatthew G. Knepley PETSC_UNUSED static PetscErrorCode DMPlexInvertCells_Internal(PetscInt dim, PetscInt numCells, PetscInt numCorners, int cells[])
35699db3b87dSMatthew G. Knepley {
35709db3b87dSMatthew G. Knepley   PetscInt       bound = numCells*numCorners, coff;
35719db3b87dSMatthew G. Knepley   PetscErrorCode ierr;
35729db3b87dSMatthew G. Knepley 
35739db3b87dSMatthew G. Knepley   PetscFunctionBegin;
35749db3b87dSMatthew G. Knepley   for (coff = 0; coff < bound; coff += numCorners) {
35759db3b87dSMatthew G. Knepley     ierr = DMPlexInvertCell(dim, numCorners, &cells[coff]);CHKERRQ(ierr);
35762e1b13c2SMatthew G. Knepley   }
35772e1b13c2SMatthew G. Knepley   PetscFunctionReturn(0);
35782e1b13c2SMatthew G. Knepley }
35792e1b13c2SMatthew G. Knepley 
3580519f805aSKarl Rupp #if defined(PETSC_HAVE_TRIANGLE)
3581552f7358SJed Brown #include <triangle.h>
3582552f7358SJed Brown 
3583552f7358SJed Brown #undef __FUNCT__
3584552f7358SJed Brown #define __FUNCT__ "InitInput_Triangle"
35850adebc6cSBarry Smith PetscErrorCode InitInput_Triangle(struct triangulateio *inputCtx)
35860adebc6cSBarry Smith {
3587552f7358SJed Brown   PetscFunctionBegin;
3588552f7358SJed Brown   inputCtx->numberofpoints             = 0;
3589552f7358SJed Brown   inputCtx->numberofpointattributes    = 0;
35900298fd71SBarry Smith   inputCtx->pointlist                  = NULL;
35910298fd71SBarry Smith   inputCtx->pointattributelist         = NULL;
35920298fd71SBarry Smith   inputCtx->pointmarkerlist            = NULL;
3593552f7358SJed Brown   inputCtx->numberofsegments           = 0;
35940298fd71SBarry Smith   inputCtx->segmentlist                = NULL;
35950298fd71SBarry Smith   inputCtx->segmentmarkerlist          = NULL;
3596552f7358SJed Brown   inputCtx->numberoftriangleattributes = 0;
35970298fd71SBarry Smith   inputCtx->trianglelist               = NULL;
3598552f7358SJed Brown   inputCtx->numberofholes              = 0;
35990298fd71SBarry Smith   inputCtx->holelist                   = NULL;
3600552f7358SJed Brown   inputCtx->numberofregions            = 0;
36010298fd71SBarry Smith   inputCtx->regionlist                 = NULL;
3602552f7358SJed Brown   PetscFunctionReturn(0);
3603552f7358SJed Brown }
3604552f7358SJed Brown 
3605552f7358SJed Brown #undef __FUNCT__
3606552f7358SJed Brown #define __FUNCT__ "InitOutput_Triangle"
36070adebc6cSBarry Smith PetscErrorCode InitOutput_Triangle(struct triangulateio *outputCtx)
36080adebc6cSBarry Smith {
3609552f7358SJed Brown   PetscFunctionBegin;
3610552f7358SJed Brown   outputCtx->numberofpoints        = 0;
36110298fd71SBarry Smith   outputCtx->pointlist             = NULL;
36120298fd71SBarry Smith   outputCtx->pointattributelist    = NULL;
36130298fd71SBarry Smith   outputCtx->pointmarkerlist       = NULL;
3614552f7358SJed Brown   outputCtx->numberoftriangles     = 0;
36150298fd71SBarry Smith   outputCtx->trianglelist          = NULL;
36160298fd71SBarry Smith   outputCtx->triangleattributelist = NULL;
36170298fd71SBarry Smith   outputCtx->neighborlist          = NULL;
36180298fd71SBarry Smith   outputCtx->segmentlist           = NULL;
36190298fd71SBarry Smith   outputCtx->segmentmarkerlist     = NULL;
3620552f7358SJed Brown   outputCtx->numberofedges         = 0;
36210298fd71SBarry Smith   outputCtx->edgelist              = NULL;
36220298fd71SBarry Smith   outputCtx->edgemarkerlist        = NULL;
3623552f7358SJed Brown   PetscFunctionReturn(0);
3624552f7358SJed Brown }
3625552f7358SJed Brown 
3626552f7358SJed Brown #undef __FUNCT__
3627552f7358SJed Brown #define __FUNCT__ "FiniOutput_Triangle"
36280adebc6cSBarry Smith PetscErrorCode FiniOutput_Triangle(struct triangulateio *outputCtx)
36290adebc6cSBarry Smith {
3630552f7358SJed Brown   PetscFunctionBegin;
3631552f7358SJed Brown   free(outputCtx->pointmarkerlist);
3632552f7358SJed Brown   free(outputCtx->edgelist);
3633552f7358SJed Brown   free(outputCtx->edgemarkerlist);
3634552f7358SJed Brown   free(outputCtx->trianglelist);
3635552f7358SJed Brown   free(outputCtx->neighborlist);
3636552f7358SJed Brown   PetscFunctionReturn(0);
3637552f7358SJed Brown }
3638552f7358SJed Brown 
3639552f7358SJed Brown #undef __FUNCT__
3640552f7358SJed Brown #define __FUNCT__ "DMPlexGenerate_Triangle"
3641552f7358SJed Brown PetscErrorCode DMPlexGenerate_Triangle(DM boundary, PetscBool interpolate, DM *dm)
3642552f7358SJed Brown {
364382f516ccSBarry Smith   MPI_Comm             comm;
3644552f7358SJed Brown   PetscInt             dim              = 2;
3645552f7358SJed Brown   const PetscBool      createConvexHull = PETSC_FALSE;
3646552f7358SJed Brown   const PetscBool      constrained      = PETSC_FALSE;
3647552f7358SJed Brown   struct triangulateio in;
3648552f7358SJed Brown   struct triangulateio out;
3649552f7358SJed Brown   PetscInt             vStart, vEnd, v, eStart, eEnd, e;
3650552f7358SJed Brown   PetscMPIInt          rank;
3651552f7358SJed Brown   PetscErrorCode       ierr;
3652552f7358SJed Brown 
3653552f7358SJed Brown   PetscFunctionBegin;
365482f516ccSBarry Smith   ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr);
3655552f7358SJed Brown   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
3656552f7358SJed Brown   ierr = InitInput_Triangle(&in);CHKERRQ(ierr);
3657552f7358SJed Brown   ierr = InitOutput_Triangle(&out);CHKERRQ(ierr);
3658552f7358SJed Brown   ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr);
36590d644c17SKarl Rupp 
3660552f7358SJed Brown   in.numberofpoints = vEnd - vStart;
3661552f7358SJed Brown   if (in.numberofpoints > 0) {
3662552f7358SJed Brown     PetscSection coordSection;
3663552f7358SJed Brown     Vec          coordinates;
3664552f7358SJed Brown     PetscScalar *array;
3665552f7358SJed Brown 
3666785e854fSJed Brown     ierr = PetscMalloc1(in.numberofpoints*dim, &in.pointlist);CHKERRQ(ierr);
3667785e854fSJed Brown     ierr = PetscMalloc1(in.numberofpoints, &in.pointmarkerlist);CHKERRQ(ierr);
3668552f7358SJed Brown     ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr);
366969d8a9ceSMatthew G. Knepley     ierr = DMGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr);
3670552f7358SJed Brown     ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr);
3671552f7358SJed Brown     for (v = vStart; v < vEnd; ++v) {
3672552f7358SJed Brown       const PetscInt idx = v - vStart;
3673552f7358SJed Brown       PetscInt       off, d;
3674552f7358SJed Brown 
3675552f7358SJed Brown       ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr);
3676552f7358SJed Brown       for (d = 0; d < dim; ++d) {
3677552f7358SJed Brown         in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]);
3678552f7358SJed Brown       }
3679552f7358SJed Brown       ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr);
3680552f7358SJed Brown     }
3681552f7358SJed Brown     ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr);
3682552f7358SJed Brown   }
3683552f7358SJed Brown   ierr  = DMPlexGetHeightStratum(boundary, 0, &eStart, &eEnd);CHKERRQ(ierr);
3684552f7358SJed Brown   in.numberofsegments = eEnd - eStart;
3685552f7358SJed Brown   if (in.numberofsegments > 0) {
3686785e854fSJed Brown     ierr = PetscMalloc1(in.numberofsegments*2, &in.segmentlist);CHKERRQ(ierr);
3687785e854fSJed Brown     ierr = PetscMalloc1(in.numberofsegments, &in.segmentmarkerlist);CHKERRQ(ierr);
3688552f7358SJed Brown     for (e = eStart; e < eEnd; ++e) {
3689552f7358SJed Brown       const PetscInt  idx = e - eStart;
3690552f7358SJed Brown       const PetscInt *cone;
3691552f7358SJed Brown 
3692552f7358SJed Brown       ierr = DMPlexGetCone(boundary, e, &cone);CHKERRQ(ierr);
36930d644c17SKarl Rupp 
3694552f7358SJed Brown       in.segmentlist[idx*2+0] = cone[0] - vStart;
3695552f7358SJed Brown       in.segmentlist[idx*2+1] = cone[1] - vStart;
36960d644c17SKarl Rupp 
3697552f7358SJed Brown       ierr = DMPlexGetLabelValue(boundary, "marker", e, &in.segmentmarkerlist[idx]);CHKERRQ(ierr);
3698552f7358SJed Brown     }
3699552f7358SJed Brown   }
3700552f7358SJed Brown #if 0 /* Do not currently support holes */
3701552f7358SJed Brown   PetscReal *holeCoords;
3702552f7358SJed Brown   PetscInt   h, d;
3703552f7358SJed Brown 
3704552f7358SJed Brown   ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr);
3705552f7358SJed Brown   if (in.numberofholes > 0) {
3706785e854fSJed Brown     ierr = PetscMalloc1(in.numberofholes*dim, &in.holelist);CHKERRQ(ierr);
3707552f7358SJed Brown     for (h = 0; h < in.numberofholes; ++h) {
3708552f7358SJed Brown       for (d = 0; d < dim; ++d) {
3709552f7358SJed Brown         in.holelist[h*dim+d] = holeCoords[h*dim+d];
3710552f7358SJed Brown       }
3711552f7358SJed Brown     }
3712552f7358SJed Brown   }
3713552f7358SJed Brown #endif
3714552f7358SJed Brown   if (!rank) {
3715552f7358SJed Brown     char args[32];
3716552f7358SJed Brown 
3717552f7358SJed Brown     /* Take away 'Q' for verbose output */
3718552f7358SJed Brown     ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr);
3719552f7358SJed Brown     if (createConvexHull) {
3720552f7358SJed Brown       ierr = PetscStrcat(args, "c");CHKERRQ(ierr);
3721552f7358SJed Brown     }
3722552f7358SJed Brown     if (constrained) {
3723552f7358SJed Brown       ierr = PetscStrcpy(args, "zepDQ");CHKERRQ(ierr);
3724552f7358SJed Brown     }
37250298fd71SBarry Smith     triangulate(args, &in, &out, NULL);
3726552f7358SJed Brown   }
3727552f7358SJed Brown   ierr = PetscFree(in.pointlist);CHKERRQ(ierr);
3728552f7358SJed Brown   ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr);
3729552f7358SJed Brown   ierr = PetscFree(in.segmentlist);CHKERRQ(ierr);
3730552f7358SJed Brown   ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr);
3731552f7358SJed Brown   ierr = PetscFree(in.holelist);CHKERRQ(ierr);
3732552f7358SJed Brown 
3733552f7358SJed Brown   {
3734552f7358SJed Brown     const PetscInt numCorners  = 3;
3735552f7358SJed Brown     const PetscInt numCells    = out.numberoftriangles;
3736552f7358SJed Brown     const PetscInt numVertices = out.numberofpoints;
3737552f7358SJed Brown     const int     *cells      = out.trianglelist;
3738552f7358SJed Brown     const double  *meshCoords = out.pointlist;
3739552f7358SJed Brown 
37400fde5641SMatthew G Knepley     ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr);
3741552f7358SJed Brown     /* Set labels */
3742552f7358SJed Brown     for (v = 0; v < numVertices; ++v) {
3743552f7358SJed Brown       if (out.pointmarkerlist[v]) {
3744552f7358SJed Brown         ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr);
3745552f7358SJed Brown       }
3746552f7358SJed Brown     }
3747552f7358SJed Brown     if (interpolate) {
3748552f7358SJed Brown       for (e = 0; e < out.numberofedges; e++) {
3749552f7358SJed Brown         if (out.edgemarkerlist[e]) {
3750552f7358SJed Brown           const PetscInt  vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells};
3751552f7358SJed Brown           const PetscInt *edges;
3752552f7358SJed Brown           PetscInt        numEdges;
3753552f7358SJed Brown 
3754552f7358SJed Brown           ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr);
3755552f7358SJed Brown           if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges);
3756552f7358SJed Brown           ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr);
3757552f7358SJed Brown           ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr);
3758552f7358SJed Brown         }
3759552f7358SJed Brown       }
3760552f7358SJed Brown     }
3761552f7358SJed Brown     ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr);
3762552f7358SJed Brown   }
3763552f7358SJed Brown #if 0 /* Do not currently support holes */
3764552f7358SJed Brown   ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr);
3765552f7358SJed Brown #endif
3766552f7358SJed Brown   ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr);
3767552f7358SJed Brown   PetscFunctionReturn(0);
3768552f7358SJed Brown }
3769552f7358SJed Brown 
3770552f7358SJed Brown #undef __FUNCT__
3771552f7358SJed Brown #define __FUNCT__ "DMPlexRefine_Triangle"
3772552f7358SJed Brown PetscErrorCode DMPlexRefine_Triangle(DM dm, double *maxVolumes, DM *dmRefined)
3773552f7358SJed Brown {
377482f516ccSBarry Smith   MPI_Comm             comm;
3775552f7358SJed Brown   PetscInt             dim  = 2;
3776552f7358SJed Brown   struct triangulateio in;
3777552f7358SJed Brown   struct triangulateio out;
3778552f7358SJed Brown   PetscInt             vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal;
3779552f7358SJed Brown   PetscMPIInt          rank;
3780552f7358SJed Brown   PetscErrorCode       ierr;
3781552f7358SJed Brown 
3782552f7358SJed Brown   PetscFunctionBegin;
378382f516ccSBarry Smith   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
3784552f7358SJed Brown   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
3785552f7358SJed Brown   ierr = InitInput_Triangle(&in);CHKERRQ(ierr);
3786552f7358SJed Brown   ierr = InitOutput_Triangle(&out);CHKERRQ(ierr);
3787552f7358SJed Brown   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
3788552f7358SJed Brown   ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr);
3789552f7358SJed Brown   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
37900d644c17SKarl Rupp 
3791552f7358SJed Brown   in.numberofpoints = vEnd - vStart;
3792552f7358SJed Brown   if (in.numberofpoints > 0) {
3793552f7358SJed Brown     PetscSection coordSection;
3794552f7358SJed Brown     Vec          coordinates;
3795552f7358SJed Brown     PetscScalar *array;
3796552f7358SJed Brown 
3797785e854fSJed Brown     ierr = PetscMalloc1(in.numberofpoints*dim, &in.pointlist);CHKERRQ(ierr);
3798785e854fSJed Brown     ierr = PetscMalloc1(in.numberofpoints, &in.pointmarkerlist);CHKERRQ(ierr);
3799552f7358SJed Brown     ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
380069d8a9ceSMatthew G. Knepley     ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr);
3801552f7358SJed Brown     ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr);
3802552f7358SJed Brown     for (v = vStart; v < vEnd; ++v) {
3803552f7358SJed Brown       const PetscInt idx = v - vStart;
3804552f7358SJed Brown       PetscInt       off, d;
3805552f7358SJed Brown 
3806552f7358SJed Brown       ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr);
3807552f7358SJed Brown       for (d = 0; d < dim; ++d) {
3808552f7358SJed Brown         in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]);
3809552f7358SJed Brown       }
3810552f7358SJed Brown       ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr);
3811552f7358SJed Brown     }
3812552f7358SJed Brown     ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr);
3813552f7358SJed Brown   }
3814552f7358SJed Brown   ierr  = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
38150d644c17SKarl Rupp 
3816552f7358SJed Brown   in.numberofcorners   = 3;
3817552f7358SJed Brown   in.numberoftriangles = cEnd - cStart;
38180d644c17SKarl Rupp 
3819552f7358SJed Brown   in.trianglearealist  = (double*) maxVolumes;
3820552f7358SJed Brown   if (in.numberoftriangles > 0) {
3821785e854fSJed Brown     ierr = PetscMalloc1(in.numberoftriangles*in.numberofcorners, &in.trianglelist);CHKERRQ(ierr);
3822552f7358SJed Brown     for (c = cStart; c < cEnd; ++c) {
3823552f7358SJed Brown       const PetscInt idx      = c - cStart;
38240298fd71SBarry Smith       PetscInt      *closure = NULL;
3825552f7358SJed Brown       PetscInt       closureSize;
3826552f7358SJed Brown 
3827552f7358SJed Brown       ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
3828552f7358SJed 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);
3829552f7358SJed Brown       for (v = 0; v < 3; ++v) {
3830552f7358SJed Brown         in.trianglelist[idx*in.numberofcorners + v] = closure[(v+closureSize-3)*2] - vStart;
3831552f7358SJed Brown       }
3832552f7358SJed Brown       ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
3833552f7358SJed Brown     }
3834552f7358SJed Brown   }
3835552f7358SJed Brown   /* TODO: Segment markers are missing on input */
3836552f7358SJed Brown #if 0 /* Do not currently support holes */
3837552f7358SJed Brown   PetscReal *holeCoords;
3838552f7358SJed Brown   PetscInt   h, d;
3839552f7358SJed Brown 
3840552f7358SJed Brown   ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr);
3841552f7358SJed Brown   if (in.numberofholes > 0) {
3842785e854fSJed Brown     ierr = PetscMalloc1(in.numberofholes*dim, &in.holelist);CHKERRQ(ierr);
3843552f7358SJed Brown     for (h = 0; h < in.numberofholes; ++h) {
3844552f7358SJed Brown       for (d = 0; d < dim; ++d) {
3845552f7358SJed Brown         in.holelist[h*dim+d] = holeCoords[h*dim+d];
3846552f7358SJed Brown       }
3847552f7358SJed Brown     }
3848552f7358SJed Brown   }
3849552f7358SJed Brown #endif
3850552f7358SJed Brown   if (!rank) {
3851552f7358SJed Brown     char args[32];
3852552f7358SJed Brown 
3853552f7358SJed Brown     /* Take away 'Q' for verbose output */
3854552f7358SJed Brown     ierr = PetscStrcpy(args, "pqezQra");CHKERRQ(ierr);
38550298fd71SBarry Smith     triangulate(args, &in, &out, NULL);
3856552f7358SJed Brown   }
3857552f7358SJed Brown   ierr = PetscFree(in.pointlist);CHKERRQ(ierr);
3858552f7358SJed Brown   ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr);
3859552f7358SJed Brown   ierr = PetscFree(in.segmentlist);CHKERRQ(ierr);
3860552f7358SJed Brown   ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr);
3861552f7358SJed Brown   ierr = PetscFree(in.trianglelist);CHKERRQ(ierr);
3862552f7358SJed Brown 
3863552f7358SJed Brown   {
3864552f7358SJed Brown     const PetscInt numCorners  = 3;
3865552f7358SJed Brown     const PetscInt numCells    = out.numberoftriangles;
3866552f7358SJed Brown     const PetscInt numVertices = out.numberofpoints;
3867552f7358SJed Brown     const int     *cells      = out.trianglelist;
3868552f7358SJed Brown     const double  *meshCoords = out.pointlist;
3869552f7358SJed Brown     PetscBool      interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE;
3870552f7358SJed Brown 
38710fde5641SMatthew G Knepley     ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr);
3872552f7358SJed Brown     /* Set labels */
3873552f7358SJed Brown     for (v = 0; v < numVertices; ++v) {
3874552f7358SJed Brown       if (out.pointmarkerlist[v]) {
3875552f7358SJed Brown         ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr);
3876552f7358SJed Brown       }
3877552f7358SJed Brown     }
3878552f7358SJed Brown     if (interpolate) {
3879552f7358SJed Brown       PetscInt e;
3880552f7358SJed Brown 
3881552f7358SJed Brown       for (e = 0; e < out.numberofedges; e++) {
3882552f7358SJed Brown         if (out.edgemarkerlist[e]) {
3883552f7358SJed Brown           const PetscInt  vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells};
3884552f7358SJed Brown           const PetscInt *edges;
3885552f7358SJed Brown           PetscInt        numEdges;
3886552f7358SJed Brown 
3887552f7358SJed Brown           ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr);
3888552f7358SJed Brown           if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges);
3889552f7358SJed Brown           ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr);
3890552f7358SJed Brown           ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr);
3891552f7358SJed Brown         }
3892552f7358SJed Brown       }
3893552f7358SJed Brown     }
3894552f7358SJed Brown     ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr);
3895552f7358SJed Brown   }
3896552f7358SJed Brown #if 0 /* Do not currently support holes */
3897552f7358SJed Brown   ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr);
3898552f7358SJed Brown #endif
3899552f7358SJed Brown   ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr);
3900552f7358SJed Brown   PetscFunctionReturn(0);
3901552f7358SJed Brown }
3902552f7358SJed Brown #endif
3903552f7358SJed Brown 
3904519f805aSKarl Rupp #if defined(PETSC_HAVE_TETGEN)
3905552f7358SJed Brown #include <tetgen.h>
3906552f7358SJed Brown #undef __FUNCT__
3907552f7358SJed Brown #define __FUNCT__ "DMPlexGenerate_Tetgen"
3908552f7358SJed Brown PetscErrorCode DMPlexGenerate_Tetgen(DM boundary, PetscBool interpolate, DM *dm)
3909552f7358SJed Brown {
391082f516ccSBarry Smith   MPI_Comm       comm;
3911552f7358SJed Brown   const PetscInt dim  = 3;
3912552f7358SJed Brown   ::tetgenio     in;
3913552f7358SJed Brown   ::tetgenio     out;
3914552f7358SJed Brown   PetscInt       vStart, vEnd, v, fStart, fEnd, f;
3915552f7358SJed Brown   PetscMPIInt    rank;
3916552f7358SJed Brown   PetscErrorCode ierr;
3917552f7358SJed Brown 
3918552f7358SJed Brown   PetscFunctionBegin;
391982f516ccSBarry Smith   ierr              = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr);
3920552f7358SJed Brown   ierr              = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
3921552f7358SJed Brown   ierr              = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr);
3922552f7358SJed Brown   in.numberofpoints = vEnd - vStart;
3923552f7358SJed Brown   if (in.numberofpoints > 0) {
3924552f7358SJed Brown     PetscSection coordSection;
3925552f7358SJed Brown     Vec          coordinates;
3926552f7358SJed Brown     PetscScalar *array;
3927552f7358SJed Brown 
3928552f7358SJed Brown     in.pointlist       = new double[in.numberofpoints*dim];
3929552f7358SJed Brown     in.pointmarkerlist = new int[in.numberofpoints];
39300d644c17SKarl Rupp 
3931552f7358SJed Brown     ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr);
393269d8a9ceSMatthew G. Knepley     ierr = DMGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr);
3933552f7358SJed Brown     ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr);
3934552f7358SJed Brown     for (v = vStart; v < vEnd; ++v) {
3935552f7358SJed Brown       const PetscInt idx = v - vStart;
3936552f7358SJed Brown       PetscInt       off, d;
3937552f7358SJed Brown 
3938552f7358SJed Brown       ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr);
39390d644c17SKarl Rupp       for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d];
3940552f7358SJed Brown       ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr);
3941552f7358SJed Brown     }
3942552f7358SJed Brown     ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr);
3943552f7358SJed Brown   }
3944552f7358SJed Brown   ierr  = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr);
39450d644c17SKarl Rupp 
3946552f7358SJed Brown   in.numberoffacets = fEnd - fStart;
3947552f7358SJed Brown   if (in.numberoffacets > 0) {
3948552f7358SJed Brown     in.facetlist       = new tetgenio::facet[in.numberoffacets];
3949552f7358SJed Brown     in.facetmarkerlist = new int[in.numberoffacets];
3950552f7358SJed Brown     for (f = fStart; f < fEnd; ++f) {
3951552f7358SJed Brown       const PetscInt idx     = f - fStart;
39520298fd71SBarry Smith       PetscInt      *points = NULL, numPoints, p, numVertices = 0, v;
3953552f7358SJed Brown 
3954552f7358SJed Brown       in.facetlist[idx].numberofpolygons = 1;
3955552f7358SJed Brown       in.facetlist[idx].polygonlist      = new tetgenio::polygon[in.facetlist[idx].numberofpolygons];
3956552f7358SJed Brown       in.facetlist[idx].numberofholes    = 0;
3957552f7358SJed Brown       in.facetlist[idx].holelist         = NULL;
3958552f7358SJed Brown 
3959552f7358SJed Brown       ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);
3960552f7358SJed Brown       for (p = 0; p < numPoints*2; p += 2) {
3961552f7358SJed Brown         const PetscInt point = points[p];
39620d644c17SKarl Rupp         if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point;
3963552f7358SJed Brown       }
3964552f7358SJed Brown 
3965552f7358SJed Brown       tetgenio::polygon *poly = in.facetlist[idx].polygonlist;
3966552f7358SJed Brown       poly->numberofvertices = numVertices;
3967552f7358SJed Brown       poly->vertexlist       = new int[poly->numberofvertices];
3968552f7358SJed Brown       for (v = 0; v < numVertices; ++v) {
3969552f7358SJed Brown         const PetscInt vIdx = points[v] - vStart;
3970552f7358SJed Brown         poly->vertexlist[v] = vIdx;
3971552f7358SJed Brown       }
3972552f7358SJed Brown       ierr = DMPlexGetLabelValue(boundary, "marker", f, &in.facetmarkerlist[idx]);CHKERRQ(ierr);
3973552f7358SJed Brown       ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);
3974552f7358SJed Brown     }
3975552f7358SJed Brown   }
3976552f7358SJed Brown   if (!rank) {
3977552f7358SJed Brown     char args[32];
3978552f7358SJed Brown 
3979552f7358SJed Brown     /* Take away 'Q' for verbose output */
3980552f7358SJed Brown     ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr);
3981552f7358SJed Brown     ::tetrahedralize(args, &in, &out);
3982552f7358SJed Brown   }
3983552f7358SJed Brown   {
3984552f7358SJed Brown     const PetscInt numCorners  = 4;
3985552f7358SJed Brown     const PetscInt numCells    = out.numberoftetrahedra;
3986552f7358SJed Brown     const PetscInt numVertices = out.numberofpoints;
3987552f7358SJed Brown     const double   *meshCoords = out.pointlist;
39881d4b4d7bSJed Brown     int            *cells      = out.tetrahedronlist;
3989552f7358SJed Brown 
39909db3b87dSMatthew G. Knepley     ierr = DMPlexInvertCells_Internal(dim, numCells, numCorners, cells);CHKERRQ(ierr);
39910fde5641SMatthew G Knepley     ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr);
3992552f7358SJed Brown     /* Set labels */
3993552f7358SJed Brown     for (v = 0; v < numVertices; ++v) {
3994552f7358SJed Brown       if (out.pointmarkerlist[v]) {
3995552f7358SJed Brown         ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr);
3996552f7358SJed Brown       }
3997552f7358SJed Brown     }
3998552f7358SJed Brown     if (interpolate) {
3999552f7358SJed Brown       PetscInt e;
4000552f7358SJed Brown 
4001552f7358SJed Brown       for (e = 0; e < out.numberofedges; e++) {
4002552f7358SJed Brown         if (out.edgemarkerlist[e]) {
4003552f7358SJed Brown           const PetscInt  vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells};
4004552f7358SJed Brown           const PetscInt *edges;
4005552f7358SJed Brown           PetscInt        numEdges;
4006552f7358SJed Brown 
4007552f7358SJed Brown           ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr);
4008552f7358SJed Brown           if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges);
4009552f7358SJed Brown           ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr);
4010552f7358SJed Brown           ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr);
4011552f7358SJed Brown         }
4012552f7358SJed Brown       }
4013552f7358SJed Brown       for (f = 0; f < out.numberoftrifaces; f++) {
4014552f7358SJed Brown         if (out.trifacemarkerlist[f]) {
4015552f7358SJed Brown           const PetscInt  vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells};
4016552f7358SJed Brown           const PetscInt *faces;
4017552f7358SJed Brown           PetscInt        numFaces;
4018552f7358SJed Brown 
4019552f7358SJed Brown           ierr = DMPlexGetJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr);
4020552f7358SJed Brown           if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces);
4021552f7358SJed Brown           ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr);
4022552f7358SJed Brown           ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr);
4023552f7358SJed Brown         }
4024552f7358SJed Brown       }
4025552f7358SJed Brown     }
4026552f7358SJed Brown     ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr);
4027552f7358SJed Brown   }
4028552f7358SJed Brown   PetscFunctionReturn(0);
4029552f7358SJed Brown }
4030552f7358SJed Brown 
4031552f7358SJed Brown #undef __FUNCT__
4032552f7358SJed Brown #define __FUNCT__ "DMPlexRefine_Tetgen"
4033552f7358SJed Brown PetscErrorCode DMPlexRefine_Tetgen(DM dm, double *maxVolumes, DM *dmRefined)
4034552f7358SJed Brown {
403582f516ccSBarry Smith   MPI_Comm       comm;
4036552f7358SJed Brown   const PetscInt dim  = 3;
4037552f7358SJed Brown   ::tetgenio     in;
4038552f7358SJed Brown   ::tetgenio     out;
4039552f7358SJed Brown   PetscInt       vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal;
4040552f7358SJed Brown   PetscMPIInt    rank;
4041552f7358SJed Brown   PetscErrorCode ierr;
4042552f7358SJed Brown 
4043552f7358SJed Brown   PetscFunctionBegin;
404482f516ccSBarry Smith   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
4045552f7358SJed Brown   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
4046552f7358SJed Brown   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
4047552f7358SJed Brown   ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr);
4048552f7358SJed Brown   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
40490d644c17SKarl Rupp 
4050552f7358SJed Brown   in.numberofpoints = vEnd - vStart;
4051552f7358SJed Brown   if (in.numberofpoints > 0) {
4052552f7358SJed Brown     PetscSection coordSection;
4053552f7358SJed Brown     Vec          coordinates;
4054552f7358SJed Brown     PetscScalar *array;
4055552f7358SJed Brown 
4056552f7358SJed Brown     in.pointlist       = new double[in.numberofpoints*dim];
4057552f7358SJed Brown     in.pointmarkerlist = new int[in.numberofpoints];
40580d644c17SKarl Rupp 
4059552f7358SJed Brown     ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
406069d8a9ceSMatthew G. Knepley     ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr);
4061552f7358SJed Brown     ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr);
4062552f7358SJed Brown     for (v = vStart; v < vEnd; ++v) {
4063552f7358SJed Brown       const PetscInt idx = v - vStart;
4064552f7358SJed Brown       PetscInt       off, d;
4065552f7358SJed Brown 
4066552f7358SJed Brown       ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr);
40670d644c17SKarl Rupp       for (d = 0; d < dim; ++d) in.pointlist[idx*dim + d] = array[off+d];
4068552f7358SJed Brown       ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr);
4069552f7358SJed Brown     }
4070552f7358SJed Brown     ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr);
4071552f7358SJed Brown   }
4072552f7358SJed Brown   ierr  = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
40730d644c17SKarl Rupp 
4074552f7358SJed Brown   in.numberofcorners       = 4;
4075552f7358SJed Brown   in.numberoftetrahedra    = cEnd - cStart;
4076552f7358SJed Brown   in.tetrahedronvolumelist = (double*) maxVolumes;
4077552f7358SJed Brown   if (in.numberoftetrahedra > 0) {
4078552f7358SJed Brown     in.tetrahedronlist = new int[in.numberoftetrahedra*in.numberofcorners];
4079552f7358SJed Brown     for (c = cStart; c < cEnd; ++c) {
4080552f7358SJed Brown       const PetscInt idx      = c - cStart;
40810298fd71SBarry Smith       PetscInt      *closure = NULL;
4082552f7358SJed Brown       PetscInt       closureSize;
4083552f7358SJed Brown 
4084552f7358SJed Brown       ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
4085552f7358SJed 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);
4086552f7358SJed Brown       for (v = 0; v < 4; ++v) {
4087552f7358SJed Brown         in.tetrahedronlist[idx*in.numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart;
4088552f7358SJed Brown       }
4089552f7358SJed Brown       ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
4090552f7358SJed Brown     }
4091552f7358SJed Brown   }
409219436ca2SJed Brown   /* TODO: Put in boundary faces with markers */
4093552f7358SJed Brown   if (!rank) {
4094552f7358SJed Brown     char args[32];
4095552f7358SJed Brown 
4096552f7358SJed Brown     /* Take away 'Q' for verbose output */
409719436ca2SJed Brown     /*ierr = PetscStrcpy(args, "qezQra");CHKERRQ(ierr); */
4098552f7358SJed Brown     ierr = PetscStrcpy(args, "qezraVVVV");CHKERRQ(ierr);
4099552f7358SJed Brown     ::tetrahedralize(args, &in, &out);
4100552f7358SJed Brown   }
4101552f7358SJed Brown   in.tetrahedronvolumelist = NULL;
4102552f7358SJed Brown 
4103552f7358SJed Brown   {
4104552f7358SJed Brown     const PetscInt numCorners  = 4;
4105552f7358SJed Brown     const PetscInt numCells    = out.numberoftetrahedra;
4106552f7358SJed Brown     const PetscInt numVertices = out.numberofpoints;
4107552f7358SJed Brown     const double   *meshCoords = out.pointlist;
41081d4b4d7bSJed Brown     int            *cells      = out.tetrahedronlist;
41091d4b4d7bSJed Brown 
4110552f7358SJed Brown     PetscBool      interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE;
4111552f7358SJed Brown 
41129db3b87dSMatthew G. Knepley     ierr = DMPlexInvertCells_Internal(dim, numCells, numCorners, cells);CHKERRQ(ierr);
41130fde5641SMatthew G Knepley     ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr);
4114552f7358SJed Brown     /* Set labels */
4115552f7358SJed Brown     for (v = 0; v < numVertices; ++v) {
4116552f7358SJed Brown       if (out.pointmarkerlist[v]) {
4117552f7358SJed Brown         ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr);
4118552f7358SJed Brown       }
4119552f7358SJed Brown     }
4120552f7358SJed Brown     if (interpolate) {
4121552f7358SJed Brown       PetscInt e, f;
4122552f7358SJed Brown 
4123552f7358SJed Brown       for (e = 0; e < out.numberofedges; e++) {
4124552f7358SJed Brown         if (out.edgemarkerlist[e]) {
4125552f7358SJed Brown           const PetscInt  vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells};
4126552f7358SJed Brown           const PetscInt *edges;
4127552f7358SJed Brown           PetscInt        numEdges;
4128552f7358SJed Brown 
4129552f7358SJed Brown           ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr);
4130552f7358SJed Brown           if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges);
4131552f7358SJed Brown           ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr);
4132552f7358SJed Brown           ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr);
4133552f7358SJed Brown         }
4134552f7358SJed Brown       }
4135552f7358SJed Brown       for (f = 0; f < out.numberoftrifaces; f++) {
4136552f7358SJed Brown         if (out.trifacemarkerlist[f]) {
4137552f7358SJed Brown           const PetscInt  vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells};
4138552f7358SJed Brown           const PetscInt *faces;
4139552f7358SJed Brown           PetscInt        numFaces;
4140552f7358SJed Brown 
4141552f7358SJed Brown           ierr = DMPlexGetJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr);
4142552f7358SJed Brown           if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces);
4143552f7358SJed Brown           ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr);
4144552f7358SJed Brown           ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr);
4145552f7358SJed Brown         }
4146552f7358SJed Brown       }
4147552f7358SJed Brown     }
4148552f7358SJed Brown     ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr);
4149552f7358SJed Brown   }
4150552f7358SJed Brown   PetscFunctionReturn(0);
4151552f7358SJed Brown }
4152552f7358SJed Brown #endif
4153552f7358SJed Brown 
4154519f805aSKarl Rupp #if defined(PETSC_HAVE_CTETGEN)
4155552f7358SJed Brown #include "ctetgen.h"
4156552f7358SJed Brown 
4157552f7358SJed Brown #undef __FUNCT__
4158552f7358SJed Brown #define __FUNCT__ "DMPlexGenerate_CTetgen"
4159552f7358SJed Brown PetscErrorCode DMPlexGenerate_CTetgen(DM boundary, PetscBool interpolate, DM *dm)
4160552f7358SJed Brown {
416182f516ccSBarry Smith   MPI_Comm       comm;
4162552f7358SJed Brown   const PetscInt dim  = 3;
4163552f7358SJed Brown   PLC           *in, *out;
4164552f7358SJed Brown   PetscInt       verbose = 0, vStart, vEnd, v, fStart, fEnd, f;
4165552f7358SJed Brown   PetscMPIInt    rank;
4166552f7358SJed Brown   PetscErrorCode ierr;
4167552f7358SJed Brown 
4168552f7358SJed Brown   PetscFunctionBegin;
416982f516ccSBarry Smith   ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr);
41700298fd71SBarry Smith   ierr = PetscOptionsGetInt(((PetscObject) boundary)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr);
4171552f7358SJed Brown   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
4172552f7358SJed Brown   ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr);
4173552f7358SJed Brown   ierr = PLCCreate(&in);CHKERRQ(ierr);
4174552f7358SJed Brown   ierr = PLCCreate(&out);CHKERRQ(ierr);
41750d644c17SKarl Rupp 
4176552f7358SJed Brown   in->numberofpoints = vEnd - vStart;
4177552f7358SJed Brown   if (in->numberofpoints > 0) {
4178552f7358SJed Brown     PetscSection coordSection;
4179552f7358SJed Brown     Vec          coordinates;
4180552f7358SJed Brown     PetscScalar *array;
4181552f7358SJed Brown 
4182785e854fSJed Brown     ierr = PetscMalloc1(in->numberofpoints*dim, &in->pointlist);CHKERRQ(ierr);
4183785e854fSJed Brown     ierr = PetscMalloc1(in->numberofpoints,       &in->pointmarkerlist);CHKERRQ(ierr);
4184552f7358SJed Brown     ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr);
418569d8a9ceSMatthew G. Knepley     ierr = DMGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr);
4186552f7358SJed Brown     ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr);
4187552f7358SJed Brown     for (v = vStart; v < vEnd; ++v) {
4188552f7358SJed Brown       const PetscInt idx = v - vStart;
4189552f7358SJed Brown       PetscInt       off, d, m;
4190552f7358SJed Brown 
4191552f7358SJed Brown       ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr);
4192552f7358SJed Brown       for (d = 0; d < dim; ++d) {
4193552f7358SJed Brown         in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]);
4194552f7358SJed Brown       }
4195552f7358SJed Brown       ierr = DMPlexGetLabelValue(boundary, "marker", v, &m);CHKERRQ(ierr);
41960d644c17SKarl Rupp 
4197552f7358SJed Brown       in->pointmarkerlist[idx] = (int) m;
4198552f7358SJed Brown     }
4199552f7358SJed Brown     ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr);
4200552f7358SJed Brown   }
4201552f7358SJed Brown   ierr  = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr);
42020d644c17SKarl Rupp 
4203552f7358SJed Brown   in->numberoffacets = fEnd - fStart;
4204552f7358SJed Brown   if (in->numberoffacets > 0) {
4205785e854fSJed Brown     ierr = PetscMalloc1(in->numberoffacets, &in->facetlist);CHKERRQ(ierr);
4206785e854fSJed Brown     ierr = PetscMalloc1(in->numberoffacets,   &in->facetmarkerlist);CHKERRQ(ierr);
4207552f7358SJed Brown     for (f = fStart; f < fEnd; ++f) {
4208552f7358SJed Brown       const PetscInt idx     = f - fStart;
42090298fd71SBarry Smith       PetscInt      *points = NULL, numPoints, p, numVertices = 0, v, m;
4210552f7358SJed Brown       polygon       *poly;
4211552f7358SJed Brown 
4212552f7358SJed Brown       in->facetlist[idx].numberofpolygons = 1;
42130d644c17SKarl Rupp 
4214785e854fSJed Brown       ierr = PetscMalloc1(in->facetlist[idx].numberofpolygons, &in->facetlist[idx].polygonlist);CHKERRQ(ierr);
42150d644c17SKarl Rupp 
4216552f7358SJed Brown       in->facetlist[idx].numberofholes    = 0;
42170298fd71SBarry Smith       in->facetlist[idx].holelist         = NULL;
4218552f7358SJed Brown 
4219552f7358SJed Brown       ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);
4220552f7358SJed Brown       for (p = 0; p < numPoints*2; p += 2) {
4221552f7358SJed Brown         const PetscInt point = points[p];
42220d644c17SKarl Rupp         if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point;
4223552f7358SJed Brown       }
4224552f7358SJed Brown 
4225552f7358SJed Brown       poly                   = in->facetlist[idx].polygonlist;
4226552f7358SJed Brown       poly->numberofvertices = numVertices;
4227785e854fSJed Brown       ierr                   = PetscMalloc1(poly->numberofvertices, &poly->vertexlist);CHKERRQ(ierr);
4228552f7358SJed Brown       for (v = 0; v < numVertices; ++v) {
4229552f7358SJed Brown         const PetscInt vIdx = points[v] - vStart;
4230552f7358SJed Brown         poly->vertexlist[v] = vIdx;
4231552f7358SJed Brown       }
4232552f7358SJed Brown       ierr                     = DMPlexGetLabelValue(boundary, "marker", f, &m);CHKERRQ(ierr);
4233552f7358SJed Brown       in->facetmarkerlist[idx] = (int) m;
4234552f7358SJed Brown       ierr                     = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);
4235552f7358SJed Brown     }
4236552f7358SJed Brown   }
4237552f7358SJed Brown   if (!rank) {
4238552f7358SJed Brown     TetGenOpts t;
4239552f7358SJed Brown 
4240552f7358SJed Brown     ierr        = TetGenOptsInitialize(&t);CHKERRQ(ierr);
4241552f7358SJed Brown     t.in        = boundary; /* Should go away */
4242552f7358SJed Brown     t.plc       = 1;
4243552f7358SJed Brown     t.quality   = 1;
4244552f7358SJed Brown     t.edgesout  = 1;
4245552f7358SJed Brown     t.zeroindex = 1;
4246552f7358SJed Brown     t.quiet     = 1;
4247552f7358SJed Brown     t.verbose   = verbose;
4248552f7358SJed Brown     ierr        = TetGenCheckOpts(&t);CHKERRQ(ierr);
4249552f7358SJed Brown     ierr        = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr);
4250552f7358SJed Brown   }
4251552f7358SJed Brown   {
4252552f7358SJed Brown     const PetscInt numCorners  = 4;
4253552f7358SJed Brown     const PetscInt numCells    = out->numberoftetrahedra;
4254552f7358SJed Brown     const PetscInt numVertices = out->numberofpoints;
4255552f7358SJed Brown     const double   *meshCoords = out->pointlist;
42561d4b4d7bSJed Brown     int            *cells      = out->tetrahedronlist;
4257552f7358SJed Brown 
42589db3b87dSMatthew G. Knepley     ierr = DMPlexInvertCells_Internal(dim, numCells, numCorners, cells);CHKERRQ(ierr);
42590fde5641SMatthew G Knepley     ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr);
4260552f7358SJed Brown     /* Set labels */
4261552f7358SJed Brown     for (v = 0; v < numVertices; ++v) {
4262552f7358SJed Brown       if (out->pointmarkerlist[v]) {
4263552f7358SJed Brown         ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr);
4264552f7358SJed Brown       }
4265552f7358SJed Brown     }
4266552f7358SJed Brown     if (interpolate) {
4267552f7358SJed Brown       PetscInt e;
4268552f7358SJed Brown 
4269552f7358SJed Brown       for (e = 0; e < out->numberofedges; e++) {
4270552f7358SJed Brown         if (out->edgemarkerlist[e]) {
4271552f7358SJed Brown           const PetscInt  vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells};
4272552f7358SJed Brown           const PetscInt *edges;
4273552f7358SJed Brown           PetscInt        numEdges;
4274552f7358SJed Brown 
4275552f7358SJed Brown           ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr);
4276552f7358SJed Brown           if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges);
4277552f7358SJed Brown           ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr);
4278552f7358SJed Brown           ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr);
4279552f7358SJed Brown         }
4280552f7358SJed Brown       }
4281552f7358SJed Brown       for (f = 0; f < out->numberoftrifaces; f++) {
4282552f7358SJed Brown         if (out->trifacemarkerlist[f]) {
4283552f7358SJed Brown           const PetscInt  vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells};
4284552f7358SJed Brown           const PetscInt *faces;
4285552f7358SJed Brown           PetscInt        numFaces;
4286552f7358SJed Brown 
4287552f7358SJed Brown           ierr = DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr);
4288552f7358SJed Brown           if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces);
4289552f7358SJed Brown           ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr);
4290552f7358SJed Brown           ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr);
4291552f7358SJed Brown         }
4292552f7358SJed Brown       }
4293552f7358SJed Brown     }
4294552f7358SJed Brown     ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr);
4295552f7358SJed Brown   }
4296552f7358SJed Brown 
4297552f7358SJed Brown   ierr = PLCDestroy(&in);CHKERRQ(ierr);
4298552f7358SJed Brown   ierr = PLCDestroy(&out);CHKERRQ(ierr);
4299552f7358SJed Brown   PetscFunctionReturn(0);
4300552f7358SJed Brown }
4301552f7358SJed Brown 
4302552f7358SJed Brown #undef __FUNCT__
4303552f7358SJed Brown #define __FUNCT__ "DMPlexRefine_CTetgen"
4304552f7358SJed Brown PetscErrorCode DMPlexRefine_CTetgen(DM dm, PetscReal *maxVolumes, DM *dmRefined)
4305552f7358SJed Brown {
430682f516ccSBarry Smith   MPI_Comm       comm;
4307552f7358SJed Brown   const PetscInt dim  = 3;
4308552f7358SJed Brown   PLC           *in, *out;
4309552f7358SJed Brown   PetscInt       verbose = 0, vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal;
4310552f7358SJed Brown   PetscMPIInt    rank;
4311552f7358SJed Brown   PetscErrorCode ierr;
4312552f7358SJed Brown 
4313552f7358SJed Brown   PetscFunctionBegin;
431482f516ccSBarry Smith   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
43150298fd71SBarry Smith   ierr = PetscOptionsGetInt(((PetscObject) dm)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr);
4316552f7358SJed Brown   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
4317552f7358SJed Brown   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
4318552f7358SJed Brown   ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr);
4319552f7358SJed Brown   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
4320552f7358SJed Brown   ierr = PLCCreate(&in);CHKERRQ(ierr);
4321552f7358SJed Brown   ierr = PLCCreate(&out);CHKERRQ(ierr);
43220d644c17SKarl Rupp 
4323552f7358SJed Brown   in->numberofpoints = vEnd - vStart;
4324552f7358SJed Brown   if (in->numberofpoints > 0) {
4325552f7358SJed Brown     PetscSection coordSection;
4326552f7358SJed Brown     Vec          coordinates;
4327552f7358SJed Brown     PetscScalar *array;
4328552f7358SJed Brown 
4329785e854fSJed Brown     ierr = PetscMalloc1(in->numberofpoints*dim, &in->pointlist);CHKERRQ(ierr);
4330785e854fSJed Brown     ierr = PetscMalloc1(in->numberofpoints,       &in->pointmarkerlist);CHKERRQ(ierr);
4331552f7358SJed Brown     ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
433269d8a9ceSMatthew G. Knepley     ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr);
4333552f7358SJed Brown     ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr);
4334552f7358SJed Brown     for (v = vStart; v < vEnd; ++v) {
4335552f7358SJed Brown       const PetscInt idx = v - vStart;
4336552f7358SJed Brown       PetscInt       off, d, m;
4337552f7358SJed Brown 
4338552f7358SJed Brown       ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr);
4339552f7358SJed Brown       for (d = 0; d < dim; ++d) {
4340552f7358SJed Brown         in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]);
4341552f7358SJed Brown       }
4342552f7358SJed Brown       ierr = DMPlexGetLabelValue(dm, "marker", v, &m);CHKERRQ(ierr);
43430d644c17SKarl Rupp 
4344552f7358SJed Brown       in->pointmarkerlist[idx] = (int) m;
4345552f7358SJed Brown     }
4346552f7358SJed Brown     ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr);
4347552f7358SJed Brown   }
4348552f7358SJed Brown   ierr  = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
43490d644c17SKarl Rupp 
4350552f7358SJed Brown   in->numberofcorners       = 4;
4351552f7358SJed Brown   in->numberoftetrahedra    = cEnd - cStart;
4352552f7358SJed Brown   in->tetrahedronvolumelist = maxVolumes;
4353552f7358SJed Brown   if (in->numberoftetrahedra > 0) {
4354785e854fSJed Brown     ierr = PetscMalloc1(in->numberoftetrahedra*in->numberofcorners, &in->tetrahedronlist);CHKERRQ(ierr);
4355552f7358SJed Brown     for (c = cStart; c < cEnd; ++c) {
4356552f7358SJed Brown       const PetscInt idx      = c - cStart;
43570298fd71SBarry Smith       PetscInt      *closure = NULL;
4358552f7358SJed Brown       PetscInt       closureSize;
4359552f7358SJed Brown 
4360552f7358SJed Brown       ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
4361552f7358SJed 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);
4362552f7358SJed Brown       for (v = 0; v < 4; ++v) {
4363552f7358SJed Brown         in->tetrahedronlist[idx*in->numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart;
4364552f7358SJed Brown       }
4365552f7358SJed Brown       ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
4366552f7358SJed Brown     }
4367552f7358SJed Brown   }
4368552f7358SJed Brown   if (!rank) {
4369552f7358SJed Brown     TetGenOpts t;
4370552f7358SJed Brown 
4371552f7358SJed Brown     ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr);
43720d644c17SKarl Rupp 
4373552f7358SJed Brown     t.in        = dm; /* Should go away */
4374552f7358SJed Brown     t.refine    = 1;
4375552f7358SJed Brown     t.varvolume = 1;
4376552f7358SJed Brown     t.quality   = 1;
4377552f7358SJed Brown     t.edgesout  = 1;
4378552f7358SJed Brown     t.zeroindex = 1;
4379552f7358SJed Brown     t.quiet     = 1;
4380552f7358SJed Brown     t.verbose   = verbose; /* Change this */
43810d644c17SKarl Rupp 
4382552f7358SJed Brown     ierr = TetGenCheckOpts(&t);CHKERRQ(ierr);
4383552f7358SJed Brown     ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr);
4384552f7358SJed Brown   }
4385552f7358SJed Brown   {
4386552f7358SJed Brown     const PetscInt numCorners  = 4;
4387552f7358SJed Brown     const PetscInt numCells    = out->numberoftetrahedra;
4388552f7358SJed Brown     const PetscInt numVertices = out->numberofpoints;
4389552f7358SJed Brown     const double   *meshCoords = out->pointlist;
43901d4b4d7bSJed Brown     int            *cells      = out->tetrahedronlist;
4391552f7358SJed Brown     PetscBool      interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE;
4392552f7358SJed Brown 
43939db3b87dSMatthew G. Knepley     ierr = DMPlexInvertCells_Internal(dim, numCells, numCorners, cells);CHKERRQ(ierr);
43940fde5641SMatthew G Knepley     ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr);
4395552f7358SJed Brown     /* Set labels */
4396552f7358SJed Brown     for (v = 0; v < numVertices; ++v) {
4397552f7358SJed Brown       if (out->pointmarkerlist[v]) {
4398552f7358SJed Brown         ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr);
4399552f7358SJed Brown       }
4400552f7358SJed Brown     }
4401552f7358SJed Brown     if (interpolate) {
4402552f7358SJed Brown       PetscInt e, f;
4403552f7358SJed Brown 
4404552f7358SJed Brown       for (e = 0; e < out->numberofedges; e++) {
4405552f7358SJed Brown         if (out->edgemarkerlist[e]) {
4406552f7358SJed Brown           const PetscInt  vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells};
4407552f7358SJed Brown           const PetscInt *edges;
4408552f7358SJed Brown           PetscInt        numEdges;
4409552f7358SJed Brown 
4410552f7358SJed Brown           ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr);
4411552f7358SJed Brown           if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges);
4412552f7358SJed Brown           ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr);
4413552f7358SJed Brown           ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr);
4414552f7358SJed Brown         }
4415552f7358SJed Brown       }
4416552f7358SJed Brown       for (f = 0; f < out->numberoftrifaces; f++) {
4417552f7358SJed Brown         if (out->trifacemarkerlist[f]) {
4418552f7358SJed Brown           const PetscInt  vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells};
4419552f7358SJed Brown           const PetscInt *faces;
4420552f7358SJed Brown           PetscInt        numFaces;
4421552f7358SJed Brown 
4422552f7358SJed Brown           ierr = DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr);
4423552f7358SJed Brown           if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces);
4424552f7358SJed Brown           ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr);
4425552f7358SJed Brown           ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr);
4426552f7358SJed Brown         }
4427552f7358SJed Brown       }
4428552f7358SJed Brown     }
4429552f7358SJed Brown     ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr);
4430552f7358SJed Brown   }
4431552f7358SJed Brown   ierr = PLCDestroy(&in);CHKERRQ(ierr);
4432552f7358SJed Brown   ierr = PLCDestroy(&out);CHKERRQ(ierr);
4433552f7358SJed Brown   PetscFunctionReturn(0);
4434552f7358SJed Brown }
4435552f7358SJed Brown #endif
4436552f7358SJed Brown 
4437552f7358SJed Brown #undef __FUNCT__
4438552f7358SJed Brown #define __FUNCT__ "DMPlexGenerate"
4439552f7358SJed Brown /*@C
4440552f7358SJed Brown   DMPlexGenerate - Generates a mesh.
4441552f7358SJed Brown 
4442552f7358SJed Brown   Not Collective
4443552f7358SJed Brown 
4444552f7358SJed Brown   Input Parameters:
4445552f7358SJed Brown + boundary - The DMPlex boundary object
4446552f7358SJed Brown . name - The mesh generation package name
4447552f7358SJed Brown - interpolate - Flag to create intermediate mesh elements
4448552f7358SJed Brown 
4449552f7358SJed Brown   Output Parameter:
4450552f7358SJed Brown . mesh - The DMPlex object
4451552f7358SJed Brown 
4452552f7358SJed Brown   Level: intermediate
4453552f7358SJed Brown 
4454552f7358SJed Brown .keywords: mesh, elements
4455552f7358SJed Brown .seealso: DMPlexCreate(), DMRefine()
4456552f7358SJed Brown @*/
4457552f7358SJed Brown PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh)
4458552f7358SJed Brown {
4459552f7358SJed Brown   PetscInt       dim;
4460552f7358SJed Brown   char           genname[1024];
4461552f7358SJed Brown   PetscBool      isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg;
4462552f7358SJed Brown   PetscErrorCode ierr;
4463552f7358SJed Brown 
4464552f7358SJed Brown   PetscFunctionBegin;
4465552f7358SJed Brown   PetscValidHeaderSpecific(boundary, DM_CLASSID, 1);
4466552f7358SJed Brown   PetscValidLogicalCollectiveBool(boundary, interpolate, 2);
4467552f7358SJed Brown   ierr = DMPlexGetDimension(boundary, &dim);CHKERRQ(ierr);
4468552f7358SJed Brown   ierr = PetscOptionsGetString(((PetscObject) boundary)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr);
44690d644c17SKarl Rupp   if (flg) name = genname;
4470552f7358SJed Brown   if (name) {
4471552f7358SJed Brown     ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr);
4472552f7358SJed Brown     ierr = PetscStrcmp(name, "tetgen",   &isTetgen);CHKERRQ(ierr);
4473552f7358SJed Brown     ierr = PetscStrcmp(name, "ctetgen",  &isCTetgen);CHKERRQ(ierr);
4474552f7358SJed Brown   }
4475552f7358SJed Brown   switch (dim) {
4476552f7358SJed Brown   case 1:
4477552f7358SJed Brown     if (!name || isTriangle) {
4478519f805aSKarl Rupp #if defined(PETSC_HAVE_TRIANGLE)
4479552f7358SJed Brown       ierr = DMPlexGenerate_Triangle(boundary, interpolate, mesh);CHKERRQ(ierr);
4480552f7358SJed Brown #else
448182f516ccSBarry Smith       SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Mesh generation needs external package support.\nPlease reconfigure with --download-triangle.");
4482552f7358SJed Brown #endif
448382f516ccSBarry Smith     } else SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name);
4484552f7358SJed Brown     break;
4485552f7358SJed Brown   case 2:
4486552f7358SJed Brown     if (!name || isCTetgen) {
4487519f805aSKarl Rupp #if defined(PETSC_HAVE_CTETGEN)
4488552f7358SJed Brown       ierr = DMPlexGenerate_CTetgen(boundary, interpolate, mesh);CHKERRQ(ierr);
4489552f7358SJed Brown #else
449082f516ccSBarry Smith       SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen.");
4491552f7358SJed Brown #endif
4492552f7358SJed Brown     } else if (isTetgen) {
4493519f805aSKarl Rupp #if defined(PETSC_HAVE_TETGEN)
4494552f7358SJed Brown       ierr = DMPlexGenerate_Tetgen(boundary, interpolate, mesh);CHKERRQ(ierr);
4495552f7358SJed Brown #else
449682f516ccSBarry Smith       SETERRQ(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen.");
4497552f7358SJed Brown #endif
449882f516ccSBarry Smith     } else SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name);
4499552f7358SJed Brown     break;
4500552f7358SJed Brown   default:
450182f516ccSBarry Smith     SETERRQ1(PetscObjectComm((PetscObject)boundary), PETSC_ERR_SUP, "Mesh generation for a dimension %d boundary is not supported.", dim);
4502552f7358SJed Brown   }
4503552f7358SJed Brown   PetscFunctionReturn(0);
4504552f7358SJed Brown }
4505552f7358SJed Brown 
4506552f7358SJed Brown #undef __FUNCT__
4507552f7358SJed Brown #define __FUNCT__ "DMRefine_Plex"
4508552f7358SJed Brown PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined)
4509552f7358SJed Brown {
4510552f7358SJed Brown   PetscReal      refinementLimit;
4511552f7358SJed Brown   PetscInt       dim, cStart, cEnd;
45120298fd71SBarry Smith   char           genname[1024], *name = NULL;
4513552f7358SJed Brown   PetscBool      isUniform, isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg;
4514552f7358SJed Brown   PetscErrorCode ierr;
4515552f7358SJed Brown 
4516552f7358SJed Brown   PetscFunctionBegin;
4517552f7358SJed Brown   ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr);
4518552f7358SJed Brown   if (isUniform) {
4519552f7358SJed Brown     CellRefiner cellRefiner;
4520552f7358SJed Brown 
4521509c9b89SMatthew G. Knepley     ierr = DMPlexGetCellRefiner_Internal(dm, &cellRefiner);CHKERRQ(ierr);
4522509c9b89SMatthew G. Knepley     ierr = DMPlexRefineUniform_Internal(dm, cellRefiner, dmRefined);CHKERRQ(ierr);
4523552f7358SJed Brown     PetscFunctionReturn(0);
4524552f7358SJed Brown   }
4525552f7358SJed Brown   ierr = DMPlexGetRefinementLimit(dm, &refinementLimit);CHKERRQ(ierr);
4526552f7358SJed Brown   if (refinementLimit == 0.0) PetscFunctionReturn(0);
4527552f7358SJed Brown   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
4528552f7358SJed Brown   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
4529552f7358SJed Brown   ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr);
45300d644c17SKarl Rupp   if (flg) name = genname;
4531552f7358SJed Brown   if (name) {
4532552f7358SJed Brown     ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr);
4533552f7358SJed Brown     ierr = PetscStrcmp(name, "tetgen",   &isTetgen);CHKERRQ(ierr);
4534552f7358SJed Brown     ierr = PetscStrcmp(name, "ctetgen",  &isCTetgen);CHKERRQ(ierr);
4535552f7358SJed Brown   }
4536552f7358SJed Brown   switch (dim) {
4537552f7358SJed Brown   case 2:
4538552f7358SJed Brown     if (!name || isTriangle) {
4539519f805aSKarl Rupp #if defined(PETSC_HAVE_TRIANGLE)
4540552f7358SJed Brown       double  *maxVolumes;
4541552f7358SJed Brown       PetscInt c;
4542552f7358SJed Brown 
4543785e854fSJed Brown       ierr = PetscMalloc1((cEnd - cStart), &maxVolumes);CHKERRQ(ierr);
45440d644c17SKarl Rupp       for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit;
4545552f7358SJed Brown       ierr = DMPlexRefine_Triangle(dm, maxVolumes, dmRefined);CHKERRQ(ierr);
45466b0a3334SMatthew G. Knepley       ierr = PetscFree(maxVolumes);CHKERRQ(ierr);
4547552f7358SJed Brown #else
454882f516ccSBarry Smith       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh refinement needs external package support.\nPlease reconfigure with --download-triangle.");
4549552f7358SJed Brown #endif
455082f516ccSBarry Smith     } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name);
4551552f7358SJed Brown     break;
4552552f7358SJed Brown   case 3:
4553552f7358SJed Brown     if (!name || isCTetgen) {
4554519f805aSKarl Rupp #if defined(PETSC_HAVE_CTETGEN)
4555552f7358SJed Brown       PetscReal *maxVolumes;
4556552f7358SJed Brown       PetscInt   c;
4557552f7358SJed Brown 
4558785e854fSJed Brown       ierr = PetscMalloc1((cEnd - cStart), &maxVolumes);CHKERRQ(ierr);
45590d644c17SKarl Rupp       for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit;
4560552f7358SJed Brown       ierr = DMPlexRefine_CTetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr);
4561552f7358SJed Brown #else
456282f516ccSBarry Smith       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen.");
4563552f7358SJed Brown #endif
4564552f7358SJed Brown     } else if (isTetgen) {
4565519f805aSKarl Rupp #if defined(PETSC_HAVE_TETGEN)
4566552f7358SJed Brown       double  *maxVolumes;
4567552f7358SJed Brown       PetscInt c;
4568552f7358SJed Brown 
4569785e854fSJed Brown       ierr = PetscMalloc1((cEnd - cStart), &maxVolumes);CHKERRQ(ierr);
45700d644c17SKarl Rupp       for (c = 0; c < cEnd-cStart; ++c) maxVolumes[c] = refinementLimit;
4571552f7358SJed Brown       ierr = DMPlexRefine_Tetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr);
4572552f7358SJed Brown #else
457382f516ccSBarry Smith       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen.");
4574552f7358SJed Brown #endif
457582f516ccSBarry Smith     } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name);
4576552f7358SJed Brown     break;
4577552f7358SJed Brown   default:
457882f516ccSBarry Smith     SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh refinement in dimension %d is not supported.", dim);
4579552f7358SJed Brown   }
4580552f7358SJed Brown   PetscFunctionReturn(0);
4581552f7358SJed Brown }
4582552f7358SJed Brown 
4583552f7358SJed Brown #undef __FUNCT__
4584aa50250dSMatthew G. Knepley #define __FUNCT__ "DMPlexGetDepthLabel"
4585552f7358SJed Brown /*@
4586aa50250dSMatthew G. Knepley   DMPlexGetDepthLabel - Get the DMLabel recording the depth of each point
4587552f7358SJed Brown 
4588552f7358SJed Brown   Not Collective
4589552f7358SJed Brown 
4590aa50250dSMatthew G. Knepley   Input Parameter:
4591552f7358SJed Brown . dm    - The DMPlex object
4592552f7358SJed Brown 
4593aa50250dSMatthew G. Knepley   Output Parameter:
4594aa50250dSMatthew G. Knepley . depthLabel - The DMLabel recording point depth
4595552f7358SJed Brown 
4596552f7358SJed Brown   Level: developer
4597552f7358SJed Brown 
4598aa50250dSMatthew G. Knepley .keywords: mesh, points
4599aa50250dSMatthew G. Knepley .seealso: DMPlexGetDepth(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum()
4600aa50250dSMatthew G. Knepley @*/
4601aa50250dSMatthew G. Knepley PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel)
4602aa50250dSMatthew G. Knepley {
4603aa50250dSMatthew G. Knepley   DM_Plex       *mesh = (DM_Plex*) dm->data;
4604aa50250dSMatthew G. Knepley   PetscErrorCode ierr;
4605aa50250dSMatthew G. Knepley 
4606aa50250dSMatthew G. Knepley   PetscFunctionBegin;
4607aa50250dSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4608aa50250dSMatthew G. Knepley   PetscValidPointer(depthLabel, 2);
460963d1a920SMatthew G. Knepley   if (!mesh->depthLabel) {ierr = DMPlexGetLabel(dm, "depth", &mesh->depthLabel);CHKERRQ(ierr);}
4610aa50250dSMatthew G. Knepley   *depthLabel = mesh->depthLabel;
4611aa50250dSMatthew G. Knepley   PetscFunctionReturn(0);
4612aa50250dSMatthew G. Knepley }
4613aa50250dSMatthew G. Knepley 
4614aa50250dSMatthew G. Knepley #undef __FUNCT__
4615aa50250dSMatthew G. Knepley #define __FUNCT__ "DMPlexGetDepth"
4616aa50250dSMatthew G. Knepley /*@
4617aa50250dSMatthew G. Knepley   DMPlexGetDepth - Get the depth of the DAG representing this mesh
4618aa50250dSMatthew G. Knepley 
4619aa50250dSMatthew G. Knepley   Not Collective
4620aa50250dSMatthew G. Knepley 
4621aa50250dSMatthew G. Knepley   Input Parameter:
4622aa50250dSMatthew G. Knepley . dm    - The DMPlex object
4623aa50250dSMatthew G. Knepley 
4624aa50250dSMatthew G. Knepley   Output Parameter:
4625aa50250dSMatthew G. Knepley . depth - The number of strata (breadth first levels) in the DAG
4626aa50250dSMatthew G. Knepley 
4627aa50250dSMatthew G. Knepley   Level: developer
4628552f7358SJed Brown 
4629552f7358SJed Brown .keywords: mesh, points
4630aa50250dSMatthew G. Knepley .seealso: DMPlexGetDepthLabel(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum()
4631552f7358SJed Brown @*/
4632552f7358SJed Brown PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth)
4633552f7358SJed Brown {
4634aa50250dSMatthew G. Knepley   DMLabel        label;
4635aa50250dSMatthew G. Knepley   PetscInt       d = 0;
4636552f7358SJed Brown   PetscErrorCode ierr;
4637552f7358SJed Brown 
4638552f7358SJed Brown   PetscFunctionBegin;
4639552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4640552f7358SJed Brown   PetscValidPointer(depth, 2);
4641aa50250dSMatthew G. Knepley   ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr);
4642aa50250dSMatthew G. Knepley   if (label) {ierr = DMLabelGetNumValues(label, &d);CHKERRQ(ierr);}
4643552f7358SJed Brown   *depth = d-1;
4644552f7358SJed Brown   PetscFunctionReturn(0);
4645552f7358SJed Brown }
4646552f7358SJed Brown 
4647552f7358SJed Brown #undef __FUNCT__
4648552f7358SJed Brown #define __FUNCT__ "DMPlexGetDepthStratum"
4649552f7358SJed Brown /*@
4650552f7358SJed Brown   DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth.
4651552f7358SJed Brown 
4652552f7358SJed Brown   Not Collective
4653552f7358SJed Brown 
4654552f7358SJed Brown   Input Parameters:
4655552f7358SJed Brown + dm           - The DMPlex object
4656552f7358SJed Brown - stratumValue - The requested depth
4657552f7358SJed Brown 
4658552f7358SJed Brown   Output Parameters:
4659552f7358SJed Brown + start - The first point at this depth
4660552f7358SJed Brown - end   - One beyond the last point at this depth
4661552f7358SJed Brown 
4662552f7358SJed Brown   Level: developer
4663552f7358SJed Brown 
4664552f7358SJed Brown .keywords: mesh, points
4665552f7358SJed Brown .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth()
4666552f7358SJed Brown @*/
46670adebc6cSBarry Smith PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end)
46680adebc6cSBarry Smith {
4669aa50250dSMatthew G. Knepley   DMLabel        label;
467063d1a920SMatthew G. Knepley   PetscInt       pStart, pEnd;
4671552f7358SJed Brown   PetscErrorCode ierr;
4672552f7358SJed Brown 
4673552f7358SJed Brown   PetscFunctionBegin;
4674552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
467563d1a920SMatthew G. Knepley   if (start) {PetscValidPointer(start, 3); *start = 0;}
467663d1a920SMatthew G. Knepley   if (end)   {PetscValidPointer(end,   4); *end   = 0;}
4677552f7358SJed Brown   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
46780d644c17SKarl Rupp   if (pStart == pEnd) PetscFunctionReturn(0);
467963d1a920SMatthew G. Knepley   if (stratumValue < 0) {
468063d1a920SMatthew G. Knepley     if (start) *start = pStart;
468163d1a920SMatthew G. Knepley     if (end)   *end   = pEnd;
468263d1a920SMatthew G. Knepley     PetscFunctionReturn(0);
4683552f7358SJed Brown   }
4684aa50250dSMatthew G. Knepley   ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr);
468563d1a920SMatthew G. Knepley   if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");
468663d1a920SMatthew G. Knepley   ierr = DMLabelGetStratumBounds(label, stratumValue, start, end);CHKERRQ(ierr);
4687552f7358SJed Brown   PetscFunctionReturn(0);
4688552f7358SJed Brown }
4689552f7358SJed Brown 
4690552f7358SJed Brown #undef __FUNCT__
4691552f7358SJed Brown #define __FUNCT__ "DMPlexGetHeightStratum"
4692552f7358SJed Brown /*@
4693552f7358SJed Brown   DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height.
4694552f7358SJed Brown 
4695552f7358SJed Brown   Not Collective
4696552f7358SJed Brown 
4697552f7358SJed Brown   Input Parameters:
4698552f7358SJed Brown + dm           - The DMPlex object
4699552f7358SJed Brown - stratumValue - The requested height
4700552f7358SJed Brown 
4701552f7358SJed Brown   Output Parameters:
4702552f7358SJed Brown + start - The first point at this height
4703552f7358SJed Brown - end   - One beyond the last point at this height
4704552f7358SJed Brown 
4705552f7358SJed Brown   Level: developer
4706552f7358SJed Brown 
4707552f7358SJed Brown .keywords: mesh, points
4708552f7358SJed Brown .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth()
4709552f7358SJed Brown @*/
47100adebc6cSBarry Smith PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end)
47110adebc6cSBarry Smith {
4712aa50250dSMatthew G. Knepley   DMLabel        label;
471363d1a920SMatthew G. Knepley   PetscInt       depth, pStart, pEnd;
4714552f7358SJed Brown   PetscErrorCode ierr;
4715552f7358SJed Brown 
4716552f7358SJed Brown   PetscFunctionBegin;
4717552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
471863d1a920SMatthew G. Knepley   if (start) {PetscValidPointer(start, 3); *start = 0;}
471963d1a920SMatthew G. Knepley   if (end)   {PetscValidPointer(end,   4); *end   = 0;}
4720552f7358SJed Brown   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
47210d644c17SKarl Rupp   if (pStart == pEnd) PetscFunctionReturn(0);
472263d1a920SMatthew G. Knepley   if (stratumValue < 0) {
472363d1a920SMatthew G. Knepley     if (start) *start = pStart;
472463d1a920SMatthew G. Knepley     if (end)   *end   = pEnd;
472563d1a920SMatthew G. Knepley     PetscFunctionReturn(0);
4726552f7358SJed Brown   }
4727aa50250dSMatthew G. Knepley   ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr);
4728aa50250dSMatthew G. Knepley   if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr);
472963d1a920SMatthew G. Knepley   ierr = DMLabelGetNumValues(label, &depth);CHKERRQ(ierr);
473063d1a920SMatthew G. Knepley   ierr = DMLabelGetStratumBounds(label, depth-1-stratumValue, start, end);CHKERRQ(ierr);
4731552f7358SJed Brown   PetscFunctionReturn(0);
4732552f7358SJed Brown }
4733552f7358SJed Brown 
4734552f7358SJed Brown #undef __FUNCT__
4735552f7358SJed Brown #define __FUNCT__ "DMPlexCreateSectionInitial"
4736552f7358SJed Brown /* Set the number of dof on each point and separate by fields */
4737a6dfd86eSKarl Rupp PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section)
4738a6dfd86eSKarl Rupp {
4739552f7358SJed Brown   PetscInt      *numDofTot;
4740916f0f19SMatthew G. Knepley   PetscInt       depth, pStart = 0, pEnd = 0;
4741916f0f19SMatthew G. Knepley   PetscInt       p, d, dep, f;
4742552f7358SJed Brown   PetscErrorCode ierr;
4743552f7358SJed Brown 
4744552f7358SJed Brown   PetscFunctionBegin;
4745785e854fSJed Brown   ierr = PetscMalloc1((dim+1), &numDofTot);CHKERRQ(ierr);
4746552f7358SJed Brown   for (d = 0; d <= dim; ++d) {
4747552f7358SJed Brown     numDofTot[d] = 0;
47480d644c17SKarl Rupp     for (f = 0; f < numFields; ++f) numDofTot[d] += numDof[f*(dim+1)+d];
4749552f7358SJed Brown   }
475082f516ccSBarry Smith   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr);
4751552f7358SJed Brown   if (numFields > 0) {
4752552f7358SJed Brown     ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr);
4753552f7358SJed Brown     if (numComp) {
4754552f7358SJed Brown       for (f = 0; f < numFields; ++f) {
4755552f7358SJed Brown         ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr);
4756552f7358SJed Brown       }
4757552f7358SJed Brown     }
4758552f7358SJed Brown   }
4759552f7358SJed Brown   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
4760552f7358SJed Brown   ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr);
4761916f0f19SMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
4762916f0f19SMatthew G. Knepley   for (dep = 0; dep <= depth; ++dep) {
4763916f0f19SMatthew G. Knepley     d    = dim == depth ? dep : (!dep ? 0 : dim);
4764916f0f19SMatthew G. Knepley     ierr = DMPlexGetDepthStratum(dm, dep, &pStart, &pEnd);CHKERRQ(ierr);
4765552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
4766552f7358SJed Brown       for (f = 0; f < numFields; ++f) {
4767552f7358SJed Brown         ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr);
4768552f7358SJed Brown       }
4769552f7358SJed Brown       ierr = PetscSectionSetDof(*section, p, numDofTot[d]);CHKERRQ(ierr);
4770552f7358SJed Brown     }
4771552f7358SJed Brown   }
4772552f7358SJed Brown   ierr = PetscFree(numDofTot);CHKERRQ(ierr);
4773552f7358SJed Brown   PetscFunctionReturn(0);
4774552f7358SJed Brown }
4775552f7358SJed Brown 
4776552f7358SJed Brown #undef __FUNCT__
4777552f7358SJed Brown #define __FUNCT__ "DMPlexCreateSectionBCDof"
4778552f7358SJed Brown /* Set the number of dof on each point and separate by fields
4779552f7358SJed Brown    If constDof is PETSC_DETERMINE, constrain every dof on the point
4780552f7358SJed Brown */
4781a6dfd86eSKarl Rupp PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscInt constDof, PetscSection section)
4782a6dfd86eSKarl Rupp {
4783552f7358SJed Brown   PetscInt       numFields;
4784552f7358SJed Brown   PetscInt       bc;
4785552f7358SJed Brown   PetscErrorCode ierr;
4786552f7358SJed Brown 
4787552f7358SJed Brown   PetscFunctionBegin;
4788552f7358SJed Brown   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
4789552f7358SJed Brown   for (bc = 0; bc < numBC; ++bc) {
4790552f7358SJed Brown     PetscInt        field = 0;
4791552f7358SJed Brown     const PetscInt *idx;
4792552f7358SJed Brown     PetscInt        n, i;
4793552f7358SJed Brown 
47940d644c17SKarl Rupp     if (numFields) field = bcField[bc];
4795552f7358SJed Brown     ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr);
4796552f7358SJed Brown     ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr);
4797552f7358SJed Brown     for (i = 0; i < n; ++i) {
4798552f7358SJed Brown       const PetscInt p        = idx[i];
4799552f7358SJed Brown       PetscInt       numConst = constDof;
4800552f7358SJed Brown 
4801552f7358SJed Brown       /* Constrain every dof on the point */
4802552f7358SJed Brown       if (numConst < 0) {
4803552f7358SJed Brown         if (numFields) {
4804552f7358SJed Brown           ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr);
4805552f7358SJed Brown         } else {
4806552f7358SJed Brown           ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr);
4807552f7358SJed Brown         }
4808552f7358SJed Brown       }
4809552f7358SJed Brown       if (numFields) {
4810552f7358SJed Brown         ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr);
4811552f7358SJed Brown       }
4812552f7358SJed Brown       ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr);
4813552f7358SJed Brown     }
4814552f7358SJed Brown     ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr);
4815552f7358SJed Brown   }
4816552f7358SJed Brown   PetscFunctionReturn(0);
4817552f7358SJed Brown }
4818552f7358SJed Brown 
4819552f7358SJed Brown #undef __FUNCT__
4820552f7358SJed Brown #define __FUNCT__ "DMPlexCreateSectionBCIndicesAll"
4821552f7358SJed Brown /* Set the constrained indices on each point and separate by fields */
48220adebc6cSBarry Smith PetscErrorCode DMPlexCreateSectionBCIndicesAll(DM dm, PetscSection section)
48230adebc6cSBarry Smith {
4824552f7358SJed Brown   PetscInt      *maxConstraints;
4825552f7358SJed Brown   PetscInt       numFields, f, pStart = 0, pEnd = 0, p;
4826552f7358SJed Brown   PetscErrorCode ierr;
4827552f7358SJed Brown 
4828552f7358SJed Brown   PetscFunctionBegin;
4829552f7358SJed Brown   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
4830552f7358SJed Brown   ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr);
4831785e854fSJed Brown   ierr = PetscMalloc1((numFields+1), &maxConstraints);CHKERRQ(ierr);
48320d644c17SKarl Rupp   for (f = 0; f <= numFields; ++f) maxConstraints[f] = 0;
4833552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
4834552f7358SJed Brown     PetscInt cdof;
4835552f7358SJed Brown 
4836552f7358SJed Brown     if (numFields) {
4837552f7358SJed Brown       for (f = 0; f < numFields; ++f) {
4838552f7358SJed Brown         ierr              = PetscSectionGetFieldConstraintDof(section, p, f, &cdof);CHKERRQ(ierr);
4839552f7358SJed Brown         maxConstraints[f] = PetscMax(maxConstraints[f], cdof);
4840552f7358SJed Brown       }
4841552f7358SJed Brown     } else {
4842552f7358SJed Brown       ierr              = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr);
4843552f7358SJed Brown       maxConstraints[0] = PetscMax(maxConstraints[0], cdof);
4844552f7358SJed Brown     }
4845552f7358SJed Brown   }
4846552f7358SJed Brown   for (f = 0; f < numFields; ++f) {
4847552f7358SJed Brown     maxConstraints[numFields] += maxConstraints[f];
4848552f7358SJed Brown   }
4849552f7358SJed Brown   if (maxConstraints[numFields]) {
4850552f7358SJed Brown     PetscInt *indices;
4851552f7358SJed Brown 
4852785e854fSJed Brown     ierr = PetscMalloc1(maxConstraints[numFields], &indices);CHKERRQ(ierr);
4853552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
4854552f7358SJed Brown       PetscInt cdof, d;
4855552f7358SJed Brown 
4856552f7358SJed Brown       ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr);
4857552f7358SJed Brown       if (cdof) {
4858552f7358SJed 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]);
4859552f7358SJed Brown         if (numFields) {
4860552f7358SJed Brown           PetscInt numConst = 0, foff = 0;
4861552f7358SJed Brown 
4862552f7358SJed Brown           for (f = 0; f < numFields; ++f) {
4863552f7358SJed Brown             PetscInt cfdof, fdof;
4864552f7358SJed Brown 
4865552f7358SJed Brown             ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr);
4866552f7358SJed Brown             ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cfdof);CHKERRQ(ierr);
4867552f7358SJed Brown             /* Change constraint numbering from absolute local dof number to field relative local dof number */
48680d644c17SKarl Rupp             for (d = 0; d < cfdof; ++d) indices[numConst+d] = d;
4869552f7358SJed Brown             ierr = PetscSectionSetFieldConstraintIndices(section, p, f, &indices[numConst]);CHKERRQ(ierr);
48700d644c17SKarl Rupp             for (d = 0; d < cfdof; ++d) indices[numConst+d] += foff;
4871552f7358SJed Brown             numConst += cfdof;
4872552f7358SJed Brown             foff     += fdof;
4873552f7358SJed Brown           }
4874552f7358SJed Brown           if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof);
4875552f7358SJed Brown         } else {
48760d644c17SKarl Rupp           for (d = 0; d < cdof; ++d) indices[d] = d;
4877552f7358SJed Brown         }
4878552f7358SJed Brown         ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr);
4879552f7358SJed Brown       }
4880552f7358SJed Brown     }
4881552f7358SJed Brown     ierr = PetscFree(indices);CHKERRQ(ierr);
4882552f7358SJed Brown   }
4883552f7358SJed Brown   ierr = PetscFree(maxConstraints);CHKERRQ(ierr);
4884552f7358SJed Brown   PetscFunctionReturn(0);
4885552f7358SJed Brown }
4886552f7358SJed Brown 
4887552f7358SJed Brown #undef __FUNCT__
4888552f7358SJed Brown #define __FUNCT__ "DMPlexCreateSectionBCIndicesField"
4889552f7358SJed Brown /* Set the constrained field indices on each point */
48900adebc6cSBarry Smith PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt field, IS bcPoints, IS constraintIndices, PetscSection section)
48910adebc6cSBarry Smith {
4892552f7358SJed Brown   const PetscInt *points, *indices;
4893552f7358SJed Brown   PetscInt        numFields, maxDof, numPoints, p, numConstraints;
4894552f7358SJed Brown   PetscErrorCode  ierr;
4895552f7358SJed Brown 
4896552f7358SJed Brown   PetscFunctionBegin;
4897552f7358SJed Brown   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
4898552f7358SJed 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);
4899552f7358SJed Brown 
4900552f7358SJed Brown   ierr = ISGetLocalSize(bcPoints, &numPoints);CHKERRQ(ierr);
4901552f7358SJed Brown   ierr = ISGetIndices(bcPoints, &points);CHKERRQ(ierr);
4902552f7358SJed Brown   if (!constraintIndices) {
4903552f7358SJed Brown     PetscInt *idx, i;
4904552f7358SJed Brown 
4905552f7358SJed Brown     ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr);
4906785e854fSJed Brown     ierr = PetscMalloc1(maxDof, &idx);CHKERRQ(ierr);
49070d644c17SKarl Rupp     for (i = 0; i < maxDof; ++i) idx[i] = i;
4908552f7358SJed Brown     for (p = 0; p < numPoints; ++p) {
4909552f7358SJed Brown       ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, idx);CHKERRQ(ierr);
4910552f7358SJed Brown     }
4911552f7358SJed Brown     ierr = PetscFree(idx);CHKERRQ(ierr);
4912552f7358SJed Brown   } else {
4913552f7358SJed Brown     ierr = ISGetLocalSize(constraintIndices, &numConstraints);CHKERRQ(ierr);
4914552f7358SJed Brown     ierr = ISGetIndices(constraintIndices, &indices);CHKERRQ(ierr);
4915552f7358SJed Brown     for (p = 0; p < numPoints; ++p) {
4916552f7358SJed Brown       PetscInt fcdof;
4917552f7358SJed Brown 
4918552f7358SJed Brown       ierr = PetscSectionGetFieldConstraintDof(section, points[p], field, &fcdof);CHKERRQ(ierr);
491982f516ccSBarry Smith       if (fcdof != numConstraints) SETERRQ4(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Section point %d field %d has %d constraints, but yo ugave %d indices", p, field, fcdof, numConstraints);
4920552f7358SJed Brown       ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, indices);CHKERRQ(ierr);
4921552f7358SJed Brown     }
4922552f7358SJed Brown     ierr = ISRestoreIndices(constraintIndices, &indices);CHKERRQ(ierr);
4923552f7358SJed Brown   }
4924552f7358SJed Brown   ierr = ISRestoreIndices(bcPoints, &points);CHKERRQ(ierr);
4925552f7358SJed Brown   PetscFunctionReturn(0);
4926552f7358SJed Brown }
4927552f7358SJed Brown 
4928552f7358SJed Brown #undef __FUNCT__
4929552f7358SJed Brown #define __FUNCT__ "DMPlexCreateSectionBCIndices"
4930552f7358SJed Brown /* Set the constrained indices on each point and separate by fields */
49310adebc6cSBarry Smith PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section)
49320adebc6cSBarry Smith {
4933552f7358SJed Brown   PetscInt      *indices;
4934552f7358SJed Brown   PetscInt       numFields, maxDof, f, pStart = 0, pEnd = 0, p;
4935552f7358SJed Brown   PetscErrorCode ierr;
4936552f7358SJed Brown 
4937552f7358SJed Brown   PetscFunctionBegin;
4938552f7358SJed Brown   ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr);
4939785e854fSJed Brown   ierr = PetscMalloc1(maxDof, &indices);CHKERRQ(ierr);
4940552f7358SJed Brown   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
494182f516ccSBarry Smith   if (!numFields) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "This function only works after users have set field constraint indices.");
4942552f7358SJed Brown   ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr);
4943552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
4944552f7358SJed Brown     PetscInt cdof, d;
4945552f7358SJed Brown 
4946552f7358SJed Brown     ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr);
4947552f7358SJed Brown     if (cdof) {
4948552f7358SJed Brown       PetscInt numConst = 0, foff = 0;
4949552f7358SJed Brown 
4950552f7358SJed Brown       for (f = 0; f < numFields; ++f) {
4951552f7358SJed Brown         const PetscInt *fcind;
4952552f7358SJed Brown         PetscInt        fdof, fcdof;
4953552f7358SJed Brown 
4954552f7358SJed Brown         ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr);
4955552f7358SJed Brown         ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr);
4956552f7358SJed Brown         if (fcdof) {ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &fcind);CHKERRQ(ierr);}
4957552f7358SJed Brown         /* Change constraint numbering from field relative local dof number to absolute local dof number */
49580d644c17SKarl Rupp         for (d = 0; d < fcdof; ++d) indices[numConst+d] = fcind[d]+foff;
4959552f7358SJed Brown         foff     += fdof;
4960552f7358SJed Brown         numConst += fcdof;
4961552f7358SJed Brown       }
496282f516ccSBarry Smith       if (cdof != numConst) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof);
4963552f7358SJed Brown       ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr);
4964552f7358SJed Brown     }
4965552f7358SJed Brown   }
4966552f7358SJed Brown   ierr = PetscFree(indices);CHKERRQ(ierr);
4967552f7358SJed Brown   PetscFunctionReturn(0);
4968552f7358SJed Brown }
4969552f7358SJed Brown 
4970552f7358SJed Brown #undef __FUNCT__
4971552f7358SJed Brown #define __FUNCT__ "DMPlexCreateSection"
4972552f7358SJed Brown /*@C
4973552f7358SJed Brown   DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided.
4974552f7358SJed Brown 
4975552f7358SJed Brown   Not Collective
4976552f7358SJed Brown 
4977552f7358SJed Brown   Input Parameters:
4978552f7358SJed Brown + dm        - The DMPlex object
4979552f7358SJed Brown . dim       - The spatial dimension of the problem
4980552f7358SJed Brown . numFields - The number of fields in the problem
4981552f7358SJed Brown . numComp   - An array of size numFields that holds the number of components for each field
4982552f7358SJed 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
4983552f7358SJed Brown . numBC     - The number of boundary conditions
4984552f7358SJed Brown . bcField   - An array of size numBC giving the field number for each boundry condition
4985552f7358SJed Brown - bcPoints  - An array of size numBC giving an IS holding the sieve points to which each boundary condition applies
4986552f7358SJed Brown 
4987552f7358SJed Brown   Output Parameter:
4988552f7358SJed Brown . section - The PetscSection object
4989552f7358SJed Brown 
4990552f7358SJed 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
4991552f7358SJed Brown   nubmer of dof for field 0 on each edge.
4992552f7358SJed Brown 
4993552f7358SJed Brown   Level: developer
4994552f7358SJed Brown 
49953813dfbdSMatthew G Knepley   Fortran Notes:
49963813dfbdSMatthew G Knepley   A Fortran 90 version is available as DMPlexCreateSectionF90()
49973813dfbdSMatthew G Knepley 
4998552f7358SJed Brown .keywords: mesh, elements
4999552f7358SJed Brown .seealso: DMPlexCreate(), PetscSectionCreate()
5000552f7358SJed Brown @*/
5001a6dfd86eSKarl Rupp PetscErrorCode DMPlexCreateSection(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscSection *section)
5002a6dfd86eSKarl Rupp {
5003552f7358SJed Brown   PetscErrorCode ierr;
5004552f7358SJed Brown 
5005552f7358SJed Brown   PetscFunctionBegin;
5006552f7358SJed Brown   ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr);
5007552f7358SJed Brown   ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcPoints, PETSC_DETERMINE, *section);CHKERRQ(ierr);
5008552f7358SJed Brown   ierr = PetscSectionSetUp(*section);CHKERRQ(ierr);
5009552f7358SJed Brown   if (numBC) {ierr = DMPlexCreateSectionBCIndicesAll(dm, *section);CHKERRQ(ierr);}
5010ce1779c8SBarry Smith   ierr = PetscSectionViewFromOptions(*section,NULL,"-section_view");CHKERRQ(ierr);
5011552f7358SJed Brown   PetscFunctionReturn(0);
5012552f7358SJed Brown }
5013552f7358SJed Brown 
5014552f7358SJed Brown #undef __FUNCT__
5015552f7358SJed Brown #define __FUNCT__ "DMCreateCoordinateDM_Plex"
50160adebc6cSBarry Smith PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm)
50170adebc6cSBarry Smith {
5018552f7358SJed Brown   PetscSection   section;
5019552f7358SJed Brown   PetscErrorCode ierr;
5020552f7358SJed Brown 
5021552f7358SJed Brown   PetscFunctionBegin;
502238221697SMatthew G. Knepley   ierr = DMClone(dm, cdm);CHKERRQ(ierr);
502382f516ccSBarry Smith   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section);CHKERRQ(ierr);
5024552f7358SJed Brown   ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr);
50251d799100SJed Brown   ierr = PetscSectionDestroy(&section);CHKERRQ(ierr);
5026552f7358SJed Brown   PetscFunctionReturn(0);
5027552f7358SJed Brown }
5028552f7358SJed Brown 
5029552f7358SJed Brown #undef __FUNCT__
5030552f7358SJed Brown #define __FUNCT__ "DMPlexGetConeSection"
50310adebc6cSBarry Smith PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section)
50320adebc6cSBarry Smith {
5033552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
5034552f7358SJed Brown 
5035552f7358SJed Brown   PetscFunctionBegin;
5036552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5037552f7358SJed Brown   if (section) *section = mesh->coneSection;
5038552f7358SJed Brown   PetscFunctionReturn(0);
5039552f7358SJed Brown }
5040552f7358SJed Brown 
5041552f7358SJed Brown #undef __FUNCT__
50428cb4d582SMatthew G. Knepley #define __FUNCT__ "DMPlexGetSupportSection"
50438cb4d582SMatthew G. Knepley PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section)
50448cb4d582SMatthew G. Knepley {
50458cb4d582SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
50468cb4d582SMatthew G. Knepley 
50478cb4d582SMatthew G. Knepley   PetscFunctionBegin;
50488cb4d582SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
50498cb4d582SMatthew G. Knepley   if (section) *section = mesh->supportSection;
50508cb4d582SMatthew G. Knepley   PetscFunctionReturn(0);
50518cb4d582SMatthew G. Knepley }
50528cb4d582SMatthew G. Knepley 
50538cb4d582SMatthew G. Knepley #undef __FUNCT__
5054552f7358SJed Brown #define __FUNCT__ "DMPlexGetCones"
5055a6dfd86eSKarl Rupp PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[])
5056a6dfd86eSKarl Rupp {
5057552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
5058552f7358SJed Brown 
5059552f7358SJed Brown   PetscFunctionBegin;
5060552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5061552f7358SJed Brown   if (cones) *cones = mesh->cones;
5062552f7358SJed Brown   PetscFunctionReturn(0);
5063552f7358SJed Brown }
5064552f7358SJed Brown 
5065552f7358SJed Brown #undef __FUNCT__
5066552f7358SJed Brown #define __FUNCT__ "DMPlexGetConeOrientations"
5067a6dfd86eSKarl Rupp PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[])
5068a6dfd86eSKarl Rupp {
5069552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
5070552f7358SJed Brown 
5071552f7358SJed Brown   PetscFunctionBegin;
5072552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5073552f7358SJed Brown   if (coneOrientations) *coneOrientations = mesh->coneOrientations;
5074552f7358SJed Brown   PetscFunctionReturn(0);
5075552f7358SJed Brown }
5076552f7358SJed Brown 
5077552f7358SJed Brown /******************************** FEM Support **********************************/
5078552f7358SJed Brown 
5079552f7358SJed Brown #undef __FUNCT__
50801a271a75SMatthew G. Knepley #define __FUNCT__ "DMPlexVecGetClosure_Depth1_Static"
50811a271a75SMatthew G. Knepley PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
5082a6dfd86eSKarl Rupp {
5083552f7358SJed Brown   PetscScalar    *array, *vArray;
5084d9917b9dSMatthew G. Knepley   const PetscInt *cone, *coneO;
50851a271a75SMatthew G. Knepley   PetscInt        pStart, pEnd, p, numPoints, size = 0, offset = 0;
5086552f7358SJed Brown   PetscErrorCode  ierr;
5087552f7358SJed Brown 
50881b406b76SMatthew G. Knepley   PetscFunctionBeginHot;
50892a3aaacfSMatthew G. Knepley   ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr);
50905a1bb5cfSMatthew G. Knepley   ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr);
50915a1bb5cfSMatthew G. Knepley   ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr);
50925a1bb5cfSMatthew G. Knepley   ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr);
50933f7cbbe7SMatthew G. Knepley   if (!values || !*values) {
50949df71ca4SMatthew G. Knepley     if ((point >= pStart) && (point < pEnd)) {
50959df71ca4SMatthew G. Knepley       PetscInt dof;
5096d9917b9dSMatthew G. Knepley 
50979df71ca4SMatthew G. Knepley       ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr);
50989df71ca4SMatthew G. Knepley       size += dof;
50999df71ca4SMatthew G. Knepley     }
51009df71ca4SMatthew G. Knepley     for (p = 0; p < numPoints; ++p) {
51019df71ca4SMatthew G. Knepley       const PetscInt cp = cone[p];
51022a3aaacfSMatthew G. Knepley       PetscInt       dof;
51035a1bb5cfSMatthew G. Knepley 
51045a1bb5cfSMatthew G. Knepley       if ((cp < pStart) || (cp >= pEnd)) continue;
51052a3aaacfSMatthew G. Knepley       ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr);
51065a1bb5cfSMatthew G. Knepley       size += dof;
51075a1bb5cfSMatthew G. Knepley     }
51083f7cbbe7SMatthew G. Knepley     if (!values) {
51093f7cbbe7SMatthew G. Knepley       if (csize) *csize = size;
51103f7cbbe7SMatthew G. Knepley       PetscFunctionReturn(0);
51113f7cbbe7SMatthew G. Knepley     }
51125a1bb5cfSMatthew G. Knepley     ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr);
5113982e9ed1SMatthew G. Knepley   } else {
5114982e9ed1SMatthew G. Knepley     array = *values;
5115982e9ed1SMatthew G. Knepley   }
51169df71ca4SMatthew G. Knepley   size = 0;
51175a1bb5cfSMatthew G. Knepley   ierr = VecGetArray(v, &vArray);CHKERRQ(ierr);
51189df71ca4SMatthew G. Knepley   if ((point >= pStart) && (point < pEnd)) {
51199df71ca4SMatthew G. Knepley     PetscInt     dof, off, d;
51209df71ca4SMatthew G. Knepley     PetscScalar *varr;
5121d9917b9dSMatthew G. Knepley 
51229df71ca4SMatthew G. Knepley     ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr);
51239df71ca4SMatthew G. Knepley     ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr);
51249df71ca4SMatthew G. Knepley     varr = &vArray[off];
51251a271a75SMatthew G. Knepley     for (d = 0; d < dof; ++d, ++offset) {
51261a271a75SMatthew G. Knepley       array[offset] = varr[d];
51279df71ca4SMatthew G. Knepley     }
51289df71ca4SMatthew G. Knepley     size += dof;
51299df71ca4SMatthew G. Knepley   }
51309df71ca4SMatthew G. Knepley   for (p = 0; p < numPoints; ++p) {
51319df71ca4SMatthew G. Knepley     const PetscInt cp = cone[p];
51329df71ca4SMatthew G. Knepley     PetscInt       o  = coneO[p];
51335a1bb5cfSMatthew G. Knepley     PetscInt       dof, off, d;
51345a1bb5cfSMatthew G. Knepley     PetscScalar   *varr;
51355a1bb5cfSMatthew G. Knepley 
513652ed52e8SMatthew G. Knepley     if ((cp < pStart) || (cp >= pEnd)) continue;
51375a1bb5cfSMatthew G. Knepley     ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr);
51385a1bb5cfSMatthew G. Knepley     ierr = PetscSectionGetOffset(section, cp, &off);CHKERRQ(ierr);
51395a1bb5cfSMatthew G. Knepley     varr = &vArray[off];
51405a1bb5cfSMatthew G. Knepley     if (o >= 0) {
51411a271a75SMatthew G. Knepley       for (d = 0; d < dof; ++d, ++offset) {
51421a271a75SMatthew G. Knepley         array[offset] = varr[d];
51435a1bb5cfSMatthew G. Knepley       }
51445a1bb5cfSMatthew G. Knepley     } else {
51451a271a75SMatthew G. Knepley       for (d = dof-1; d >= 0; --d, ++offset) {
51461a271a75SMatthew G. Knepley         array[offset] = varr[d];
51475a1bb5cfSMatthew G. Knepley       }
51485a1bb5cfSMatthew G. Knepley     }
51499df71ca4SMatthew G. Knepley     size += dof;
51505a1bb5cfSMatthew G. Knepley   }
51515a1bb5cfSMatthew G. Knepley   ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr);
51529df71ca4SMatthew G. Knepley   if (!*values) {
51535a1bb5cfSMatthew G. Knepley     if (csize) *csize = size;
51545a1bb5cfSMatthew G. Knepley     *values = array;
51559df71ca4SMatthew G. Knepley   } else {
51569df71ca4SMatthew G. Knepley     if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %d < actual size %d", *csize, size);
51578c312ff3SMatthew G. Knepley     *csize = size;
51589df71ca4SMatthew G. Knepley   }
51595a1bb5cfSMatthew G. Knepley   PetscFunctionReturn(0);
51605a1bb5cfSMatthew G. Knepley }
5161d9917b9dSMatthew G. Knepley 
5162d9917b9dSMatthew G. Knepley #undef __FUNCT__
51631a271a75SMatthew G. Knepley #define __FUNCT__ "DMPlexVecGetClosure_Static"
51641a271a75SMatthew G. Knepley PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Static(PetscSection section, PetscInt numPoints, const PetscInt points[], const PetscScalar vArray[], PetscInt *size, PetscScalar array[])
51651a271a75SMatthew G. Knepley {
51661a271a75SMatthew G. Knepley   PetscInt       offset = 0, p;
51671a271a75SMatthew G. Knepley   PetscErrorCode ierr;
51681a271a75SMatthew G. Knepley 
51691a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
5170fe02ba77SJed Brown   *size = 0;
51711a271a75SMatthew G. Knepley   for (p = 0; p < numPoints*2; p += 2) {
51721a271a75SMatthew G. Knepley     const PetscInt point = points[p];
51731a271a75SMatthew G. Knepley     const PetscInt o     = points[p+1];
51741a271a75SMatthew G. Knepley     PetscInt       dof, off, d;
51751a271a75SMatthew G. Knepley     const PetscScalar *varr;
51761a271a75SMatthew G. Knepley 
51771a271a75SMatthew G. Knepley     ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr);
51781a271a75SMatthew G. Knepley     ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr);
51791a271a75SMatthew G. Knepley     varr = &vArray[off];
51801a271a75SMatthew G. Knepley     if (o >= 0) {
51811a271a75SMatthew G. Knepley       for (d = 0; d < dof; ++d, ++offset)    array[offset] = varr[d];
51821a271a75SMatthew G. Knepley     } else {
51831a271a75SMatthew G. Knepley       for (d = dof-1; d >= 0; --d, ++offset) array[offset] = varr[d];
51841a271a75SMatthew G. Knepley     }
51851a271a75SMatthew G. Knepley   }
51861a271a75SMatthew G. Knepley   *size = offset;
51871a271a75SMatthew G. Knepley   PetscFunctionReturn(0);
51881a271a75SMatthew G. Knepley }
51891a271a75SMatthew G. Knepley 
51901a271a75SMatthew G. Knepley #undef __FUNCT__
51911a271a75SMatthew G. Knepley #define __FUNCT__ "DMPlexVecGetClosure_Fields_Static"
51921a271a75SMatthew G. Knepley PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Fields_Static(PetscSection section, PetscInt numPoints, const PetscInt points[], PetscInt numFields, const PetscScalar vArray[], PetscInt *size, PetscScalar array[])
51931a271a75SMatthew G. Knepley {
51941a271a75SMatthew G. Knepley   PetscInt       offset = 0, f;
51951a271a75SMatthew G. Knepley   PetscErrorCode ierr;
51961a271a75SMatthew G. Knepley 
51971a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
5198fe02ba77SJed Brown   *size = 0;
51991a271a75SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
52001a271a75SMatthew G. Knepley     PetscInt fcomp, p;
52011a271a75SMatthew G. Knepley 
52021a271a75SMatthew G. Knepley     ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr);
52031a271a75SMatthew G. Knepley     for (p = 0; p < numPoints*2; p += 2) {
52041a271a75SMatthew G. Knepley       const PetscInt point = points[p];
52051a271a75SMatthew G. Knepley       const PetscInt o     = points[p+1];
52061a271a75SMatthew G. Knepley       PetscInt       fdof, foff, d, c;
52071a271a75SMatthew G. Knepley       const PetscScalar *varr;
52081a271a75SMatthew G. Knepley 
52091a271a75SMatthew G. Knepley       ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr);
52101a271a75SMatthew G. Knepley       ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr);
52111a271a75SMatthew G. Knepley       varr = &vArray[foff];
52121a271a75SMatthew G. Knepley       if (o >= 0) {
52131a271a75SMatthew G. Knepley         for (d = 0; d < fdof; ++d, ++offset) array[offset] = varr[d];
52141a271a75SMatthew G. Knepley       } else {
52151a271a75SMatthew G. Knepley         for (d = fdof/fcomp-1; d >= 0; --d) {
52161a271a75SMatthew G. Knepley           for (c = 0; c < fcomp; ++c, ++offset) {
52171a271a75SMatthew G. Knepley             array[offset] = varr[d*fcomp+c];
52181a271a75SMatthew G. Knepley           }
52191a271a75SMatthew G. Knepley         }
52201a271a75SMatthew G. Knepley       }
52211a271a75SMatthew G. Knepley     }
52221a271a75SMatthew G. Knepley   }
52231a271a75SMatthew G. Knepley   *size = offset;
52241a271a75SMatthew G. Knepley   PetscFunctionReturn(0);
52251a271a75SMatthew G. Knepley }
52261a271a75SMatthew G. Knepley 
52271a271a75SMatthew G. Knepley #undef __FUNCT__
5228552f7358SJed Brown #define __FUNCT__ "DMPlexVecGetClosure"
5229552f7358SJed Brown /*@C
5230552f7358SJed Brown   DMPlexVecGetClosure - Get an array of the values on the closure of 'point'
5231552f7358SJed Brown 
5232552f7358SJed Brown   Not collective
5233552f7358SJed Brown 
5234552f7358SJed Brown   Input Parameters:
5235552f7358SJed Brown + dm - The DM
5236552f7358SJed Brown . section - The section describing the layout in v, or NULL to use the default section
5237552f7358SJed Brown . v - The local vector
5238552f7358SJed Brown - point - The sieve point in the DM
5239552f7358SJed Brown 
5240552f7358SJed Brown   Output Parameters:
5241552f7358SJed Brown + csize - The number of values in the closure, or NULL
5242552f7358SJed Brown - values - The array of values, which is a borrowed array and should not be freed
5243552f7358SJed Brown 
5244552f7358SJed Brown   Fortran Notes:
5245552f7358SJed Brown   Since it returns an array, this routine is only available in Fortran 90, and you must
5246552f7358SJed Brown   include petsc.h90 in your code.
5247552f7358SJed Brown 
5248552f7358SJed Brown   The csize argument is not present in the Fortran 90 binding since it is internal to the array.
5249552f7358SJed Brown 
5250552f7358SJed Brown   Level: intermediate
5251552f7358SJed Brown 
5252552f7358SJed Brown .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure()
5253552f7358SJed Brown @*/
5254552f7358SJed Brown PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
5255552f7358SJed Brown {
5256552f7358SJed Brown   PetscSection    clSection;
5257d9917b9dSMatthew G. Knepley   IS              clPoints;
5258552f7358SJed Brown   PetscScalar    *array, *vArray;
5259552f7358SJed Brown   PetscInt       *points = NULL;
5260d9917b9dSMatthew G. Knepley   const PetscInt *clp;
52611a271a75SMatthew G. Knepley   PetscInt        depth, numFields, numPoints, size;
5262552f7358SJed Brown   PetscErrorCode  ierr;
5263552f7358SJed Brown 
5264d9917b9dSMatthew G. Knepley   PetscFunctionBeginHot;
5265552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5266552f7358SJed Brown   if (!section) {ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);}
52671a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
52681a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
5269552f7358SJed Brown   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
5270552f7358SJed Brown   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
5271552f7358SJed Brown   if (depth == 1 && numFields < 2) {
52721a271a75SMatthew G. Knepley     ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr);
5273552f7358SJed Brown     PetscFunctionReturn(0);
5274552f7358SJed Brown   }
52751a271a75SMatthew G. Knepley   /* Get points */
5276d9917b9dSMatthew G. Knepley   ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr);
5277d9917b9dSMatthew G. Knepley   if (!clPoints) {
52781a271a75SMatthew G. Knepley     PetscInt pStart, pEnd, p, q;
5279552f7358SJed Brown 
52801a271a75SMatthew G. Knepley     ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr);
5281552f7358SJed Brown     ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);
5282552f7358SJed Brown     /* Compress out points not in the section */
5283552f7358SJed Brown     for (p = 0, q = 0; p < numPoints*2; p += 2) {
5284552f7358SJed Brown       if ((points[p] >= pStart) && (points[p] < pEnd)) {
5285552f7358SJed Brown         points[q*2]   = points[p];
5286552f7358SJed Brown         points[q*2+1] = points[p+1];
5287552f7358SJed Brown         ++q;
5288552f7358SJed Brown       }
5289552f7358SJed Brown     }
5290552f7358SJed Brown     numPoints = q;
5291d9917b9dSMatthew G. Knepley   } else {
5292d9917b9dSMatthew G. Knepley     PetscInt dof, off;
5293552f7358SJed Brown 
5294d9917b9dSMatthew G. Knepley     ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr);
5295d9917b9dSMatthew G. Knepley     ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr);
5296d9917b9dSMatthew G. Knepley     ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr);
52971a271a75SMatthew G. Knepley     numPoints = dof/2;
5298d9917b9dSMatthew G. Knepley     points    = (PetscInt *) &clp[off];
5299552f7358SJed Brown   }
53001a271a75SMatthew G. Knepley   /* Get array */
5301552f7358SJed Brown   if (!values || !*values) {
53021a271a75SMatthew G. Knepley     PetscInt asize = 0, dof, p;
5303552f7358SJed Brown 
53041a271a75SMatthew G. Knepley     for (p = 0; p < numPoints*2; p += 2) {
5305552f7358SJed Brown       ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr);
53061a271a75SMatthew G. Knepley       asize += dof;
5307552f7358SJed Brown     }
5308bd6c0d32SMatthew G. Knepley     if (!values) {
5309d9917b9dSMatthew G. Knepley       if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);}
53101a271a75SMatthew G. Knepley       else           {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);}
53111a271a75SMatthew G. Knepley       if (csize) *csize = asize;
5312bd6c0d32SMatthew G. Knepley       PetscFunctionReturn(0);
5313bd6c0d32SMatthew G. Knepley     }
53141a271a75SMatthew G. Knepley     ierr = DMGetWorkArray(dm, asize, PETSC_SCALAR, &array);CHKERRQ(ierr);
5315d0f6b257SMatthew G. Knepley   } else {
5316d0f6b257SMatthew G. Knepley     array = *values;
5317d0f6b257SMatthew G. Knepley   }
5318552f7358SJed Brown   ierr = VecGetArray(v, &vArray);CHKERRQ(ierr);
53191a271a75SMatthew G. Knepley   /* Get values */
53201a271a75SMatthew G. Knepley   if (numFields > 1) {ierr = DMPlexVecGetClosure_Fields_Static(section, numPoints, points, numFields, vArray, &size, array);CHKERRQ(ierr);}
53211a271a75SMatthew G. Knepley   else               {ierr = DMPlexVecGetClosure_Static(section, numPoints, points, vArray, &size, array);CHKERRQ(ierr);}
53221a271a75SMatthew G. Knepley   /* Cleanup points */
53231a271a75SMatthew G. Knepley   if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);}
53241a271a75SMatthew G. Knepley   else           {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);}
53251a271a75SMatthew G. Knepley   /* Cleanup array */
5326552f7358SJed Brown   ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr);
5327d0f6b257SMatthew G. Knepley   if (!*values) {
5328552f7358SJed Brown     if (csize) *csize = size;
5329552f7358SJed Brown     *values = array;
5330d0f6b257SMatthew G. Knepley   } else {
5331d0f6b257SMatthew G. Knepley     if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %d < actual size %d", *csize, size);
5332d0f6b257SMatthew G. Knepley     *csize = size;
5333d0f6b257SMatthew G. Knepley   }
5334552f7358SJed Brown   PetscFunctionReturn(0);
5335552f7358SJed Brown }
5336552f7358SJed Brown 
5337552f7358SJed Brown #undef __FUNCT__
5338552f7358SJed Brown #define __FUNCT__ "DMPlexVecRestoreClosure"
5339552f7358SJed Brown /*@C
5340552f7358SJed Brown   DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point'
5341552f7358SJed Brown 
5342552f7358SJed Brown   Not collective
5343552f7358SJed Brown 
5344552f7358SJed Brown   Input Parameters:
5345552f7358SJed Brown + dm - The DM
53460298fd71SBarry Smith . section - The section describing the layout in v, or NULL to use the default section
5347552f7358SJed Brown . v - The local vector
5348552f7358SJed Brown . point - The sieve point in the DM
53490298fd71SBarry Smith . csize - The number of values in the closure, or NULL
5350552f7358SJed Brown - values - The array of values, which is a borrowed array and should not be freed
5351552f7358SJed Brown 
53523813dfbdSMatthew G Knepley   Fortran Notes:
53533813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
53543813dfbdSMatthew G Knepley   include petsc.h90 in your code.
53553813dfbdSMatthew G Knepley 
53563813dfbdSMatthew G Knepley   The csize argument is not present in the Fortran 90 binding since it is internal to the array.
53573813dfbdSMatthew G Knepley 
5358552f7358SJed Brown   Level: intermediate
5359552f7358SJed Brown 
5360552f7358SJed Brown .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure()
5361552f7358SJed Brown @*/
53627c1f9639SMatthew G Knepley PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
5363a6dfd86eSKarl Rupp {
5364552f7358SJed Brown   PetscInt       size = 0;
5365552f7358SJed Brown   PetscErrorCode ierr;
5366552f7358SJed Brown 
5367552f7358SJed Brown   PetscFunctionBegin;
5368552f7358SJed Brown   /* Should work without recalculating size */
5369552f7358SJed Brown   ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void*) values);CHKERRQ(ierr);
5370552f7358SJed Brown   PetscFunctionReturn(0);
5371552f7358SJed Brown }
5372552f7358SJed Brown 
5373552f7358SJed Brown PETSC_STATIC_INLINE void add   (PetscScalar *x, PetscScalar y) {*x += y;}
5374552f7358SJed Brown PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x  = y;}
5375552f7358SJed Brown 
5376552f7358SJed Brown #undef __FUNCT__
5377552f7358SJed Brown #define __FUNCT__ "updatePoint_private"
53781a271a75SMatthew G. Knepley PETSC_STATIC_INLINE PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[])
5379552f7358SJed Brown {
5380552f7358SJed Brown   PetscInt        cdof;   /* The number of constraints on this point */
5381552f7358SJed Brown   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
5382552f7358SJed Brown   PetscScalar    *a;
5383552f7358SJed Brown   PetscInt        off, cind = 0, k;
5384552f7358SJed Brown   PetscErrorCode  ierr;
5385552f7358SJed Brown 
5386552f7358SJed Brown   PetscFunctionBegin;
5387552f7358SJed Brown   ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr);
5388552f7358SJed Brown   ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr);
5389552f7358SJed Brown   a    = &array[off];
5390552f7358SJed Brown   if (!cdof || setBC) {
5391552f7358SJed Brown     if (orientation >= 0) {
5392552f7358SJed Brown       for (k = 0; k < dof; ++k) {
5393552f7358SJed Brown         fuse(&a[k], values[k]);
5394552f7358SJed Brown       }
5395552f7358SJed Brown     } else {
5396552f7358SJed Brown       for (k = 0; k < dof; ++k) {
5397552f7358SJed Brown         fuse(&a[k], values[dof-k-1]);
5398552f7358SJed Brown       }
5399552f7358SJed Brown     }
5400552f7358SJed Brown   } else {
5401552f7358SJed Brown     ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr);
5402552f7358SJed Brown     if (orientation >= 0) {
5403552f7358SJed Brown       for (k = 0; k < dof; ++k) {
5404552f7358SJed Brown         if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
5405552f7358SJed Brown         fuse(&a[k], values[k]);
5406552f7358SJed Brown       }
5407552f7358SJed Brown     } else {
5408552f7358SJed Brown       for (k = 0; k < dof; ++k) {
5409552f7358SJed Brown         if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
5410552f7358SJed Brown         fuse(&a[k], values[dof-k-1]);
5411552f7358SJed Brown       }
5412552f7358SJed Brown     }
5413552f7358SJed Brown   }
5414552f7358SJed Brown   PetscFunctionReturn(0);
5415552f7358SJed Brown }
5416552f7358SJed Brown 
5417552f7358SJed Brown #undef __FUNCT__
5418a5e93ea8SMatthew G. Knepley #define __FUNCT__ "updatePointBC_private"
54191a271a75SMatthew G. Knepley PETSC_STATIC_INLINE PetscErrorCode updatePointBC_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscInt orientation, const PetscScalar values[], PetscScalar array[])
5420a5e93ea8SMatthew G. Knepley {
5421a5e93ea8SMatthew G. Knepley   PetscInt        cdof;   /* The number of constraints on this point */
5422a5e93ea8SMatthew G. Knepley   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
5423a5e93ea8SMatthew G. Knepley   PetscScalar    *a;
5424a5e93ea8SMatthew G. Knepley   PetscInt        off, cind = 0, k;
5425a5e93ea8SMatthew G. Knepley   PetscErrorCode  ierr;
5426a5e93ea8SMatthew G. Knepley 
5427a5e93ea8SMatthew G. Knepley   PetscFunctionBegin;
5428a5e93ea8SMatthew G. Knepley   ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr);
5429a5e93ea8SMatthew G. Knepley   ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr);
5430a5e93ea8SMatthew G. Knepley   a    = &array[off];
5431a5e93ea8SMatthew G. Knepley   if (cdof) {
5432a5e93ea8SMatthew G. Knepley     ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr);
5433a5e93ea8SMatthew G. Knepley     if (orientation >= 0) {
5434a5e93ea8SMatthew G. Knepley       for (k = 0; k < dof; ++k) {
5435a5e93ea8SMatthew G. Knepley         if ((cind < cdof) && (k == cdofs[cind])) {
5436a5e93ea8SMatthew G. Knepley           fuse(&a[k], values[k]);
5437a5e93ea8SMatthew G. Knepley           ++cind;
5438a5e93ea8SMatthew G. Knepley         }
5439a5e93ea8SMatthew G. Knepley       }
5440a5e93ea8SMatthew G. Knepley     } else {
5441a5e93ea8SMatthew G. Knepley       for (k = 0; k < dof; ++k) {
5442a5e93ea8SMatthew G. Knepley         if ((cind < cdof) && (k == cdofs[cind])) {
5443a5e93ea8SMatthew G. Knepley           fuse(&a[k], values[dof-k-1]);
5444a5e93ea8SMatthew G. Knepley           ++cind;
5445a5e93ea8SMatthew G. Knepley         }
5446a5e93ea8SMatthew G. Knepley       }
5447a5e93ea8SMatthew G. Knepley     }
5448a5e93ea8SMatthew G. Knepley   }
5449a5e93ea8SMatthew G. Knepley   PetscFunctionReturn(0);
5450a5e93ea8SMatthew G. Knepley }
5451a5e93ea8SMatthew G. Knepley 
5452a5e93ea8SMatthew G. Knepley #undef __FUNCT__
5453552f7358SJed Brown #define __FUNCT__ "updatePointFields_private"
54541a271a75SMatthew G. Knepley PETSC_STATIC_INLINE PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt o, PetscInt f, PetscInt fcomp, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, const PetscScalar values[], PetscInt *offset, PetscScalar array[])
5455a6dfd86eSKarl Rupp {
5456552f7358SJed Brown   PetscScalar    *a;
54571a271a75SMatthew G. Knepley   PetscInt        fdof, foff, fcdof, foffset = *offset;
54581a271a75SMatthew G. Knepley   const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
54591a271a75SMatthew G. Knepley   PetscInt        cind = 0, k, c;
5460552f7358SJed Brown   PetscErrorCode  ierr;
5461552f7358SJed Brown 
5462552f7358SJed Brown   PetscFunctionBegin;
5463552f7358SJed Brown   ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr);
5464552f7358SJed Brown   ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr);
54651a271a75SMatthew G. Knepley   ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr);
54661a271a75SMatthew G. Knepley   a    = &array[foff];
5467552f7358SJed Brown   if (!fcdof || setBC) {
54681a271a75SMatthew G. Knepley     if (o >= 0) {
54691a271a75SMatthew G. Knepley       for (k = 0; k < fdof; ++k) fuse(&a[k], values[foffset+k]);
5470552f7358SJed Brown     } else {
5471552f7358SJed Brown       for (k = fdof/fcomp-1; k >= 0; --k) {
5472552f7358SJed Brown         for (c = 0; c < fcomp; ++c) {
54731a271a75SMatthew G. Knepley           fuse(&a[(fdof/fcomp-1-k)*fcomp+c], values[foffset+k*fcomp+c]);
5474552f7358SJed Brown         }
5475552f7358SJed Brown       }
5476552f7358SJed Brown     }
5477552f7358SJed Brown   } else {
5478552f7358SJed Brown     ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr);
54791a271a75SMatthew G. Knepley     if (o >= 0) {
5480552f7358SJed Brown       for (k = 0; k < fdof; ++k) {
5481552f7358SJed Brown         if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;}
54821a271a75SMatthew G. Knepley         fuse(&a[k], values[foffset+k]);
5483552f7358SJed Brown       }
5484552f7358SJed Brown     } else {
5485552f7358SJed Brown       for (k = fdof/fcomp-1; k >= 0; --k) {
5486552f7358SJed Brown         for (c = 0; c < fcomp; ++c) {
5487552f7358SJed Brown           if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;}
54881a271a75SMatthew G. Knepley           fuse(&a[(fdof/fcomp-1-k)*fcomp+c], values[foffset+k*fcomp+c]);
5489552f7358SJed Brown         }
5490552f7358SJed Brown       }
5491552f7358SJed Brown     }
5492552f7358SJed Brown   }
54931a271a75SMatthew G. Knepley   *offset += fdof;
5494552f7358SJed Brown   PetscFunctionReturn(0);
5495552f7358SJed Brown }
5496552f7358SJed Brown 
5497552f7358SJed Brown #undef __FUNCT__
5498a5e93ea8SMatthew G. Knepley #define __FUNCT__ "updatePointFieldsBC_private"
54991a271a75SMatthew G. Knepley PETSC_STATIC_INLINE PetscErrorCode updatePointFieldsBC_private(PetscSection section, PetscInt point, PetscInt o, PetscInt f, PetscInt fcomp, void (*fuse)(PetscScalar*, PetscScalar), const PetscScalar values[], PetscInt *offset, PetscScalar array[])
5500a5e93ea8SMatthew G. Knepley {
5501a5e93ea8SMatthew G. Knepley   PetscScalar    *a;
55021a271a75SMatthew G. Knepley   PetscInt        fdof, foff, fcdof, foffset = *offset;
55031a271a75SMatthew G. Knepley   const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
55041a271a75SMatthew G. Knepley   PetscInt        cind = 0, k, c;
5505a5e93ea8SMatthew G. Knepley   PetscErrorCode  ierr;
5506a5e93ea8SMatthew G. Knepley 
5507a5e93ea8SMatthew G. Knepley   PetscFunctionBegin;
5508a5e93ea8SMatthew G. Knepley   ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr);
5509a5e93ea8SMatthew G. Knepley   ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr);
55101a271a75SMatthew G. Knepley   ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr);
55111a271a75SMatthew G. Knepley   a    = &array[foff];
5512a5e93ea8SMatthew G. Knepley   if (fcdof) {
5513a5e93ea8SMatthew G. Knepley     ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr);
55141a271a75SMatthew G. Knepley     if (o >= 0) {
5515a5e93ea8SMatthew G. Knepley       for (k = 0; k < fdof; ++k) {
5516a5e93ea8SMatthew G. Knepley         if ((cind < fcdof) && (k == fcdofs[cind])) {
55171a271a75SMatthew G. Knepley           fuse(&a[k], values[foffset+k]);
5518a5e93ea8SMatthew G. Knepley           ++cind;
5519a5e93ea8SMatthew G. Knepley         }
5520a5e93ea8SMatthew G. Knepley       }
5521a5e93ea8SMatthew G. Knepley     } else {
5522a5e93ea8SMatthew G. Knepley       for (k = fdof/fcomp-1; k >= 0; --k) {
5523a5e93ea8SMatthew G. Knepley         for (c = 0; c < fcomp; ++c) {
5524a5e93ea8SMatthew G. Knepley           if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {
55251a271a75SMatthew G. Knepley             fuse(&a[(fdof/fcomp-1-k)*fcomp+c], values[foffset+k*fcomp+c]);
5526a5e93ea8SMatthew G. Knepley             ++cind;
5527a5e93ea8SMatthew G. Knepley           }
5528a5e93ea8SMatthew G. Knepley         }
5529a5e93ea8SMatthew G. Knepley       }
5530a5e93ea8SMatthew G. Knepley     }
5531a5e93ea8SMatthew G. Knepley   }
55321a271a75SMatthew G. Knepley   *offset += fdof;
5533a5e93ea8SMatthew G. Knepley   PetscFunctionReturn(0);
5534a5e93ea8SMatthew G. Knepley }
5535a5e93ea8SMatthew G. Knepley 
5536a5e93ea8SMatthew G. Knepley #undef __FUNCT__
55371b406b76SMatthew G. Knepley #define __FUNCT__ "DMPlexVecSetClosure_Static"
55381a271a75SMatthew G. Knepley PETSC_STATIC_INLINE PetscErrorCode DMPlexVecSetClosure_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode)
5539a6dfd86eSKarl Rupp {
5540552f7358SJed Brown   PetscScalar    *array;
55411b406b76SMatthew G. Knepley   const PetscInt *cone, *coneO;
55421b406b76SMatthew G. Knepley   PetscInt        pStart, pEnd, p, numPoints, off, dof;
5543552f7358SJed Brown   PetscErrorCode  ierr;
5544552f7358SJed Brown 
55451b406b76SMatthew G. Knepley   PetscFunctionBeginHot;
5546b6ebb6e6SMatthew G. Knepley   ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr);
5547b6ebb6e6SMatthew G. Knepley   ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr);
5548b6ebb6e6SMatthew G. Knepley   ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr);
5549b6ebb6e6SMatthew G. Knepley   ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr);
5550b6ebb6e6SMatthew G. Knepley   ierr = VecGetArray(v, &array);CHKERRQ(ierr);
5551b6ebb6e6SMatthew G. Knepley   for (p = 0, off = 0; p <= numPoints; ++p, off += dof) {
5552b6ebb6e6SMatthew G. Knepley     const PetscInt cp = !p ? point : cone[p-1];
5553b6ebb6e6SMatthew G. Knepley     const PetscInt o  = !p ? 0     : coneO[p-1];
5554b6ebb6e6SMatthew G. Knepley 
5555b6ebb6e6SMatthew G. Knepley     if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;}
5556b6ebb6e6SMatthew G. Knepley     ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr);
5557b6ebb6e6SMatthew G. Knepley     /* ADD_VALUES */
5558b6ebb6e6SMatthew G. Knepley     {
5559b6ebb6e6SMatthew G. Knepley       const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
5560b6ebb6e6SMatthew G. Knepley       PetscScalar    *a;
5561b6ebb6e6SMatthew G. Knepley       PetscInt        cdof, coff, cind = 0, k;
5562b6ebb6e6SMatthew G. Knepley 
5563b6ebb6e6SMatthew G. Knepley       ierr = PetscSectionGetConstraintDof(section, cp, &cdof);CHKERRQ(ierr);
5564b6ebb6e6SMatthew G. Knepley       ierr = PetscSectionGetOffset(section, cp, &coff);CHKERRQ(ierr);
5565b6ebb6e6SMatthew G. Knepley       a    = &array[coff];
5566b6ebb6e6SMatthew G. Knepley       if (!cdof) {
5567b6ebb6e6SMatthew G. Knepley         if (o >= 0) {
5568b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
5569b6ebb6e6SMatthew G. Knepley             a[k] += values[off+k];
5570b6ebb6e6SMatthew G. Knepley           }
5571b6ebb6e6SMatthew G. Knepley         } else {
5572b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
5573b6ebb6e6SMatthew G. Knepley             a[k] += values[off+dof-k-1];
5574b6ebb6e6SMatthew G. Knepley           }
5575b6ebb6e6SMatthew G. Knepley         }
5576b6ebb6e6SMatthew G. Knepley       } else {
5577b6ebb6e6SMatthew G. Knepley         ierr = PetscSectionGetConstraintIndices(section, cp, &cdofs);CHKERRQ(ierr);
5578b6ebb6e6SMatthew G. Knepley         if (o >= 0) {
5579b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
5580b6ebb6e6SMatthew G. Knepley             if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
5581b6ebb6e6SMatthew G. Knepley             a[k] += values[off+k];
5582b6ebb6e6SMatthew G. Knepley           }
5583b6ebb6e6SMatthew G. Knepley         } else {
5584b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
5585b6ebb6e6SMatthew G. Knepley             if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
5586b6ebb6e6SMatthew G. Knepley             a[k] += values[off+dof-k-1];
5587b6ebb6e6SMatthew G. Knepley           }
5588b6ebb6e6SMatthew G. Knepley         }
5589b6ebb6e6SMatthew G. Knepley       }
5590b6ebb6e6SMatthew G. Knepley     }
5591b6ebb6e6SMatthew G. Knepley   }
5592b6ebb6e6SMatthew G. Knepley   ierr = VecRestoreArray(v, &array);CHKERRQ(ierr);
5593b6ebb6e6SMatthew G. Knepley   PetscFunctionReturn(0);
5594b6ebb6e6SMatthew G. Knepley }
55951b406b76SMatthew G. Knepley 
55961b406b76SMatthew G. Knepley #undef __FUNCT__
55971b406b76SMatthew G. Knepley #define __FUNCT__ "DMPlexVecSetClosure"
55981b406b76SMatthew G. Knepley /*@C
55991b406b76SMatthew G. Knepley   DMPlexVecSetClosure - Set an array of the values on the closure of 'point'
56001b406b76SMatthew G. Knepley 
56011b406b76SMatthew G. Knepley   Not collective
56021b406b76SMatthew G. Knepley 
56031b406b76SMatthew G. Knepley   Input Parameters:
56041b406b76SMatthew G. Knepley + dm - The DM
56051b406b76SMatthew G. Knepley . section - The section describing the layout in v, or NULL to use the default section
56061b406b76SMatthew G. Knepley . v - The local vector
56071b406b76SMatthew G. Knepley . point - The sieve point in the DM
56081b406b76SMatthew G. Knepley . values - The array of values
56091b406b76SMatthew G. Knepley - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions
56101b406b76SMatthew G. Knepley 
56111b406b76SMatthew G. Knepley   Fortran Notes:
56121b406b76SMatthew G. Knepley   This routine is only available in Fortran 90, and you must include petsc.h90 in your code.
56131b406b76SMatthew G. Knepley 
56141b406b76SMatthew G. Knepley   Level: intermediate
56151b406b76SMatthew G. Knepley 
56161b406b76SMatthew G. Knepley .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure()
56171b406b76SMatthew G. Knepley @*/
56181b406b76SMatthew G. Knepley PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode)
56191b406b76SMatthew G. Knepley {
56201b406b76SMatthew G. Knepley   PetscSection    clSection;
56211b406b76SMatthew G. Knepley   IS              clPoints;
56221b406b76SMatthew G. Knepley   PetscScalar    *array;
56231b406b76SMatthew G. Knepley   PetscInt       *points = NULL;
56241b406b76SMatthew G. Knepley   const PetscInt *clp;
56251a271a75SMatthew G. Knepley   PetscInt        depth, numFields, numPoints, p;
56261b406b76SMatthew G. Knepley   PetscErrorCode  ierr;
56271b406b76SMatthew G. Knepley 
56281a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
56291b406b76SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
56301b406b76SMatthew G. Knepley   if (!section) {ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);}
56311a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
56321a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
56331b406b76SMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
56341b406b76SMatthew G. Knepley   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
56351b406b76SMatthew G. Knepley   if (depth == 1 && numFields < 2 && mode == ADD_VALUES) {
56361a271a75SMatthew G. Knepley     ierr = DMPlexVecSetClosure_Static(dm, section, v, point, values, mode);CHKERRQ(ierr);
56371b406b76SMatthew G. Knepley     PetscFunctionReturn(0);
56381b406b76SMatthew G. Knepley   }
56391a271a75SMatthew G. Knepley   /* Get points */
56401b406b76SMatthew G. Knepley   ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr);
56411b406b76SMatthew G. Knepley   if (!clPoints) {
56421a271a75SMatthew G. Knepley     PetscInt pStart, pEnd, q;
56431a271a75SMatthew G. Knepley 
56441a271a75SMatthew G. Knepley     ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr);
5645552f7358SJed Brown     ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);
5646552f7358SJed Brown     /* Compress out points not in the section */
5647552f7358SJed Brown     for (p = 0, q = 0; p < numPoints*2; p += 2) {
5648552f7358SJed Brown       if ((points[p] >= pStart) && (points[p] < pEnd)) {
5649552f7358SJed Brown         points[q*2]   = points[p];
5650552f7358SJed Brown         points[q*2+1] = points[p+1];
5651552f7358SJed Brown         ++q;
5652552f7358SJed Brown       }
5653552f7358SJed Brown     }
5654552f7358SJed Brown     numPoints = q;
56551b406b76SMatthew G. Knepley   } else {
56561b406b76SMatthew G. Knepley     PetscInt dof, off;
5657552f7358SJed Brown 
56581b406b76SMatthew G. Knepley     ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr);
56591b406b76SMatthew G. Knepley     ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr);
56601b406b76SMatthew G. Knepley     ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr);
56611a271a75SMatthew G. Knepley     numPoints = dof/2;
56621b406b76SMatthew G. Knepley     points    = (PetscInt *) &clp[off];
5663552f7358SJed Brown   }
56641a271a75SMatthew G. Knepley   /* Get array */
5665552f7358SJed Brown   ierr = VecGetArray(v, &array);CHKERRQ(ierr);
56661a271a75SMatthew G. Knepley   /* Get values */
5667f723297eSMatthew G. Knepley   if (numFields > 1) {
56681a271a75SMatthew G. Knepley     PetscInt offset = 0, fcomp, f;
5669552f7358SJed Brown     for (f = 0; f < numFields; ++f) {
56701a271a75SMatthew G. Knepley       ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr);
5671552f7358SJed Brown       switch (mode) {
5672552f7358SJed Brown       case INSERT_VALUES:
5673552f7358SJed Brown         for (p = 0; p < numPoints*2; p += 2) {
56741a271a75SMatthew G. Knepley           const PetscInt point = points[p];
56751a271a75SMatthew G. Knepley           const PetscInt o     = points[p+1];
56761a271a75SMatthew G. Knepley           updatePointFields_private(section, point, o, f, fcomp, insert, PETSC_FALSE, values, &offset, array);
5677552f7358SJed Brown         } break;
5678552f7358SJed Brown       case INSERT_ALL_VALUES:
5679552f7358SJed Brown         for (p = 0; p < numPoints*2; p += 2) {
56801a271a75SMatthew G. Knepley           const PetscInt point = points[p];
56811a271a75SMatthew G. Knepley           const PetscInt o     = points[p+1];
56821a271a75SMatthew G. Knepley           updatePointFields_private(section, point, o, f, fcomp, insert, PETSC_TRUE, values, &offset, array);
5683552f7358SJed Brown         } break;
5684a5e93ea8SMatthew G. Knepley       case INSERT_BC_VALUES:
5685a5e93ea8SMatthew G. Knepley         for (p = 0; p < numPoints*2; p += 2) {
56861a271a75SMatthew G. Knepley           const PetscInt point = points[p];
56871a271a75SMatthew G. Knepley           const PetscInt o     = points[p+1];
56881a271a75SMatthew G. Knepley           updatePointFieldsBC_private(section, point, o, f, fcomp, insert, values, &offset, array);
5689a5e93ea8SMatthew G. Knepley         } break;
5690552f7358SJed Brown       case ADD_VALUES:
5691552f7358SJed Brown         for (p = 0; p < numPoints*2; p += 2) {
56921a271a75SMatthew G. Knepley           const PetscInt point = points[p];
56931a271a75SMatthew G. Knepley           const PetscInt o     = points[p+1];
56941a271a75SMatthew G. Knepley           updatePointFields_private(section, point, o, f, fcomp, add, PETSC_FALSE, values, &offset, array);
5695552f7358SJed Brown         } break;
5696552f7358SJed Brown       case ADD_ALL_VALUES:
5697552f7358SJed Brown         for (p = 0; p < numPoints*2; p += 2) {
56981a271a75SMatthew G. Knepley           const PetscInt point = points[p];
56991a271a75SMatthew G. Knepley           const PetscInt o     = points[p+1];
57001a271a75SMatthew G. Knepley           updatePointFields_private(section, point, o, f, fcomp, add, PETSC_TRUE, values, &offset, array);
5701552f7358SJed Brown         } break;
5702552f7358SJed Brown       default:
570382f516ccSBarry Smith         SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode);
5704552f7358SJed Brown       }
57051a271a75SMatthew G. Knepley     }
5706552f7358SJed Brown   } else {
57071a271a75SMatthew G. Knepley     PetscInt dof, off;
57081a271a75SMatthew G. Knepley 
5709552f7358SJed Brown     switch (mode) {
5710552f7358SJed Brown     case INSERT_VALUES:
5711552f7358SJed Brown       for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) {
5712552f7358SJed Brown         PetscInt o = points[p+1];
5713552f7358SJed Brown         ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr);
5714552f7358SJed Brown         updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array);
5715552f7358SJed Brown       } break;
5716552f7358SJed Brown     case INSERT_ALL_VALUES:
5717552f7358SJed Brown       for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) {
5718552f7358SJed Brown         PetscInt o = points[p+1];
5719552f7358SJed Brown         ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr);
5720552f7358SJed Brown         updatePoint_private(section, points[p], dof, insert, PETSC_TRUE,  o, &values[off], array);
5721552f7358SJed Brown       } break;
5722a5e93ea8SMatthew G. Knepley     case INSERT_BC_VALUES:
5723a5e93ea8SMatthew G. Knepley       for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) {
5724a5e93ea8SMatthew G. Knepley         PetscInt o = points[p+1];
5725a5e93ea8SMatthew G. Knepley         ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr);
5726a5e93ea8SMatthew G. Knepley         updatePointBC_private(section, points[p], dof, insert,  o, &values[off], array);
5727a5e93ea8SMatthew G. Knepley       } break;
5728552f7358SJed Brown     case ADD_VALUES:
5729552f7358SJed Brown       for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) {
5730552f7358SJed Brown         PetscInt o = points[p+1];
5731552f7358SJed Brown         ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr);
5732552f7358SJed Brown         updatePoint_private(section, points[p], dof, add,    PETSC_FALSE, o, &values[off], array);
5733552f7358SJed Brown       } break;
5734552f7358SJed Brown     case ADD_ALL_VALUES:
5735552f7358SJed Brown       for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) {
5736552f7358SJed Brown         PetscInt o = points[p+1];
5737552f7358SJed Brown         ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr);
5738552f7358SJed Brown         updatePoint_private(section, points[p], dof, add,    PETSC_TRUE,  o, &values[off], array);
5739552f7358SJed Brown       } break;
5740552f7358SJed Brown     default:
574182f516ccSBarry Smith       SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode);
5742552f7358SJed Brown     }
5743552f7358SJed Brown   }
57441a271a75SMatthew G. Knepley   /* Cleanup points */
57451a271a75SMatthew G. Knepley   if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);}
57461a271a75SMatthew G. Knepley   else           {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);}
57471a271a75SMatthew G. Knepley   /* Cleanup array */
5748552f7358SJed Brown   ierr = VecRestoreArray(v, &array);CHKERRQ(ierr);
5749552f7358SJed Brown   PetscFunctionReturn(0);
5750552f7358SJed Brown }
5751552f7358SJed Brown 
5752552f7358SJed Brown #undef __FUNCT__
5753552f7358SJed Brown #define __FUNCT__ "DMPlexPrintMatSetValues"
57547c1f9639SMatthew G Knepley PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numIndices, const PetscInt indices[], const PetscScalar values[])
5755552f7358SJed Brown {
5756552f7358SJed Brown   PetscMPIInt    rank;
5757552f7358SJed Brown   PetscInt       i, j;
5758552f7358SJed Brown   PetscErrorCode ierr;
5759552f7358SJed Brown 
5760552f7358SJed Brown   PetscFunctionBegin;
576182f516ccSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr);
576277a6746dSMatthew G Knepley   ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat for sieve point %D\n", rank, point);CHKERRQ(ierr);
5763552f7358SJed Brown   for (i = 0; i < numIndices; i++) {
576477a6746dSMatthew G Knepley     ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat indices[%D] = %D\n", rank, i, indices[i]);CHKERRQ(ierr);
5765552f7358SJed Brown   }
5766552f7358SJed Brown   for (i = 0; i < numIndices; i++) {
576777a6746dSMatthew G Knepley     ierr = PetscViewerASCIIPrintf(viewer, "[%D]", rank);CHKERRQ(ierr);
5768552f7358SJed Brown     for (j = 0; j < numIndices; j++) {
5769519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX)
577057622a8eSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numIndices+j]), (double)PetscImaginaryPart(values[i*numIndices+j]));CHKERRQ(ierr);
5771552f7358SJed Brown #else
577257622a8eSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numIndices+j]);CHKERRQ(ierr);
5773552f7358SJed Brown #endif
5774552f7358SJed Brown     }
577577a6746dSMatthew G Knepley     ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr);
5776552f7358SJed Brown   }
5777552f7358SJed Brown   PetscFunctionReturn(0);
5778552f7358SJed Brown }
5779552f7358SJed Brown 
5780552f7358SJed Brown #undef __FUNCT__
5781552f7358SJed Brown #define __FUNCT__ "indicesPoint_private"
5782552f7358SJed Brown /* . off - The global offset of this point */
5783e6ccafaeSMatthew G Knepley PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, PetscInt orientation, PetscInt indices[])
5784a6dfd86eSKarl Rupp {
5785e6ccafaeSMatthew G Knepley   PetscInt        dof;    /* The number of unknowns on this point */
5786552f7358SJed Brown   PetscInt        cdof;   /* The number of constraints on this point */
5787552f7358SJed Brown   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
5788552f7358SJed Brown   PetscInt        cind = 0, k;
5789552f7358SJed Brown   PetscErrorCode  ierr;
5790552f7358SJed Brown 
5791552f7358SJed Brown   PetscFunctionBegin;
5792552f7358SJed Brown   ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr);
5793552f7358SJed Brown   ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr);
5794552f7358SJed Brown   if (!cdof || setBC) {
5795552f7358SJed Brown     if (orientation >= 0) {
5796e6ccafaeSMatthew G Knepley       for (k = 0; k < dof; ++k) indices[*loff+k] = off+k;
5797552f7358SJed Brown     } else {
5798e6ccafaeSMatthew G Knepley       for (k = 0; k < dof; ++k) indices[*loff+dof-k-1] = off+k;
5799552f7358SJed Brown     }
5800552f7358SJed Brown   } else {
5801552f7358SJed Brown     ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr);
5802552f7358SJed Brown     if (orientation >= 0) {
5803552f7358SJed Brown       for (k = 0; k < dof; ++k) {
5804552f7358SJed Brown         if ((cind < cdof) && (k == cdofs[cind])) {
5805552f7358SJed Brown           /* Insert check for returning constrained indices */
5806e6ccafaeSMatthew G Knepley           indices[*loff+k] = -(off+k+1);
5807552f7358SJed Brown           ++cind;
5808552f7358SJed Brown         } else {
5809e6ccafaeSMatthew G Knepley           indices[*loff+k] = off+k-cind;
5810552f7358SJed Brown         }
5811552f7358SJed Brown       }
5812552f7358SJed Brown     } else {
5813552f7358SJed Brown       for (k = 0; k < dof; ++k) {
5814552f7358SJed Brown         if ((cind < cdof) && (k == cdofs[cind])) {
5815552f7358SJed Brown           /* Insert check for returning constrained indices */
5816e6ccafaeSMatthew G Knepley           indices[*loff+dof-k-1] = -(off+k+1);
5817552f7358SJed Brown           ++cind;
5818552f7358SJed Brown         } else {
5819e6ccafaeSMatthew G Knepley           indices[*loff+dof-k-1] = off+k-cind;
5820552f7358SJed Brown         }
5821552f7358SJed Brown       }
5822552f7358SJed Brown     }
5823552f7358SJed Brown   }
5824e6ccafaeSMatthew G Knepley   *loff += dof;
5825552f7358SJed Brown   PetscFunctionReturn(0);
5826552f7358SJed Brown }
5827552f7358SJed Brown 
5828552f7358SJed Brown #undef __FUNCT__
5829552f7358SJed Brown #define __FUNCT__ "indicesPointFields_private"
5830552f7358SJed Brown /* . off - The global offset of this point */
5831a6dfd86eSKarl Rupp PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[])
5832a6dfd86eSKarl Rupp {
5833552f7358SJed Brown   PetscInt       numFields, foff, f;
5834552f7358SJed Brown   PetscErrorCode ierr;
5835552f7358SJed Brown 
5836552f7358SJed Brown   PetscFunctionBegin;
5837552f7358SJed Brown   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
5838552f7358SJed Brown   for (f = 0, foff = 0; f < numFields; ++f) {
5839552f7358SJed Brown     PetscInt        fdof, fcomp, cfdof;
5840552f7358SJed Brown     const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
5841552f7358SJed Brown     PetscInt        cind = 0, k, c;
5842552f7358SJed Brown 
5843552f7358SJed Brown     ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr);
5844552f7358SJed Brown     ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr);
5845552f7358SJed Brown     ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr);
5846552f7358SJed Brown     if (!cfdof || setBC) {
5847552f7358SJed Brown       if (orientation >= 0) {
58480d644c17SKarl Rupp         for (k = 0; k < fdof; ++k) indices[foffs[f]+k] = off+foff+k;
5849552f7358SJed Brown       } else {
5850552f7358SJed Brown         for (k = fdof/fcomp-1; k >= 0; --k) {
5851552f7358SJed Brown           for (c = 0; c < fcomp; ++c) {
5852552f7358SJed Brown             indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c;
5853552f7358SJed Brown           }
5854552f7358SJed Brown         }
5855552f7358SJed Brown       }
5856552f7358SJed Brown     } else {
5857552f7358SJed Brown       ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr);
5858552f7358SJed Brown       if (orientation >= 0) {
5859552f7358SJed Brown         for (k = 0; k < fdof; ++k) {
5860552f7358SJed Brown           if ((cind < cfdof) && (k == fcdofs[cind])) {
5861552f7358SJed Brown             indices[foffs[f]+k] = -(off+foff+k+1);
5862552f7358SJed Brown             ++cind;
5863552f7358SJed Brown           } else {
5864552f7358SJed Brown             indices[foffs[f]+k] = off+foff+k-cind;
5865552f7358SJed Brown           }
5866552f7358SJed Brown         }
5867552f7358SJed Brown       } else {
5868552f7358SJed Brown         for (k = fdof/fcomp-1; k >= 0; --k) {
5869552f7358SJed Brown           for (c = 0; c < fcomp; ++c) {
5870552f7358SJed Brown             if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) {
5871552f7358SJed Brown               indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1);
5872552f7358SJed Brown               ++cind;
5873552f7358SJed Brown             } else {
5874552f7358SJed Brown               indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind;
5875552f7358SJed Brown             }
5876552f7358SJed Brown           }
5877552f7358SJed Brown         }
5878552f7358SJed Brown       }
5879552f7358SJed Brown     }
5880552f7358SJed Brown     foff     += fdof - cfdof;
5881552f7358SJed Brown     foffs[f] += fdof;
5882552f7358SJed Brown   }
5883552f7358SJed Brown   PetscFunctionReturn(0);
5884552f7358SJed Brown }
5885552f7358SJed Brown 
5886552f7358SJed Brown #undef __FUNCT__
5887552f7358SJed Brown #define __FUNCT__ "DMPlexMatSetClosure"
58887f5d1fdeSMatthew G. Knepley /*@C
58897f5d1fdeSMatthew G. Knepley   DMPlexMatSetClosure - Set an array of the values on the closure of 'point'
58907f5d1fdeSMatthew G. Knepley 
58917f5d1fdeSMatthew G. Knepley   Not collective
58927f5d1fdeSMatthew G. Knepley 
58937f5d1fdeSMatthew G. Knepley   Input Parameters:
58947f5d1fdeSMatthew G. Knepley + dm - The DM
5895ebd6d717SJed Brown . section - The section describing the layout in v, or NULL to use the default section
5896ebd6d717SJed Brown . globalSection - The section describing the layout in v, or NULL to use the default global section
58977f5d1fdeSMatthew G. Knepley . A - The matrix
58987f5d1fdeSMatthew G. Knepley . point - The sieve point in the DM
58997f5d1fdeSMatthew G. Knepley . values - The array of values
59007f5d1fdeSMatthew G. Knepley - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions
59017f5d1fdeSMatthew G. Knepley 
59027f5d1fdeSMatthew G. Knepley   Fortran Notes:
59037f5d1fdeSMatthew G. Knepley   This routine is only available in Fortran 90, and you must include petsc.h90 in your code.
59047f5d1fdeSMatthew G. Knepley 
59057f5d1fdeSMatthew G. Knepley   Level: intermediate
59067f5d1fdeSMatthew G. Knepley 
59077f5d1fdeSMatthew G. Knepley .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure()
59087f5d1fdeSMatthew G. Knepley @*/
59097c1f9639SMatthew G Knepley PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
5910552f7358SJed Brown {
5911552f7358SJed Brown   DM_Plex        *mesh   = (DM_Plex*) dm->data;
59121b406b76SMatthew G. Knepley   PetscSection    clSection;
59131b406b76SMatthew G. Knepley   IS              clPoints;
59140298fd71SBarry Smith   PetscInt       *points = NULL;
59151b406b76SMatthew G. Knepley   const PetscInt *clp;
5916552f7358SJed Brown   PetscInt       *indices;
5917552f7358SJed Brown   PetscInt        offsets[32];
5918552f7358SJed Brown   PetscInt        numFields, numPoints, numIndices, dof, off, globalOff, pStart, pEnd, p, q, f;
5919552f7358SJed Brown   PetscErrorCode  ierr;
5920552f7358SJed Brown 
5921552f7358SJed Brown   PetscFunctionBegin;
5922552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5923ebd6d717SJed Brown   if (!section) {ierr = DMGetDefaultSection(dm, &section);CHKERRQ(ierr);}
59243dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
5925ebd6d717SJed Brown   if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);}
59263dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3);
59273dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 4);
5928552f7358SJed Brown   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
592982f516ccSBarry Smith   if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields);
5930552f7358SJed Brown   ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr);
59311b406b76SMatthew G. Knepley   ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr);
59321b406b76SMatthew G. Knepley   if (!clPoints) {
5933552f7358SJed Brown     ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);
5934552f7358SJed Brown     /* Compress out points not in the section */
5935552f7358SJed Brown     ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr);
5936552f7358SJed Brown     for (p = 0, q = 0; p < numPoints*2; p += 2) {
5937552f7358SJed Brown       if ((points[p] >= pStart) && (points[p] < pEnd)) {
5938552f7358SJed Brown         points[q*2]   = points[p];
5939552f7358SJed Brown         points[q*2+1] = points[p+1];
5940552f7358SJed Brown         ++q;
5941552f7358SJed Brown       }
5942552f7358SJed Brown     }
5943552f7358SJed Brown     numPoints = q;
59441b406b76SMatthew G. Knepley   } else {
59451b406b76SMatthew G. Knepley     PetscInt dof, off;
59461b406b76SMatthew G. Knepley 
59471b406b76SMatthew G. Knepley     ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr);
59481b406b76SMatthew G. Knepley     numPoints = dof/2;
59491b406b76SMatthew G. Knepley     ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr);
59501b406b76SMatthew G. Knepley     ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr);
59511b406b76SMatthew G. Knepley     points = (PetscInt *) &clp[off];
59521b406b76SMatthew G. Knepley   }
5953552f7358SJed Brown   for (p = 0, numIndices = 0; p < numPoints*2; p += 2) {
5954552f7358SJed Brown     PetscInt fdof;
5955552f7358SJed Brown 
5956552f7358SJed Brown     ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr);
5957552f7358SJed Brown     for (f = 0; f < numFields; ++f) {
5958552f7358SJed Brown       ierr          = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr);
5959552f7358SJed Brown       offsets[f+1] += fdof;
5960552f7358SJed Brown     }
5961552f7358SJed Brown     numIndices += dof;
5962552f7358SJed Brown   }
59630d644c17SKarl Rupp   for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f];
59640d644c17SKarl Rupp 
596582f516ccSBarry Smith   if (numFields && offsets[numFields] != numIndices) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices);
5966552f7358SJed Brown   ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr);
5967552f7358SJed Brown   if (numFields) {
5968552f7358SJed Brown     for (p = 0; p < numPoints*2; p += 2) {
5969552f7358SJed Brown       PetscInt o = points[p+1];
5970552f7358SJed Brown       ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr);
5971552f7358SJed Brown       indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices);
5972552f7358SJed Brown     }
5973552f7358SJed Brown   } else {
5974e6ccafaeSMatthew G Knepley     for (p = 0, off = 0; p < numPoints*2; p += 2) {
5975552f7358SJed Brown       PetscInt o = points[p+1];
5976552f7358SJed Brown       ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr);
5977e6ccafaeSMatthew G Knepley       indicesPoint_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, indices);
5978552f7358SJed Brown     }
5979552f7358SJed Brown   }
598077a6746dSMatthew G Knepley   if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr);}
5981552f7358SJed Brown   ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode);
5982552f7358SJed Brown   if (ierr) {
5983552f7358SJed Brown     PetscMPIInt    rank;
5984552f7358SJed Brown     PetscErrorCode ierr2;
5985552f7358SJed Brown 
598682f516ccSBarry Smith     ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2);
598777a6746dSMatthew G Knepley     ierr2 = (*PetscErrorPrintf)("[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2);
598877a6746dSMatthew G Knepley     ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, values);CHKERRQ(ierr2);
59896a415b8fSMatthew G Knepley     ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2);
5990552f7358SJed Brown     CHKERRQ(ierr);
5991552f7358SJed Brown   }
59921b406b76SMatthew G. Knepley   if (!clPoints) {
5993552f7358SJed Brown     ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);
59941b406b76SMatthew G. Knepley   } else {
59951b406b76SMatthew G. Knepley     ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);
59961b406b76SMatthew G. Knepley   }
5997552f7358SJed Brown   ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr);
5998552f7358SJed Brown   PetscFunctionReturn(0);
5999552f7358SJed Brown }
6000552f7358SJed Brown 
6001552f7358SJed Brown #undef __FUNCT__
6002770b213bSMatthew G Knepley #define __FUNCT__ "DMPlexGetHybridBounds"
6003f96281f8SMatthew G. Knepley /*@
6004f96281f8SMatthew G. Knepley   DMPlexGetHybridBounds - Get the first mesh point of each dimension which is a hybrid
6005f96281f8SMatthew G. Knepley 
6006f96281f8SMatthew G. Knepley   Input Parameter:
6007f96281f8SMatthew G. Knepley . dm - The DMPlex object
6008f96281f8SMatthew G. Knepley 
6009f96281f8SMatthew G. Knepley   Output Parameters:
6010f96281f8SMatthew G. Knepley + cMax - The first hybrid cell
6011f96281f8SMatthew G. Knepley . cMax - The first hybrid face
6012f96281f8SMatthew G. Knepley . cMax - The first hybrid edge
6013f96281f8SMatthew G. Knepley - cMax - The first hybrid vertex
6014f96281f8SMatthew G. Knepley 
6015f96281f8SMatthew G. Knepley   Level: developer
6016f96281f8SMatthew G. Knepley 
6017f96281f8SMatthew G. Knepley .seealso DMPlexCreateHybridMesh()
6018f96281f8SMatthew G. Knepley @*/
6019770b213bSMatthew G Knepley PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax)
6020552f7358SJed Brown {
6021552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
6022770b213bSMatthew G Knepley   PetscInt       dim;
6023770b213bSMatthew G Knepley   PetscErrorCode ierr;
6024552f7358SJed Brown 
6025552f7358SJed Brown   PetscFunctionBegin;
6026552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6027770b213bSMatthew G Knepley   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
6028770b213bSMatthew G Knepley   if (cMax) *cMax = mesh->hybridPointMax[dim];
6029770b213bSMatthew G Knepley   if (fMax) *fMax = mesh->hybridPointMax[dim-1];
6030770b213bSMatthew G Knepley   if (eMax) *eMax = mesh->hybridPointMax[1];
6031770b213bSMatthew G Knepley   if (vMax) *vMax = mesh->hybridPointMax[0];
6032552f7358SJed Brown   PetscFunctionReturn(0);
6033552f7358SJed Brown }
6034552f7358SJed Brown 
6035552f7358SJed Brown #undef __FUNCT__
6036770b213bSMatthew G Knepley #define __FUNCT__ "DMPlexSetHybridBounds"
6037770b213bSMatthew G Knepley PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax)
6038552f7358SJed Brown {
6039552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
6040770b213bSMatthew G Knepley   PetscInt       dim;
6041770b213bSMatthew G Knepley   PetscErrorCode ierr;
6042552f7358SJed Brown 
6043552f7358SJed Brown   PetscFunctionBegin;
6044552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6045770b213bSMatthew G Knepley   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
6046770b213bSMatthew G Knepley   if (cMax >= 0) mesh->hybridPointMax[dim]   = cMax;
6047770b213bSMatthew G Knepley   if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax;
6048770b213bSMatthew G Knepley   if (eMax >= 0) mesh->hybridPointMax[1]     = eMax;
6049770b213bSMatthew G Knepley   if (vMax >= 0) mesh->hybridPointMax[0]     = vMax;
6050552f7358SJed Brown   PetscFunctionReturn(0);
6051552f7358SJed Brown }
6052552f7358SJed Brown 
6053552f7358SJed Brown #undef __FUNCT__
6054552f7358SJed Brown #define __FUNCT__ "DMPlexGetVTKCellHeight"
6055552f7358SJed Brown PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight)
6056552f7358SJed Brown {
6057552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
6058552f7358SJed Brown 
6059552f7358SJed Brown   PetscFunctionBegin;
6060552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6061552f7358SJed Brown   PetscValidPointer(cellHeight, 2);
6062552f7358SJed Brown   *cellHeight = mesh->vtkCellHeight;
6063552f7358SJed Brown   PetscFunctionReturn(0);
6064552f7358SJed Brown }
6065552f7358SJed Brown 
6066552f7358SJed Brown #undef __FUNCT__
6067552f7358SJed Brown #define __FUNCT__ "DMPlexSetVTKCellHeight"
6068552f7358SJed Brown PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight)
6069552f7358SJed Brown {
6070552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
6071552f7358SJed Brown 
6072552f7358SJed Brown   PetscFunctionBegin;
6073552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6074552f7358SJed Brown   mesh->vtkCellHeight = cellHeight;
6075552f7358SJed Brown   PetscFunctionReturn(0);
6076552f7358SJed Brown }
6077552f7358SJed Brown 
6078552f7358SJed Brown #undef __FUNCT__
6079552f7358SJed Brown #define __FUNCT__ "DMPlexCreateNumbering_Private"
6080552f7358SJed Brown /* We can easily have a form that takes an IS instead */
6081552f7358SJed Brown PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscSF sf, IS *numbering)
6082552f7358SJed Brown {
6083552f7358SJed Brown   PetscSection   section, globalSection;
6084552f7358SJed Brown   PetscInt      *numbers, p;
6085552f7358SJed Brown   PetscErrorCode ierr;
6086552f7358SJed Brown 
6087552f7358SJed Brown   PetscFunctionBegin;
608882f516ccSBarry Smith   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section);CHKERRQ(ierr);
6089552f7358SJed Brown   ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr);
6090552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
6091552f7358SJed Brown     ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr);
6092552f7358SJed Brown   }
6093552f7358SJed Brown   ierr = PetscSectionSetUp(section);CHKERRQ(ierr);
6094552f7358SJed Brown   ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr);
6095785e854fSJed Brown   ierr = PetscMalloc1((pEnd - pStart), &numbers);CHKERRQ(ierr);
6096552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
6097552f7358SJed Brown     ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr);
6098552f7358SJed Brown   }
609982f516ccSBarry Smith   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr);
6100552f7358SJed Brown   ierr = PetscSectionDestroy(&section);CHKERRQ(ierr);
6101552f7358SJed Brown   ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr);
6102552f7358SJed Brown   PetscFunctionReturn(0);
6103552f7358SJed Brown }
6104552f7358SJed Brown 
6105552f7358SJed Brown #undef __FUNCT__
6106552f7358SJed Brown #define __FUNCT__ "DMPlexGetCellNumbering"
6107552f7358SJed Brown PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers)
6108552f7358SJed Brown {
6109552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
6110552f7358SJed Brown   PetscInt       cellHeight, cStart, cEnd, cMax;
6111552f7358SJed Brown   PetscErrorCode ierr;
6112552f7358SJed Brown 
6113552f7358SJed Brown   PetscFunctionBegin;
6114552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6115552f7358SJed Brown   if (!mesh->globalCellNumbers) {
6116552f7358SJed Brown     ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr);
6117552f7358SJed Brown     ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);
61180298fd71SBarry Smith     ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr);
61190d644c17SKarl Rupp     if (cMax >= 0) cEnd = PetscMin(cEnd, cMax);
6120552f7358SJed Brown     ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr);
6121552f7358SJed Brown   }
6122552f7358SJed Brown   *globalCellNumbers = mesh->globalCellNumbers;
6123552f7358SJed Brown   PetscFunctionReturn(0);
6124552f7358SJed Brown }
6125552f7358SJed Brown 
6126552f7358SJed Brown #undef __FUNCT__
6127552f7358SJed Brown #define __FUNCT__ "DMPlexGetVertexNumbering"
6128552f7358SJed Brown PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers)
6129552f7358SJed Brown {
6130552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
6131552f7358SJed Brown   PetscInt       vStart, vEnd, vMax;
6132552f7358SJed Brown   PetscErrorCode ierr;
6133552f7358SJed Brown 
6134552f7358SJed Brown   PetscFunctionBegin;
6135552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6136552f7358SJed Brown   if (!mesh->globalVertexNumbers) {
6137552f7358SJed Brown     ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
61380298fd71SBarry Smith     ierr = DMPlexGetHybridBounds(dm, NULL, NULL, NULL, &vMax);CHKERRQ(ierr);
61390d644c17SKarl Rupp     if (vMax >= 0) vEnd = PetscMin(vEnd, vMax);
6140552f7358SJed Brown     ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr);
6141552f7358SJed Brown   }
6142552f7358SJed Brown   *globalVertexNumbers = mesh->globalVertexNumbers;
6143552f7358SJed Brown   PetscFunctionReturn(0);
6144552f7358SJed Brown }
6145552f7358SJed Brown 
6146552f7358SJed Brown 
6147552f7358SJed Brown #undef __FUNCT__
6148552f7358SJed Brown #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel"
6149552f7358SJed Brown /*@C
6150552f7358SJed Brown   PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using
6151552f7358SJed Brown   the local section and an SF describing the section point overlap.
6152552f7358SJed Brown 
6153552f7358SJed Brown   Input Parameters:
6154552f7358SJed Brown   + s - The PetscSection for the local field layout
6155552f7358SJed Brown   . sf - The SF describing parallel layout of the section points
6156552f7358SJed Brown   . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs
6157552f7358SJed Brown   . label - The label specifying the points
6158552f7358SJed Brown   - labelValue - The label stratum specifying the points
6159552f7358SJed Brown 
6160552f7358SJed Brown   Output Parameter:
6161552f7358SJed Brown   . gsection - The PetscSection for the global field layout
6162552f7358SJed Brown 
6163552f7358SJed Brown   Note: This gives negative sizes and offsets to points not owned by this process
6164552f7358SJed Brown 
6165552f7358SJed Brown   Level: developer
6166552f7358SJed Brown 
6167552f7358SJed Brown .seealso: PetscSectionCreate()
6168552f7358SJed Brown @*/
6169552f7358SJed Brown PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection)
6170552f7358SJed Brown {
61717ec39499SMatthew G. Knepley   PetscInt      *neg = NULL, *tmpOff = NULL;
6172552f7358SJed Brown   PetscInt       pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots;
6173552f7358SJed Brown   PetscErrorCode ierr;
6174552f7358SJed Brown 
6175552f7358SJed Brown   PetscFunctionBegin;
6176552f7358SJed Brown   ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr);
6177552f7358SJed Brown   ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr);
6178552f7358SJed Brown   ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr);
61797ec39499SMatthew G. Knepley   ierr = PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);CHKERRQ(ierr);
61807ec39499SMatthew G. Knepley   if (nroots >= 0) {
61817ec39499SMatthew G. Knepley     if (nroots < pEnd-pStart) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PetscSF nroots %d < %d section size", nroots, pEnd-pStart);
61821795a4d1SJed Brown     ierr = PetscCalloc1(nroots, &neg);CHKERRQ(ierr);
61837ec39499SMatthew G. Knepley     if (nroots > pEnd-pStart) {
61841795a4d1SJed Brown       ierr = PetscCalloc1(nroots, &tmpOff);CHKERRQ(ierr);
61857ec39499SMatthew G. Knepley     } else {
61867ec39499SMatthew G. Knepley       tmpOff = &(*gsection)->atlasDof[-pStart];
61877ec39499SMatthew G. Knepley     }
61887ec39499SMatthew G. Knepley   }
6189552f7358SJed Brown   /* Mark ghost points with negative dof */
6190552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
6191552f7358SJed Brown     PetscInt value;
6192552f7358SJed Brown 
6193552f7358SJed Brown     ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr);
6194552f7358SJed Brown     if (value != labelValue) continue;
6195552f7358SJed Brown     ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr);
6196552f7358SJed Brown     ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr);
6197552f7358SJed Brown     ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr);
6198552f7358SJed Brown     if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);}
61997ec39499SMatthew G. Knepley     if (neg) neg[p] = -(dof+1);
6200552f7358SJed Brown   }
6201552f7358SJed Brown   ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr);
6202552f7358SJed Brown   if (nroots >= 0) {
62037ec39499SMatthew G. Knepley     ierr = PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr);
62047ec39499SMatthew G. Knepley     ierr = PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr);
6205552f7358SJed Brown     if (nroots > pEnd-pStart) {
62067ec39499SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpOff[p];}
6207552f7358SJed Brown     }
6208552f7358SJed Brown   }
6209552f7358SJed Brown   /* Calculate new sizes, get proccess offset, and calculate point offsets */
6210552f7358SJed Brown   for (p = 0, off = 0; p < pEnd-pStart; ++p) {
6211552f7358SJed Brown     cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0;
6212552f7358SJed Brown     (*gsection)->atlasOff[p] = off;
6213552f7358SJed Brown     off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0;
6214552f7358SJed Brown   }
6215552f7358SJed Brown   ierr       = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr);
6216552f7358SJed Brown   globalOff -= off;
6217552f7358SJed Brown   for (p = 0, off = 0; p < pEnd-pStart; ++p) {
6218552f7358SJed Brown     (*gsection)->atlasOff[p] += globalOff;
62197ec39499SMatthew G. Knepley     if (neg) neg[p] = -((*gsection)->atlasOff[p]+1);
6220552f7358SJed Brown   }
6221552f7358SJed Brown   /* Put in negative offsets for ghost points */
6222552f7358SJed Brown   if (nroots >= 0) {
62237ec39499SMatthew G. Knepley     ierr = PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr);
62247ec39499SMatthew G. Knepley     ierr = PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr);
6225552f7358SJed Brown     if (nroots > pEnd-pStart) {
62267ec39499SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p];}
6227552f7358SJed Brown     }
6228552f7358SJed Brown   }
62297ec39499SMatthew G. Knepley   if (nroots >= 0 && nroots > pEnd-pStart) {ierr = PetscFree(tmpOff);CHKERRQ(ierr);}
6230552f7358SJed Brown   ierr = PetscFree(neg);CHKERRQ(ierr);
6231552f7358SJed Brown   PetscFunctionReturn(0);
6232552f7358SJed Brown }
6233ca8062c8SMatthew G. Knepley 
6234ca8062c8SMatthew G. Knepley #undef __FUNCT__
6235ca8062c8SMatthew G. Knepley #define __FUNCT__ "DMPlexCheckSymmetry"
6236ca8062c8SMatthew G. Knepley /*@
6237ca8062c8SMatthew G. Knepley   DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric.
6238ca8062c8SMatthew G. Knepley 
6239ca8062c8SMatthew G. Knepley   Input Parameters:
6240ca8062c8SMatthew G. Knepley   + dm - The DMPlex object
6241ca8062c8SMatthew G. Knepley 
6242ca8062c8SMatthew G. Knepley   Note: This is a useful diagnostic when creating meshes programmatically.
6243ca8062c8SMatthew G. Knepley 
6244ca8062c8SMatthew G. Knepley   Level: developer
6245ca8062c8SMatthew G. Knepley 
62469bf0dad6SMatthew G. Knepley .seealso: DMCreate(), DMCheckSkeleton(), DMCheckFaces()
6247ca8062c8SMatthew G. Knepley @*/
6248ca8062c8SMatthew G. Knepley PetscErrorCode DMPlexCheckSymmetry(DM dm)
6249ca8062c8SMatthew G. Knepley {
6250ca8062c8SMatthew G. Knepley   PetscSection    coneSection, supportSection;
6251ca8062c8SMatthew G. Knepley   const PetscInt *cone, *support;
6252ca8062c8SMatthew G. Knepley   PetscInt        coneSize, c, supportSize, s;
6253ca8062c8SMatthew G. Knepley   PetscInt        pStart, pEnd, p, csize, ssize;
6254ca8062c8SMatthew G. Knepley   PetscErrorCode  ierr;
6255ca8062c8SMatthew G. Knepley 
6256ca8062c8SMatthew G. Knepley   PetscFunctionBegin;
6257ca8062c8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6258ca8062c8SMatthew G. Knepley   ierr = DMPlexGetConeSection(dm, &coneSection);CHKERRQ(ierr);
6259ca8062c8SMatthew G. Knepley   ierr = DMPlexGetSupportSection(dm, &supportSection);CHKERRQ(ierr);
6260ca8062c8SMatthew G. Knepley   /* Check that point p is found in the support of its cone points, and vice versa */
6261ca8062c8SMatthew G. Knepley   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
6262ca8062c8SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
6263ca8062c8SMatthew G. Knepley     ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
6264ca8062c8SMatthew G. Knepley     ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr);
6265ca8062c8SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
6266ca8062c8SMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, cone[c], &supportSize);CHKERRQ(ierr);
6267ca8062c8SMatthew G. Knepley       ierr = DMPlexGetSupport(dm, cone[c], &support);CHKERRQ(ierr);
6268ca8062c8SMatthew G. Knepley       for (s = 0; s < supportSize; ++s) {
6269ca8062c8SMatthew G. Knepley         if (support[s] == p) break;
6270ca8062c8SMatthew G. Knepley       }
6271ca8062c8SMatthew G. Knepley       if (s >= supportSize) {
6272ca8062c8SMatthew G. Knepley         ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d cone: ", p);
6273ca8062c8SMatthew G. Knepley         for (s = 0; s < coneSize; ++s) {
6274ca8062c8SMatthew G. Knepley           ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", cone[s]);
6275ca8062c8SMatthew G. Knepley         }
6276ca8062c8SMatthew G. Knepley         ierr = PetscPrintf(PETSC_COMM_SELF, "\n");
6277ca8062c8SMatthew G. Knepley         ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d support: ", cone[c]);
6278ca8062c8SMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
6279ca8062c8SMatthew G. Knepley           ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", support[s]);
6280ca8062c8SMatthew G. Knepley         }
6281ca8062c8SMatthew G. Knepley         ierr = PetscPrintf(PETSC_COMM_SELF, "\n");
6282ca8062c8SMatthew G. Knepley         SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %d not found in support of cone point %d", p, cone[c]);
6283ca8062c8SMatthew G. Knepley       }
6284ca8062c8SMatthew G. Knepley     }
6285ca8062c8SMatthew G. Knepley     ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr);
6286ca8062c8SMatthew G. Knepley     ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr);
6287ca8062c8SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
6288ca8062c8SMatthew G. Knepley       ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
6289ca8062c8SMatthew G. Knepley       ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
6290ca8062c8SMatthew G. Knepley       for (c = 0; c < coneSize; ++c) {
6291ca8062c8SMatthew G. Knepley         if (cone[c] == p) break;
6292ca8062c8SMatthew G. Knepley       }
6293ca8062c8SMatthew G. Knepley       if (c >= coneSize) {
6294ca8062c8SMatthew G. Knepley         ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d support: ", p);
6295ca8062c8SMatthew G. Knepley         for (c = 0; c < supportSize; ++c) {
6296ca8062c8SMatthew G. Knepley           ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", support[c]);
6297ca8062c8SMatthew G. Knepley         }
6298ca8062c8SMatthew G. Knepley         ierr = PetscPrintf(PETSC_COMM_SELF, "\n");
6299ca8062c8SMatthew G. Knepley         ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d cone: ", support[s]);
6300ca8062c8SMatthew G. Knepley         for (c = 0; c < coneSize; ++c) {
6301ca8062c8SMatthew G. Knepley           ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", cone[c]);
6302ca8062c8SMatthew G. Knepley         }
6303ca8062c8SMatthew G. Knepley         ierr = PetscPrintf(PETSC_COMM_SELF, "\n");
6304ca8062c8SMatthew G. Knepley         SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %d not found in cone of support point %d", p, support[s]);
6305ca8062c8SMatthew G. Knepley       }
6306ca8062c8SMatthew G. Knepley     }
6307ca8062c8SMatthew G. Knepley   }
6308ca8062c8SMatthew G. Knepley   ierr = PetscSectionGetStorageSize(coneSection, &csize);CHKERRQ(ierr);
6309ca8062c8SMatthew G. Knepley   ierr = PetscSectionGetStorageSize(supportSection, &ssize);CHKERRQ(ierr);
6310ca8062c8SMatthew G. Knepley   if (csize != ssize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %d != Total support size %d", csize, ssize);
6311ca8062c8SMatthew G. Knepley   PetscFunctionReturn(0);
6312ca8062c8SMatthew G. Knepley }
6313ca8062c8SMatthew G. Knepley 
6314ca8062c8SMatthew G. Knepley #undef __FUNCT__
6315ca8062c8SMatthew G. Knepley #define __FUNCT__ "DMPlexCheckSkeleton"
6316ca8062c8SMatthew G. Knepley /*@
6317ca8062c8SMatthew G. Knepley   DMPlexCheckSkeleton - Check that each cell has the correct number of vertices
6318ca8062c8SMatthew G. Knepley 
6319ca8062c8SMatthew G. Knepley   Input Parameters:
6320ca8062c8SMatthew G. Knepley + dm - The DMPlex object
632158723a97SMatthew G. Knepley . isSimplex - Are the cells simplices or tensor products
632258723a97SMatthew G. Knepley - cellHeight - Normally 0
6323ca8062c8SMatthew G. Knepley 
6324ca8062c8SMatthew G. Knepley   Note: This is a useful diagnostic when creating meshes programmatically.
6325ca8062c8SMatthew G. Knepley 
6326ca8062c8SMatthew G. Knepley   Level: developer
6327ca8062c8SMatthew G. Knepley 
63289bf0dad6SMatthew G. Knepley .seealso: DMCreate(), DMCheckSymmetry(), DMCheckFaces()
6329ca8062c8SMatthew G. Knepley @*/
633058723a97SMatthew G. Knepley PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscBool isSimplex, PetscInt cellHeight)
6331ca8062c8SMatthew G. Knepley {
633242363296SMatthew G. Knepley   PetscInt       dim, numCorners, numHybridCorners, vStart, vEnd, cStart, cEnd, cMax, c;
6333ca8062c8SMatthew G. Knepley   PetscErrorCode ierr;
6334ca8062c8SMatthew G. Knepley 
6335ca8062c8SMatthew G. Knepley   PetscFunctionBegin;
6336ca8062c8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6337ca8062c8SMatthew G. Knepley   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
6338ca8062c8SMatthew G. Knepley   switch (dim) {
633942363296SMatthew G. Knepley   case 1: numCorners = isSimplex ? 2 : 2; numHybridCorners = isSimplex ? 2 : 2; break;
634042363296SMatthew G. Knepley   case 2: numCorners = isSimplex ? 3 : 4; numHybridCorners = isSimplex ? 4 : 4; break;
634142363296SMatthew G. Knepley   case 3: numCorners = isSimplex ? 4 : 8; numHybridCorners = isSimplex ? 6 : 8; break;
6342ca8062c8SMatthew G. Knepley   default:
6343ca8062c8SMatthew G. Knepley     SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle meshes of dimension %d", dim);
6344ca8062c8SMatthew G. Knepley   }
634558723a97SMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
634658723a97SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);
6347ca8062c8SMatthew G. Knepley   ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr);
6348ca8062c8SMatthew G. Knepley   cMax = cMax >= 0 ? cMax : cEnd;
6349ca8062c8SMatthew G. Knepley   for (c = cStart; c < cMax; ++c) {
635058723a97SMatthew G. Knepley     PetscInt *closure = NULL, closureSize, cl, coneSize = 0;
635158723a97SMatthew G. Knepley 
635258723a97SMatthew G. Knepley     ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
635358723a97SMatthew G. Knepley     for (cl = 0; cl < closureSize*2; cl += 2) {
635458723a97SMatthew G. Knepley       const PetscInt p = closure[cl];
635558723a97SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) ++coneSize;
635658723a97SMatthew G. Knepley     }
635758723a97SMatthew G. Knepley     ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
6358ca8062c8SMatthew G. Knepley     if (coneSize != numCorners) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %d has  %d vertices != %d", c, coneSize, numCorners);
6359ca8062c8SMatthew G. Knepley   }
636042363296SMatthew G. Knepley   for (c = cMax; c < cEnd; ++c) {
636142363296SMatthew G. Knepley     PetscInt *closure = NULL, closureSize, cl, coneSize = 0;
636242363296SMatthew G. Knepley 
636342363296SMatthew G. Knepley     ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
636442363296SMatthew G. Knepley     for (cl = 0; cl < closureSize*2; cl += 2) {
636542363296SMatthew G. Knepley       const PetscInt p = closure[cl];
636642363296SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) ++coneSize;
636742363296SMatthew G. Knepley     }
636842363296SMatthew G. Knepley     ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
636942363296SMatthew G. Knepley     if (coneSize > numHybridCorners) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Hybrid cell %d has  %d vertices > %d", c, coneSize, numHybridCorners);
637042363296SMatthew G. Knepley   }
6371ca8062c8SMatthew G. Knepley   PetscFunctionReturn(0);
6372ca8062c8SMatthew G. Knepley }
63739bf0dad6SMatthew G. Knepley 
63749bf0dad6SMatthew G. Knepley #undef __FUNCT__
63759bf0dad6SMatthew G. Knepley #define __FUNCT__ "DMPlexCheckFaces"
63769bf0dad6SMatthew G. Knepley /*@
63779bf0dad6SMatthew G. Knepley   DMPlexCheckFaces - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type
63789bf0dad6SMatthew G. Knepley 
63799bf0dad6SMatthew G. Knepley   Input Parameters:
63809bf0dad6SMatthew G. Knepley + dm - The DMPlex object
63819bf0dad6SMatthew G. Knepley . isSimplex - Are the cells simplices or tensor products
63829bf0dad6SMatthew G. Knepley - cellHeight - Normally 0
63839bf0dad6SMatthew G. Knepley 
63849bf0dad6SMatthew G. Knepley   Note: This is a useful diagnostic when creating meshes programmatically.
63859bf0dad6SMatthew G. Knepley 
63869bf0dad6SMatthew G. Knepley   Level: developer
63879bf0dad6SMatthew G. Knepley 
63889bf0dad6SMatthew G. Knepley .seealso: DMCreate(), DMCheckSymmetry(), DMCheckSkeleton()
63899bf0dad6SMatthew G. Knepley @*/
63909bf0dad6SMatthew G. Knepley PetscErrorCode DMPlexCheckFaces(DM dm, PetscBool isSimplex, PetscInt cellHeight)
63919bf0dad6SMatthew G. Knepley {
63923554e41dSMatthew G. Knepley   PetscInt       pMax[4];
63933554e41dSMatthew G. Knepley   PetscInt       dim, vStart, vEnd, cStart, cEnd, c, h;
63949bf0dad6SMatthew G. Knepley   PetscErrorCode ierr;
63959bf0dad6SMatthew G. Knepley 
63969bf0dad6SMatthew G. Knepley   PetscFunctionBegin;
63979bf0dad6SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
63989bf0dad6SMatthew G. Knepley   ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr);
63999bf0dad6SMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
640025abba81SMatthew G. Knepley   ierr = DMPlexGetHybridBounds(dm, &pMax[dim], &pMax[dim-1], &pMax[1], &pMax[0]);CHKERRQ(ierr);
64013554e41dSMatthew G. Knepley   for (h = cellHeight; h < dim; ++h) {
64023554e41dSMatthew G. Knepley     ierr = DMPlexGetHeightStratum(dm, h, &cStart, &cEnd);CHKERRQ(ierr);
64033554e41dSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
64049bf0dad6SMatthew G. Knepley       const PetscInt *cone, *ornt, *faces;
64059bf0dad6SMatthew G. Knepley       PetscInt        numFaces, faceSize, coneSize,f;
64069bf0dad6SMatthew G. Knepley       PetscInt       *closure = NULL, closureSize, cl, numCorners = 0;
64079bf0dad6SMatthew G. Knepley 
640825abba81SMatthew G. Knepley       if (pMax[dim-h] >= 0 && c >= pMax[dim-h]) continue;
64099bf0dad6SMatthew G. Knepley       ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr);
64109bf0dad6SMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
64119bf0dad6SMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
64129bf0dad6SMatthew G. Knepley       ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
64139bf0dad6SMatthew G. Knepley       for (cl = 0; cl < closureSize*2; cl += 2) {
64149bf0dad6SMatthew G. Knepley         const PetscInt p = closure[cl];
64159bf0dad6SMatthew G. Knepley         if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p;
64169bf0dad6SMatthew G. Knepley       }
64173554e41dSMatthew G. Knepley       ierr = DMPlexGetRawFaces_Internal(dm, dim-h, numCorners, closure, &numFaces, &faceSize, &faces);CHKERRQ(ierr);
64189bf0dad6SMatthew G. Knepley       if (coneSize != numFaces) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %d has %d faces but should have %d", c, coneSize, numFaces);
64199bf0dad6SMatthew G. Knepley       for (f = 0; f < numFaces; ++f) {
64209bf0dad6SMatthew G. Knepley         PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v;
64219bf0dad6SMatthew G. Knepley 
64229bf0dad6SMatthew G. Knepley         ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr);
64239bf0dad6SMatthew G. Knepley         for (cl = 0; cl < fclosureSize*2; cl += 2) {
64249bf0dad6SMatthew G. Knepley           const PetscInt p = fclosure[cl];
64259bf0dad6SMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p;
64269bf0dad6SMatthew G. Knepley         }
6427e003ed69SMatthew G. Knepley         if (fnumCorners != faceSize) SETERRQ5(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %d (%d) of cell %d has %d vertices but should have %d", cone[f], f, c, fnumCorners, faceSize);
64289bf0dad6SMatthew G. Knepley         for (v = 0; v < fnumCorners; ++v) {
6429e003ed69SMatthew G. Knepley           if (fclosure[v] != faces[f*faceSize+v]) SETERRQ6(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %d (%d) of cell %d vertex %d, %d != %d", cone[f], f, c, v, fclosure[v], faces[f*faceSize+v]);
64309bf0dad6SMatthew G. Knepley         }
64319bf0dad6SMatthew G. Knepley         ierr = DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr);
64329bf0dad6SMatthew G. Knepley       }
64339bf0dad6SMatthew G. Knepley       ierr = DMPlexRestoreFaces_Internal(dm, dim, c, &numFaces, &faceSize, &faces);CHKERRQ(ierr);
64349bf0dad6SMatthew G. Knepley       ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
64359bf0dad6SMatthew G. Knepley     }
64363554e41dSMatthew G. Knepley   }
6437552f7358SJed Brown   PetscFunctionReturn(0);
6438552f7358SJed Brown }
6439