xref: /petsc/src/dm/impls/plex/plex.c (revision 0682b8bb985f79c3eb46559cecc19abcac94ee66)
1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h>   /*I      "petscdmplex.h"   I*/
2af0996ceSBarry Smith #include <petsc/private/isimpl.h>
3e5c6e791SKarl Rupp #include <petsc/private/vecimpl.h>
48135c375SStefano Zampini #include <petsc/private/glvisvecimpl.h>
50c312b8eSJed Brown #include <petscsf.h>
6e228b242SToby Isaac #include <petscds.h>
7e412dcbdSMatthew G. Knepley #include <petscdraw.h>
8f19dbd58SToby Isaac #include <petscdmfield.h>
9012bc364SMatthew G. Knepley #include <petscdmplextransform.h>
10552f7358SJed Brown 
11552f7358SJed Brown /* Logging support */
1202f7d72cSksagiyam PetscLogEvent DMPLEX_Interpolate, DMPLEX_Partition, DMPLEX_Distribute, DMPLEX_DistributeCones, DMPLEX_DistributeLabels, DMPLEX_DistributeSF, DMPLEX_DistributeOverlap, DMPLEX_DistributeField, DMPLEX_DistributeData, DMPLEX_Migrate, DMPLEX_InterpolateSF, DMPLEX_GlobalToNaturalBegin, DMPLEX_GlobalToNaturalEnd, DMPLEX_NaturalToGlobalBegin, DMPLEX_NaturalToGlobalEnd, DMPLEX_Stratify, DMPLEX_Symmetrize, DMPLEX_Preallocate, DMPLEX_ResidualFEM, DMPLEX_JacobianFEM, DMPLEX_InterpolatorFEM, DMPLEX_InjectorFEM, DMPLEX_IntegralFEM, DMPLEX_CreateGmsh, DMPLEX_RebalanceSharedPoints, DMPLEX_PartSelf, DMPLEX_PartLabelInvert, DMPLEX_PartLabelCreateSF, DMPLEX_PartStratSF, DMPLEX_CreatePointSF,DMPLEX_LocatePoints,DMPLEX_TopologyView,DMPLEX_LabelsView,DMPLEX_CoordinatesView,DMPLEX_SectionView,DMPLEX_GlobalVectorView,DMPLEX_LocalVectorView,DMPLEX_TopologyLoad,DMPLEX_LabelsLoad,DMPLEX_CoordinatesLoad,DMPLEX_SectionLoad,DMPLEX_GlobalVectorLoad,DMPLEX_LocalVectorLoad;
13552f7358SJed Brown 
145a576424SJed Brown PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer);
15552f7358SJed Brown 
16e5337592SStefano Zampini /*@
179318fe57SMatthew G. Knepley   DMPlexIsSimplex - Is the first cell in this mesh a simplex?
189318fe57SMatthew G. Knepley 
199318fe57SMatthew G. Knepley   Input Parameter:
209318fe57SMatthew G. Knepley . dm      - The DMPlex object
219318fe57SMatthew G. Knepley 
229318fe57SMatthew G. Knepley   Output Parameter:
239318fe57SMatthew G. Knepley . simplex - Flag checking for a simplex
249318fe57SMatthew G. Knepley 
259318fe57SMatthew G. Knepley   Note: This just gives the first range of cells found. If the mesh has several cell types, it will only give the first.
269318fe57SMatthew G. Knepley   If the mesh has no cells, this returns PETSC_FALSE.
279318fe57SMatthew G. Knepley 
289318fe57SMatthew G. Knepley   Level: intermediate
299318fe57SMatthew G. Knepley 
309318fe57SMatthew G. Knepley .seealso DMPlexGetSimplexOrBoxCells(), DMPlexGetCellType(), DMPlexGetHeightStratum(), DMPolytopeTypeGetNumVertices()
319318fe57SMatthew G. Knepley @*/
329318fe57SMatthew G. Knepley PetscErrorCode DMPlexIsSimplex(DM dm, PetscBool *simplex)
339318fe57SMatthew G. Knepley {
349318fe57SMatthew G. Knepley   DMPolytopeType ct;
359318fe57SMatthew G. Knepley   PetscInt       cStart, cEnd;
369318fe57SMatthew G. Knepley   PetscErrorCode ierr;
379318fe57SMatthew G. Knepley 
389318fe57SMatthew G. Knepley   PetscFunctionBegin;
399318fe57SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
409318fe57SMatthew G. Knepley   if (cEnd <= cStart) {*simplex = PETSC_FALSE; PetscFunctionReturn(0);}
419318fe57SMatthew G. Knepley   ierr = DMPlexGetCellType(dm, cStart, &ct);CHKERRQ(ierr);
429318fe57SMatthew G. Knepley   *simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE;
439318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
449318fe57SMatthew G. Knepley }
459318fe57SMatthew G. Knepley 
469318fe57SMatthew G. Knepley /*@
47412e9a14SMatthew G. Knepley   DMPlexGetSimplexOrBoxCells - Get the range of cells which are neither prisms nor ghost FV cells
48e5337592SStefano Zampini 
49d8d19677SJose E. Roman   Input Parameters:
50412e9a14SMatthew G. Knepley + dm     - The DMPlex object
51412e9a14SMatthew G. Knepley - height - The cell height in the Plex, 0 is the default
52e5337592SStefano Zampini 
53e5337592SStefano Zampini   Output Parameters:
54412e9a14SMatthew G. Knepley + cStart - The first "normal" cell
55412e9a14SMatthew G. Knepley - cEnd   - The upper bound on "normal"" cells
56e5337592SStefano Zampini 
57412e9a14SMatthew G. Knepley   Note: This just gives the first range of cells found. If the mesh has several cell types, it will only give the first.
58e5337592SStefano Zampini 
59412e9a14SMatthew G. Knepley   Level: developer
60e5337592SStefano Zampini 
618065b584SMatthew Knepley .seealso DMPlexConstructGhostCells(), DMPlexGetGhostCellStratum()
62e5337592SStefano Zampini @*/
63412e9a14SMatthew G. Knepley PetscErrorCode DMPlexGetSimplexOrBoxCells(DM dm, PetscInt height, PetscInt *cStart, PetscInt *cEnd)
64e5337592SStefano Zampini {
65412e9a14SMatthew G. Knepley   DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
66412e9a14SMatthew G. Knepley   PetscInt       cS, cE, c;
67e5337592SStefano Zampini   PetscErrorCode ierr;
68e5337592SStefano Zampini 
69e5337592SStefano Zampini   PetscFunctionBegin;
70412e9a14SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, PetscMax(height, 0), &cS, &cE);CHKERRQ(ierr);
71412e9a14SMatthew G. Knepley   for (c = cS; c < cE; ++c) {
72412e9a14SMatthew G. Knepley     DMPolytopeType cct;
73412e9a14SMatthew G. Knepley 
74412e9a14SMatthew G. Knepley     ierr = DMPlexGetCellType(dm, c, &cct);CHKERRQ(ierr);
75412e9a14SMatthew G. Knepley     if ((PetscInt) cct < 0) break;
76412e9a14SMatthew G. Knepley     switch (cct) {
77ba2698f1SMatthew G. Knepley       case DM_POLYTOPE_POINT:
78ba2698f1SMatthew G. Knepley       case DM_POLYTOPE_SEGMENT:
79ba2698f1SMatthew G. Knepley       case DM_POLYTOPE_TRIANGLE:
80ba2698f1SMatthew G. Knepley       case DM_POLYTOPE_QUADRILATERAL:
81ba2698f1SMatthew G. Knepley       case DM_POLYTOPE_TETRAHEDRON:
82ba2698f1SMatthew G. Knepley       case DM_POLYTOPE_HEXAHEDRON:
83412e9a14SMatthew G. Knepley         ct = cct;
84e5337592SStefano Zampini         break;
85412e9a14SMatthew G. Knepley       default: break;
86e5337592SStefano Zampini     }
87412e9a14SMatthew G. Knepley     if (ct != DM_POLYTOPE_UNKNOWN) break;
88e5337592SStefano Zampini   }
89412e9a14SMatthew G. Knepley   if (ct != DM_POLYTOPE_UNKNOWN) {
90412e9a14SMatthew G. Knepley     DMLabel ctLabel;
91412e9a14SMatthew G. Knepley 
92412e9a14SMatthew G. Knepley     ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr);
93412e9a14SMatthew G. Knepley     ierr = DMLabelGetStratumBounds(ctLabel, ct, &cS, &cE);CHKERRQ(ierr);
94e5337592SStefano Zampini   }
95412e9a14SMatthew G. Knepley   if (cStart) *cStart = cS;
96412e9a14SMatthew G. Knepley   if (cEnd)   *cEnd   = cE;
97e5337592SStefano Zampini   PetscFunctionReturn(0);
98e5337592SStefano Zampini }
99e5337592SStefano Zampini 
1007afe7537SMatthew G. Knepley PetscErrorCode DMPlexGetFieldType_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *sStart, PetscInt *sEnd, PetscViewerVTKFieldType *ft)
1017e42fee7SMatthew G. Knepley {
102412e9a14SMatthew G. Knepley   PetscInt       cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd;
103a99a26bcSAdrian Croucher   PetscInt       vcdof[2] = {0,0}, globalvcdof[2];
1047e42fee7SMatthew G. Knepley   PetscErrorCode ierr;
1057e42fee7SMatthew G. Knepley 
1067e42fee7SMatthew G. Knepley   PetscFunctionBegin;
107e630c359SToby Isaac   *ft  = PETSC_VTK_INVALID;
108f094498dSMatthew G. Knepley   ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr);
1097e42fee7SMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
110412e9a14SMatthew G. Knepley   ierr = DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
1117e42fee7SMatthew G. Knepley   ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr);
1127e42fee7SMatthew G. Knepley   if (field >= 0) {
113a99a26bcSAdrian Croucher     if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetFieldDof(section, vStart, field, &vcdof[0]);CHKERRQ(ierr);}
114a99a26bcSAdrian Croucher     if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetFieldDof(section, cStart, field, &vcdof[1]);CHKERRQ(ierr);}
1157e42fee7SMatthew G. Knepley   } else {
116a99a26bcSAdrian Croucher     if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetDof(section, vStart, &vcdof[0]);CHKERRQ(ierr);}
117a99a26bcSAdrian Croucher     if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetDof(section, cStart, &vcdof[1]);CHKERRQ(ierr);}
1187e42fee7SMatthew G. Knepley   }
119ffc4695bSBarry Smith   ierr = MPI_Allreduce(vcdof, globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr);
120a99a26bcSAdrian Croucher   if (globalvcdof[0]) {
1217e42fee7SMatthew G. Knepley     *sStart = vStart;
1227e42fee7SMatthew G. Knepley     *sEnd   = vEnd;
123f094498dSMatthew G. Knepley     if (globalvcdof[0] == cdim) *ft = PETSC_VTK_POINT_VECTOR_FIELD;
1247e42fee7SMatthew G. Knepley     else                        *ft = PETSC_VTK_POINT_FIELD;
125a99a26bcSAdrian Croucher   } else if (globalvcdof[1]) {
1267e42fee7SMatthew G. Knepley     *sStart = cStart;
1277e42fee7SMatthew G. Knepley     *sEnd   = cEnd;
128f094498dSMatthew G. Knepley     if (globalvcdof[1] == cdim) *ft = PETSC_VTK_CELL_VECTOR_FIELD;
1297e42fee7SMatthew G. Knepley     else                        *ft = PETSC_VTK_CELL_FIELD;
130e630c359SToby Isaac   } else {
131e630c359SToby Isaac     if (field >= 0) {
132e630c359SToby Isaac       const char *fieldname;
133e630c359SToby Isaac 
134e630c359SToby Isaac       ierr = PetscSectionGetFieldName(section, field, &fieldname);CHKERRQ(ierr);
1357d3de750SJacob Faibussowitsch       ierr = PetscInfo((PetscObject) dm, "Could not classify VTK output type of section field %D \"%s\"\n", field, fieldname);CHKERRQ(ierr);
136e630c359SToby Isaac     } else {
1376823f3c5SBlaise Bourdin       ierr = PetscInfo((PetscObject) dm, "Could not classify VTK output type of section\"%s\"\n");CHKERRQ(ierr);
138e630c359SToby Isaac     }
139e630c359SToby Isaac   }
1407e42fee7SMatthew G. Knepley   PetscFunctionReturn(0);
1417e42fee7SMatthew G. Knepley }
1427e42fee7SMatthew G. Knepley 
1437cd05799SMatthew G. Knepley static PetscErrorCode VecView_Plex_Local_Draw(Vec v, PetscViewer viewer)
144e412dcbdSMatthew G. Knepley {
145e412dcbdSMatthew G. Knepley   DM                 dm;
146d1df6f1dSMatthew G. Knepley   PetscSection       s;
147e412dcbdSMatthew G. Knepley   PetscDraw          draw, popup;
148e412dcbdSMatthew G. Knepley   DM                 cdm;
149e412dcbdSMatthew G. Knepley   PetscSection       coordSection;
150e412dcbdSMatthew G. Knepley   Vec                coordinates;
151e412dcbdSMatthew G. Knepley   const PetscScalar *coords, *array;
152e412dcbdSMatthew G. Knepley   PetscReal          bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL};
153339e3443SMatthew G. Knepley   PetscReal          vbound[2], time;
154339e3443SMatthew G. Knepley   PetscBool          isnull, flg;
155d1df6f1dSMatthew G. Knepley   PetscInt           dim, Nf, f, Nc, comp, vStart, vEnd, cStart, cEnd, c, N, level, step, w = 0;
156e412dcbdSMatthew G. Knepley   const char        *name;
157339e3443SMatthew G. Knepley   char               title[PETSC_MAX_PATH_LEN];
158e412dcbdSMatthew G. Knepley   PetscErrorCode     ierr;
159e412dcbdSMatthew G. Knepley 
160e412dcbdSMatthew G. Knepley   PetscFunctionBegin;
161d1df6f1dSMatthew G. Knepley   ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr);
162d1df6f1dSMatthew G. Knepley   ierr = PetscDrawIsNull(draw, &isnull);CHKERRQ(ierr);
163d1df6f1dSMatthew G. Knepley   if (isnull) PetscFunctionReturn(0);
164d1df6f1dSMatthew G. Knepley 
165e412dcbdSMatthew G. Knepley   ierr = VecGetDM(v, &dm);CHKERRQ(ierr);
166e412dcbdSMatthew G. Knepley   ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr);
1672c71b3e2SJacob Faibussowitsch   PetscCheckFalse(dim != 2,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %D. Use PETSCVIEWERGLVIS", dim);
16892fd8e1eSJed Brown   ierr = DMGetLocalSection(dm, &s);CHKERRQ(ierr);
169d1df6f1dSMatthew G. Knepley   ierr = PetscSectionGetNumFields(s, &Nf);CHKERRQ(ierr);
170e412dcbdSMatthew G. Knepley   ierr = DMGetCoarsenLevel(dm, &level);CHKERRQ(ierr);
171e412dcbdSMatthew G. Knepley   ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
17292fd8e1eSJed Brown   ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr);
173e412dcbdSMatthew G. Knepley   ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
174e412dcbdSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
175e412dcbdSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
176e412dcbdSMatthew G. Knepley 
177e412dcbdSMatthew G. Knepley   ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr);
178339e3443SMatthew G. Knepley   ierr = DMGetOutputSequenceNumber(dm, &step, &time);CHKERRQ(ierr);
179e412dcbdSMatthew G. Knepley 
180e412dcbdSMatthew G. Knepley   ierr = VecGetLocalSize(coordinates, &N);CHKERRQ(ierr);
181e412dcbdSMatthew G. Knepley   ierr = VecGetArrayRead(coordinates, &coords);CHKERRQ(ierr);
182e412dcbdSMatthew G. Knepley   for (c = 0; c < N; c += dim) {
1830c81f2a8SMatthew G. Knepley     bound[0] = PetscMin(bound[0], PetscRealPart(coords[c]));   bound[2] = PetscMax(bound[2], PetscRealPart(coords[c]));
1840c81f2a8SMatthew G. Knepley     bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1]));
185e412dcbdSMatthew G. Knepley   }
186e412dcbdSMatthew G. Knepley   ierr = VecRestoreArrayRead(coordinates, &coords);CHKERRQ(ierr);
187e412dcbdSMatthew G. Knepley   ierr = PetscDrawClear(draw);CHKERRQ(ierr);
188e412dcbdSMatthew G. Knepley 
189d1df6f1dSMatthew G. Knepley   /* Could implement something like DMDASelectFields() */
190d1df6f1dSMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
191d1df6f1dSMatthew G. Knepley     DM   fdm = dm;
192d1df6f1dSMatthew G. Knepley     Vec  fv  = v;
193d1df6f1dSMatthew G. Knepley     IS   fis;
194d1df6f1dSMatthew G. Knepley     char prefix[PETSC_MAX_PATH_LEN];
195d1df6f1dSMatthew G. Knepley     const char *fname;
196d1df6f1dSMatthew G. Knepley 
197d1df6f1dSMatthew G. Knepley     ierr = PetscSectionGetFieldComponents(s, f, &Nc);CHKERRQ(ierr);
198d1df6f1dSMatthew G. Knepley     ierr = PetscSectionGetFieldName(s, f, &fname);CHKERRQ(ierr);
199d1df6f1dSMatthew G. Knepley 
200a126751eSBarry Smith     if (v->hdr.prefix) {ierr = PetscStrncpy(prefix, v->hdr.prefix,sizeof(prefix));CHKERRQ(ierr);}
201d1df6f1dSMatthew G. Knepley     else               {prefix[0] = '\0';}
202d1df6f1dSMatthew G. Knepley     if (Nf > 1) {
203d1df6f1dSMatthew G. Knepley       ierr = DMCreateSubDM(dm, 1, &f, &fis, &fdm);CHKERRQ(ierr);
204d1df6f1dSMatthew G. Knepley       ierr = VecGetSubVector(v, fis, &fv);CHKERRQ(ierr);
205a126751eSBarry Smith       ierr = PetscStrlcat(prefix, fname,sizeof(prefix));CHKERRQ(ierr);
206a126751eSBarry Smith       ierr = PetscStrlcat(prefix, "_",sizeof(prefix));CHKERRQ(ierr);
207d1df6f1dSMatthew G. Knepley     }
208d1df6f1dSMatthew G. Knepley     for (comp = 0; comp < Nc; ++comp, ++w) {
209d1df6f1dSMatthew G. Knepley       PetscInt nmax = 2;
210d1df6f1dSMatthew G. Knepley 
211d1df6f1dSMatthew G. Knepley       ierr = PetscViewerDrawGetDraw(viewer, w, &draw);CHKERRQ(ierr);
212d1df6f1dSMatthew G. Knepley       if (Nc > 1) {ierr = PetscSNPrintf(title, sizeof(title), "%s:%s_%D Step: %D Time: %.4g", name, fname, comp, step, time);CHKERRQ(ierr);}
213d1df6f1dSMatthew G. Knepley       else        {ierr = PetscSNPrintf(title, sizeof(title), "%s:%s Step: %D Time: %.4g", name, fname, step, time);CHKERRQ(ierr);}
214d1df6f1dSMatthew G. Knepley       ierr = PetscDrawSetTitle(draw, title);CHKERRQ(ierr);
215d1df6f1dSMatthew G. Knepley 
216d1df6f1dSMatthew G. Knepley       /* TODO Get max and min only for this component */
217d1df6f1dSMatthew G. Knepley       ierr = PetscOptionsGetRealArray(NULL, prefix, "-vec_view_bounds", vbound, &nmax, &flg);CHKERRQ(ierr);
218339e3443SMatthew G. Knepley       if (!flg) {
219d1df6f1dSMatthew G. Knepley         ierr = VecMin(fv, NULL, &vbound[0]);CHKERRQ(ierr);
220d1df6f1dSMatthew G. Knepley         ierr = VecMax(fv, NULL, &vbound[1]);CHKERRQ(ierr);
221d1df6f1dSMatthew G. Knepley         if (vbound[1] <= vbound[0]) vbound[1] = vbound[0] + 1.0;
222339e3443SMatthew G. Knepley       }
223e412dcbdSMatthew G. Knepley       ierr = PetscDrawGetPopup(draw, &popup);CHKERRQ(ierr);
224339e3443SMatthew G. Knepley       ierr = PetscDrawScalePopup(popup, vbound[0], vbound[1]);CHKERRQ(ierr);
225d1df6f1dSMatthew G. Knepley       ierr = PetscDrawSetCoordinates(draw, bound[0], bound[1], bound[2], bound[3]);CHKERRQ(ierr);
226e412dcbdSMatthew G. Knepley 
227d1df6f1dSMatthew G. Knepley       ierr = VecGetArrayRead(fv, &array);CHKERRQ(ierr);
228e412dcbdSMatthew G. Knepley       for (c = cStart; c < cEnd; ++c) {
22999a2f7bcSMatthew G. Knepley         PetscScalar *coords = NULL, *a = NULL;
230e56f9228SJed Brown         PetscInt     numCoords, color[4] = {-1,-1,-1,-1};
231e412dcbdSMatthew G. Knepley 
232d1df6f1dSMatthew G. Knepley         ierr = DMPlexPointLocalRead(fdm, c, array, &a);CHKERRQ(ierr);
233339e3443SMatthew G. Knepley         if (a) {
234d1df6f1dSMatthew G. Knepley           color[0] = PetscDrawRealToColor(PetscRealPart(a[comp]), vbound[0], vbound[1]);
235339e3443SMatthew G. Knepley           color[1] = color[2] = color[3] = color[0];
236339e3443SMatthew G. Knepley         } else {
237339e3443SMatthew G. Knepley           PetscScalar *vals = NULL;
238339e3443SMatthew G. Knepley           PetscInt     numVals, va;
239339e3443SMatthew G. Knepley 
240d1df6f1dSMatthew G. Knepley           ierr = DMPlexVecGetClosure(fdm, NULL, fv, c, &numVals, &vals);CHKERRQ(ierr);
2412c71b3e2SJacob Faibussowitsch           PetscCheckFalse(numVals % Nc,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The number of components %D does not divide the number of values in the closure %D", Nc, numVals);
242d1df6f1dSMatthew G. Knepley           switch (numVals/Nc) {
243d1df6f1dSMatthew G. Knepley           case 3: /* P1 Triangle */
244d1df6f1dSMatthew G. Knepley           case 4: /* P1 Quadrangle */
245d1df6f1dSMatthew G. Knepley             for (va = 0; va < numVals/Nc; ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va*Nc+comp]), vbound[0], vbound[1]);
246339e3443SMatthew G. Knepley             break;
247d1df6f1dSMatthew G. Knepley           case 6: /* P2 Triangle */
248d1df6f1dSMatthew G. Knepley           case 8: /* P2 Quadrangle */
249d1df6f1dSMatthew G. Knepley             for (va = 0; va < numVals/(Nc*2); ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va*Nc+comp + numVals/(Nc*2)]), vbound[0], vbound[1]);
250d1df6f1dSMatthew G. Knepley             break;
25198921bdaSJacob Faibussowitsch           default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of values for cell closure %D cannot be handled", numVals/Nc);
252339e3443SMatthew G. Knepley           }
253d1df6f1dSMatthew G. Knepley           ierr = DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals);CHKERRQ(ierr);
254339e3443SMatthew G. Knepley         }
255e412dcbdSMatthew G. Knepley         ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr);
256e412dcbdSMatthew G. Knepley         switch (numCoords) {
257e412dcbdSMatthew G. Knepley         case 6:
2589edc3542SMatthew Knepley         case 12: /* Localized triangle */
259339e3443SMatthew G. Knepley           ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), color[0], color[1], color[2]);CHKERRQ(ierr);
260e412dcbdSMatthew G. Knepley           break;
261e412dcbdSMatthew G. Knepley         case 8:
2629edc3542SMatthew Knepley         case 16: /* Localized quadrilateral */
263339e3443SMatthew G. Knepley           ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), color[0], color[1], color[2]);CHKERRQ(ierr);
264339e3443SMatthew G. Knepley           ierr = PetscDrawTriangle(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), color[2], color[3], color[0]);CHKERRQ(ierr);
265e412dcbdSMatthew G. Knepley           break;
26698921bdaSJacob Faibussowitsch         default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %D coordinates", numCoords);
267e412dcbdSMatthew G. Knepley         }
268e412dcbdSMatthew G. Knepley         ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr);
269e412dcbdSMatthew G. Knepley       }
270d1df6f1dSMatthew G. Knepley       ierr = VecRestoreArrayRead(fv, &array);CHKERRQ(ierr);
271e412dcbdSMatthew G. Knepley       ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
272e412dcbdSMatthew G. Knepley       ierr = PetscDrawPause(draw);CHKERRQ(ierr);
273e412dcbdSMatthew G. Knepley       ierr = PetscDrawSave(draw);CHKERRQ(ierr);
274d1df6f1dSMatthew G. Knepley     }
275d1df6f1dSMatthew G. Knepley     if (Nf > 1) {
276d1df6f1dSMatthew G. Knepley       ierr = VecRestoreSubVector(v, fis, &fv);CHKERRQ(ierr);
277d1df6f1dSMatthew G. Knepley       ierr = ISDestroy(&fis);CHKERRQ(ierr);
278d1df6f1dSMatthew G. Knepley       ierr = DMDestroy(&fdm);CHKERRQ(ierr);
279d1df6f1dSMatthew G. Knepley     }
280d1df6f1dSMatthew G. Knepley   }
281e412dcbdSMatthew G. Knepley   PetscFunctionReturn(0);
282e412dcbdSMatthew G. Knepley }
283e412dcbdSMatthew G. Knepley 
284684b87d9SLisandro Dalcin static PetscErrorCode VecView_Plex_Local_VTK(Vec v, PetscViewer viewer)
285684b87d9SLisandro Dalcin {
286684b87d9SLisandro Dalcin   DM                      dm;
287684b87d9SLisandro Dalcin   Vec                     locv;
288684b87d9SLisandro Dalcin   const char              *name;
289684b87d9SLisandro Dalcin   PetscSection            section;
290684b87d9SLisandro Dalcin   PetscInt                pStart, pEnd;
291e630c359SToby Isaac   PetscInt                numFields;
292684b87d9SLisandro Dalcin   PetscViewerVTKFieldType ft;
293684b87d9SLisandro Dalcin   PetscErrorCode          ierr;
294684b87d9SLisandro Dalcin 
295684b87d9SLisandro Dalcin   PetscFunctionBegin;
296684b87d9SLisandro Dalcin   ierr = VecGetDM(v, &dm);CHKERRQ(ierr);
297684b87d9SLisandro Dalcin   ierr = DMCreateLocalVector(dm, &locv);CHKERRQ(ierr); /* VTK viewer requires exclusive ownership of the vector */
298684b87d9SLisandro Dalcin   ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr);
299684b87d9SLisandro Dalcin   ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr);
300684b87d9SLisandro Dalcin   ierr = VecCopy(v, locv);CHKERRQ(ierr);
30192fd8e1eSJed Brown   ierr = DMGetLocalSection(dm, &section);CHKERRQ(ierr);
302e630c359SToby Isaac   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
303e630c359SToby Isaac   if (!numFields) {
304684b87d9SLisandro Dalcin     ierr = DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft);CHKERRQ(ierr);
305e630c359SToby Isaac     ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, PETSC_TRUE,(PetscObject) locv);CHKERRQ(ierr);
306e630c359SToby Isaac   } else {
307e630c359SToby Isaac     PetscInt f;
308e630c359SToby Isaac 
309e630c359SToby Isaac     for (f = 0; f < numFields; f++) {
310e630c359SToby Isaac       ierr = DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft);CHKERRQ(ierr);
311e630c359SToby Isaac       if (ft == PETSC_VTK_INVALID) continue;
312e630c359SToby Isaac       ierr = PetscObjectReference((PetscObject)locv);CHKERRQ(ierr);
313e630c359SToby Isaac       ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE,(PetscObject) locv);CHKERRQ(ierr);
314e630c359SToby Isaac     }
315e630c359SToby Isaac     ierr = VecDestroy(&locv);CHKERRQ(ierr);
316e630c359SToby Isaac   }
317684b87d9SLisandro Dalcin   PetscFunctionReturn(0);
318684b87d9SLisandro Dalcin }
319684b87d9SLisandro Dalcin 
320552f7358SJed Brown PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer)
321552f7358SJed Brown {
322552f7358SJed Brown   DM             dm;
323684b87d9SLisandro Dalcin   PetscBool      isvtk, ishdf5, isdraw, isglvis;
324552f7358SJed Brown   PetscErrorCode ierr;
325552f7358SJed Brown 
326552f7358SJed Brown   PetscFunctionBegin;
327552f7358SJed Brown   ierr = VecGetDM(v, &dm);CHKERRQ(ierr);
3282c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
329552f7358SJed Brown   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK,   &isvtk);CHKERRQ(ierr);
330b136c2c9SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
331f13a32a3SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW,  &isdraw);CHKERRQ(ierr);
3328135c375SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr);
333684b87d9SLisandro Dalcin   if (isvtk || ishdf5 || isdraw || isglvis) {
334684b87d9SLisandro Dalcin     PetscInt    i,numFields;
335684b87d9SLisandro Dalcin     PetscObject fe;
336ef31f671SMatthew G. Knepley     PetscBool   fem = PETSC_FALSE;
337684b87d9SLisandro Dalcin     Vec         locv = v;
338684b87d9SLisandro Dalcin     const char  *name;
339684b87d9SLisandro Dalcin     PetscInt    step;
340684b87d9SLisandro Dalcin     PetscReal   time;
341ef31f671SMatthew G. Knepley 
342ef31f671SMatthew G. Knepley     ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr);
343684b87d9SLisandro Dalcin     for (i=0; i<numFields; i++) {
34444a7f3ddSMatthew G. Knepley       ierr = DMGetField(dm, i, NULL, &fe);CHKERRQ(ierr);
345684b87d9SLisandro Dalcin       if (fe->classid == PETSCFE_CLASSID) { fem = PETSC_TRUE; break; }
346ef31f671SMatthew G. Knepley     }
347684b87d9SLisandro Dalcin     if (fem) {
348798534f6SMatthew G. Knepley       PetscObject isZero;
349798534f6SMatthew G. Knepley 
350684b87d9SLisandro Dalcin       ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr);
351684b87d9SLisandro Dalcin       ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr);
352684b87d9SLisandro Dalcin       ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr);
353798534f6SMatthew G. Knepley       ierr = PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero);CHKERRQ(ierr);
354798534f6SMatthew G. Knepley       ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero);CHKERRQ(ierr);
355684b87d9SLisandro Dalcin       ierr = VecCopy(v, locv);CHKERRQ(ierr);
356684b87d9SLisandro Dalcin       ierr = DMGetOutputSequenceNumber(dm, NULL, &time);CHKERRQ(ierr);
357684b87d9SLisandro Dalcin       ierr = DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL);CHKERRQ(ierr);
358ef31f671SMatthew G. Knepley     }
359552f7358SJed Brown     if (isvtk) {
360684b87d9SLisandro Dalcin       ierr = VecView_Plex_Local_VTK(locv, viewer);CHKERRQ(ierr);
361b136c2c9SMatthew G. Knepley     } else if (ishdf5) {
362b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
363684b87d9SLisandro Dalcin       ierr = VecView_Plex_Local_HDF5_Internal(locv, viewer);CHKERRQ(ierr);
364b136c2c9SMatthew G. Knepley #else
365b136c2c9SMatthew G. Knepley       SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
366b136c2c9SMatthew G. Knepley #endif
367f13a32a3SMatthew G. Knepley     } else if (isdraw) {
368684b87d9SLisandro Dalcin       ierr = VecView_Plex_Local_Draw(locv, viewer);CHKERRQ(ierr);
369684b87d9SLisandro Dalcin     } else if (isglvis) {
370684b87d9SLisandro Dalcin       ierr = DMGetOutputSequenceNumber(dm, &step, NULL);CHKERRQ(ierr);
371684b87d9SLisandro Dalcin       ierr = PetscViewerGLVisSetSnapId(viewer, step);CHKERRQ(ierr);
372684b87d9SLisandro Dalcin       ierr = VecView_GLVis(locv, viewer);CHKERRQ(ierr);
373684b87d9SLisandro Dalcin     }
374798534f6SMatthew G. Knepley     if (fem) {
375798534f6SMatthew G. Knepley       ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL);CHKERRQ(ierr);
376798534f6SMatthew G. Knepley       ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr);
377798534f6SMatthew G. Knepley     }
378552f7358SJed Brown   } else {
379684b87d9SLisandro Dalcin     PetscBool isseq;
380684b87d9SLisandro Dalcin 
381684b87d9SLisandro Dalcin     ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr);
38255f2e967SMatthew G. Knepley     if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);}
38355f2e967SMatthew G. Knepley     else       {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);}
384552f7358SJed Brown   }
385552f7358SJed Brown   PetscFunctionReturn(0);
386552f7358SJed Brown }
387552f7358SJed Brown 
388552f7358SJed Brown PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer)
389552f7358SJed Brown {
390552f7358SJed Brown   DM             dm;
3916823f3c5SBlaise Bourdin   PetscBool      isvtk, ishdf5, isdraw, isglvis, isexodusii;
392552f7358SJed Brown   PetscErrorCode ierr;
393552f7358SJed Brown 
394552f7358SJed Brown   PetscFunctionBegin;
395552f7358SJed Brown   ierr = VecGetDM(v, &dm);CHKERRQ(ierr);
3962c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
397552f7358SJed Brown   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK,      &isvtk);CHKERRQ(ierr);
39833c3e6b4SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,     &ishdf5);CHKERRQ(ierr);
399e412dcbdSMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW,     &isdraw);CHKERRQ(ierr);
4008135c375SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS,    &isglvis);CHKERRQ(ierr);
4016823f3c5SBlaise Bourdin   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii);CHKERRQ(ierr);
402684b87d9SLisandro Dalcin   if (isvtk || isdraw || isglvis) {
403552f7358SJed Brown     Vec         locv;
404798534f6SMatthew G. Knepley     PetscObject isZero;
405552f7358SJed Brown     const char *name;
406552f7358SJed Brown 
407c8dd51e9SBarry Smith     ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr);
408552f7358SJed Brown     ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr);
409552f7358SJed Brown     ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr);
410552f7358SJed Brown     ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr);
411552f7358SJed Brown     ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr);
412798534f6SMatthew G. Knepley     ierr = PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero);CHKERRQ(ierr);
413798534f6SMatthew G. Knepley     ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero);CHKERRQ(ierr);
414552f7358SJed Brown     ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr);
415798534f6SMatthew G. Knepley     ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL);CHKERRQ(ierr);
416c8dd51e9SBarry Smith     ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr);
417b136c2c9SMatthew G. Knepley   } else if (ishdf5) {
418b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
41939d25373SMatthew G. Knepley     ierr = VecView_Plex_HDF5_Internal(v, viewer);CHKERRQ(ierr);
420b136c2c9SMatthew G. Knepley #else
421b136c2c9SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
422b136c2c9SMatthew G. Knepley #endif
4236823f3c5SBlaise Bourdin   } else if (isexodusii) {
4246823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII)
4256823f3c5SBlaise Bourdin     ierr = VecView_PlexExodusII_Internal(v, viewer);CHKERRQ(ierr);
4266823f3c5SBlaise Bourdin #else
4276823f3c5SBlaise Bourdin     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii");
4286823f3c5SBlaise Bourdin #endif
429552f7358SJed Brown   } else {
430684b87d9SLisandro Dalcin     PetscBool isseq;
431684b87d9SLisandro Dalcin 
432684b87d9SLisandro Dalcin     ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr);
43355f2e967SMatthew G. Knepley     if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);}
43455f2e967SMatthew G. Knepley     else       {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);}
435552f7358SJed Brown   }
436552f7358SJed Brown   PetscFunctionReturn(0);
437552f7358SJed Brown }
438552f7358SJed Brown 
439d930f514SMatthew G. Knepley PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer)
440d930f514SMatthew G. Knepley {
441d930f514SMatthew G. Knepley   DM                dm;
442d930f514SMatthew G. Knepley   MPI_Comm          comm;
443d930f514SMatthew G. Knepley   PetscViewerFormat format;
444d930f514SMatthew G. Knepley   Vec               v;
445d930f514SMatthew G. Knepley   PetscBool         isvtk, ishdf5;
446d930f514SMatthew G. Knepley   PetscErrorCode    ierr;
447d930f514SMatthew G. Knepley 
448d930f514SMatthew G. Knepley   PetscFunctionBegin;
449d930f514SMatthew G. Knepley   ierr = VecGetDM(originalv, &dm);CHKERRQ(ierr);
450d930f514SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject) originalv, &comm);CHKERRQ(ierr);
4512c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!dm,comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
452d930f514SMatthew G. Knepley   ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr);
453d930f514SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr);
454d930f514SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK,  &isvtk);CHKERRQ(ierr);
455d930f514SMatthew G. Knepley   if (format == PETSC_VIEWER_NATIVE) {
456a8ad634aSStefano Zampini     /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */
457a8ad634aSStefano Zampini     /* this need a better fix */
458a8ad634aSStefano Zampini     if (dm->useNatural) {
459a8ad634aSStefano Zampini       if (dm->sfNatural) {
460d930f514SMatthew G. Knepley         const char *vecname;
461d930f514SMatthew G. Knepley         PetscInt    n, nroots;
462d930f514SMatthew G. Knepley 
463ca43db0aSBarry Smith         ierr = VecGetLocalSize(originalv, &n);CHKERRQ(ierr);
464d930f514SMatthew G. Knepley         ierr = PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL);CHKERRQ(ierr);
465d930f514SMatthew G. Knepley         if (n == nroots) {
466d930f514SMatthew G. Knepley           ierr = DMGetGlobalVector(dm, &v);CHKERRQ(ierr);
467d930f514SMatthew G. Knepley           ierr = DMPlexGlobalToNaturalBegin(dm, originalv, v);CHKERRQ(ierr);
468d930f514SMatthew G. Knepley           ierr = DMPlexGlobalToNaturalEnd(dm, originalv, v);CHKERRQ(ierr);
469d930f514SMatthew G. Knepley           ierr = PetscObjectGetName((PetscObject) originalv, &vecname);CHKERRQ(ierr);
470d930f514SMatthew G. Knepley           ierr = PetscObjectSetName((PetscObject) v, vecname);CHKERRQ(ierr);
471d930f514SMatthew G. Knepley         } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors");
472d930f514SMatthew G. Knepley       } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created");
473a8ad634aSStefano Zampini     } else v = originalv;
474a8ad634aSStefano Zampini   } else v = originalv;
475a8ad634aSStefano Zampini 
476d930f514SMatthew G. Knepley   if (ishdf5) {
477d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
47839d25373SMatthew G. Knepley     ierr = VecView_Plex_HDF5_Native_Internal(v, viewer);CHKERRQ(ierr);
479d930f514SMatthew G. Knepley #else
480d930f514SMatthew G. Knepley     SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
481d930f514SMatthew G. Knepley #endif
482d930f514SMatthew G. Knepley   } else if (isvtk) {
483d930f514SMatthew G. Knepley     SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5.");
484d930f514SMatthew G. Knepley   } else {
485d930f514SMatthew G. Knepley     PetscBool isseq;
486d930f514SMatthew G. Knepley 
487d930f514SMatthew G. Knepley     ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr);
488d930f514SMatthew G. Knepley     if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);}
489d930f514SMatthew G. Knepley     else       {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);}
490d930f514SMatthew G. Knepley   }
491a8ad634aSStefano Zampini   if (v != originalv) {ierr = DMRestoreGlobalVector(dm, &v);CHKERRQ(ierr);}
492d930f514SMatthew G. Knepley   PetscFunctionReturn(0);
493d930f514SMatthew G. Knepley }
494d930f514SMatthew G. Knepley 
4952c40f234SMatthew G. Knepley PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer)
4962c40f234SMatthew G. Knepley {
4972c40f234SMatthew G. Knepley   DM             dm;
4982c40f234SMatthew G. Knepley   PetscBool      ishdf5;
4992c40f234SMatthew G. Knepley   PetscErrorCode ierr;
5002c40f234SMatthew G. Knepley 
5012c40f234SMatthew G. Knepley   PetscFunctionBegin;
5022c40f234SMatthew G. Knepley   ierr = VecGetDM(v, &dm);CHKERRQ(ierr);
5032c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
5042c40f234SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr);
5052c40f234SMatthew G. Knepley   if (ishdf5) {
5062c40f234SMatthew G. Knepley     DM          dmBC;
5072c40f234SMatthew G. Knepley     Vec         gv;
5082c40f234SMatthew G. Knepley     const char *name;
5092c40f234SMatthew G. Knepley 
5102c40f234SMatthew G. Knepley     ierr = DMGetOutputDM(dm, &dmBC);CHKERRQ(ierr);
5112c40f234SMatthew G. Knepley     ierr = DMGetGlobalVector(dmBC, &gv);CHKERRQ(ierr);
5122c40f234SMatthew G. Knepley     ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr);
5132c40f234SMatthew G. Knepley     ierr = PetscObjectSetName((PetscObject) gv, name);CHKERRQ(ierr);
5142c40f234SMatthew G. Knepley     ierr = VecLoad_Default(gv, viewer);CHKERRQ(ierr);
5152c40f234SMatthew G. Knepley     ierr = DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v);CHKERRQ(ierr);
5162c40f234SMatthew G. Knepley     ierr = DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v);CHKERRQ(ierr);
5172c40f234SMatthew G. Knepley     ierr = DMRestoreGlobalVector(dmBC, &gv);CHKERRQ(ierr);
5182c40f234SMatthew G. Knepley   } else {
5192c40f234SMatthew G. Knepley     ierr = VecLoad_Default(v, viewer);CHKERRQ(ierr);
5202c40f234SMatthew G. Knepley   }
5212c40f234SMatthew G. Knepley   PetscFunctionReturn(0);
5222c40f234SMatthew G. Knepley }
5232c40f234SMatthew G. Knepley 
5242c40f234SMatthew G. Knepley PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer)
5252c40f234SMatthew G. Knepley {
5262c40f234SMatthew G. Knepley   DM             dm;
5276823f3c5SBlaise Bourdin   PetscBool      ishdf5,isexodusii;
5282c40f234SMatthew G. Knepley   PetscErrorCode ierr;
5292c40f234SMatthew G. Knepley 
5302c40f234SMatthew G. Knepley   PetscFunctionBegin;
5312c40f234SMatthew G. Knepley   ierr = VecGetDM(v, &dm);CHKERRQ(ierr);
5322c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
5332c40f234SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,     &ishdf5);CHKERRQ(ierr);
5346823f3c5SBlaise Bourdin   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii);CHKERRQ(ierr);
5352c40f234SMatthew G. Knepley   if (ishdf5) {
536878b459fSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
53739d25373SMatthew G. Knepley     ierr = VecLoad_Plex_HDF5_Internal(v, viewer);CHKERRQ(ierr);
538b136c2c9SMatthew G. Knepley #else
539b136c2c9SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
540878b459fSMatthew G. Knepley #endif
5416823f3c5SBlaise Bourdin   } else if (isexodusii) {
5426823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII)
5436823f3c5SBlaise Bourdin     ierr = VecLoad_PlexExodusII_Internal(v, viewer);CHKERRQ(ierr);
5446823f3c5SBlaise Bourdin #else
5456823f3c5SBlaise Bourdin     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii");
5466823f3c5SBlaise Bourdin #endif
5472c40f234SMatthew G. Knepley   } else {
5482c40f234SMatthew G. Knepley     ierr = VecLoad_Default(v, viewer);CHKERRQ(ierr);
549552f7358SJed Brown   }
550552f7358SJed Brown   PetscFunctionReturn(0);
551552f7358SJed Brown }
552552f7358SJed Brown 
553d930f514SMatthew G. Knepley PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer)
554d930f514SMatthew G. Knepley {
555d930f514SMatthew G. Knepley   DM                dm;
556d930f514SMatthew G. Knepley   PetscViewerFormat format;
557d930f514SMatthew G. Knepley   PetscBool         ishdf5;
558d930f514SMatthew G. Knepley   PetscErrorCode    ierr;
559d930f514SMatthew G. Knepley 
560d930f514SMatthew G. Knepley   PetscFunctionBegin;
561d930f514SMatthew G. Knepley   ierr = VecGetDM(originalv, &dm);CHKERRQ(ierr);
5622c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!dm,PetscObjectComm((PetscObject) originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
563d930f514SMatthew G. Knepley   ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr);
564d930f514SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr);
565d930f514SMatthew G. Knepley   if (format == PETSC_VIEWER_NATIVE) {
566a8ad634aSStefano Zampini     if (dm->useNatural) {
567d930f514SMatthew G. Knepley       if (dm->sfNatural) {
568d930f514SMatthew G. Knepley         if (ishdf5) {
569d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
570d930f514SMatthew G. Knepley           Vec         v;
571d930f514SMatthew G. Knepley           const char *vecname;
572d930f514SMatthew G. Knepley 
573d930f514SMatthew G. Knepley           ierr = DMGetGlobalVector(dm, &v);CHKERRQ(ierr);
574d930f514SMatthew G. Knepley           ierr = PetscObjectGetName((PetscObject) originalv, &vecname);CHKERRQ(ierr);
575d930f514SMatthew G. Knepley           ierr = PetscObjectSetName((PetscObject) v, vecname);CHKERRQ(ierr);
57639d25373SMatthew G. Knepley           ierr = VecLoad_Plex_HDF5_Native_Internal(v, viewer);CHKERRQ(ierr);
577d930f514SMatthew G. Knepley           ierr = DMPlexNaturalToGlobalBegin(dm, v, originalv);CHKERRQ(ierr);
578d930f514SMatthew G. Knepley           ierr = DMPlexNaturalToGlobalEnd(dm, v, originalv);CHKERRQ(ierr);
579d930f514SMatthew G. Knepley           ierr = DMRestoreGlobalVector(dm, &v);CHKERRQ(ierr);
580d930f514SMatthew G. Knepley #else
581d930f514SMatthew G. Knepley           SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
582d930f514SMatthew G. Knepley #endif
583d930f514SMatthew G. Knepley         } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5.");
584d930f514SMatthew G. Knepley       }
585a8ad634aSStefano Zampini     } else {
586a8ad634aSStefano Zampini       ierr = VecLoad_Default(originalv, viewer);CHKERRQ(ierr);
587a8ad634aSStefano Zampini     }
588d930f514SMatthew G. Knepley   }
589d930f514SMatthew G. Knepley   PetscFunctionReturn(0);
590d930f514SMatthew G. Knepley }
591d930f514SMatthew G. Knepley 
5927cd05799SMatthew G. Knepley PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer)
593731e8ddeSMatthew G. Knepley {
594731e8ddeSMatthew G. Knepley   PetscSection       coordSection;
595731e8ddeSMatthew G. Knepley   Vec                coordinates;
596ba2698f1SMatthew G. Knepley   DMLabel            depthLabel, celltypeLabel;
597731e8ddeSMatthew G. Knepley   const char        *name[4];
598731e8ddeSMatthew G. Knepley   const PetscScalar *a;
599731e8ddeSMatthew G. Knepley   PetscInt           dim, pStart, pEnd, cStart, cEnd, c;
600731e8ddeSMatthew G. Knepley   PetscErrorCode     ierr;
601731e8ddeSMatthew G. Knepley 
602731e8ddeSMatthew G. Knepley   PetscFunctionBegin;
603731e8ddeSMatthew G. Knepley   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
604731e8ddeSMatthew G. Knepley   ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
605731e8ddeSMatthew G. Knepley   ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr);
606731e8ddeSMatthew G. Knepley   ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr);
607ba2698f1SMatthew G. Knepley   ierr = DMPlexGetCellTypeLabel(dm, &celltypeLabel);CHKERRQ(ierr);
608731e8ddeSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
609731e8ddeSMatthew G. Knepley   ierr = PetscSectionGetChart(coordSection, &pStart, &pEnd);CHKERRQ(ierr);
610731e8ddeSMatthew G. Knepley   ierr = VecGetArrayRead(coordinates, &a);CHKERRQ(ierr);
611731e8ddeSMatthew G. Knepley   name[0]     = "vertex";
612731e8ddeSMatthew G. Knepley   name[1]     = "edge";
613731e8ddeSMatthew G. Knepley   name[dim-1] = "face";
614731e8ddeSMatthew G. Knepley   name[dim]   = "cell";
615731e8ddeSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
616731e8ddeSMatthew G. Knepley     PetscInt *closure = NULL;
617ba2698f1SMatthew G. Knepley     PetscInt  closureSize, cl, ct;
618731e8ddeSMatthew G. Knepley 
619ba2698f1SMatthew G. Knepley     ierr = DMLabelGetValue(celltypeLabel, c, &ct);CHKERRQ(ierr);
620ba2698f1SMatthew G. Knepley     ierr = PetscViewerASCIIPrintf(viewer, "Geometry for cell %D polytope type %s:\n", c, DMPolytopeTypes[ct]);CHKERRQ(ierr);
621731e8ddeSMatthew G. Knepley     ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
622731e8ddeSMatthew G. Knepley     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
623731e8ddeSMatthew G. Knepley     for (cl = 0; cl < closureSize*2; cl += 2) {
624731e8ddeSMatthew G. Knepley       PetscInt point = closure[cl], depth, dof, off, d, p;
625731e8ddeSMatthew G. Knepley 
626731e8ddeSMatthew G. Knepley       if ((point < pStart) || (point >= pEnd)) continue;
627731e8ddeSMatthew G. Knepley       ierr = PetscSectionGetDof(coordSection, point, &dof);CHKERRQ(ierr);
628731e8ddeSMatthew G. Knepley       if (!dof) continue;
629731e8ddeSMatthew G. Knepley       ierr = DMLabelGetValue(depthLabel, point, &depth);CHKERRQ(ierr);
630731e8ddeSMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSection, point, &off);CHKERRQ(ierr);
631f347f43bSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer, "%s %D coords:", name[depth], point);CHKERRQ(ierr);
632731e8ddeSMatthew G. Knepley       for (p = 0; p < dof/dim; ++p) {
633731e8ddeSMatthew G. Knepley         ierr = PetscViewerASCIIPrintf(viewer, " (");CHKERRQ(ierr);
634731e8ddeSMatthew G. Knepley         for (d = 0; d < dim; ++d) {
635731e8ddeSMatthew G. Knepley           if (d > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);}
636087ef6b2SMatthew G. Knepley           ierr = PetscViewerASCIIPrintf(viewer, "%g", (double) PetscRealPart(a[off+p*dim+d]));CHKERRQ(ierr);
637731e8ddeSMatthew G. Knepley         }
638731e8ddeSMatthew G. Knepley         ierr = PetscViewerASCIIPrintf(viewer, ")");CHKERRQ(ierr);
639731e8ddeSMatthew G. Knepley       }
640731e8ddeSMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr);
641731e8ddeSMatthew G. Knepley     }
642731e8ddeSMatthew G. Knepley     ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
643731e8ddeSMatthew G. Knepley     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
644731e8ddeSMatthew G. Knepley   }
645731e8ddeSMatthew G. Knepley   ierr = VecRestoreArrayRead(coordinates, &a);CHKERRQ(ierr);
646731e8ddeSMatthew G. Knepley   PetscFunctionReturn(0);
647731e8ddeSMatthew G. Knepley }
648731e8ddeSMatthew G. Knepley 
64919ad8254SMatthew G. Knepley typedef enum {CS_CARTESIAN, CS_POLAR, CS_CYLINDRICAL, CS_SPHERICAL} CoordSystem;
65019ad8254SMatthew G. Knepley const char *CoordSystems[] = {"cartesian", "polar", "cylindrical", "spherical", "CoordSystem", "CS_", NULL};
65119ad8254SMatthew G. Knepley 
65219ad8254SMatthew G. Knepley static PetscErrorCode DMPlexView_Ascii_Coordinates(PetscViewer viewer, CoordSystem cs, PetscInt dim, const PetscScalar x[])
65319ad8254SMatthew G. Knepley {
65419ad8254SMatthew G. Knepley   PetscInt       i;
65519ad8254SMatthew G. Knepley   PetscErrorCode ierr;
65619ad8254SMatthew G. Knepley 
65719ad8254SMatthew G. Knepley   PetscFunctionBegin;
65819ad8254SMatthew G. Knepley   if (dim > 3) {
65919ad8254SMatthew G. Knepley     for (i = 0; i < dim; ++i) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double) PetscRealPart(x[i]));CHKERRQ(ierr);}
66019ad8254SMatthew G. Knepley   } else {
66119ad8254SMatthew G. Knepley     PetscReal coords[3], trcoords[3];
66219ad8254SMatthew G. Knepley 
66319ad8254SMatthew G. Knepley     for (i = 0; i < dim; ++i) coords[i] = PetscRealPart(x[i]);
66419ad8254SMatthew G. Knepley     switch (cs) {
66519ad8254SMatthew G. Knepley       case CS_CARTESIAN: for (i = 0; i < dim; ++i) trcoords[i] = coords[i];break;
66619ad8254SMatthew G. Knepley       case CS_POLAR:
6672c71b3e2SJacob Faibussowitsch         PetscCheckFalse(dim != 2,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Polar coordinates are for 2 dimension, not %D", dim);
66819ad8254SMatthew G. Knepley         trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]));
66919ad8254SMatthew G. Knepley         trcoords[1] = PetscAtan2Real(coords[1], coords[0]);
67019ad8254SMatthew G. Knepley         break;
67119ad8254SMatthew G. Knepley       case CS_CYLINDRICAL:
6722c71b3e2SJacob Faibussowitsch         PetscCheckFalse(dim != 3,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cylindrical coordinates are for 3 dimension, not %D", dim);
67319ad8254SMatthew G. Knepley         trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]));
67419ad8254SMatthew G. Knepley         trcoords[1] = PetscAtan2Real(coords[1], coords[0]);
67519ad8254SMatthew G. Knepley         trcoords[2] = coords[2];
67619ad8254SMatthew G. Knepley         break;
67719ad8254SMatthew G. Knepley       case CS_SPHERICAL:
6782c71b3e2SJacob Faibussowitsch         PetscCheckFalse(dim != 3,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Spherical coordinates are for 3 dimension, not %D", dim);
67919ad8254SMatthew G. Knepley         trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]) + PetscSqr(coords[2]));
68019ad8254SMatthew G. Knepley         trcoords[1] = PetscAtan2Real(PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])), coords[2]);
68119ad8254SMatthew G. Knepley         trcoords[2] = PetscAtan2Real(coords[1], coords[0]);
68219ad8254SMatthew G. Knepley         break;
68319ad8254SMatthew G. Knepley     }
68419ad8254SMatthew G. Knepley     for (i = 0; i < dim; ++i) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double) trcoords[i]);CHKERRQ(ierr);}
68519ad8254SMatthew G. Knepley   }
68619ad8254SMatthew G. Knepley   PetscFunctionReturn(0);
68719ad8254SMatthew G. Knepley }
68819ad8254SMatthew G. Knepley 
6897cd05799SMatthew G. Knepley static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer)
690552f7358SJed Brown {
691552f7358SJed Brown   DM_Plex          *mesh = (DM_Plex*) dm->data;
692552f7358SJed Brown   DM                cdm;
693552f7358SJed Brown   PetscSection      coordSection;
694552f7358SJed Brown   Vec               coordinates;
695552f7358SJed Brown   PetscViewerFormat format;
696552f7358SJed Brown   PetscErrorCode    ierr;
697552f7358SJed Brown 
698552f7358SJed Brown   PetscFunctionBegin;
699552f7358SJed Brown   ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
70092fd8e1eSJed Brown   ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr);
701552f7358SJed Brown   ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
702552f7358SJed Brown   ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr);
703552f7358SJed Brown   if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
704552f7358SJed Brown     const char *name;
705f73eea6eSMatthew G. Knepley     PetscInt    dim, cellHeight, maxConeSize, maxSupportSize;
7069318fe57SMatthew G. Knepley     PetscInt    pStart, pEnd, p, numLabels, l;
707552f7358SJed Brown     PetscMPIInt rank, size;
708552f7358SJed Brown 
709ffc4695bSBarry Smith     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRMPI(ierr);
710ffc4695bSBarry Smith     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRMPI(ierr);
711552f7358SJed Brown     ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr);
712552f7358SJed Brown     ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
713552f7358SJed Brown     ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr);
714f73eea6eSMatthew G. Knepley     ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
715f73eea6eSMatthew G. Knepley     ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr);
716f73eea6eSMatthew G. Knepley     if (name) {ierr = PetscViewerASCIIPrintf(viewer, "%s in %D dimension%s:\n", name, dim, dim == 1 ? "" : "s");CHKERRQ(ierr);}
717f73eea6eSMatthew G. Knepley     else      {ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimension%s:\n", dim, dim == 1 ? "" : "s");CHKERRQ(ierr);}
718f73eea6eSMatthew G. Knepley     if (cellHeight) {ierr = PetscViewerASCIIPrintf(viewer, "  Cells are at height %D\n", cellHeight);CHKERRQ(ierr);}
719e9cb465cSMatthew G. Knepley     ierr = PetscViewerASCIIPrintf(viewer, "Supports:\n", name);CHKERRQ(ierr);
7204d4c343aSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr);
721e9cb465cSMatthew G. Knepley     ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %D\n", rank, maxSupportSize);CHKERRQ(ierr);
722552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
723552f7358SJed Brown       PetscInt dof, off, s;
724552f7358SJed Brown 
725552f7358SJed Brown       ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr);
726552f7358SJed Brown       ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr);
727552f7358SJed Brown       for (s = off; s < off+dof; ++s) {
728e4b003c7SBarry Smith         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr);
729552f7358SJed Brown       }
730552f7358SJed Brown     }
731552f7358SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
732e9cb465cSMatthew G. Knepley     ierr = PetscViewerASCIIPrintf(viewer, "Cones:\n", name);CHKERRQ(ierr);
733e9cb465cSMatthew G. Knepley     ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %D\n", rank, maxConeSize);CHKERRQ(ierr);
734552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
735552f7358SJed Brown       PetscInt dof, off, c;
736552f7358SJed Brown 
737552f7358SJed Brown       ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr);
738552f7358SJed Brown       ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr);
739552f7358SJed Brown       for (c = off; c < off+dof; ++c) {
740e4b003c7SBarry Smith         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr);
741552f7358SJed Brown       }
742552f7358SJed Brown     }
743552f7358SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
7444d4c343aSBarry Smith     ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr);
7453d2e540fSStefano Zampini     if (coordSection && coordinates) {
74619ad8254SMatthew G. Knepley       CoordSystem        cs = CS_CARTESIAN;
74719ad8254SMatthew G. Knepley       const PetscScalar *array;
74819ad8254SMatthew G. Knepley       PetscInt           Nf, Nc, pStart, pEnd, p;
74919ad8254SMatthew G. Knepley       PetscMPIInt        rank;
75019ad8254SMatthew G. Knepley       const char        *name;
75119ad8254SMatthew G. Knepley 
75219ad8254SMatthew G. Knepley       ierr = PetscOptionsGetEnum(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_coord_system", CoordSystems, (PetscEnum *) &cs, NULL);CHKERRQ(ierr);
75319ad8254SMatthew G. Knepley       ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);CHKERRMPI(ierr);
75419ad8254SMatthew G. Knepley       ierr = PetscSectionGetNumFields(coordSection, &Nf);CHKERRQ(ierr);
7552c71b3e2SJacob Faibussowitsch       PetscCheckFalse(Nf != 1,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate section should have 1 field, not %D", Nf);
75619ad8254SMatthew G. Knepley       ierr = PetscSectionGetFieldComponents(coordSection, 0, &Nc);CHKERRQ(ierr);
75719ad8254SMatthew G. Knepley       ierr = PetscSectionGetChart(coordSection, &pStart, &pEnd);CHKERRQ(ierr);
75819ad8254SMatthew G. Knepley       ierr = PetscObjectGetName((PetscObject) coordinates, &name);CHKERRQ(ierr);
75919ad8254SMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "%s with %D fields\n", name, Nf);CHKERRQ(ierr);
760d410b0cfSMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "  field 0 with %D components\n", Nc);CHKERRQ(ierr);
76119ad8254SMatthew G. Knepley       if (cs != CS_CARTESIAN) {ierr = PetscViewerASCIIPrintf(viewer, "  output coordinate system: %s\n", CoordSystems[cs]);CHKERRQ(ierr);}
76219ad8254SMatthew G. Knepley 
76319ad8254SMatthew G. Knepley       ierr = VecGetArrayRead(coordinates, &array);CHKERRQ(ierr);
76419ad8254SMatthew G. Knepley       ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr);
76519ad8254SMatthew G. Knepley       ierr = PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank);CHKERRQ(ierr);
76619ad8254SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
76719ad8254SMatthew G. Knepley         PetscInt dof, off;
76819ad8254SMatthew G. Knepley 
76919ad8254SMatthew G. Knepley         ierr = PetscSectionGetDof(coordSection, p, &dof);CHKERRQ(ierr);
77019ad8254SMatthew G. Knepley         ierr = PetscSectionGetOffset(coordSection, p, &off);CHKERRQ(ierr);
77119ad8254SMatthew G. Knepley         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "  (%4D) dim %2D offset %3D", p, dof, off);CHKERRQ(ierr);
77219ad8254SMatthew G. Knepley         ierr = DMPlexView_Ascii_Coordinates(viewer, cs, dof, &array[off]);CHKERRQ(ierr);
77319ad8254SMatthew G. Knepley         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\n");CHKERRQ(ierr);
77419ad8254SMatthew G. Knepley       }
77519ad8254SMatthew G. Knepley       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
77619ad8254SMatthew G. Knepley       ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr);
77719ad8254SMatthew G. Knepley       ierr = VecRestoreArrayRead(coordinates, &array);CHKERRQ(ierr);
7783d2e540fSStefano Zampini     }
7799318fe57SMatthew G. Knepley     ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr);
7809318fe57SMatthew G. Knepley     if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Labels:\n");CHKERRQ(ierr);}
7819318fe57SMatthew G. Knepley     for (l = 0; l < numLabels; ++l) {
7829318fe57SMatthew G. Knepley       DMLabel     label;
7839318fe57SMatthew G. Knepley       PetscBool   isdepth;
7849318fe57SMatthew G. Knepley       const char *name;
7859318fe57SMatthew G. Knepley 
7869318fe57SMatthew G. Knepley       ierr = DMGetLabelName(dm, l, &name);CHKERRQ(ierr);
7879318fe57SMatthew G. Knepley       ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr);
7889318fe57SMatthew G. Knepley       if (isdepth) continue;
7899318fe57SMatthew G. Knepley       ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr);
7909318fe57SMatthew G. Knepley       ierr = DMLabelView(label, viewer);CHKERRQ(ierr);
7919318fe57SMatthew G. Knepley     }
792552f7358SJed Brown     if (size > 1) {
793552f7358SJed Brown       PetscSF sf;
794552f7358SJed Brown 
795552f7358SJed Brown       ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr);
796552f7358SJed Brown       ierr = PetscSFView(sf, viewer);CHKERRQ(ierr);
797552f7358SJed Brown     }
798552f7358SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
799552f7358SJed Brown   } else if (format == PETSC_VIEWER_ASCII_LATEX) {
8000588280cSMatthew G. Knepley     const char  *name, *color;
8010588280cSMatthew G. Knepley     const char  *defcolors[3]  = {"gray", "orange", "green"};
8020588280cSMatthew G. Knepley     const char  *deflcolors[4] = {"blue", "cyan", "red", "magenta"};
803fe1cc32dSStefano Zampini     char         lname[PETSC_MAX_PATH_LEN];
804552f7358SJed Brown     PetscReal    scale         = 2.0;
80578081901SStefano Zampini     PetscReal    tikzscale     = 1.0;
806b7f6ffafSMatthew G. Knepley     PetscBool    useNumbers    = PETSC_TRUE, drawNumbers[4], drawColors[4], useLabels, useColors, plotEdges, drawHasse = PETSC_FALSE;
8070588280cSMatthew G. Knepley     double       tcoords[3];
808552f7358SJed Brown     PetscScalar *coords;
809b7f6ffafSMatthew G. Knepley     PetscInt     numLabels, l, numColors, numLColors, dim, d, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p, n;
810552f7358SJed Brown     PetscMPIInt  rank, size;
8110588280cSMatthew G. Knepley     char         **names, **colors, **lcolors;
812b7f6ffafSMatthew G. Knepley     PetscBool    flg, lflg;
813fe1cc32dSStefano Zampini     PetscBT      wp = NULL;
814fe1cc32dSStefano Zampini     PetscInt     pEnd, pStart;
815552f7358SJed Brown 
8160588280cSMatthew G. Knepley     ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
817552f7358SJed Brown     ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
818c58f1c22SToby Isaac     ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr);
8190588280cSMatthew G. Knepley     numLabels  = PetscMax(numLabels, 10);
8200588280cSMatthew G. Knepley     numColors  = 10;
8210588280cSMatthew G. Knepley     numLColors = 10;
8220588280cSMatthew G. Knepley     ierr = PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors);CHKERRQ(ierr);
823c5929fdfSBarry Smith     ierr = PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_scale", &scale, NULL);CHKERRQ(ierr);
82478081901SStefano Zampini     ierr = PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL);CHKERRQ(ierr);
825c5929fdfSBarry Smith     ierr = PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL);CHKERRQ(ierr);
826b7f6ffafSMatthew G. Knepley     for (d = 0; d < 4; ++d) drawNumbers[d] = useNumbers;
827b7f6ffafSMatthew G. Knepley     for (d = 0; d < 4; ++d) drawColors[d]  = PETSC_TRUE;
828b7f6ffafSMatthew G. Knepley     n = 4;
829b7f6ffafSMatthew G. Knepley     ierr = PetscOptionsGetBoolArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers_depth", drawNumbers, &n, &flg);CHKERRQ(ierr);
8302c71b3e2SJacob Faibussowitsch     PetscCheckFalse(flg && n != dim+1,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %D != %D dim+1", n, dim+1);
831b7f6ffafSMatthew G. Knepley     ierr = PetscOptionsGetBoolArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors_depth", drawColors, &n, &flg);CHKERRQ(ierr);
8322c71b3e2SJacob Faibussowitsch     PetscCheckFalse(flg && n != dim+1,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %D != %D dim+1", n, dim+1);
833c5929fdfSBarry Smith     ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels);CHKERRQ(ierr);
8340588280cSMatthew G. Knepley     if (!useLabels) numLabels = 0;
835c5929fdfSBarry Smith     ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors);CHKERRQ(ierr);
8360588280cSMatthew G. Knepley     if (!useColors) {
8370588280cSMatthew G. Knepley       numColors = 3;
8380588280cSMatthew G. Knepley       for (c = 0; c < numColors; ++c) {ierr = PetscStrallocpy(defcolors[c], &colors[c]);CHKERRQ(ierr);}
8390588280cSMatthew G. Knepley     }
840c5929fdfSBarry Smith     ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors);CHKERRQ(ierr);
8410588280cSMatthew G. Knepley     if (!useColors) {
8420588280cSMatthew G. Knepley       numLColors = 4;
8430588280cSMatthew G. Knepley       for (c = 0; c < numLColors; ++c) {ierr = PetscStrallocpy(deflcolors[c], &lcolors[c]);CHKERRQ(ierr);}
8440588280cSMatthew G. Knepley     }
845589a23caSBarry Smith     ierr = PetscOptionsGetString(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg);CHKERRQ(ierr);
846b7f6ffafSMatthew G. Knepley     plotEdges = (PetscBool)(depth > 1 && drawNumbers[1] && dim < 3);
847202fd40aSStefano Zampini     ierr = PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg);CHKERRQ(ierr);
8482c71b3e2SJacob Faibussowitsch     PetscCheckFalse(flg && plotEdges && depth < dim,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Mesh must be interpolated");
849202fd40aSStefano Zampini     if (depth < dim) plotEdges = PETSC_FALSE;
850b7f6ffafSMatthew G. Knepley     ierr = PetscOptionsGetBool(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_hasse", &drawHasse, NULL);CHKERRQ(ierr);
851fe1cc32dSStefano Zampini 
852fe1cc32dSStefano Zampini     /* filter points with labelvalue != labeldefaultvalue */
853fe1cc32dSStefano Zampini     ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
854b7f6ffafSMatthew G. Knepley     ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
855b7f6ffafSMatthew G. Knepley     ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
856b7f6ffafSMatthew G. Knepley     ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
857fe1cc32dSStefano Zampini     if (lflg) {
858fe1cc32dSStefano Zampini       DMLabel lbl;
859fe1cc32dSStefano Zampini 
860fe1cc32dSStefano Zampini       ierr = DMGetLabel(dm, lname, &lbl);CHKERRQ(ierr);
861fe1cc32dSStefano Zampini       if (lbl) {
862fe1cc32dSStefano Zampini         PetscInt val, defval;
863fe1cc32dSStefano Zampini 
864fe1cc32dSStefano Zampini         ierr = DMLabelGetDefaultValue(lbl, &defval);CHKERRQ(ierr);
865fe1cc32dSStefano Zampini         ierr = PetscBTCreate(pEnd-pStart, &wp);CHKERRQ(ierr);
866fe1cc32dSStefano Zampini         for (c = pStart;  c < pEnd; c++) {
867fe1cc32dSStefano Zampini           PetscInt *closure = NULL;
868fe1cc32dSStefano Zampini           PetscInt  closureSize;
869fe1cc32dSStefano Zampini 
870fe1cc32dSStefano Zampini           ierr = DMLabelGetValue(lbl, c, &val);CHKERRQ(ierr);
871fe1cc32dSStefano Zampini           if (val == defval) continue;
872fe1cc32dSStefano Zampini 
873fe1cc32dSStefano Zampini           ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
874fe1cc32dSStefano Zampini           for (p = 0; p < closureSize*2; p += 2) {
875fe1cc32dSStefano Zampini             ierr = PetscBTSet(wp, closure[p] - pStart);CHKERRQ(ierr);
876fe1cc32dSStefano Zampini           }
877fe1cc32dSStefano Zampini           ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
878fe1cc32dSStefano Zampini         }
879fe1cc32dSStefano Zampini       }
880fe1cc32dSStefano Zampini     }
881fe1cc32dSStefano Zampini 
882ffc4695bSBarry Smith     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRMPI(ierr);
883ffc4695bSBarry Smith     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRMPI(ierr);
884552f7358SJed Brown     ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr);
885770b213bSMatthew G Knepley     ierr = PetscViewerASCIIPrintf(viewer, "\
8860588280cSMatthew G. Knepley \\documentclass[tikz]{standalone}\n\n\
887552f7358SJed Brown \\usepackage{pgflibraryshapes}\n\
888552f7358SJed Brown \\usetikzlibrary{backgrounds}\n\
889552f7358SJed Brown \\usetikzlibrary{arrows}\n\
8900588280cSMatthew G. Knepley \\begin{document}\n");CHKERRQ(ierr);
8910588280cSMatthew G. Knepley     if (size > 1) {
892f738dd31SMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "%s for process ", name);CHKERRQ(ierr);
893770b213bSMatthew G Knepley       for (p = 0; p < size; ++p) {
894770b213bSMatthew G Knepley         if (p > 0 && p == size-1) {
895770b213bSMatthew G Knepley           ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr);
896770b213bSMatthew G Knepley         } else if (p > 0) {
897770b213bSMatthew G Knepley           ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr);
898770b213bSMatthew G Knepley         }
899770b213bSMatthew G Knepley         ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr);
900770b213bSMatthew G Knepley       }
9010588280cSMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, ".\n\n\n");CHKERRQ(ierr);
9020588280cSMatthew G. Knepley     }
903b7f6ffafSMatthew G. Knepley     if (drawHasse) {
904b7f6ffafSMatthew G. Knepley       PetscInt maxStratum = PetscMax(vEnd-vStart, PetscMax(eEnd-eStart, cEnd-cStart));
905b7f6ffafSMatthew G. Knepley 
906b7f6ffafSMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vStart}{%D}\n", vStart);CHKERRQ(ierr);
907b7f6ffafSMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vEnd}{%D}\n", vEnd-1);CHKERRQ(ierr);
908b7f6ffafSMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numVertices}{%D}\n", vEnd-vStart);CHKERRQ(ierr);
909b7f6ffafSMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vShift}{%.2f}\n", 3 + (maxStratum-(vEnd-vStart))/2.);CHKERRQ(ierr);
910b7f6ffafSMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eStart}{%D}\n", eStart);CHKERRQ(ierr);
911b7f6ffafSMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eEnd}{%D}\n", eEnd-1);CHKERRQ(ierr);
912b7f6ffafSMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eShift}{%.2f}\n", 3 + (maxStratum-(eEnd-eStart))/2.);CHKERRQ(ierr);
913b7f6ffafSMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numEdges}{%D}\n", eEnd-eStart);CHKERRQ(ierr);
914b7f6ffafSMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cStart}{%D}\n", cStart);CHKERRQ(ierr);
915b7f6ffafSMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cEnd}{%D}\n", cEnd-1);CHKERRQ(ierr);
916b7f6ffafSMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numCells}{%D}\n", cEnd-cStart);CHKERRQ(ierr);
917b7f6ffafSMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cShift}{%.2f}\n", 3 + (maxStratum-(cEnd-cStart))/2.);CHKERRQ(ierr);
918b7f6ffafSMatthew G. Knepley     }
919087ef6b2SMatthew G. Knepley     ierr = PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double) tikzscale);CHKERRQ(ierr);
920fe1cc32dSStefano Zampini 
921552f7358SJed Brown     /* Plot vertices */
922552f7358SJed Brown     ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr);
9234d4c343aSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr);
924552f7358SJed Brown     for (v = vStart; v < vEnd; ++v) {
925552f7358SJed Brown       PetscInt  off, dof, d;
9260588280cSMatthew G. Knepley       PetscBool isLabeled = PETSC_FALSE;
927552f7358SJed Brown 
928fe1cc32dSStefano Zampini       if (wp && !PetscBTLookup(wp,v - pStart)) continue;
929552f7358SJed Brown       ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr);
930552f7358SJed Brown       ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr);
9310588280cSMatthew G. Knepley       ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\path (");CHKERRQ(ierr);
9322c71b3e2SJacob Faibussowitsch       PetscCheckFalse(dof > 3,PETSC_COMM_SELF,PETSC_ERR_PLIB,"coordSection vertex %D has dof %D > 3",v,dof);
9330588280cSMatthew G. Knepley       for (d = 0; d < dof; ++d) {
9340588280cSMatthew G. Knepley         tcoords[d] = (double) (scale*PetscRealPart(coords[off+d]));
935c068d9bbSLisandro Dalcin         tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
9360588280cSMatthew G. Knepley       }
9370588280cSMatthew G. Knepley       /* Rotate coordinates since PGF makes z point out of the page instead of up */
9380588280cSMatthew G. Knepley       if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;}
939552f7358SJed Brown       for (d = 0; d < dof; ++d) {
940552f7358SJed Brown         if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);}
941087ef6b2SMatthew G. Knepley         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) tcoords[d]);CHKERRQ(ierr);
942552f7358SJed Brown       }
943b7f6ffafSMatthew G. Knepley       if (drawHasse) color = colors[0%numColors];
944b7f6ffafSMatthew G. Knepley       else           color = colors[rank%numColors];
9450588280cSMatthew G. Knepley       for (l = 0; l < numLabels; ++l) {
9460588280cSMatthew G. Knepley         PetscInt val;
947c58f1c22SToby Isaac         ierr = DMGetLabelValue(dm, names[l], v, &val);CHKERRQ(ierr);
9480588280cSMatthew G. Knepley         if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;}
9490588280cSMatthew G. Knepley       }
950b7f6ffafSMatthew G. Knepley       if (drawNumbers[0]) {
951e4b003c7SBarry Smith         ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D};\n", v, rank, color, v);CHKERRQ(ierr);
952b7f6ffafSMatthew G. Knepley       } else if (drawColors[0]) {
953e4b003c7SBarry Smith         ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color);CHKERRQ(ierr);
954b7f6ffafSMatthew G. Knepley       } else {
955b7f6ffafSMatthew G. Knepley         ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [] {};\n", v, rank);CHKERRQ(ierr);
9560588280cSMatthew G. Knepley       }
957552f7358SJed Brown     }
958552f7358SJed Brown     ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr);
959552f7358SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
960b7f6ffafSMatthew G. Knepley     /* Plot edges */
961b7f6ffafSMatthew G. Knepley     if (plotEdges) {
962b7f6ffafSMatthew G. Knepley       ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr);
963b7f6ffafSMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr);
964b7f6ffafSMatthew G. Knepley       for (e = eStart; e < eEnd; ++e) {
965b7f6ffafSMatthew G. Knepley         const PetscInt *cone;
966b7f6ffafSMatthew G. Knepley         PetscInt        coneSize, offA, offB, dof, d;
967b7f6ffafSMatthew G. Knepley 
968b7f6ffafSMatthew G. Knepley         if (wp && !PetscBTLookup(wp,e - pStart)) continue;
969b7f6ffafSMatthew G. Knepley         ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr);
9702c71b3e2SJacob Faibussowitsch         PetscCheckFalse(coneSize != 2,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %D cone should have two vertices, not %D", e, coneSize);
971b7f6ffafSMatthew G. Knepley         ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr);
972b7f6ffafSMatthew G. Knepley         ierr = PetscSectionGetDof(coordSection, cone[0], &dof);CHKERRQ(ierr);
973b7f6ffafSMatthew G. Knepley         ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr);
974b7f6ffafSMatthew G. Knepley         ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr);
975b7f6ffafSMatthew G. Knepley         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr);
976b7f6ffafSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
977b7f6ffafSMatthew G. Knepley           tcoords[d] = (double) (0.5*scale*PetscRealPart(coords[offA+d]+coords[offB+d]));
978b7f6ffafSMatthew G. Knepley           tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
979b7f6ffafSMatthew G. Knepley         }
980b7f6ffafSMatthew G. Knepley         /* Rotate coordinates since PGF makes z point out of the page instead of up */
981b7f6ffafSMatthew G. Knepley         if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;}
982b7f6ffafSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
983b7f6ffafSMatthew G. Knepley           if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);}
984b7f6ffafSMatthew G. Knepley           ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d]);CHKERRQ(ierr);
985b7f6ffafSMatthew G. Knepley         }
986b7f6ffafSMatthew G. Knepley         if (drawHasse) color = colors[1%numColors];
987b7f6ffafSMatthew G. Knepley         else           color = colors[rank%numColors];
988b7f6ffafSMatthew G. Knepley         for (l = 0; l < numLabels; ++l) {
989b7f6ffafSMatthew G. Knepley           PetscInt val;
990b7f6ffafSMatthew G. Knepley           ierr = DMGetLabelValue(dm, names[l], v, &val);CHKERRQ(ierr);
991b7f6ffafSMatthew G. Knepley           if (val >= 0) {color = lcolors[l%numLColors]; break;}
992b7f6ffafSMatthew G. Knepley         }
993b7f6ffafSMatthew G. Knepley         ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D} --\n", e, rank, color, e);CHKERRQ(ierr);
994b7f6ffafSMatthew G. Knepley       }
995b7f6ffafSMatthew G. Knepley       ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr);
996b7f6ffafSMatthew G. Knepley       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
997b7f6ffafSMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr);
998b7f6ffafSMatthew G. Knepley     }
999846a3e8bSMatthew G. Knepley     /* Plot cells */
1000b7f6ffafSMatthew G. Knepley     if (dim == 3 || !drawNumbers[1]) {
1001846a3e8bSMatthew G. Knepley       for (e = eStart; e < eEnd; ++e) {
1002846a3e8bSMatthew G. Knepley         const PetscInt *cone;
1003846a3e8bSMatthew G. Knepley 
1004fe1cc32dSStefano Zampini         if (wp && !PetscBTLookup(wp,e - pStart)) continue;
1005846a3e8bSMatthew G. Knepley         color = colors[rank%numColors];
1006846a3e8bSMatthew G. Knepley         for (l = 0; l < numLabels; ++l) {
1007846a3e8bSMatthew G. Knepley           PetscInt val;
1008846a3e8bSMatthew G. Knepley           ierr = DMGetLabelValue(dm, names[l], e, &val);CHKERRQ(ierr);
1009846a3e8bSMatthew G. Knepley           if (val >= 0) {color = lcolors[l%numLColors]; break;}
1010846a3e8bSMatthew G. Knepley         }
1011846a3e8bSMatthew G. Knepley         ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr);
1012846a3e8bSMatthew G. Knepley         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%D_%d) -- (%D_%d);\n", color, cone[0], rank, cone[1], rank);CHKERRQ(ierr);
1013846a3e8bSMatthew G. Knepley       }
1014846a3e8bSMatthew G. Knepley     } else {
1015b7f6ffafSMatthew G. Knepley        DMPolytopeType ct;
1016846a3e8bSMatthew G. Knepley 
1017b7f6ffafSMatthew G. Knepley       /* Drawing a 2D polygon */
1018b7f6ffafSMatthew G. Knepley       for (c = cStart; c < cEnd; ++c) {
1019fe1cc32dSStefano Zampini         if (wp && !PetscBTLookup(wp, c - pStart)) continue;
1020b7f6ffafSMatthew G. Knepley         ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr);
1021b7f6ffafSMatthew G. Knepley         if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR ||
1022b7f6ffafSMatthew G. Knepley             ct == DM_POLYTOPE_TRI_PRISM_TENSOR ||
1023b7f6ffafSMatthew G. Knepley             ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) {
1024b7f6ffafSMatthew G. Knepley           const PetscInt *cone;
1025b7f6ffafSMatthew G. Knepley           PetscInt        coneSize, e;
1026b7f6ffafSMatthew G. Knepley 
1027b7f6ffafSMatthew G. Knepley           ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
1028b7f6ffafSMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr);
1029b7f6ffafSMatthew G. Knepley           for (e = 0; e < coneSize; ++e) {
1030b7f6ffafSMatthew G. Knepley             const PetscInt *econe;
1031b7f6ffafSMatthew G. Knepley 
1032b7f6ffafSMatthew G. Knepley             ierr = DMPlexGetCone(dm, cone[e], &econe);CHKERRQ(ierr);
1033b7f6ffafSMatthew G. Knepley             ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%D_%d) -- (%D_%d) -- (%D_%d);\n", colors[rank%numColors], econe[0], rank, cone[e], rank, econe[1], rank);CHKERRQ(ierr);
1034b7f6ffafSMatthew G. Knepley           }
1035b7f6ffafSMatthew G. Knepley         } else {
1036b7f6ffafSMatthew G. Knepley           PetscInt *closure = NULL;
1037b7f6ffafSMatthew G. Knepley           PetscInt  closureSize, Nv = 0, v;
1038b7f6ffafSMatthew G. Knepley 
1039846a3e8bSMatthew G. Knepley           ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
1040846a3e8bSMatthew G. Knepley           for (p = 0; p < closureSize*2; p += 2) {
1041846a3e8bSMatthew G. Knepley             const PetscInt point = closure[p];
1042846a3e8bSMatthew G. Knepley 
1043b7f6ffafSMatthew G. Knepley             if ((point >= vStart) && (point < vEnd)) closure[Nv++] = point;
1044846a3e8bSMatthew G. Knepley           }
1045b7f6ffafSMatthew G. Knepley           ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]);CHKERRQ(ierr);
1046b7f6ffafSMatthew G. Knepley           for (v = 0; v <= Nv; ++v) {
1047b7f6ffafSMatthew G. Knepley             const PetscInt vertex = closure[v%Nv];
1048b7f6ffafSMatthew G. Knepley 
1049b7f6ffafSMatthew G. Knepley             if (v > 0) {
1050b7f6ffafSMatthew G. Knepley               if (plotEdges) {
1051b7f6ffafSMatthew G. Knepley                 const PetscInt *edge;
1052b7f6ffafSMatthew G. Knepley                 PetscInt        endpoints[2], ne;
1053b7f6ffafSMatthew G. Knepley 
1054b7f6ffafSMatthew G. Knepley                 endpoints[0] = closure[v-1]; endpoints[1] = vertex;
1055b7f6ffafSMatthew G. Knepley                 ierr = DMPlexGetJoin(dm, 2, endpoints, &ne, &edge);CHKERRQ(ierr);
10562c71b3e2SJacob Faibussowitsch                 PetscCheckFalse(ne != 1,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find edge for vertices %D, %D", endpoints[0], endpoints[1]);
1057b7f6ffafSMatthew G. Knepley                 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%d) -- ", edge[0], rank);CHKERRQ(ierr);
1058b7f6ffafSMatthew G. Knepley                 ierr = DMPlexRestoreJoin(dm, 2, endpoints, &ne, &edge);CHKERRQ(ierr);
1059b7f6ffafSMatthew G. Knepley               } else {
1060b7f6ffafSMatthew G. Knepley                 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- ");CHKERRQ(ierr);
1061b7f6ffafSMatthew G. Knepley               }
1062b7f6ffafSMatthew G. Knepley             }
1063b7f6ffafSMatthew G. Knepley             ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%d)", vertex, rank);CHKERRQ(ierr);
1064b7f6ffafSMatthew G. Knepley           }
1065b7f6ffafSMatthew G. Knepley           ierr = PetscViewerASCIISynchronizedPrintf(viewer, ";\n");CHKERRQ(ierr);
1066846a3e8bSMatthew G. Knepley           ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
1067846a3e8bSMatthew G. Knepley         }
1068846a3e8bSMatthew G. Knepley       }
1069b7f6ffafSMatthew G. Knepley     }
1070846a3e8bSMatthew G. Knepley     ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr);
1071846a3e8bSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
1072846a3e8bSMatthew G. Knepley       double    ccoords[3] = {0.0, 0.0, 0.0};
1073846a3e8bSMatthew G. Knepley       PetscBool isLabeled  = PETSC_FALSE;
1074846a3e8bSMatthew G. Knepley       PetscInt *closure    = NULL;
1075846a3e8bSMatthew G. Knepley       PetscInt  closureSize, dof, d, n = 0;
1076846a3e8bSMatthew G. Knepley 
1077fe1cc32dSStefano Zampini       if (wp && !PetscBTLookup(wp,c - pStart)) continue;
1078846a3e8bSMatthew G. Knepley       ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
1079846a3e8bSMatthew G. Knepley       ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\path (");CHKERRQ(ierr);
1080846a3e8bSMatthew G. Knepley       for (p = 0; p < closureSize*2; p += 2) {
1081846a3e8bSMatthew G. Knepley         const PetscInt point = closure[p];
1082846a3e8bSMatthew G. Knepley         PetscInt       off;
1083846a3e8bSMatthew G. Knepley 
1084846a3e8bSMatthew G. Knepley         if ((point < vStart) || (point >= vEnd)) continue;
1085846a3e8bSMatthew G. Knepley         ierr = PetscSectionGetDof(coordSection, point, &dof);CHKERRQ(ierr);
1086846a3e8bSMatthew G. Knepley         ierr = PetscSectionGetOffset(coordSection, point, &off);CHKERRQ(ierr);
1087846a3e8bSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
1088846a3e8bSMatthew G. Knepley           tcoords[d] = (double) (scale*PetscRealPart(coords[off+d]));
1089846a3e8bSMatthew G. Knepley           tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
1090846a3e8bSMatthew G. Knepley         }
1091846a3e8bSMatthew G. Knepley         /* Rotate coordinates since PGF makes z point out of the page instead of up */
1092846a3e8bSMatthew G. Knepley         if (dof == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;}
1093846a3e8bSMatthew G. Knepley         for (d = 0; d < dof; ++d) {ccoords[d] += tcoords[d];}
1094846a3e8bSMatthew G. Knepley         ++n;
1095846a3e8bSMatthew G. Knepley       }
1096846a3e8bSMatthew G. Knepley       for (d = 0; d < dof; ++d) {ccoords[d] /= n;}
1097846a3e8bSMatthew G. Knepley       ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
1098846a3e8bSMatthew G. Knepley       for (d = 0; d < dof; ++d) {
1099846a3e8bSMatthew G. Knepley         if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);}
1100087ef6b2SMatthew G. Knepley         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) ccoords[d]);CHKERRQ(ierr);
1101846a3e8bSMatthew G. Knepley       }
1102b7f6ffafSMatthew G. Knepley       if (drawHasse) color = colors[depth%numColors];
1103b7f6ffafSMatthew G. Knepley       else           color = colors[rank%numColors];
1104846a3e8bSMatthew G. Knepley       for (l = 0; l < numLabels; ++l) {
1105846a3e8bSMatthew G. Knepley         PetscInt val;
1106846a3e8bSMatthew G. Knepley         ierr = DMGetLabelValue(dm, names[l], c, &val);CHKERRQ(ierr);
1107846a3e8bSMatthew G. Knepley         if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;}
1108846a3e8bSMatthew G. Knepley       }
1109b7f6ffafSMatthew G. Knepley       if (drawNumbers[dim]) {
1110846a3e8bSMatthew G. Knepley         ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D};\n", c, rank, color, c);CHKERRQ(ierr);
1111b7f6ffafSMatthew G. Knepley       } else if (drawColors[dim]) {
1112846a3e8bSMatthew G. Knepley         ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color);CHKERRQ(ierr);
1113b7f6ffafSMatthew G. Knepley       } else {
1114b7f6ffafSMatthew G. Knepley         ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [] {};\n", c, rank);CHKERRQ(ierr);
1115846a3e8bSMatthew G. Knepley       }
1116846a3e8bSMatthew G. Knepley     }
1117846a3e8bSMatthew G. Knepley     ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr);
1118b7f6ffafSMatthew G. Knepley     if (drawHasse) {
1119b7f6ffafSMatthew G. Knepley       color = colors[depth%numColors];
1120b7f6ffafSMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "%% Cells\n");CHKERRQ(ierr);
1121b7f6ffafSMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "\\foreach \\c in {\\cStart,...,\\cEnd}\n");CHKERRQ(ierr);
1122b7f6ffafSMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "{\n");CHKERRQ(ierr);
1123b7f6ffafSMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "  \\node(\\c_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\cShift+\\c-\\cStart,0) {\\c};\n", rank, color);CHKERRQ(ierr);
1124b7f6ffafSMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "}\n");CHKERRQ(ierr);
1125552f7358SJed Brown 
1126b7f6ffafSMatthew G. Knepley       color = colors[1%numColors];
1127b7f6ffafSMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "%% Edges\n");CHKERRQ(ierr);
1128b7f6ffafSMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "\\foreach \\e in {\\eStart,...,\\eEnd}\n");CHKERRQ(ierr);
1129b7f6ffafSMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "{\n");CHKERRQ(ierr);
1130b7f6ffafSMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "  \\node(\\e_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\eShift+\\e-\\eStart,1) {\\e};\n", rank, color);CHKERRQ(ierr);
1131b7f6ffafSMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "}\n");CHKERRQ(ierr);
1132b7f6ffafSMatthew G. Knepley 
1133b7f6ffafSMatthew G. Knepley       color = colors[0%numColors];
1134b7f6ffafSMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "%% Vertices\n");CHKERRQ(ierr);
1135b7f6ffafSMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "\\foreach \\v in {\\vStart,...,\\vEnd}\n");CHKERRQ(ierr);
1136b7f6ffafSMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "{\n");CHKERRQ(ierr);
1137b7f6ffafSMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "  \\node(\\v_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\vShift+\\v-\\vStart,2) {\\v};\n", rank, color);CHKERRQ(ierr);
1138b7f6ffafSMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "}\n");CHKERRQ(ierr);
1139b7f6ffafSMatthew G. Knepley 
1140b7f6ffafSMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
1141b7f6ffafSMatthew G. Knepley         const PetscInt *cone;
1142b7f6ffafSMatthew G. Knepley         PetscInt        coneSize, cp;
1143b7f6ffafSMatthew G. Knepley 
1144b7f6ffafSMatthew G. Knepley         ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr);
1145b7f6ffafSMatthew G. Knepley         ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
1146b7f6ffafSMatthew G. Knepley         for (cp = 0; cp < coneSize; ++cp) {
1147b7f6ffafSMatthew G. Knepley           ierr = PetscViewerASCIIPrintf(viewer, "\\draw[->, shorten >=1pt] (%D_%d) -- (%D_%d);\n", cone[cp], rank, p, rank);CHKERRQ(ierr);
1148552f7358SJed Brown         }
11490588280cSMatthew G. Knepley       }
11500588280cSMatthew G. Knepley     }
1151552f7358SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
11524d4c343aSBarry Smith     ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr);
11530588280cSMatthew G. Knepley     ierr = PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n");CHKERRQ(ierr);
1154770b213bSMatthew G Knepley     ierr = PetscViewerASCIIPrintf(viewer, "\\end{document}\n", name);CHKERRQ(ierr);
11550588280cSMatthew G. Knepley     for (l = 0; l < numLabels;  ++l) {ierr = PetscFree(names[l]);CHKERRQ(ierr);}
11560588280cSMatthew G. Knepley     for (c = 0; c < numColors;  ++c) {ierr = PetscFree(colors[c]);CHKERRQ(ierr);}
11570588280cSMatthew G. Knepley     for (c = 0; c < numLColors; ++c) {ierr = PetscFree(lcolors[c]);CHKERRQ(ierr);}
11580588280cSMatthew G. Knepley     ierr = PetscFree3(names, colors, lcolors);CHKERRQ(ierr);
1159fe1cc32dSStefano Zampini     ierr = PetscBTDestroy(&wp);CHKERRQ(ierr);
11600f7d6e4aSStefano Zampini   } else if (format == PETSC_VIEWER_LOAD_BALANCE) {
11610f7d6e4aSStefano Zampini     Vec                    cown,acown;
11620f7d6e4aSStefano Zampini     VecScatter             sct;
11630f7d6e4aSStefano Zampini     ISLocalToGlobalMapping g2l;
11640f7d6e4aSStefano Zampini     IS                     gid,acis;
11650f7d6e4aSStefano Zampini     MPI_Comm               comm,ncomm = MPI_COMM_NULL;
11660f7d6e4aSStefano Zampini     MPI_Group              ggroup,ngroup;
11670f7d6e4aSStefano Zampini     PetscScalar            *array,nid;
11680f7d6e4aSStefano Zampini     const PetscInt         *idxs;
11690f7d6e4aSStefano Zampini     PetscInt               *idxs2,*start,*adjacency,*work;
11700f7d6e4aSStefano Zampini     PetscInt64             lm[3],gm[3];
11710f7d6e4aSStefano Zampini     PetscInt               i,c,cStart,cEnd,cum,numVertices,ect,ectn,cellHeight;
11720f7d6e4aSStefano Zampini     PetscMPIInt            d1,d2,rank;
11730f7d6e4aSStefano Zampini 
11740f7d6e4aSStefano Zampini     ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
1175ffc4695bSBarry Smith     ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
1176b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
1177ffc4695bSBarry Smith     ierr = MPI_Comm_split_type(comm,MPI_COMM_TYPE_SHARED,rank,MPI_INFO_NULL,&ncomm);CHKERRMPI(ierr);
11780f7d6e4aSStefano Zampini #endif
11790f7d6e4aSStefano Zampini     if (ncomm != MPI_COMM_NULL) {
1180ffc4695bSBarry Smith       ierr = MPI_Comm_group(comm,&ggroup);CHKERRMPI(ierr);
1181ffc4695bSBarry Smith       ierr = MPI_Comm_group(ncomm,&ngroup);CHKERRMPI(ierr);
11820f7d6e4aSStefano Zampini       d1   = 0;
1183ffc4695bSBarry Smith       ierr = MPI_Group_translate_ranks(ngroup,1,&d1,ggroup,&d2);CHKERRMPI(ierr);
11840f7d6e4aSStefano Zampini       nid  = d2;
1185ffc4695bSBarry Smith       ierr = MPI_Group_free(&ggroup);CHKERRMPI(ierr);
1186ffc4695bSBarry Smith       ierr = MPI_Group_free(&ngroup);CHKERRMPI(ierr);
1187ffc4695bSBarry Smith       ierr = MPI_Comm_free(&ncomm);CHKERRMPI(ierr);
11880f7d6e4aSStefano Zampini     } else nid = 0.0;
11890f7d6e4aSStefano Zampini 
11900f7d6e4aSStefano Zampini     /* Get connectivity */
11910f7d6e4aSStefano Zampini     ierr = DMPlexGetVTKCellHeight(dm,&cellHeight);CHKERRQ(ierr);
11920f7d6e4aSStefano Zampini     ierr = DMPlexCreatePartitionerGraph(dm,cellHeight,&numVertices,&start,&adjacency,&gid);CHKERRQ(ierr);
11930f7d6e4aSStefano Zampini 
11940f7d6e4aSStefano Zampini     /* filter overlapped local cells */
11950f7d6e4aSStefano Zampini     ierr = DMPlexGetHeightStratum(dm,cellHeight,&cStart,&cEnd);CHKERRQ(ierr);
11960f7d6e4aSStefano Zampini     ierr = ISGetIndices(gid,&idxs);CHKERRQ(ierr);
11970f7d6e4aSStefano Zampini     ierr = ISGetLocalSize(gid,&cum);CHKERRQ(ierr);
11980f7d6e4aSStefano Zampini     ierr = PetscMalloc1(cum,&idxs2);CHKERRQ(ierr);
11990f7d6e4aSStefano Zampini     for (c = cStart, cum = 0; c < cEnd; c++) {
12000f7d6e4aSStefano Zampini       if (idxs[c-cStart] < 0) continue;
12010f7d6e4aSStefano Zampini       idxs2[cum++] = idxs[c-cStart];
12020f7d6e4aSStefano Zampini     }
12030f7d6e4aSStefano Zampini     ierr = ISRestoreIndices(gid,&idxs);CHKERRQ(ierr);
12042c71b3e2SJacob Faibussowitsch     PetscCheckFalse(numVertices != cum,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected %D != %D",numVertices,cum);
12050f7d6e4aSStefano Zampini     ierr = ISDestroy(&gid);CHKERRQ(ierr);
12060f7d6e4aSStefano Zampini     ierr = ISCreateGeneral(comm,numVertices,idxs2,PETSC_OWN_POINTER,&gid);CHKERRQ(ierr);
12070f7d6e4aSStefano Zampini 
12080f7d6e4aSStefano Zampini     /* support for node-aware cell locality */
12090f7d6e4aSStefano Zampini     ierr = ISCreateGeneral(comm,start[numVertices],adjacency,PETSC_USE_POINTER,&acis);CHKERRQ(ierr);
12100f7d6e4aSStefano Zampini     ierr = VecCreateSeq(PETSC_COMM_SELF,start[numVertices],&acown);CHKERRQ(ierr);
12110f7d6e4aSStefano Zampini     ierr = VecCreateMPI(comm,numVertices,PETSC_DECIDE,&cown);CHKERRQ(ierr);
12120f7d6e4aSStefano Zampini     ierr = VecGetArray(cown,&array);CHKERRQ(ierr);
12130f7d6e4aSStefano Zampini     for (c = 0; c < numVertices; c++) array[c] = nid;
12140f7d6e4aSStefano Zampini     ierr = VecRestoreArray(cown,&array);CHKERRQ(ierr);
12150f7d6e4aSStefano Zampini     ierr = VecScatterCreate(cown,acis,acown,NULL,&sct);CHKERRQ(ierr);
12160f7d6e4aSStefano Zampini     ierr = VecScatterBegin(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12170f7d6e4aSStefano Zampini     ierr = VecScatterEnd(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12180f7d6e4aSStefano Zampini     ierr = ISDestroy(&acis);CHKERRQ(ierr);
12190f7d6e4aSStefano Zampini     ierr = VecScatterDestroy(&sct);CHKERRQ(ierr);
12200f7d6e4aSStefano Zampini     ierr = VecDestroy(&cown);CHKERRQ(ierr);
12210f7d6e4aSStefano Zampini 
12220f7d6e4aSStefano Zampini     /* compute edgeCut */
12230f7d6e4aSStefano Zampini     for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum,start[c+1]-start[c]);
12240f7d6e4aSStefano Zampini     ierr = PetscMalloc1(cum,&work);CHKERRQ(ierr);
12250f7d6e4aSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(gid,&g2l);CHKERRQ(ierr);
12260f7d6e4aSStefano Zampini     ierr = ISLocalToGlobalMappingSetType(g2l,ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr);
12270f7d6e4aSStefano Zampini     ierr = ISDestroy(&gid);CHKERRQ(ierr);
12280f7d6e4aSStefano Zampini     ierr = VecGetArray(acown,&array);CHKERRQ(ierr);
12290f7d6e4aSStefano Zampini     for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) {
12300f7d6e4aSStefano Zampini       PetscInt totl;
12310f7d6e4aSStefano Zampini 
12320f7d6e4aSStefano Zampini       totl = start[c+1]-start[c];
12330f7d6e4aSStefano Zampini       ierr = ISGlobalToLocalMappingApply(g2l,IS_GTOLM_MASK,totl,adjacency+start[c],NULL,work);CHKERRQ(ierr);
12340f7d6e4aSStefano Zampini       for (i = 0; i < totl; i++) {
12350f7d6e4aSStefano Zampini         if (work[i] < 0) {
12360f7d6e4aSStefano Zampini           ect  += 1;
12370f7d6e4aSStefano Zampini           ectn += (array[i + start[c]] != nid) ? 0 : 1;
12380f7d6e4aSStefano Zampini         }
12390f7d6e4aSStefano Zampini       }
12400f7d6e4aSStefano Zampini     }
12410f7d6e4aSStefano Zampini     ierr  = PetscFree(work);CHKERRQ(ierr);
12420f7d6e4aSStefano Zampini     ierr  = VecRestoreArray(acown,&array);CHKERRQ(ierr);
12430f7d6e4aSStefano Zampini     lm[0] = numVertices > 0 ?  numVertices : PETSC_MAX_INT;
12440f7d6e4aSStefano Zampini     lm[1] = -numVertices;
1245820f2d46SBarry Smith     ierr  = MPIU_Allreduce(lm,gm,2,MPIU_INT64,MPI_MIN,comm);CHKERRMPI(ierr);
12460f7d6e4aSStefano Zampini     ierr  = PetscViewerASCIIPrintf(viewer,"  Cell balance: %.2f (max %D, min %D",-((double)gm[1])/((double)gm[0]),-(PetscInt)gm[1],(PetscInt)gm[0]);CHKERRQ(ierr);
12470f7d6e4aSStefano Zampini     lm[0] = ect; /* edgeCut */
12480f7d6e4aSStefano Zampini     lm[1] = ectn; /* node-aware edgeCut */
12490f7d6e4aSStefano Zampini     lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */
1250820f2d46SBarry Smith     ierr  = MPIU_Allreduce(lm,gm,3,MPIU_INT64,MPI_SUM,comm);CHKERRMPI(ierr);
12510f7d6e4aSStefano Zampini     ierr  = PetscViewerASCIIPrintf(viewer,", empty %D)\n",(PetscInt)gm[2]);CHKERRQ(ierr);
1252b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
12530f7d6e4aSStefano Zampini     ierr  = PetscViewerASCIIPrintf(viewer,"  Edge Cut: %D (on node %.3f)\n",(PetscInt)(gm[0]/2),gm[0] ? ((double)(gm[1]))/((double)gm[0]) : 1.);CHKERRQ(ierr);
12540f7d6e4aSStefano Zampini #else
12550f7d6e4aSStefano Zampini     ierr  = PetscViewerASCIIPrintf(viewer,"  Edge Cut: %D (on node %.3f)\n",(PetscInt)(gm[0]/2),0.0);CHKERRQ(ierr);
12560f7d6e4aSStefano Zampini #endif
12570f7d6e4aSStefano Zampini     ierr  = ISLocalToGlobalMappingDestroy(&g2l);CHKERRQ(ierr);
12580f7d6e4aSStefano Zampini     ierr  = PetscFree(start);CHKERRQ(ierr);
12590f7d6e4aSStefano Zampini     ierr  = PetscFree(adjacency);CHKERRQ(ierr);
12600f7d6e4aSStefano Zampini     ierr  = VecDestroy(&acown);CHKERRQ(ierr);
1261552f7358SJed Brown   } else {
1262412e9a14SMatthew G. Knepley     const char    *name;
1263d80ece95SMatthew G. Knepley     PetscInt      *sizes, *hybsizes, *ghostsizes;
1264412e9a14SMatthew G. Knepley     PetscInt       locDepth, depth, cellHeight, dim, d;
1265d80ece95SMatthew G. Knepley     PetscInt       pStart, pEnd, p, gcStart, gcEnd, gcNum;
1266ca7bf7eeSMatthew G. Knepley     PetscInt       numLabels, l, maxSize = 17;
12679318fe57SMatthew G. Knepley     DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN;
1268412e9a14SMatthew G. Knepley     MPI_Comm       comm;
1269412e9a14SMatthew G. Knepley     PetscMPIInt    size, rank;
1270552f7358SJed Brown 
127182f516ccSBarry Smith     ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr);
1272ffc4695bSBarry Smith     ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr);
1273ffc4695bSBarry Smith     ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
1274c73cfb54SMatthew G. Knepley     ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
1275f73eea6eSMatthew G. Knepley     ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr);
12765f64d76eSMatthew G. Knepley     ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr);
1277f73eea6eSMatthew G. Knepley     if (name) {ierr = PetscViewerASCIIPrintf(viewer, "%s in %D dimension%s:\n", name, dim, dim == 1 ? "" : "s");CHKERRQ(ierr);}
1278f73eea6eSMatthew G. Knepley     else      {ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimension%s:\n", dim, dim == 1 ? "" : "s");CHKERRQ(ierr);}
1279f73eea6eSMatthew G. Knepley     if (cellHeight) {ierr = PetscViewerASCIIPrintf(viewer, "  Cells are at height %D\n", cellHeight);CHKERRQ(ierr);}
1280552f7358SJed Brown     ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr);
1281820f2d46SBarry Smith     ierr = MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRMPI(ierr);
1282d80ece95SMatthew G. Knepley     ierr = DMPlexGetGhostCellStratum(dm, &gcStart, &gcEnd);CHKERRQ(ierr);
1283d80ece95SMatthew G. Knepley     gcNum = gcEnd - gcStart;
1284ca7bf7eeSMatthew G. Knepley     if (size < maxSize) {ierr = PetscCalloc3(size, &sizes, size, &hybsizes, size, &ghostsizes);CHKERRQ(ierr);}
1285ca7bf7eeSMatthew G. Knepley     else                {ierr = PetscCalloc3(3,    &sizes, 3,    &hybsizes, 3,    &ghostsizes);CHKERRQ(ierr);}
1286412e9a14SMatthew G. Knepley     for (d = 0; d <= depth; d++) {
1287412e9a14SMatthew G. Knepley       PetscInt Nc[2] = {0, 0}, ict;
1288412e9a14SMatthew G. Knepley 
1289552f7358SJed Brown       ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr);
12909318fe57SMatthew G. Knepley       if (pStart < pEnd) {ierr = DMPlexGetCellType(dm, pStart, &ct0);CHKERRQ(ierr);}
1291412e9a14SMatthew G. Knepley       ict  = ct0;
1292ffc4695bSBarry Smith       ierr = MPI_Bcast(&ict, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr);
1293412e9a14SMatthew G. Knepley       ct0  = (DMPolytopeType) ict;
1294412e9a14SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
1295412e9a14SMatthew G. Knepley         DMPolytopeType ct;
1296412e9a14SMatthew G. Knepley 
1297412e9a14SMatthew G. Knepley         ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
1298412e9a14SMatthew G. Knepley         if (ct == ct0) ++Nc[0];
1299412e9a14SMatthew G. Knepley         else           ++Nc[1];
1300412e9a14SMatthew G. Knepley       }
1301ca7bf7eeSMatthew G. Knepley       if (size < maxSize) {
1302ffc4695bSBarry Smith         ierr = MPI_Gather(&Nc[0], 1, MPIU_INT, sizes,    1, MPIU_INT, 0, comm);CHKERRMPI(ierr);
1303ffc4695bSBarry Smith         ierr = MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr);
1304ffc4695bSBarry Smith         if (d == depth) {ierr = MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr);}
13059880b877SBarry Smith         ierr = PetscViewerASCIIPrintf(viewer, "  Number of %D-cells per rank:", (depth == 1) && d ? dim : d);CHKERRQ(ierr);
1306834065abSMatthew G. Knepley         for (p = 0; p < size; ++p) {
1307dd400576SPatrick Sanan           if (rank == 0) {
1308412e9a14SMatthew G. Knepley             ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]+hybsizes[p]);CHKERRQ(ierr);
1309412e9a14SMatthew G. Knepley             if (hybsizes[p]   > 0) {ierr = PetscViewerASCIIPrintf(viewer, " (%D)", hybsizes[p]);CHKERRQ(ierr);}
1310412e9a14SMatthew G. Knepley             if (ghostsizes[p] > 0) {ierr = PetscViewerASCIIPrintf(viewer, " [%D]", ghostsizes[p]);CHKERRQ(ierr);}
1311834065abSMatthew G. Knepley           }
1312cbb7f117SMark Adams         }
1313ca7bf7eeSMatthew G. Knepley       } else {
1314ca7bf7eeSMatthew G. Knepley         PetscInt locMinMax[2];
1315ca7bf7eeSMatthew G. Knepley 
1316ca7bf7eeSMatthew G. Knepley         locMinMax[0] = Nc[0]+Nc[1]; locMinMax[1] = Nc[0]+Nc[1];
1317ca7bf7eeSMatthew G. Knepley         ierr = PetscGlobalMinMaxInt(comm, locMinMax, sizes);CHKERRQ(ierr);
1318ca7bf7eeSMatthew G. Knepley         locMinMax[0] = Nc[1]; locMinMax[1] = Nc[1];
1319ca7bf7eeSMatthew G. Knepley         ierr = PetscGlobalMinMaxInt(comm, locMinMax, hybsizes);CHKERRQ(ierr);
1320ca7bf7eeSMatthew G. Knepley         if (d == depth) {
1321ca7bf7eeSMatthew G. Knepley           locMinMax[0] = gcNum; locMinMax[1] = gcNum;
1322ca7bf7eeSMatthew G. Knepley           ierr = PetscGlobalMinMaxInt(comm, locMinMax, ghostsizes);CHKERRQ(ierr);
1323ca7bf7eeSMatthew G. Knepley         }
1324ca7bf7eeSMatthew G. Knepley         ierr = PetscViewerASCIIPrintf(viewer, "  Min/Max of %D-cells per rank:", (depth == 1) && d ? dim : d);CHKERRQ(ierr);
1325ca7bf7eeSMatthew G. Knepley         ierr = PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1]);CHKERRQ(ierr);
1326ca7bf7eeSMatthew G. Knepley         if (hybsizes[0]   > 0) {ierr = PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT "/%" PetscInt_FMT ")", hybsizes[0], hybsizes[1]);CHKERRQ(ierr);}
1327ca7bf7eeSMatthew G. Knepley         if (ghostsizes[0] > 0) {ierr = PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "/%" PetscInt_FMT "]", ghostsizes[0], ghostsizes[1]);CHKERRQ(ierr);}
1328ca7bf7eeSMatthew G. Knepley       }
1329552f7358SJed Brown       ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr);
1330552f7358SJed Brown     }
1331d80ece95SMatthew G. Knepley     ierr = PetscFree3(sizes, hybsizes, ghostsizes);CHKERRQ(ierr);
13329318fe57SMatthew G. Knepley     {
13339318fe57SMatthew G. Knepley       const PetscReal      *maxCell;
13349318fe57SMatthew G. Knepley       const PetscReal      *L;
13359318fe57SMatthew G. Knepley       const DMBoundaryType *bd;
13369318fe57SMatthew G. Knepley       PetscBool             per, localized;
13379318fe57SMatthew G. Knepley 
13389318fe57SMatthew G. Knepley       ierr = DMGetPeriodicity(dm, &per, &maxCell, &L, &bd);CHKERRQ(ierr);
13399318fe57SMatthew G. Knepley       ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr);
13409318fe57SMatthew G. Knepley       if (per) {
13419318fe57SMatthew G. Knepley         ierr = PetscViewerASCIIPrintf(viewer, "Periodic mesh (");CHKERRQ(ierr);
13429318fe57SMatthew G. Knepley         ierr = PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);CHKERRQ(ierr);
13439318fe57SMatthew G. Knepley         for (d = 0; d < dim; ++d) {
13449318fe57SMatthew G. Knepley           if (bd && d > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);}
13459318fe57SMatthew G. Knepley           if (bd)    {ierr = PetscViewerASCIIPrintf(viewer, "%s", DMBoundaryTypes[bd[d]]);CHKERRQ(ierr);}
13469318fe57SMatthew G. Knepley         }
13479318fe57SMatthew G. Knepley         ierr = PetscViewerASCIIPrintf(viewer, ") coordinates %s\n", localized ? "localized" : "not localized");CHKERRQ(ierr);
13489318fe57SMatthew G. Knepley         ierr = PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);CHKERRQ(ierr);
13499318fe57SMatthew G. Knepley       }
13509318fe57SMatthew G. Knepley     }
1351c58f1c22SToby Isaac     ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr);
1352a57dd577SMatthew G Knepley     if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Labels:\n");CHKERRQ(ierr);}
1353a57dd577SMatthew G Knepley     for (l = 0; l < numLabels; ++l) {
1354a57dd577SMatthew G Knepley       DMLabel         label;
1355a57dd577SMatthew G Knepley       const char     *name;
1356a57dd577SMatthew G Knepley       IS              valueIS;
1357a57dd577SMatthew G Knepley       const PetscInt *values;
1358a57dd577SMatthew G Knepley       PetscInt        numValues, v;
1359a57dd577SMatthew G Knepley 
1360c58f1c22SToby Isaac       ierr = DMGetLabelName(dm, l, &name);CHKERRQ(ierr);
1361c58f1c22SToby Isaac       ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr);
1362a57dd577SMatthew G Knepley       ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr);
1363d72f73ffSMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "  %s: %D strata with value/size (", name, numValues);CHKERRQ(ierr);
1364a57dd577SMatthew G Knepley       ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr);
1365a57dd577SMatthew G Knepley       ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr);
1366120dea56SMatthew G. Knepley       ierr = PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);CHKERRQ(ierr);
1367a57dd577SMatthew G Knepley       for (v = 0; v < numValues; ++v) {
1368a57dd577SMatthew G Knepley         PetscInt size;
1369a57dd577SMatthew G Knepley 
1370a57dd577SMatthew G Knepley         ierr = DMLabelGetStratumSize(label, values[v], &size);CHKERRQ(ierr);
1371a57dd577SMatthew G Knepley         if (v > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);}
1372d72f73ffSMatthew G. Knepley         ierr = PetscViewerASCIIPrintf(viewer, "%D (%D)", values[v], size);CHKERRQ(ierr);
1373a57dd577SMatthew G Knepley       }
1374a57dd577SMatthew G Knepley       ierr = PetscViewerASCIIPrintf(viewer, ")\n");CHKERRQ(ierr);
1375120dea56SMatthew G. Knepley       ierr = PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);CHKERRQ(ierr);
1376a57dd577SMatthew G Knepley       ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr);
13774d41221fSMatthew G Knepley       ierr = ISDestroy(&valueIS);CHKERRQ(ierr);
1378a57dd577SMatthew G Knepley     }
1379c1cad2e7SMatthew G. Knepley     {
1380c1cad2e7SMatthew G. Knepley       char    **labelNames;
1381c1cad2e7SMatthew G. Knepley       PetscInt  Nl = numLabels;
1382c1cad2e7SMatthew G. Knepley       PetscBool flg;
1383c1cad2e7SMatthew G. Knepley 
1384c1cad2e7SMatthew G. Knepley       ierr = PetscMalloc1(Nl, &labelNames);CHKERRQ(ierr);
1385c1cad2e7SMatthew G. Knepley       ierr = PetscOptionsGetStringArray(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_plex_view_labels", labelNames, &Nl, &flg);CHKERRQ(ierr);
1386c1cad2e7SMatthew G. Knepley       for (l = 0; l < Nl; ++l) {
1387c1cad2e7SMatthew G. Knepley         DMLabel label;
1388c1cad2e7SMatthew G. Knepley 
1389c1cad2e7SMatthew G. Knepley         ierr = DMHasLabel(dm, labelNames[l], &flg);CHKERRQ(ierr);
1390c1cad2e7SMatthew G. Knepley         if (flg) {
1391c1cad2e7SMatthew G. Knepley           ierr = DMGetLabel(dm, labelNames[l], &label);CHKERRQ(ierr);
1392c1cad2e7SMatthew G. Knepley           ierr = DMLabelView(label, viewer);CHKERRQ(ierr);
1393c1cad2e7SMatthew G. Knepley         }
1394c1cad2e7SMatthew G. Knepley         ierr = PetscFree(labelNames[l]);CHKERRQ(ierr);
1395c1cad2e7SMatthew G. Knepley       }
1396c1cad2e7SMatthew G. Knepley       ierr = PetscFree(labelNames);CHKERRQ(ierr);
1397c1cad2e7SMatthew G. Knepley     }
139834aa8a36SMatthew G. Knepley     /* If no fields are specified, people do not want to see adjacency */
139934aa8a36SMatthew G. Knepley     if (dm->Nf) {
140034aa8a36SMatthew G. Knepley       PetscInt f;
140134aa8a36SMatthew G. Knepley 
140234aa8a36SMatthew G. Knepley       for (f = 0; f < dm->Nf; ++f) {
140334aa8a36SMatthew G. Knepley         const char *name;
140434aa8a36SMatthew G. Knepley 
140534aa8a36SMatthew G. Knepley         ierr = PetscObjectGetName(dm->fields[f].disc, &name);CHKERRQ(ierr);
140634aa8a36SMatthew G. Knepley         if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Field %s:\n", name);CHKERRQ(ierr);}
140734aa8a36SMatthew G. Knepley         ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
140834aa8a36SMatthew G. Knepley         if (dm->fields[f].label) {ierr = DMLabelView(dm->fields[f].label, viewer);CHKERRQ(ierr);}
140934aa8a36SMatthew G. Knepley         if (dm->fields[f].adjacency[0]) {
141034aa8a36SMatthew G. Knepley           if (dm->fields[f].adjacency[1]) {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n");CHKERRQ(ierr);}
1411ed59e46eSMatthew G. Knepley           else                            {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FVM\n");CHKERRQ(ierr);}
141234aa8a36SMatthew G. Knepley         } else {
141334aa8a36SMatthew G. Knepley           if (dm->fields[f].adjacency[1]) {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FEM\n");CHKERRQ(ierr);}
141434aa8a36SMatthew G. Knepley           else                            {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n");CHKERRQ(ierr);}
141534aa8a36SMatthew G. Knepley         }
141634aa8a36SMatthew G. Knepley         ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
141734aa8a36SMatthew G. Knepley       }
141834aa8a36SMatthew G. Knepley     }
1419a8fb8f29SToby Isaac     ierr = DMGetCoarseDM(dm, &cdm);CHKERRQ(ierr);
14208e7ff633SMatthew G. Knepley     if (cdm) {
14218e7ff633SMatthew G. Knepley       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
14228e7ff633SMatthew G. Knepley       ierr = DMPlexView_Ascii(cdm, viewer);CHKERRQ(ierr);
14238e7ff633SMatthew G. Knepley       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
14248e7ff633SMatthew G. Knepley     }
1425552f7358SJed Brown   }
1426552f7358SJed Brown   PetscFunctionReturn(0);
1427552f7358SJed Brown }
1428552f7358SJed Brown 
1429e5c487bfSMatthew G. Knepley static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[])
1430e5c487bfSMatthew G. Knepley {
1431e5c487bfSMatthew G. Knepley   DMPolytopeType ct;
1432e5c487bfSMatthew G. Knepley   PetscMPIInt    rank;
1433a12d352dSMatthew G. Knepley   PetscInt       cdim;
1434e5c487bfSMatthew G. Knepley   PetscErrorCode ierr;
1435e5c487bfSMatthew G. Knepley 
1436e5c487bfSMatthew G. Knepley   PetscFunctionBegin;
1437ffc4695bSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr);
1438e5c487bfSMatthew G. Knepley   ierr = DMPlexGetCellType(dm, cell, &ct);CHKERRQ(ierr);
1439a12d352dSMatthew G. Knepley   ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr);
1440e5c487bfSMatthew G. Knepley   switch (ct) {
1441a12d352dSMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
1442a12d352dSMatthew G. Knepley   case DM_POLYTOPE_POINT_PRISM_TENSOR:
1443a12d352dSMatthew G. Knepley     switch (cdim) {
1444a12d352dSMatthew G. Knepley     case 1:
1445a12d352dSMatthew G. Knepley     {
1446a12d352dSMatthew G. Knepley       const PetscReal y  = 0.5;  /* TODO Put it in the middle of the viewport */
1447a12d352dSMatthew G. Knepley       const PetscReal dy = 0.05; /* TODO Make it a fraction of the total length */
1448a12d352dSMatthew G. Knepley 
1449a12d352dSMatthew G. Knepley       ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), y,    PetscRealPart(coords[1]), y,    PETSC_DRAW_BLACK);CHKERRQ(ierr);
1450a12d352dSMatthew G. Knepley       ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), y+dy, PetscRealPart(coords[0]), y-dy, PETSC_DRAW_BLACK);CHKERRQ(ierr);
1451a12d352dSMatthew G. Knepley       ierr = PetscDrawLine(draw, PetscRealPart(coords[1]), y+dy, PetscRealPart(coords[1]), y-dy, PETSC_DRAW_BLACK);CHKERRQ(ierr);
1452a12d352dSMatthew G. Knepley     }
1453a12d352dSMatthew G. Knepley     break;
1454a12d352dSMatthew G. Knepley     case 2:
1455a12d352dSMatthew G. Knepley     {
1456a12d352dSMatthew G. Knepley       const PetscReal dx = (PetscRealPart(coords[3]) - PetscRealPart(coords[1]));
1457a12d352dSMatthew G. Knepley       const PetscReal dy = (PetscRealPart(coords[2]) - PetscRealPart(coords[0]));
1458a12d352dSMatthew G. Knepley       const PetscReal l  = 0.1/PetscSqrtReal(dx*dx + dy*dy);
1459a12d352dSMatthew G. Knepley 
1460a12d352dSMatthew G. Knepley       ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK);CHKERRQ(ierr);
1461a12d352dSMatthew G. Knepley       ierr = PetscDrawLine(draw, PetscRealPart(coords[0])+l*dx, PetscRealPart(coords[1])+l*dy, PetscRealPart(coords[0])-l*dx, PetscRealPart(coords[1])-l*dy, PETSC_DRAW_BLACK);CHKERRQ(ierr);
1462a12d352dSMatthew G. Knepley       ierr = PetscDrawLine(draw, PetscRealPart(coords[2])+l*dx, PetscRealPart(coords[3])+l*dy, PetscRealPart(coords[2])-l*dx, PetscRealPart(coords[3])-l*dy, PETSC_DRAW_BLACK);CHKERRQ(ierr);
1463a12d352dSMatthew G. Knepley     }
1464a12d352dSMatthew G. Knepley     break;
146598921bdaSJacob Faibussowitsch     default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of dimension %D", cdim);
1466a12d352dSMatthew G. Knepley     }
1467a12d352dSMatthew G. Knepley     break;
1468e5c487bfSMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
1469e5c487bfSMatthew G. Knepley     ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]),
1470e5c487bfSMatthew G. Knepley                              PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2,
1471e5c487bfSMatthew G. Knepley                              PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2,
1472e5c487bfSMatthew G. Knepley                              PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr);
1473e5c487bfSMatthew G. Knepley     ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK);CHKERRQ(ierr);
1474e5c487bfSMatthew G. Knepley     ierr = PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK);CHKERRQ(ierr);
1475e5c487bfSMatthew G. Knepley     ierr = PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK);CHKERRQ(ierr);
1476e5c487bfSMatthew G. Knepley     break;
1477e5c487bfSMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
1478e5c487bfSMatthew G. Knepley     ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]),
1479e5c487bfSMatthew G. Knepley                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2,
1480e5c487bfSMatthew G. Knepley                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2,
1481e5c487bfSMatthew G. Knepley                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr);
1482e5c487bfSMatthew G. Knepley     ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]),
1483e5c487bfSMatthew G. Knepley                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2,
1484e5c487bfSMatthew G. Knepley                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2,
1485e5c487bfSMatthew G. Knepley                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr);
1486e5c487bfSMatthew G. Knepley     ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK);CHKERRQ(ierr);
1487e5c487bfSMatthew G. Knepley     ierr = PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK);CHKERRQ(ierr);
1488e5c487bfSMatthew G. Knepley     ierr = PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK);CHKERRQ(ierr);
1489e5c487bfSMatthew G. Knepley     ierr = PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK);CHKERRQ(ierr);
1490e5c487bfSMatthew G. Knepley     break;
149198921bdaSJacob Faibussowitsch   default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]);
1492e5c487bfSMatthew G. Knepley   }
1493e5c487bfSMatthew G. Knepley   PetscFunctionReturn(0);
1494e5c487bfSMatthew G. Knepley }
1495e5c487bfSMatthew G. Knepley 
1496e5c487bfSMatthew G. Knepley static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[])
1497e5c487bfSMatthew G. Knepley {
1498e5c487bfSMatthew G. Knepley   DMPolytopeType ct;
1499e5c487bfSMatthew G. Knepley   PetscReal      centroid[2] = {0., 0.};
1500e5c487bfSMatthew G. Knepley   PetscMPIInt    rank;
1501e5c487bfSMatthew G. Knepley   PetscInt       fillColor, v, e, d;
1502e5c487bfSMatthew G. Knepley   PetscErrorCode ierr;
1503e5c487bfSMatthew G. Knepley 
1504e5c487bfSMatthew G. Knepley   PetscFunctionBegin;
1505ffc4695bSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr);
1506e5c487bfSMatthew G. Knepley   ierr = DMPlexGetCellType(dm, cell, &ct);CHKERRQ(ierr);
1507e5c487bfSMatthew G. Knepley   fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2;
1508e5c487bfSMatthew G. Knepley   switch (ct) {
1509e5c487bfSMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
1510e5c487bfSMatthew G. Knepley     {
1511e5c487bfSMatthew G. Knepley       PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.};
1512e5c487bfSMatthew G. Knepley 
1513e5c487bfSMatthew G. Knepley       for (v = 0; v < 3; ++v) {centroid[0] += PetscRealPart(coords[v*2+0])/3.;centroid[1] += PetscRealPart(coords[v*2+1])/3.;}
1514e5c487bfSMatthew G. Knepley       for (e = 0; e < 3; ++e) {
1515e5c487bfSMatthew G. Knepley         refCoords[0] = refVertices[e*2+0];
1516e5c487bfSMatthew G. Knepley         refCoords[1] = refVertices[e*2+1];
1517e5c487bfSMatthew G. Knepley         for (d = 1; d <= edgeDiv; ++d) {
1518e5c487bfSMatthew G. Knepley           refCoords[d*2+0] = refCoords[0] + (refVertices[(e+1)%3 * 2 + 0] - refCoords[0])*d/edgeDiv;
1519e5c487bfSMatthew G. Knepley           refCoords[d*2+1] = refCoords[1] + (refVertices[(e+1)%3 * 2 + 1] - refCoords[1])*d/edgeDiv;
1520e5c487bfSMatthew G. Knepley         }
1521e5c487bfSMatthew G. Knepley         ierr = DMPlexReferenceToCoordinates(dm, cell, edgeDiv+1, refCoords, edgeCoords);CHKERRQ(ierr);
1522e5c487bfSMatthew G. Knepley         for (d = 0; d < edgeDiv; ++d) {
1523e5c487bfSMatthew G. Knepley           ierr = PetscDrawTriangle(draw, centroid[0], centroid[1], edgeCoords[d*2+0], edgeCoords[d*2+1], edgeCoords[(d+1)*2+0], edgeCoords[(d+1)*2+1], fillColor, fillColor, fillColor);CHKERRQ(ierr);
1524e5c487bfSMatthew G. Knepley           ierr = PetscDrawLine(draw, edgeCoords[d*2+0], edgeCoords[d*2+1], edgeCoords[(d+1)*2+0], edgeCoords[(d+1)*2+1], PETSC_DRAW_BLACK);CHKERRQ(ierr);
1525e5c487bfSMatthew G. Knepley         }
1526e5c487bfSMatthew G. Knepley       }
1527e5c487bfSMatthew G. Knepley     }
1528e5c487bfSMatthew G. Knepley     break;
152998921bdaSJacob Faibussowitsch   default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]);
1530e5c487bfSMatthew G. Knepley   }
1531e5c487bfSMatthew G. Knepley   PetscFunctionReturn(0);
1532e5c487bfSMatthew G. Knepley }
1533e5c487bfSMatthew G. Knepley 
15347cd05799SMatthew G. Knepley static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer)
1535e412dcbdSMatthew G. Knepley {
1536e412dcbdSMatthew G. Knepley   PetscDraw          draw;
1537e412dcbdSMatthew G. Knepley   DM                 cdm;
1538e412dcbdSMatthew G. Knepley   PetscSection       coordSection;
1539e412dcbdSMatthew G. Knepley   Vec                coordinates;
1540e412dcbdSMatthew G. Knepley   const PetscScalar *coords;
154129494db1SLisandro Dalcin   PetscReal          xyl[2],xyr[2],bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL};
1542e5c487bfSMatthew G. Knepley   PetscReal         *refCoords, *edgeCoords;
1543e5c487bfSMatthew G. Knepley   PetscBool          isnull, drawAffine = PETSC_TRUE;
1544e5c487bfSMatthew G. Knepley   PetscInt           dim, vStart, vEnd, cStart, cEnd, c, N, edgeDiv = 4;
1545e412dcbdSMatthew G. Knepley   PetscErrorCode     ierr;
1546e412dcbdSMatthew G. Knepley 
1547e412dcbdSMatthew G. Knepley   PetscFunctionBegin;
1548e412dcbdSMatthew G. Knepley   ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr);
15492c71b3e2SJacob Faibussowitsch   PetscCheckFalse(dim > 2,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %D", dim);
1550e5c487bfSMatthew G. Knepley   ierr = PetscOptionsGetBool(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL);CHKERRQ(ierr);
1551e5c487bfSMatthew G. Knepley   if (!drawAffine) {ierr = PetscMalloc2((edgeDiv+1)*dim, &refCoords, (edgeDiv+1)*dim, &edgeCoords);CHKERRQ(ierr);}
1552e412dcbdSMatthew G. Knepley   ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
155392fd8e1eSJed Brown   ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr);
1554e412dcbdSMatthew G. Knepley   ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
1555e412dcbdSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
1556e412dcbdSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
1557e412dcbdSMatthew G. Knepley 
1558e412dcbdSMatthew G. Knepley   ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr);
1559e412dcbdSMatthew G. Knepley   ierr = PetscDrawIsNull(draw, &isnull);CHKERRQ(ierr);
1560e412dcbdSMatthew G. Knepley   if (isnull) PetscFunctionReturn(0);
1561e412dcbdSMatthew G. Knepley   ierr = PetscDrawSetTitle(draw, "Mesh");CHKERRQ(ierr);
1562e412dcbdSMatthew G. Knepley 
1563e412dcbdSMatthew G. Knepley   ierr = VecGetLocalSize(coordinates, &N);CHKERRQ(ierr);
1564e412dcbdSMatthew G. Knepley   ierr = VecGetArrayRead(coordinates, &coords);CHKERRQ(ierr);
1565e412dcbdSMatthew G. Knepley   for (c = 0; c < N; c += dim) {
15660c81f2a8SMatthew G. Knepley     bound[0] = PetscMin(bound[0], PetscRealPart(coords[c]));   bound[2] = PetscMax(bound[2], PetscRealPart(coords[c]));
15670c81f2a8SMatthew G. Knepley     bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1]));
1568e412dcbdSMatthew G. Knepley   }
1569e412dcbdSMatthew G. Knepley   ierr = VecRestoreArrayRead(coordinates, &coords);CHKERRQ(ierr);
1570820f2d46SBarry Smith   ierr = MPIU_Allreduce(&bound[0],xyl,2,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr);
1571820f2d46SBarry Smith   ierr = MPIU_Allreduce(&bound[2],xyr,2,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr);
157229494db1SLisandro Dalcin   ierr = PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1]);CHKERRQ(ierr);
1573e412dcbdSMatthew G. Knepley   ierr = PetscDrawClear(draw);CHKERRQ(ierr);
1574e412dcbdSMatthew G. Knepley 
1575cf3064d3SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1576cf3064d3SMatthew G. Knepley     PetscScalar *coords = NULL;
1577ba2698f1SMatthew G. Knepley     PetscInt     numCoords;
1578cf3064d3SMatthew G. Knepley 
1579e5c487bfSMatthew G. Knepley     ierr = DMPlexVecGetClosureAtDepth_Internal(dm, coordSection, coordinates, c, 0, &numCoords, &coords);CHKERRQ(ierr);
1580e5c487bfSMatthew G. Knepley     if (drawAffine) {
1581e5c487bfSMatthew G. Knepley       ierr = DMPlexDrawCell(dm, draw, c, coords);CHKERRQ(ierr);
1582e5c487bfSMatthew G. Knepley     } else {
1583e5c487bfSMatthew G. Knepley       ierr = DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords);CHKERRQ(ierr);
1584cf3064d3SMatthew G. Knepley     }
1585cf3064d3SMatthew G. Knepley     ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr);
1586cf3064d3SMatthew G. Knepley   }
1587e5c487bfSMatthew G. Knepley   if (!drawAffine) {ierr = PetscFree2(refCoords, edgeCoords);CHKERRQ(ierr);}
1588e412dcbdSMatthew G. Knepley   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
1589e412dcbdSMatthew G. Knepley   ierr = PetscDrawPause(draw);CHKERRQ(ierr);
1590e412dcbdSMatthew G. Knepley   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
1591e412dcbdSMatthew G. Knepley   PetscFunctionReturn(0);
1592e412dcbdSMatthew G. Knepley }
1593e412dcbdSMatthew G. Knepley 
15941e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII)
15951e50132fSMatthew G. Knepley #include <exodusII.h>
15966823f3c5SBlaise Bourdin #include <petscviewerexodusii.h>
15971e50132fSMatthew G. Knepley #endif
15981e50132fSMatthew G. Knepley 
1599552f7358SJed Brown PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer)
1600552f7358SJed Brown {
16011e50132fSMatthew G. Knepley   PetscBool      iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus;
1602002a2709SMatthew G. Knepley   char           name[PETSC_MAX_PATH_LEN];
1603552f7358SJed Brown   PetscErrorCode ierr;
1604552f7358SJed Brown 
1605552f7358SJed Brown   PetscFunctionBegin;
1606552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1607552f7358SJed Brown   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1608552f7358SJed Brown   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII,    &iascii);CHKERRQ(ierr);
1609fcf6c8fdSToby Isaac   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK,      &isvtk);CHKERRQ(ierr);
1610c6ccd67eSMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,     &ishdf5);CHKERRQ(ierr);
1611e412dcbdSMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW,     &isdraw);CHKERRQ(ierr);
16128135c375SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS,    &isglvis);CHKERRQ(ierr);
16131e50132fSMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodus);CHKERRQ(ierr);
1614552f7358SJed Brown   if (iascii) {
16158135c375SStefano Zampini     PetscViewerFormat format;
16168135c375SStefano Zampini     ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr);
16178135c375SStefano Zampini     if (format == PETSC_VIEWER_ASCII_GLVIS) {
16188135c375SStefano Zampini       ierr = DMPlexView_GLVis(dm, viewer);CHKERRQ(ierr);
16198135c375SStefano Zampini     } else {
1620552f7358SJed Brown       ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr);
16218135c375SStefano Zampini     }
1622c6ccd67eSMatthew G. Knepley   } else if (ishdf5) {
1623c6ccd67eSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
162439d25373SMatthew G. Knepley     ierr = DMPlexView_HDF5_Internal(dm, viewer);CHKERRQ(ierr);
1625c6ccd67eSMatthew G. Knepley #else
1626c6ccd67eSMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1627552f7358SJed Brown #endif
1628e412dcbdSMatthew G. Knepley   } else if (isvtk) {
1629fcf6c8fdSToby Isaac     ierr = DMPlexVTKWriteAll((PetscObject) dm,viewer);CHKERRQ(ierr);
1630e412dcbdSMatthew G. Knepley   } else if (isdraw) {
1631e412dcbdSMatthew G. Knepley     ierr = DMPlexView_Draw(dm, viewer);CHKERRQ(ierr);
16328135c375SStefano Zampini   } else if (isglvis) {
16338135c375SStefano Zampini     ierr = DMPlexView_GLVis(dm, viewer);CHKERRQ(ierr);
16341e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII)
16351e50132fSMatthew G. Knepley   } else if (isexodus) {
16366823f3c5SBlaise Bourdin /*
16376823f3c5SBlaise Bourdin       exodusII requires that all sets be part of exactly one cell set.
16386823f3c5SBlaise Bourdin       If the dm does not have a "Cell Sets" label defined, we create one
16396823f3c5SBlaise Bourdin       with ID 1, containig all cells.
16406823f3c5SBlaise Bourdin       Note that if the Cell Sets label is defined but does not cover all cells,
16416823f3c5SBlaise Bourdin       we may still have a problem. This should probably be checked here or in the viewer;
16426823f3c5SBlaise Bourdin     */
16436823f3c5SBlaise Bourdin     PetscInt numCS;
16446823f3c5SBlaise Bourdin     ierr = DMGetLabelSize(dm,"Cell Sets",&numCS);CHKERRQ(ierr);
16456823f3c5SBlaise Bourdin     if (!numCS) {
16461e50132fSMatthew G. Knepley       PetscInt cStart, cEnd, c;
16471e50132fSMatthew G. Knepley       ierr = DMCreateLabel(dm, "Cell Sets");CHKERRQ(ierr);
16481e50132fSMatthew G. Knepley       ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
16491e50132fSMatthew G. Knepley       for (c = cStart; c < cEnd; ++c) {ierr = DMSetLabelValue(dm, "Cell Sets", c, 1);CHKERRQ(ierr);}
16506823f3c5SBlaise Bourdin     }
16516823f3c5SBlaise Bourdin     ierr = DMView_PlexExodusII(dm, viewer);CHKERRQ(ierr);
16521e50132fSMatthew G. Knepley #endif
165362201deeSVaclav Hapla   } else {
165498921bdaSJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name);
1655fcf6c8fdSToby Isaac   }
1656cb3ba0daSMatthew G. Knepley   /* Optionally view the partition */
1657cb3ba0daSMatthew G. Knepley   ierr = PetscOptionsHasName(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_partition_view", &flg);CHKERRQ(ierr);
1658cb3ba0daSMatthew G. Knepley   if (flg) {
1659cb3ba0daSMatthew G. Knepley     Vec ranks;
1660cb3ba0daSMatthew G. Knepley     ierr = DMPlexCreateRankField(dm, &ranks);CHKERRQ(ierr);
1661cb3ba0daSMatthew G. Knepley     ierr = VecView(ranks, viewer);CHKERRQ(ierr);
1662cb3ba0daSMatthew G. Knepley     ierr = VecDestroy(&ranks);CHKERRQ(ierr);
1663cb3ba0daSMatthew G. Knepley   }
1664002a2709SMatthew G. Knepley   /* Optionally view a label */
1665589a23caSBarry Smith   ierr = PetscOptionsGetString(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_label_view", name, sizeof(name), &flg);CHKERRQ(ierr);
1666002a2709SMatthew G. Knepley   if (flg) {
1667002a2709SMatthew G. Knepley     DMLabel label;
1668002a2709SMatthew G. Knepley     Vec     val;
1669002a2709SMatthew G. Knepley 
1670002a2709SMatthew G. Knepley     ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr);
16712c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name);
1672002a2709SMatthew G. Knepley     ierr = DMPlexCreateLabelField(dm, label, &val);CHKERRQ(ierr);
1673002a2709SMatthew G. Knepley     ierr = VecView(val, viewer);CHKERRQ(ierr);
1674002a2709SMatthew G. Knepley     ierr = VecDestroy(&val);CHKERRQ(ierr);
1675002a2709SMatthew G. Knepley   }
1676552f7358SJed Brown   PetscFunctionReturn(0);
1677552f7358SJed Brown }
1678552f7358SJed Brown 
16797f96f51bSksagiyam /*@
16807f96f51bSksagiyam   DMPlexTopologyView - Saves a DMPlex topology into a file
16817f96f51bSksagiyam 
16827f96f51bSksagiyam   Collective on DM
16837f96f51bSksagiyam 
16847f96f51bSksagiyam   Input Parameters:
16857f96f51bSksagiyam + dm     - The DM whose topology is to be saved
16867f96f51bSksagiyam - viewer - The PetscViewer for saving
16877f96f51bSksagiyam 
16887f96f51bSksagiyam   Level: advanced
16897f96f51bSksagiyam 
16907f96f51bSksagiyam .seealso: DMView(), DMPlexCoordinatesView(), DMPlexLabelsView(), DMPlexTopologyLoad()
16917f96f51bSksagiyam @*/
16927f96f51bSksagiyam PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer)
16937f96f51bSksagiyam {
16947f96f51bSksagiyam   PetscBool      ishdf5;
16957f96f51bSksagiyam   PetscErrorCode ierr;
16967f96f51bSksagiyam 
16977f96f51bSksagiyam   PetscFunctionBegin;
16987f96f51bSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
16997f96f51bSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
17007f96f51bSksagiyam   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr);
170102f7d72cSksagiyam   ierr = PetscLogEventBegin(DMPLEX_TopologyView,viewer,0,0,0);CHKERRQ(ierr);
17027f96f51bSksagiyam   if (ishdf5) {
17037f96f51bSksagiyam #if defined(PETSC_HAVE_HDF5)
17047f96f51bSksagiyam     PetscViewerFormat format;
17057f96f51bSksagiyam     ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr);
17067f96f51bSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
17077f96f51bSksagiyam       IS globalPointNumbering;
17087f96f51bSksagiyam 
17097f96f51bSksagiyam       ierr = DMPlexCreatePointNumbering(dm, &globalPointNumbering);CHKERRQ(ierr);
17107f96f51bSksagiyam       ierr = DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer);CHKERRQ(ierr);
17117f96f51bSksagiyam       ierr = ISDestroy(&globalPointNumbering);CHKERRQ(ierr);
171298921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]);
17137f96f51bSksagiyam #else
17147f96f51bSksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
17157f96f51bSksagiyam #endif
17167f96f51bSksagiyam   }
171702f7d72cSksagiyam   ierr = PetscLogEventEnd(DMPLEX_TopologyView,viewer,0,0,0);CHKERRQ(ierr);
17187f96f51bSksagiyam   PetscFunctionReturn(0);
17197f96f51bSksagiyam }
17207f96f51bSksagiyam 
172177b8e257Sksagiyam /*@
172277b8e257Sksagiyam   DMPlexCoordinatesView - Saves DMPlex coordinates into a file
172377b8e257Sksagiyam 
172477b8e257Sksagiyam   Collective on DM
172577b8e257Sksagiyam 
172677b8e257Sksagiyam   Input Parameters:
172777b8e257Sksagiyam + dm     - The DM whose coordinates are to be saved
172877b8e257Sksagiyam - viewer - The PetscViewer for saving
172977b8e257Sksagiyam 
173077b8e257Sksagiyam   Level: advanced
173177b8e257Sksagiyam 
173277b8e257Sksagiyam .seealso: DMView(), DMPlexTopologyView(), DMPlexLabelsView(), DMPlexCoordinatesLoad()
173377b8e257Sksagiyam @*/
173477b8e257Sksagiyam PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer)
173577b8e257Sksagiyam {
173677b8e257Sksagiyam   PetscBool      ishdf5;
173777b8e257Sksagiyam   PetscErrorCode ierr;
173877b8e257Sksagiyam 
173977b8e257Sksagiyam   PetscFunctionBegin;
174077b8e257Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
174177b8e257Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
174277b8e257Sksagiyam   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr);
174302f7d72cSksagiyam   ierr = PetscLogEventBegin(DMPLEX_CoordinatesView,viewer,0,0,0);CHKERRQ(ierr);
174477b8e257Sksagiyam   if (ishdf5) {
174577b8e257Sksagiyam #if defined(PETSC_HAVE_HDF5)
174677b8e257Sksagiyam     PetscViewerFormat format;
174777b8e257Sksagiyam     ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr);
174877b8e257Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
174977b8e257Sksagiyam       ierr = DMPlexCoordinatesView_HDF5_Internal(dm, viewer);CHKERRQ(ierr);
175098921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
175177b8e257Sksagiyam #else
175277b8e257Sksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
175377b8e257Sksagiyam #endif
175477b8e257Sksagiyam   }
175502f7d72cSksagiyam   ierr = PetscLogEventEnd(DMPLEX_CoordinatesView,viewer,0,0,0);CHKERRQ(ierr);
175677b8e257Sksagiyam   PetscFunctionReturn(0);
175777b8e257Sksagiyam }
175877b8e257Sksagiyam 
1759bd6565f1Sksagiyam /*@
1760bd6565f1Sksagiyam   DMPlexLabelsView - Saves DMPlex labels into a file
1761bd6565f1Sksagiyam 
1762bd6565f1Sksagiyam   Collective on DM
1763bd6565f1Sksagiyam 
1764bd6565f1Sksagiyam   Input Parameters:
1765bd6565f1Sksagiyam + dm     - The DM whose labels are to be saved
1766bd6565f1Sksagiyam - viewer - The PetscViewer for saving
1767bd6565f1Sksagiyam 
1768bd6565f1Sksagiyam   Level: advanced
1769bd6565f1Sksagiyam 
1770bd6565f1Sksagiyam .seealso: DMView(), DMPlexTopologyView(), DMPlexCoordinatesView(), DMPlexLabelsLoad()
1771bd6565f1Sksagiyam @*/
1772bd6565f1Sksagiyam PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer)
1773bd6565f1Sksagiyam {
1774bd6565f1Sksagiyam   PetscBool      ishdf5;
1775bd6565f1Sksagiyam   PetscErrorCode ierr;
1776bd6565f1Sksagiyam 
1777bd6565f1Sksagiyam   PetscFunctionBegin;
1778bd6565f1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1779bd6565f1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1780bd6565f1Sksagiyam   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr);
178102f7d72cSksagiyam   ierr = PetscLogEventBegin(DMPLEX_LabelsView,viewer,0,0,0);CHKERRQ(ierr);
1782bd6565f1Sksagiyam   if (ishdf5) {
1783bd6565f1Sksagiyam #if defined(PETSC_HAVE_HDF5)
1784bd6565f1Sksagiyam     IS                globalPointNumbering;
1785bd6565f1Sksagiyam     PetscViewerFormat format;
1786bd6565f1Sksagiyam 
1787bd6565f1Sksagiyam     ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr);
1788bd6565f1Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
1789bd6565f1Sksagiyam       ierr = DMPlexCreatePointNumbering(dm, &globalPointNumbering);CHKERRQ(ierr);
1790bd6565f1Sksagiyam       ierr = DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer);CHKERRQ(ierr);
1791bd6565f1Sksagiyam       ierr = ISDestroy(&globalPointNumbering);CHKERRQ(ierr);
179298921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
1793bd6565f1Sksagiyam #else
1794bd6565f1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1795bd6565f1Sksagiyam #endif
1796bd6565f1Sksagiyam   }
179702f7d72cSksagiyam   ierr = PetscLogEventEnd(DMPLEX_LabelsView,viewer,0,0,0);CHKERRQ(ierr);
1798bd6565f1Sksagiyam   PetscFunctionReturn(0);
1799bd6565f1Sksagiyam }
1800bd6565f1Sksagiyam 
1801021affd3Sksagiyam /*@
1802021affd3Sksagiyam   DMPlexSectionView - Saves a section associated with a DMPlex
1803021affd3Sksagiyam 
1804021affd3Sksagiyam   Collective on DM
1805021affd3Sksagiyam 
1806021affd3Sksagiyam   Input Parameters:
1807021affd3Sksagiyam + dm         - The DM that contains the topology on which the section to be saved is defined
1808021affd3Sksagiyam . viewer     - The PetscViewer for saving
1809021affd3Sksagiyam - sectiondm  - The DM that contains the section to be saved
1810021affd3Sksagiyam 
1811021affd3Sksagiyam   Level: advanced
1812021affd3Sksagiyam 
1813021affd3Sksagiyam   Notes:
1814021affd3Sksagiyam   This function is a wrapper around PetscSectionView(); in addition to the raw section, it saves information that associates the section points to the topology (dm) points. When the topology (dm) and the section are later loaded with DMPlexTopologyLoad() and DMPlexSectionLoad(), respectively, this information is used to match section points with topology points.
1815021affd3Sksagiyam 
1816021affd3Sksagiyam   In general dm and sectiondm are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with PetscObjectSetName(). In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name.
1817021affd3Sksagiyam 
1818021affd3Sksagiyam .seealso: DMView(), DMPlexTopologyView(), DMPlexCoordinatesView(), DMPlexLabelsView(), DMPlexGlobalVectorView(), DMPlexLocalVectorView(), PetscSectionView(), DMPlexSectionLoad()
1819021affd3Sksagiyam @*/
1820021affd3Sksagiyam PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm)
1821021affd3Sksagiyam {
1822021affd3Sksagiyam   PetscBool      ishdf5;
1823021affd3Sksagiyam   PetscErrorCode ierr;
1824021affd3Sksagiyam 
1825021affd3Sksagiyam   PetscFunctionBegin;
1826021affd3Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1827021affd3Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1828021affd3Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
1829021affd3Sksagiyam   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr);
183002f7d72cSksagiyam   ierr = PetscLogEventBegin(DMPLEX_SectionView,viewer,0,0,0);CHKERRQ(ierr);
1831021affd3Sksagiyam   if (ishdf5) {
1832021affd3Sksagiyam #if defined(PETSC_HAVE_HDF5)
1833021affd3Sksagiyam     ierr = DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm);CHKERRQ(ierr);
1834021affd3Sksagiyam #else
1835021affd3Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1836021affd3Sksagiyam #endif
1837021affd3Sksagiyam   }
183802f7d72cSksagiyam   ierr = PetscLogEventEnd(DMPLEX_SectionView,viewer,0,0,0);CHKERRQ(ierr);
1839021affd3Sksagiyam   PetscFunctionReturn(0);
1840021affd3Sksagiyam }
1841021affd3Sksagiyam 
18423e97647fSksagiyam /*@
18433e97647fSksagiyam   DMPlexGlobalVectorView - Saves a global vector
18443e97647fSksagiyam 
18453e97647fSksagiyam   Collective on DM
18463e97647fSksagiyam 
18473e97647fSksagiyam   Input Parameters:
18483e97647fSksagiyam + dm        - The DM that represents the topology
18493e97647fSksagiyam . viewer    - The PetscViewer to save data with
18503e97647fSksagiyam . sectiondm - The DM that contains the global section on which vec is defined
18513e97647fSksagiyam - vec       - The global vector to be saved
18523e97647fSksagiyam 
18533e97647fSksagiyam   Level: advanced
18543e97647fSksagiyam 
18553e97647fSksagiyam   Notes:
18563e97647fSksagiyam   In general dm and sectiondm are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with PetscObjectSetName(). In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name.
18573e97647fSksagiyam 
18583e97647fSksagiyam   Typical calling sequence
18593e97647fSksagiyam $       DMCreate(PETSC_COMM_WORLD, &dm);
18603e97647fSksagiyam $       DMSetType(dm, DMPLEX);
18613e97647fSksagiyam $       PetscObjectSetName((PetscObject)dm, "topologydm_name");
18623e97647fSksagiyam $       DMClone(dm, &sectiondm);
18633e97647fSksagiyam $       PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
18643e97647fSksagiyam $       PetscSectionCreate(PETSC_COMM_WORLD, &section);
18653e97647fSksagiyam $       DMPlexGetChart(sectiondm, &pStart, &pEnd);
18663e97647fSksagiyam $       PetscSectionSetChart(section, pStart, pEnd);
18673e97647fSksagiyam $       PetscSectionSetUp(section);
18683e97647fSksagiyam $       DMSetLocalSection(sectiondm, section);
18693e97647fSksagiyam $       PetscSectionDestroy(&section);
18703e97647fSksagiyam $       DMGetGlobalVector(sectiondm, &vec);
18713e97647fSksagiyam $       PetscObjectSetName((PetscObject)vec, "vec_name");
18723e97647fSksagiyam $       DMPlexTopologyView(dm, viewer);
18733e97647fSksagiyam $       DMPlexSectionView(dm, viewer, sectiondm);
18743e97647fSksagiyam $       DMPlexGlobalVectorView(dm, viewer, sectiondm, vec);
18753e97647fSksagiyam $       DMRestoreGlobalVector(sectiondm, &vec);
18763e97647fSksagiyam $       DMDestroy(&sectiondm);
18773e97647fSksagiyam $       DMDestroy(&dm);
18783e97647fSksagiyam 
18793e97647fSksagiyam .seealso: DMPlexTopologyView(), DMPlexSectionView(), DMPlexLocalVectorView(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad()
18803e97647fSksagiyam @*/
18813e97647fSksagiyam PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec)
18823e97647fSksagiyam {
18833e97647fSksagiyam   PetscBool       ishdf5;
18843e97647fSksagiyam   PetscErrorCode  ierr;
18853e97647fSksagiyam 
18863e97647fSksagiyam   PetscFunctionBegin;
18873e97647fSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
18883e97647fSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
18893e97647fSksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
18903e97647fSksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 4);
18913e97647fSksagiyam   /* Check consistency */
18923e97647fSksagiyam   {
18933e97647fSksagiyam     PetscSection  section;
18943e97647fSksagiyam     PetscBool     includesConstraints;
18953e97647fSksagiyam     PetscInt      m, m1;
18963e97647fSksagiyam 
18973e97647fSksagiyam     ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr);
18983e97647fSksagiyam     ierr = DMGetGlobalSection(sectiondm, &section);CHKERRQ(ierr);
18993e97647fSksagiyam     ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr);
19003e97647fSksagiyam     if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);}
19013e97647fSksagiyam     else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);}
19022c71b3e2SJacob Faibussowitsch     PetscCheckFalse(m1 != m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%D) != global section storage size (%D)", m1, m);
19033e97647fSksagiyam   }
19043e97647fSksagiyam   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr);
190502f7d72cSksagiyam   ierr = PetscLogEventBegin(DMPLEX_GlobalVectorView,viewer,0,0,0);CHKERRQ(ierr);
19063e97647fSksagiyam   if (ishdf5) {
19073e97647fSksagiyam #if defined(PETSC_HAVE_HDF5)
19083e97647fSksagiyam     ierr = DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec);CHKERRQ(ierr);
19093e97647fSksagiyam #else
19103e97647fSksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
19113e97647fSksagiyam #endif
19123e97647fSksagiyam   }
191302f7d72cSksagiyam   ierr = PetscLogEventEnd(DMPLEX_GlobalVectorView,viewer,0,0,0);CHKERRQ(ierr);
19143e97647fSksagiyam   PetscFunctionReturn(0);
19153e97647fSksagiyam }
19163e97647fSksagiyam 
19173e97647fSksagiyam /*@
19183e97647fSksagiyam   DMPlexLocalVectorView - Saves a local vector
19193e97647fSksagiyam 
19203e97647fSksagiyam   Collective on DM
19213e97647fSksagiyam 
19223e97647fSksagiyam   Input Parameters:
19233e97647fSksagiyam + dm        - The DM that represents the topology
19243e97647fSksagiyam . viewer    - The PetscViewer to save data with
19253e97647fSksagiyam . sectiondm - The DM that contains the local section on which vec is defined; may be the same as dm
19263e97647fSksagiyam - vec       - The local vector to be saved
19273e97647fSksagiyam 
19283e97647fSksagiyam   Level: advanced
19293e97647fSksagiyam 
19303e97647fSksagiyam   Notes:
19313e97647fSksagiyam   In general dm and sectiondm are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with PetscObjectSetName(). In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name.
19323e97647fSksagiyam 
19333e97647fSksagiyam   Typical calling sequence
19343e97647fSksagiyam $       DMCreate(PETSC_COMM_WORLD, &dm);
19353e97647fSksagiyam $       DMSetType(dm, DMPLEX);
19363e97647fSksagiyam $       PetscObjectSetName((PetscObject)dm, "topologydm_name");
19373e97647fSksagiyam $       DMClone(dm, &sectiondm);
19383e97647fSksagiyam $       PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
19393e97647fSksagiyam $       PetscSectionCreate(PETSC_COMM_WORLD, &section);
19403e97647fSksagiyam $       DMPlexGetChart(sectiondm, &pStart, &pEnd);
19413e97647fSksagiyam $       PetscSectionSetChart(section, pStart, pEnd);
19423e97647fSksagiyam $       PetscSectionSetUp(section);
19433e97647fSksagiyam $       DMSetLocalSection(sectiondm, section);
19443e97647fSksagiyam $       DMGetLocalVector(sectiondm, &vec);
19453e97647fSksagiyam $       PetscObjectSetName((PetscObject)vec, "vec_name");
19463e97647fSksagiyam $       DMPlexTopologyView(dm, viewer);
19473e97647fSksagiyam $       DMPlexSectionView(dm, viewer, sectiondm);
19483e97647fSksagiyam $       DMPlexLocalVectorView(dm, viewer, sectiondm, vec);
19493e97647fSksagiyam $       DMRestoreLocalVector(sectiondm, &vec);
19503e97647fSksagiyam $       DMDestroy(&sectiondm);
19513e97647fSksagiyam $       DMDestroy(&dm);
19523e97647fSksagiyam 
19533e97647fSksagiyam .seealso: DMPlexTopologyView(), DMPlexSectionView(), DMPlexGlobalVectorView(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad()
19543e97647fSksagiyam @*/
19553e97647fSksagiyam PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec)
19563e97647fSksagiyam {
19573e97647fSksagiyam   PetscBool       ishdf5;
19583e97647fSksagiyam   PetscErrorCode  ierr;
19593e97647fSksagiyam 
19603e97647fSksagiyam   PetscFunctionBegin;
19613e97647fSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
19623e97647fSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
19633e97647fSksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
19643e97647fSksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 4);
19653e97647fSksagiyam   /* Check consistency */
19663e97647fSksagiyam   {
19673e97647fSksagiyam     PetscSection  section;
19683e97647fSksagiyam     PetscBool     includesConstraints;
19693e97647fSksagiyam     PetscInt      m, m1;
19703e97647fSksagiyam 
19713e97647fSksagiyam     ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr);
19723e97647fSksagiyam     ierr = DMGetLocalSection(sectiondm, &section);CHKERRQ(ierr);
19733e97647fSksagiyam     ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr);
19743e97647fSksagiyam     if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);}
19753e97647fSksagiyam     else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);}
19762c71b3e2SJacob Faibussowitsch     PetscCheckFalse(m1 != m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%D) != local section storage size (%D)", m1, m);
19773e97647fSksagiyam   }
19783e97647fSksagiyam   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr);
197902f7d72cSksagiyam   ierr = PetscLogEventBegin(DMPLEX_LocalVectorView,viewer,0,0,0);CHKERRQ(ierr);
19803e97647fSksagiyam   if (ishdf5) {
19813e97647fSksagiyam #if defined(PETSC_HAVE_HDF5)
19823e97647fSksagiyam     ierr = DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec);CHKERRQ(ierr);
19833e97647fSksagiyam #else
19843e97647fSksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
19853e97647fSksagiyam #endif
19863e97647fSksagiyam   }
198702f7d72cSksagiyam   ierr = PetscLogEventEnd(DMPLEX_LocalVectorView,viewer,0,0,0);CHKERRQ(ierr);
19883e97647fSksagiyam   PetscFunctionReturn(0);
19893e97647fSksagiyam }
19903e97647fSksagiyam 
19912c40f234SMatthew G. Knepley PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer)
19922c40f234SMatthew G. Knepley {
1993d4f5a9a0SVaclav Hapla   PetscBool      ishdf5;
19942c40f234SMatthew G. Knepley   PetscErrorCode ierr;
19952c40f234SMatthew G. Knepley 
19962c40f234SMatthew G. Knepley   PetscFunctionBegin;
19972c40f234SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
19982c40f234SMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
19992c40f234SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,   &ishdf5);CHKERRQ(ierr);
2000d4f5a9a0SVaclav Hapla   if (ishdf5) {
20012c40f234SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
20029c48423bSVaclav Hapla     PetscViewerFormat format;
20039c48423bSVaclav Hapla     ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr);
20049c48423bSVaclav Hapla     if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) {
20059c48423bSVaclav Hapla       ierr = DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer);CHKERRQ(ierr);
2006509517efSVaclav Hapla     } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
200739d25373SMatthew G. Knepley       ierr = DMPlexLoad_HDF5_Internal(dm, viewer);CHKERRQ(ierr);
200898921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2009b458e8f1SJose E. Roman     PetscFunctionReturn(0);
20102c40f234SMatthew G. Knepley #else
20112c40f234SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2012552f7358SJed Brown #endif
201398921bdaSJacob Faibussowitsch   } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name);
2014552f7358SJed Brown }
2015552f7358SJed Brown 
2016ea8e1828Sksagiyam /*@
2017ea8e1828Sksagiyam   DMPlexTopologyLoad - Loads a topology into a DMPlex
2018ea8e1828Sksagiyam 
2019ea8e1828Sksagiyam   Collective on DM
2020ea8e1828Sksagiyam 
2021ea8e1828Sksagiyam   Input Parameters:
2022ea8e1828Sksagiyam + dm     - The DM into which the topology is loaded
2023ea8e1828Sksagiyam - viewer - The PetscViewer for the saved topology
2024ea8e1828Sksagiyam 
2025dec9e869Sksagiyam   Output Parameters:
2026f84dd6b4Sksagiyam . globalToLocalPointSF - The PetscSF that pushes points in [0, N) to the associated points in the loaded plex, where N is the global number of points; NULL if unneeded
2027dec9e869Sksagiyam 
2028ea8e1828Sksagiyam   Level: advanced
2029ea8e1828Sksagiyam 
2030b08ad5deSksagiyam .seealso: DMLoad(), DMPlexCoordinatesLoad(), DMPlexLabelsLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat()
2031ea8e1828Sksagiyam @*/
2032f84dd6b4Sksagiyam PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF)
2033ea8e1828Sksagiyam {
2034ea8e1828Sksagiyam   PetscBool      ishdf5;
2035ea8e1828Sksagiyam   PetscErrorCode ierr;
2036ea8e1828Sksagiyam 
2037ea8e1828Sksagiyam   PetscFunctionBegin;
2038ea8e1828Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2039ea8e1828Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2040f84dd6b4Sksagiyam   if (globalToLocalPointSF) PetscValidPointer(globalToLocalPointSF, 3);
2041ea8e1828Sksagiyam   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr);
204202f7d72cSksagiyam   ierr = PetscLogEventBegin(DMPLEX_TopologyLoad,viewer,0,0,0);CHKERRQ(ierr);
2043ea8e1828Sksagiyam   if (ishdf5) {
2044ea8e1828Sksagiyam #if defined(PETSC_HAVE_HDF5)
2045ea8e1828Sksagiyam     PetscViewerFormat format;
2046ea8e1828Sksagiyam     ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr);
2047ea8e1828Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
2048f84dd6b4Sksagiyam       ierr = DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF);CHKERRQ(ierr);
204998921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2050ea8e1828Sksagiyam #else
2051ea8e1828Sksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2052ea8e1828Sksagiyam #endif
2053ea8e1828Sksagiyam   }
205402f7d72cSksagiyam   ierr = PetscLogEventEnd(DMPLEX_TopologyLoad,viewer,0,0,0);CHKERRQ(ierr);
2055ea8e1828Sksagiyam   PetscFunctionReturn(0);
2056ea8e1828Sksagiyam }
2057ea8e1828Sksagiyam 
20583e701f1cSksagiyam /*@
20593e701f1cSksagiyam   DMPlexCoordinatesLoad - Loads coordinates into a DMPlex
20603e701f1cSksagiyam 
20613e701f1cSksagiyam   Collective on DM
20623e701f1cSksagiyam 
20633e701f1cSksagiyam   Input Parameters:
20643e701f1cSksagiyam + dm     - The DM into which the coordinates are loaded
2065c9ad657eSksagiyam . viewer - The PetscViewer for the saved coordinates
2066c9ad657eSksagiyam - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer
20673e701f1cSksagiyam 
20683e701f1cSksagiyam   Level: advanced
20693e701f1cSksagiyam 
2070b08ad5deSksagiyam .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexLabelsLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat()
20713e701f1cSksagiyam @*/
2072c9ad657eSksagiyam PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF)
20733e701f1cSksagiyam {
20743e701f1cSksagiyam   PetscBool      ishdf5;
20753e701f1cSksagiyam   PetscErrorCode ierr;
20763e701f1cSksagiyam 
20773e701f1cSksagiyam   PetscFunctionBegin;
20783e701f1cSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
20793e701f1cSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2080c9ad657eSksagiyam   PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3);
20813e701f1cSksagiyam   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr);
208202f7d72cSksagiyam   ierr = PetscLogEventBegin(DMPLEX_CoordinatesLoad,viewer,0,0,0);CHKERRQ(ierr);
20833e701f1cSksagiyam   if (ishdf5) {
20843e701f1cSksagiyam #if defined(PETSC_HAVE_HDF5)
20853e701f1cSksagiyam     PetscViewerFormat format;
20863e701f1cSksagiyam     ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr);
20873e701f1cSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
2088c9ad657eSksagiyam       ierr = DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF);CHKERRQ(ierr);
208998921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
20903e701f1cSksagiyam #else
20913e701f1cSksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
20923e701f1cSksagiyam #endif
20933e701f1cSksagiyam   }
209402f7d72cSksagiyam   ierr = PetscLogEventEnd(DMPLEX_CoordinatesLoad,viewer,0,0,0);CHKERRQ(ierr);
20953e701f1cSksagiyam   PetscFunctionReturn(0);
20963e701f1cSksagiyam }
20973e701f1cSksagiyam 
2098b08ad5deSksagiyam /*@
2099b08ad5deSksagiyam   DMPlexLabelsLoad - Loads labels into a DMPlex
2100b08ad5deSksagiyam 
2101b08ad5deSksagiyam   Collective on DM
2102b08ad5deSksagiyam 
2103b08ad5deSksagiyam   Input Parameters:
2104b08ad5deSksagiyam + dm     - The DM into which the labels are loaded
2105e6368b79SVaclav Hapla . viewer - The PetscViewer for the saved labels
2106e6368b79SVaclav Hapla - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer
2107b08ad5deSksagiyam 
2108b08ad5deSksagiyam   Level: advanced
2109b08ad5deSksagiyam 
2110e6368b79SVaclav Hapla   Notes:
2111e6368b79SVaclav Hapla   The PetscSF argument must not be NULL if the DM is distributed, otherwise an error occurs.
2112e6368b79SVaclav Hapla 
2113b08ad5deSksagiyam .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexCoordinatesLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat()
2114b08ad5deSksagiyam @*/
2115e6368b79SVaclav Hapla PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF)
2116b08ad5deSksagiyam {
2117b08ad5deSksagiyam   PetscBool      ishdf5;
2118b08ad5deSksagiyam   PetscErrorCode ierr;
2119b08ad5deSksagiyam 
2120b08ad5deSksagiyam   PetscFunctionBegin;
2121b08ad5deSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2122b08ad5deSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2123e6368b79SVaclav Hapla   if (globalToLocalPointSF) PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3);
2124b08ad5deSksagiyam   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr);
212502f7d72cSksagiyam   ierr = PetscLogEventBegin(DMPLEX_LabelsLoad,viewer,0,0,0);CHKERRQ(ierr);
2126b08ad5deSksagiyam   if (ishdf5) {
2127b08ad5deSksagiyam #if defined(PETSC_HAVE_HDF5)
2128b08ad5deSksagiyam     PetscViewerFormat format;
2129b08ad5deSksagiyam 
2130b08ad5deSksagiyam     ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr);
2131b08ad5deSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
2132e6368b79SVaclav Hapla       ierr = DMPlexLabelsLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF);CHKERRQ(ierr);
213398921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2134b08ad5deSksagiyam #else
2135b08ad5deSksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2136b08ad5deSksagiyam #endif
2137b08ad5deSksagiyam   }
213802f7d72cSksagiyam   ierr = PetscLogEventEnd(DMPLEX_LabelsLoad,viewer,0,0,0);CHKERRQ(ierr);
2139b08ad5deSksagiyam   PetscFunctionReturn(0);
2140b08ad5deSksagiyam }
2141b08ad5deSksagiyam 
2142f84dd6b4Sksagiyam /*@
2143f84dd6b4Sksagiyam   DMPlexSectionLoad - Loads section into a DMPlex
2144f84dd6b4Sksagiyam 
2145f84dd6b4Sksagiyam   Collective on DM
2146f84dd6b4Sksagiyam 
2147f84dd6b4Sksagiyam   Input Parameters:
2148f84dd6b4Sksagiyam + dm          - The DM that represents the topology
2149f84dd6b4Sksagiyam . viewer      - The PetscViewer that represents the on-disk section (sectionA)
2150f84dd6b4Sksagiyam . sectiondm   - The DM into which the on-disk section (sectionA) is migrated
2151f84dd6b4Sksagiyam - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer
2152f84dd6b4Sksagiyam 
2153f84dd6b4Sksagiyam   Output Parameters
2154f84dd6b4Sksagiyam + globalDofSF - The SF that migrates any on-disk Vec data associated with sectionA into a global Vec associated with the sectiondm's global section (NULL if not needed)
2155f84dd6b4Sksagiyam - localDofSF  - The SF that migrates any on-disk Vec data associated with sectionA into a local Vec associated with the sectiondm's local section (NULL if not needed)
2156f84dd6b4Sksagiyam 
2157f84dd6b4Sksagiyam   Level: advanced
2158f84dd6b4Sksagiyam 
2159f84dd6b4Sksagiyam   Notes:
2160f84dd6b4Sksagiyam   This function is a wrapper around PetscSectionLoad(); it loads, in addition to the raw section, a list of global point numbers that associates each on-disk section point with a global point number in [0, NX), where NX is the number of topology points in dm. Noting that globalToLocalPointSF associates each topology point in dm with a global number in [0, NX), one can readily establish an association of the on-disk section points with the topology points.
2161f84dd6b4Sksagiyam 
2162f84dd6b4Sksagiyam   In general dm and sectiondm are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with PetscObjectSetName(). In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name.
2163f84dd6b4Sksagiyam 
2164f84dd6b4Sksagiyam   The output parameter, globalDofSF (localDofSF), can later be used with DMPlexGlobalVectorLoad() (DMPlexLocalVectorLoad()) to load on-disk vectors into global (local) vectors associated with sectiondm's global (local) section.
2165f84dd6b4Sksagiyam 
2166f84dd6b4Sksagiyam   Example using 2 processes:
2167f84dd6b4Sksagiyam $  NX (number of points on dm): 4
2168f84dd6b4Sksagiyam $  sectionA                   : the on-disk section
2169f84dd6b4Sksagiyam $  vecA                       : a vector associated with sectionA
2170f84dd6b4Sksagiyam $  sectionB                   : sectiondm's local section constructed in this function
2171f84dd6b4Sksagiyam $  vecB (local)               : a vector associated with sectiondm's local section
2172f84dd6b4Sksagiyam $  vecB (global)              : a vector associated with sectiondm's global section
2173f84dd6b4Sksagiyam $
2174f84dd6b4Sksagiyam $                                     rank 0    rank 1
2175f84dd6b4Sksagiyam $  vecA (global)                  : [.0 .4 .1 | .2 .3]        <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad()
2176f84dd6b4Sksagiyam $  sectionA->atlasOff             :       0 2 | 1             <- loaded in PetscSectionLoad()
2177f84dd6b4Sksagiyam $  sectionA->atlasDof             :       1 3 | 1             <- loaded in PetscSectionLoad()
2178f84dd6b4Sksagiyam $  sectionA's global point numbers:       0 2 | 3             <- loaded in DMPlexSectionLoad()
2179f84dd6b4Sksagiyam $  [0, NX)                        :       0 1 | 2 3           <- conceptual partition used in globalToLocalPointSF
2180f84dd6b4Sksagiyam $  sectionB's global point numbers:     0 1 3 | 3 2           <- associated with [0, NX) by globalToLocalPointSF
2181f84dd6b4Sksagiyam $  sectionB->atlasDof             :     1 0 1 | 1 3
2182f84dd6b4Sksagiyam $  sectionB->atlasOff (no perm)   :     0 1 1 | 0 1
2183f84dd6b4Sksagiyam $  vecB (local)                   :   [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF
2184f84dd6b4Sksagiyam $  vecB (global)                  :    [.0 .4 | .1 .2 .3]     <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF
2185f84dd6b4Sksagiyam $
2186f84dd6b4Sksagiyam $  where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0.
2187f84dd6b4Sksagiyam 
2188f84dd6b4Sksagiyam .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexCoordinatesLoad(), DMPlexLabelsLoad(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad(), PetscSectionLoad(), DMPlexSectionView()
2189f84dd6b4Sksagiyam @*/
2190f84dd6b4Sksagiyam PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF globalToLocalPointSF, PetscSF *globalDofSF, PetscSF *localDofSF)
2191f84dd6b4Sksagiyam {
2192f84dd6b4Sksagiyam   PetscBool      ishdf5;
2193f84dd6b4Sksagiyam   PetscErrorCode ierr;
2194f84dd6b4Sksagiyam 
2195f84dd6b4Sksagiyam   PetscFunctionBegin;
2196f84dd6b4Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2197f84dd6b4Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2198f84dd6b4Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
2199f84dd6b4Sksagiyam   PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4);
2200f84dd6b4Sksagiyam   if (globalDofSF) PetscValidPointer(globalDofSF, 5);
2201f84dd6b4Sksagiyam   if (localDofSF) PetscValidPointer(localDofSF, 6);
2202f84dd6b4Sksagiyam   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr);
220302f7d72cSksagiyam   ierr = PetscLogEventBegin(DMPLEX_SectionLoad,viewer,0,0,0);CHKERRQ(ierr);
2204f84dd6b4Sksagiyam   if (ishdf5) {
2205f84dd6b4Sksagiyam #if defined(PETSC_HAVE_HDF5)
2206f84dd6b4Sksagiyam     ierr = DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF);CHKERRQ(ierr);
2207f84dd6b4Sksagiyam #else
2208f84dd6b4Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2209f84dd6b4Sksagiyam #endif
2210f84dd6b4Sksagiyam   }
221102f7d72cSksagiyam   ierr = PetscLogEventEnd(DMPLEX_SectionLoad,viewer,0,0,0);CHKERRQ(ierr);
2212f84dd6b4Sksagiyam   PetscFunctionReturn(0);
2213f84dd6b4Sksagiyam }
2214f84dd6b4Sksagiyam 
22158be3dfe1Sksagiyam /*@
22168be3dfe1Sksagiyam   DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector
22178be3dfe1Sksagiyam 
22188be3dfe1Sksagiyam   Collective on DM
22198be3dfe1Sksagiyam 
22208be3dfe1Sksagiyam   Input Parameters:
22218be3dfe1Sksagiyam + dm        - The DM that represents the topology
22228be3dfe1Sksagiyam . viewer    - The PetscViewer that represents the on-disk vector data
22238be3dfe1Sksagiyam . sectiondm - The DM that contains the global section on which vec is defined
22248be3dfe1Sksagiyam . sf        - The SF that migrates the on-disk vector data into vec
22258be3dfe1Sksagiyam - vec       - The global vector to set values of
22268be3dfe1Sksagiyam 
22278be3dfe1Sksagiyam   Level: advanced
22288be3dfe1Sksagiyam 
22298be3dfe1Sksagiyam   Notes:
22308be3dfe1Sksagiyam   In general dm and sectiondm are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with PetscObjectSetName(). In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name.
22318be3dfe1Sksagiyam 
22328be3dfe1Sksagiyam   Typical calling sequence
22338be3dfe1Sksagiyam $       DMCreate(PETSC_COMM_WORLD, &dm);
22348be3dfe1Sksagiyam $       DMSetType(dm, DMPLEX);
22358be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)dm, "topologydm_name");
22368be3dfe1Sksagiyam $       DMPlexTopologyLoad(dm, viewer, &sfX);
22378be3dfe1Sksagiyam $       DMClone(dm, &sectiondm);
22388be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
22398be3dfe1Sksagiyam $       DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL);
22408be3dfe1Sksagiyam $       DMGetGlobalVector(sectiondm, &vec);
22418be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)vec, "vec_name");
22428be3dfe1Sksagiyam $       DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec);
22438be3dfe1Sksagiyam $       DMRestoreGlobalVector(sectiondm, &vec);
22448be3dfe1Sksagiyam $       PetscSFDestroy(&gsf);
22458be3dfe1Sksagiyam $       PetscSFDestroy(&sfX);
22468be3dfe1Sksagiyam $       DMDestroy(&sectiondm);
22478be3dfe1Sksagiyam $       DMDestroy(&dm);
22488be3dfe1Sksagiyam 
22498be3dfe1Sksagiyam .seealso: DMPlexTopologyLoad(), DMPlexSectionLoad(), DMPlexLocalVectorLoad(), DMPlexGlobalVectorView(), DMPlexLocalVectorView()
22508be3dfe1Sksagiyam @*/
22518be3dfe1Sksagiyam PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec)
22528be3dfe1Sksagiyam {
22538be3dfe1Sksagiyam   PetscBool       ishdf5;
22548be3dfe1Sksagiyam   PetscErrorCode  ierr;
22558be3dfe1Sksagiyam 
22568be3dfe1Sksagiyam   PetscFunctionBegin;
22578be3dfe1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
22588be3dfe1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
22598be3dfe1Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
22608be3dfe1Sksagiyam   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4);
22618be3dfe1Sksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 5);
22628be3dfe1Sksagiyam   /* Check consistency */
22638be3dfe1Sksagiyam   {
22648be3dfe1Sksagiyam     PetscSection  section;
22658be3dfe1Sksagiyam     PetscBool     includesConstraints;
22668be3dfe1Sksagiyam     PetscInt      m, m1;
22678be3dfe1Sksagiyam 
22688be3dfe1Sksagiyam     ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr);
22698be3dfe1Sksagiyam     ierr = DMGetGlobalSection(sectiondm, &section);CHKERRQ(ierr);
22708be3dfe1Sksagiyam     ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr);
22718be3dfe1Sksagiyam     if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);}
22728be3dfe1Sksagiyam     else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);}
22732c71b3e2SJacob Faibussowitsch     PetscCheckFalse(m1 != m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%D) != global section storage size (%D)", m1, m);
22748be3dfe1Sksagiyam   }
22758be3dfe1Sksagiyam   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr);
227602f7d72cSksagiyam   ierr = PetscLogEventBegin(DMPLEX_GlobalVectorLoad,viewer,0,0,0);CHKERRQ(ierr);
22778be3dfe1Sksagiyam   if (ishdf5) {
22788be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5)
22798be3dfe1Sksagiyam     ierr = DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec);CHKERRQ(ierr);
22808be3dfe1Sksagiyam #else
22818be3dfe1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
22828be3dfe1Sksagiyam #endif
22838be3dfe1Sksagiyam   }
228402f7d72cSksagiyam   ierr = PetscLogEventEnd(DMPLEX_GlobalVectorLoad,viewer,0,0,0);CHKERRQ(ierr);
22858be3dfe1Sksagiyam   PetscFunctionReturn(0);
22868be3dfe1Sksagiyam }
22878be3dfe1Sksagiyam 
22888be3dfe1Sksagiyam /*@
22898be3dfe1Sksagiyam   DMPlexLocalVectorLoad - Loads on-disk vector data into a local vector
22908be3dfe1Sksagiyam 
22918be3dfe1Sksagiyam   Collective on DM
22928be3dfe1Sksagiyam 
22938be3dfe1Sksagiyam   Input Parameters:
22948be3dfe1Sksagiyam + dm        - The DM that represents the topology
22958be3dfe1Sksagiyam . viewer    - The PetscViewer that represents the on-disk vector data
22968be3dfe1Sksagiyam . sectiondm - The DM that contains the local section on which vec is defined
22978be3dfe1Sksagiyam . sf        - The SF that migrates the on-disk vector data into vec
22988be3dfe1Sksagiyam - vec       - The local vector to set values of
22998be3dfe1Sksagiyam 
23008be3dfe1Sksagiyam   Level: advanced
23018be3dfe1Sksagiyam 
23028be3dfe1Sksagiyam   Notes:
23038be3dfe1Sksagiyam   In general dm and sectiondm are two different objects, the former carrying the topology and the latter carrying the section, and have been given a topology name and a section name, respectively, with PetscObjectSetName(). In practice, however, they can be the same object if it carries both topology and section; in that case the name of the object is used as both the topology name and the section name.
23048be3dfe1Sksagiyam 
23058be3dfe1Sksagiyam   Typical calling sequence
23068be3dfe1Sksagiyam $       DMCreate(PETSC_COMM_WORLD, &dm);
23078be3dfe1Sksagiyam $       DMSetType(dm, DMPLEX);
23088be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)dm, "topologydm_name");
23098be3dfe1Sksagiyam $       DMPlexTopologyLoad(dm, viewer, &sfX);
23108be3dfe1Sksagiyam $       DMClone(dm, &sectiondm);
23118be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
23128be3dfe1Sksagiyam $       DMPlexSectionLoad(dm, viewer, sectiondm, sfX, NULL, &lsf);
23138be3dfe1Sksagiyam $       DMGetLocalVector(sectiondm, &vec);
23148be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)vec, "vec_name");
23158be3dfe1Sksagiyam $       DMPlexLocalVectorLoad(dm, viewer, sectiondm, lsf, vec);
23168be3dfe1Sksagiyam $       DMRestoreLocalVector(sectiondm, &vec);
23178be3dfe1Sksagiyam $       PetscSFDestroy(&lsf);
23188be3dfe1Sksagiyam $       PetscSFDestroy(&sfX);
23198be3dfe1Sksagiyam $       DMDestroy(&sectiondm);
23208be3dfe1Sksagiyam $       DMDestroy(&dm);
23218be3dfe1Sksagiyam 
23228be3dfe1Sksagiyam .seealso: DMPlexTopologyLoad(), DMPlexSectionLoad(), DMPlexGlobalVectorLoad(), DMPlexGlobalVectorView(), DMPlexLocalVectorView()
23238be3dfe1Sksagiyam @*/
23248be3dfe1Sksagiyam PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec)
23258be3dfe1Sksagiyam {
23268be3dfe1Sksagiyam   PetscBool       ishdf5;
23278be3dfe1Sksagiyam   PetscErrorCode  ierr;
23288be3dfe1Sksagiyam 
23298be3dfe1Sksagiyam   PetscFunctionBegin;
23308be3dfe1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
23318be3dfe1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
23328be3dfe1Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
23338be3dfe1Sksagiyam   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4);
23348be3dfe1Sksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 5);
23358be3dfe1Sksagiyam   /* Check consistency */
23368be3dfe1Sksagiyam   {
23378be3dfe1Sksagiyam     PetscSection  section;
23388be3dfe1Sksagiyam     PetscBool     includesConstraints;
23398be3dfe1Sksagiyam     PetscInt      m, m1;
23408be3dfe1Sksagiyam 
23418be3dfe1Sksagiyam     ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr);
23428be3dfe1Sksagiyam     ierr = DMGetLocalSection(sectiondm, &section);CHKERRQ(ierr);
23438be3dfe1Sksagiyam     ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr);
23448be3dfe1Sksagiyam     if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);}
23458be3dfe1Sksagiyam     else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);}
23462c71b3e2SJacob Faibussowitsch     PetscCheckFalse(m1 != m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%D) != local section storage size (%D)", m1, m);
23478be3dfe1Sksagiyam   }
23488be3dfe1Sksagiyam   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr);
234902f7d72cSksagiyam   ierr = PetscLogEventBegin(DMPLEX_LocalVectorLoad,viewer,0,0,0);CHKERRQ(ierr);
23508be3dfe1Sksagiyam   if (ishdf5) {
23518be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5)
23528be3dfe1Sksagiyam     ierr = DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec);CHKERRQ(ierr);
23538be3dfe1Sksagiyam #else
23548be3dfe1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
23558be3dfe1Sksagiyam #endif
23568be3dfe1Sksagiyam   }
235702f7d72cSksagiyam   ierr = PetscLogEventEnd(DMPLEX_LocalVectorLoad,viewer,0,0,0);CHKERRQ(ierr);
23588be3dfe1Sksagiyam   PetscFunctionReturn(0);
23598be3dfe1Sksagiyam }
23608be3dfe1Sksagiyam 
2361552f7358SJed Brown PetscErrorCode DMDestroy_Plex(DM dm)
2362552f7358SJed Brown {
2363552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2364552f7358SJed Brown   PetscErrorCode ierr;
2365552f7358SJed Brown 
2366552f7358SJed Brown   PetscFunctionBegin;
23678135c375SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)dm,"DMSetUpGLVisViewer_C",NULL);CHKERRQ(ierr);
23688135c375SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertBoundaryValues_C", NULL);CHKERRQ(ierr);
236928d58a37SPierre Jolivet   ierr = PetscObjectComposeFunction((PetscObject)dm,"DMCreateNeumannOverlap_C", NULL);CHKERRQ(ierr);
23701eb70e55SToby Isaac   ierr = PetscObjectComposeFunction((PetscObject)dm,"DMInterpolateSolution_C", NULL);CHKERRQ(ierr);
23710d644c17SKarl Rupp   if (--mesh->refct > 0) PetscFunctionReturn(0);
2372552f7358SJed Brown   ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr);
2373552f7358SJed Brown   ierr = PetscFree(mesh->cones);CHKERRQ(ierr);
2374552f7358SJed Brown   ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr);
2375552f7358SJed Brown   ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr);
2376be36d101SStefano Zampini   ierr = PetscSectionDestroy(&mesh->subdomainSection);CHKERRQ(ierr);
2377552f7358SJed Brown   ierr = PetscFree(mesh->supports);CHKERRQ(ierr);
2378552f7358SJed Brown   ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr);
2379d9deefdfSMatthew G. Knepley   ierr = PetscFree(mesh->tetgenOpts);CHKERRQ(ierr);
2380d9deefdfSMatthew G. Knepley   ierr = PetscFree(mesh->triangleOpts);CHKERRQ(ierr);
2381012bc364SMatthew G. Knepley   ierr = PetscFree(mesh->transformType);CHKERRQ(ierr);
238277623264SMatthew G. Knepley   ierr = PetscPartitionerDestroy(&mesh->partitioner);CHKERRQ(ierr);
2383a89082eeSMatthew G Knepley   ierr = DMLabelDestroy(&mesh->subpointMap);CHKERRQ(ierr);
238497d8846cSMatthew Knepley   ierr = ISDestroy(&mesh->subpointIS);CHKERRQ(ierr);
2385552f7358SJed Brown   ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr);
2386552f7358SJed Brown   ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr);
2387a68b90caSToby Isaac   ierr = PetscSectionDestroy(&mesh->anchorSection);CHKERRQ(ierr);
2388a68b90caSToby Isaac   ierr = ISDestroy(&mesh->anchorIS);CHKERRQ(ierr);
2389d961a43aSToby Isaac   ierr = PetscSectionDestroy(&mesh->parentSection);CHKERRQ(ierr);
2390d961a43aSToby Isaac   ierr = PetscFree(mesh->parents);CHKERRQ(ierr);
2391d961a43aSToby Isaac   ierr = PetscFree(mesh->childIDs);CHKERRQ(ierr);
2392d961a43aSToby Isaac   ierr = PetscSectionDestroy(&mesh->childSection);CHKERRQ(ierr);
2393d961a43aSToby Isaac   ierr = PetscFree(mesh->children);CHKERRQ(ierr);
2394d6a7ad0dSToby Isaac   ierr = DMDestroy(&mesh->referenceTree);CHKERRQ(ierr);
2395fec49543SMatthew G. Knepley   ierr = PetscGridHashDestroy(&mesh->lbox);CHKERRQ(ierr);
23960a19bb7dSprj-   ierr = PetscFree(mesh->neighbors);CHKERRQ(ierr);
239731b70465SJoe Wallwork   if (mesh->metricCtx) { ierr = PetscFree(mesh->metricCtx);CHKERRQ(ierr); }
2398552f7358SJed Brown   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
2399552f7358SJed Brown   ierr = PetscFree(mesh);CHKERRQ(ierr);
2400552f7358SJed Brown   PetscFunctionReturn(0);
2401552f7358SJed Brown }
2402552f7358SJed Brown 
2403b412c318SBarry Smith PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J)
2404552f7358SJed Brown {
24058d1174e4SMatthew G. Knepley   PetscSection           sectionGlobal;
2406acd755d7SMatthew G. Knepley   PetscInt               bs = -1, mbs;
2407552f7358SJed Brown   PetscInt               localSize;
2408837628f4SStefano Zampini   PetscBool              isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS;
2409552f7358SJed Brown   PetscErrorCode         ierr;
2410b412c318SBarry Smith   MatType                mtype;
24111428887cSShri Abhyankar   ISLocalToGlobalMapping ltog;
2412552f7358SJed Brown 
2413552f7358SJed Brown   PetscFunctionBegin;
2414607a6623SBarry Smith   ierr = MatInitializePackage();CHKERRQ(ierr);
2415b412c318SBarry Smith   mtype = dm->mattype;
2416e87a4003SBarry Smith   ierr = DMGetGlobalSection(dm, &sectionGlobal);CHKERRQ(ierr);
2417552f7358SJed Brown   /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */
2418552f7358SJed Brown   ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr);
241982f516ccSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)dm), J);CHKERRQ(ierr);
2420552f7358SJed Brown   ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
2421552f7358SJed Brown   ierr = MatSetType(*J, mtype);CHKERRQ(ierr);
2422552f7358SJed Brown   ierr = MatSetFromOptions(*J);CHKERRQ(ierr);
2423acd755d7SMatthew G. Knepley   ierr = MatGetBlockSize(*J, &mbs);CHKERRQ(ierr);
2424acd755d7SMatthew G. Knepley   if (mbs > 1) bs = mbs;
2425552f7358SJed Brown   ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr);
2426552f7358SJed Brown   ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr);
2427552f7358SJed Brown   ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr);
2428552f7358SJed Brown   ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr);
2429552f7358SJed Brown   ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr);
2430552f7358SJed Brown   ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr);
2431552f7358SJed Brown   ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr);
2432837628f4SStefano Zampini   ierr = PetscStrcmp(mtype, MATIS, &isMatIS);CHKERRQ(ierr);
2433552f7358SJed Brown   if (!isShell) {
2434837628f4SStefano Zampini     PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS);
2435e432b41dSStefano Zampini     PetscInt  *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2];
2436fad22124SMatthew G Knepley     PetscInt  pStart, pEnd, p, dof, cdof;
2437552f7358SJed Brown 
243800140cc3SStefano Zampini     ierr = DMGetLocalToGlobalMapping(dm,&ltog);CHKERRQ(ierr);
2439552f7358SJed Brown     ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr);
2440e432b41dSStefano Zampini     for (p = pStart; p < pEnd; ++p) {
2441a9d99c84SMatthew G. Knepley       PetscInt bdof;
2442a9d99c84SMatthew G. Knepley 
2443552f7358SJed Brown       ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr);
2444fad22124SMatthew G Knepley       ierr = PetscSectionGetConstraintDof(sectionGlobal, p, &cdof);CHKERRQ(ierr);
24451d17a0a3SMatthew G. Knepley       dof  = dof < 0 ? -(dof+1) : dof;
24461d17a0a3SMatthew G. Knepley       bdof = cdof && (dof-cdof) ? 1 : dof;
24471d17a0a3SMatthew G. Knepley       if (dof) {
24481d17a0a3SMatthew G. Knepley         if (bs < 0)          {bs = bdof;}
2449e432b41dSStefano Zampini         else if (bs != bdof) {bs = 1; break;}
2450552f7358SJed Brown       }
24512a28c762SMatthew G Knepley     }
24522a28c762SMatthew G Knepley     /* Must have same blocksize on all procs (some might have no points) */
2453e432b41dSStefano Zampini     bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs;
2454e432b41dSStefano Zampini     bsLocal[1] = bs;
24550be3e97aSMatthew G. Knepley     ierr = PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);CHKERRQ(ierr);
2456e432b41dSStefano Zampini     if (bsMinMax[0] != bsMinMax[1]) bs = 1;
2457e432b41dSStefano Zampini     else bs = bsMinMax[0];
24586fd5c86aSStefano Zampini     bs = PetscMax(1,bs);
2459be36d101SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*J,ltog,ltog);CHKERRQ(ierr);
2460*0682b8bbSJed Brown     if (dm->prealloc_skip) { // User will likely use MatSetPreallocationCOO(), but still set structural parameters
2461*0682b8bbSJed Brown       ierr = MatSetBlockSize(*J, bs);CHKERRQ(ierr);
2462*0682b8bbSJed Brown       ierr = MatSetUp(*J);CHKERRQ(ierr);
2463*0682b8bbSJed Brown     } else {
24641795a4d1SJed Brown       ierr = PetscCalloc4(localSize/bs, &dnz, localSize/bs, &onz, localSize/bs, &dnzu, localSize/bs, &onzu);CHKERRQ(ierr);
24658d1174e4SMatthew G. Knepley       ierr = DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr);
2466552f7358SJed Brown       ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr);
2467552f7358SJed Brown     }
2468aa0f6e3cSJed Brown   }
2469b1f74addSMatthew G. Knepley   ierr = MatSetDM(*J, dm);CHKERRQ(ierr);
2470552f7358SJed Brown   PetscFunctionReturn(0);
2471552f7358SJed Brown }
2472552f7358SJed Brown 
24737cd05799SMatthew G. Knepley /*@
2474a8f00d21SMatthew G. Knepley   DMPlexGetSubdomainSection - Returns the section associated with the subdomain
2475be36d101SStefano Zampini 
2476be36d101SStefano Zampini   Not collective
2477be36d101SStefano Zampini 
2478be36d101SStefano Zampini   Input Parameter:
2479be36d101SStefano Zampini . mesh - The DMPlex
2480be36d101SStefano Zampini 
2481be36d101SStefano Zampini   Output Parameters:
2482be36d101SStefano Zampini . subsection - The subdomain section
2483be36d101SStefano Zampini 
2484be36d101SStefano Zampini   Level: developer
2485be36d101SStefano Zampini 
2486be36d101SStefano Zampini .seealso:
24877cd05799SMatthew G. Knepley @*/
2488be36d101SStefano Zampini PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection)
2489be36d101SStefano Zampini {
2490be36d101SStefano Zampini   DM_Plex       *mesh = (DM_Plex*) dm->data;
2491be36d101SStefano Zampini   PetscErrorCode ierr;
2492be36d101SStefano Zampini 
2493be36d101SStefano Zampini   PetscFunctionBegin;
2494be36d101SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2495be36d101SStefano Zampini   if (!mesh->subdomainSection) {
2496be36d101SStefano Zampini     PetscSection section;
2497be36d101SStefano Zampini     PetscSF      sf;
2498be36d101SStefano Zampini 
2499be36d101SStefano Zampini     ierr = PetscSFCreate(PETSC_COMM_SELF,&sf);CHKERRQ(ierr);
250092fd8e1eSJed Brown     ierr = DMGetLocalSection(dm,&section);CHKERRQ(ierr);
2501be36d101SStefano Zampini     ierr = PetscSectionCreateGlobalSection(section,sf,PETSC_FALSE,PETSC_TRUE,&mesh->subdomainSection);CHKERRQ(ierr);
2502be36d101SStefano Zampini     ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
2503be36d101SStefano Zampini   }
2504be36d101SStefano Zampini   *subsection = mesh->subdomainSection;
2505be36d101SStefano Zampini   PetscFunctionReturn(0);
2506be36d101SStefano Zampini }
2507be36d101SStefano Zampini 
2508552f7358SJed Brown /*@
2509552f7358SJed Brown   DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd)
2510552f7358SJed Brown 
2511552f7358SJed Brown   Not collective
2512552f7358SJed Brown 
2513552f7358SJed Brown   Input Parameter:
2514552f7358SJed Brown . mesh - The DMPlex
2515552f7358SJed Brown 
2516552f7358SJed Brown   Output Parameters:
2517552f7358SJed Brown + pStart - The first mesh point
2518552f7358SJed Brown - pEnd   - The upper bound for mesh points
2519552f7358SJed Brown 
2520552f7358SJed Brown   Level: beginner
2521552f7358SJed Brown 
2522552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetChart()
2523552f7358SJed Brown @*/
2524552f7358SJed Brown PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd)
2525552f7358SJed Brown {
2526552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2527552f7358SJed Brown   PetscErrorCode ierr;
2528552f7358SJed Brown 
2529552f7358SJed Brown   PetscFunctionBegin;
2530552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2531552f7358SJed Brown   ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr);
2532552f7358SJed Brown   PetscFunctionReturn(0);
2533552f7358SJed Brown }
2534552f7358SJed Brown 
2535552f7358SJed Brown /*@
2536552f7358SJed Brown   DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd)
2537552f7358SJed Brown 
2538552f7358SJed Brown   Not collective
2539552f7358SJed Brown 
2540552f7358SJed Brown   Input Parameters:
2541552f7358SJed Brown + mesh - The DMPlex
2542552f7358SJed Brown . pStart - The first mesh point
2543552f7358SJed Brown - pEnd   - The upper bound for mesh points
2544552f7358SJed Brown 
2545552f7358SJed Brown   Output Parameters:
2546552f7358SJed Brown 
2547552f7358SJed Brown   Level: beginner
2548552f7358SJed Brown 
2549552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetChart()
2550552f7358SJed Brown @*/
2551552f7358SJed Brown PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd)
2552552f7358SJed Brown {
2553552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2554552f7358SJed Brown   PetscErrorCode ierr;
2555552f7358SJed Brown 
2556552f7358SJed Brown   PetscFunctionBegin;
2557552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2558552f7358SJed Brown   ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr);
2559552f7358SJed Brown   ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr);
2560552f7358SJed Brown   PetscFunctionReturn(0);
2561552f7358SJed Brown }
2562552f7358SJed Brown 
2563552f7358SJed Brown /*@
2564eaf898f9SPatrick Sanan   DMPlexGetConeSize - Return the number of in-edges for this point in the DAG
2565552f7358SJed Brown 
2566552f7358SJed Brown   Not collective
2567552f7358SJed Brown 
2568552f7358SJed Brown   Input Parameters:
2569552f7358SJed Brown + mesh - The DMPlex
2570eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
2571552f7358SJed Brown 
2572552f7358SJed Brown   Output Parameter:
2573552f7358SJed Brown . size - The cone size for point p
2574552f7358SJed Brown 
2575552f7358SJed Brown   Level: beginner
2576552f7358SJed Brown 
2577552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart()
2578552f7358SJed Brown @*/
2579552f7358SJed Brown PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size)
2580552f7358SJed Brown {
2581552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2582552f7358SJed Brown   PetscErrorCode ierr;
2583552f7358SJed Brown 
2584552f7358SJed Brown   PetscFunctionBegin;
2585552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2586552f7358SJed Brown   PetscValidPointer(size, 3);
2587552f7358SJed Brown   ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr);
2588552f7358SJed Brown   PetscFunctionReturn(0);
2589552f7358SJed Brown }
2590552f7358SJed Brown 
2591552f7358SJed Brown /*@
2592eaf898f9SPatrick Sanan   DMPlexSetConeSize - Set the number of in-edges for this point in the DAG
2593552f7358SJed Brown 
2594552f7358SJed Brown   Not collective
2595552f7358SJed Brown 
2596552f7358SJed Brown   Input Parameters:
2597552f7358SJed Brown + mesh - The DMPlex
2598eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
2599552f7358SJed Brown - size - The cone size for point p
2600552f7358SJed Brown 
2601552f7358SJed Brown   Output Parameter:
2602552f7358SJed Brown 
2603552f7358SJed Brown   Note:
2604552f7358SJed Brown   This should be called after DMPlexSetChart().
2605552f7358SJed Brown 
2606552f7358SJed Brown   Level: beginner
2607552f7358SJed Brown 
2608552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart()
2609552f7358SJed Brown @*/
2610552f7358SJed Brown PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size)
2611552f7358SJed Brown {
2612552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2613552f7358SJed Brown   PetscErrorCode ierr;
2614552f7358SJed Brown 
2615552f7358SJed Brown   PetscFunctionBegin;
2616552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2617552f7358SJed Brown   ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr);
26180d644c17SKarl Rupp 
2619552f7358SJed Brown   mesh->maxConeSize = PetscMax(mesh->maxConeSize, size);
2620552f7358SJed Brown   PetscFunctionReturn(0);
2621552f7358SJed Brown }
2622552f7358SJed Brown 
2623f5a469b9SMatthew G. Knepley /*@
2624eaf898f9SPatrick Sanan   DMPlexAddConeSize - Add the given number of in-edges to this point in the DAG
2625f5a469b9SMatthew G. Knepley 
2626f5a469b9SMatthew G. Knepley   Not collective
2627f5a469b9SMatthew G. Knepley 
2628f5a469b9SMatthew G. Knepley   Input Parameters:
2629f5a469b9SMatthew G. Knepley + mesh - The DMPlex
2630eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
2631f5a469b9SMatthew G. Knepley - size - The additional cone size for point p
2632f5a469b9SMatthew G. Knepley 
2633f5a469b9SMatthew G. Knepley   Output Parameter:
2634f5a469b9SMatthew G. Knepley 
2635f5a469b9SMatthew G. Knepley   Note:
2636f5a469b9SMatthew G. Knepley   This should be called after DMPlexSetChart().
2637f5a469b9SMatthew G. Knepley 
2638f5a469b9SMatthew G. Knepley   Level: beginner
2639f5a469b9SMatthew G. Knepley 
2640f5a469b9SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexGetConeSize(), DMPlexSetChart()
2641f5a469b9SMatthew G. Knepley @*/
2642f5a469b9SMatthew G. Knepley PetscErrorCode DMPlexAddConeSize(DM dm, PetscInt p, PetscInt size)
2643f5a469b9SMatthew G. Knepley {
2644f5a469b9SMatthew G. Knepley   DM_Plex       *mesh = (DM_Plex*) dm->data;
2645f5a469b9SMatthew G. Knepley   PetscInt       csize;
2646f5a469b9SMatthew G. Knepley   PetscErrorCode ierr;
2647f5a469b9SMatthew G. Knepley 
2648f5a469b9SMatthew G. Knepley   PetscFunctionBegin;
2649f5a469b9SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2650f5a469b9SMatthew G. Knepley   ierr = PetscSectionAddDof(mesh->coneSection, p, size);CHKERRQ(ierr);
2651f5a469b9SMatthew G. Knepley   ierr = PetscSectionGetDof(mesh->coneSection, p, &csize);CHKERRQ(ierr);
2652f5a469b9SMatthew G. Knepley 
2653f5a469b9SMatthew G. Knepley   mesh->maxConeSize = PetscMax(mesh->maxConeSize, csize);
2654f5a469b9SMatthew G. Knepley   PetscFunctionReturn(0);
2655f5a469b9SMatthew G. Knepley }
2656f5a469b9SMatthew G. Knepley 
2657552f7358SJed Brown /*@C
2658eaf898f9SPatrick Sanan   DMPlexGetCone - Return the points on the in-edges for this point in the DAG
2659552f7358SJed Brown 
2660552f7358SJed Brown   Not collective
2661552f7358SJed Brown 
2662552f7358SJed Brown   Input Parameters:
2663833c876bSVaclav Hapla + dm - The DMPlex
2664eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
2665552f7358SJed Brown 
2666552f7358SJed Brown   Output Parameter:
2667552f7358SJed Brown . cone - An array of points which are on the in-edges for point p
2668552f7358SJed Brown 
2669552f7358SJed Brown   Level: beginner
2670552f7358SJed Brown 
26713813dfbdSMatthew G Knepley   Fortran Notes:
26723813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
26733813dfbdSMatthew G Knepley   include petsc.h90 in your code.
2674922102d1SVaclav Hapla   You must also call DMPlexRestoreCone() after you finish using the returned array.
2675922102d1SVaclav Hapla   DMPlexRestoreCone() is not needed/available in C.
26763813dfbdSMatthew G Knepley 
2677e45f02b0SMatthew G. Knepley .seealso: DMPlexGetConeSize(), DMPlexSetCone(), DMPlexGetConeTuple(), DMPlexSetChart()
2678552f7358SJed Brown @*/
2679552f7358SJed Brown PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[])
2680552f7358SJed Brown {
2681552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2682552f7358SJed Brown   PetscInt       off;
2683552f7358SJed Brown   PetscErrorCode ierr;
2684552f7358SJed Brown 
2685552f7358SJed Brown   PetscFunctionBegin;
2686552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2687552f7358SJed Brown   PetscValidPointer(cone, 3);
2688552f7358SJed Brown   ierr  = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr);
2689552f7358SJed Brown   *cone = &mesh->cones[off];
2690552f7358SJed Brown   PetscFunctionReturn(0);
2691552f7358SJed Brown }
2692552f7358SJed Brown 
26930ce7577fSVaclav Hapla /*@C
26940ce7577fSVaclav Hapla   DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG
26950ce7577fSVaclav Hapla 
26960ce7577fSVaclav Hapla   Not collective
26970ce7577fSVaclav Hapla 
26980ce7577fSVaclav Hapla   Input Parameters:
26990ce7577fSVaclav Hapla + dm - The DMPlex
27000ce7577fSVaclav Hapla - p - The IS of points, which must lie in the chart set with DMPlexSetChart()
27010ce7577fSVaclav Hapla 
2702d8d19677SJose E. Roman   Output Parameters:
27030ce7577fSVaclav Hapla + pConesSection - PetscSection describing the layout of pCones
27040ce7577fSVaclav Hapla - pCones - An array of points which are on the in-edges for the point set p
27050ce7577fSVaclav Hapla 
27060ce7577fSVaclav Hapla   Level: intermediate
27070ce7577fSVaclav Hapla 
2708d4636a37SVaclav Hapla .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeRecursive(), DMPlexSetChart()
27090ce7577fSVaclav Hapla @*/
27100ce7577fSVaclav Hapla PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones)
27110ce7577fSVaclav Hapla {
27120ce7577fSVaclav Hapla   PetscSection        cs, newcs;
27130ce7577fSVaclav Hapla   PetscInt            *cones;
27140ce7577fSVaclav Hapla   PetscInt            *newarr=NULL;
27150ce7577fSVaclav Hapla   PetscInt            n;
27160ce7577fSVaclav Hapla   PetscErrorCode      ierr;
27170ce7577fSVaclav Hapla 
27180ce7577fSVaclav Hapla   PetscFunctionBegin;
27190ce7577fSVaclav Hapla   ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr);
27200ce7577fSVaclav Hapla   ierr = DMPlexGetConeSection(dm, &cs);CHKERRQ(ierr);
27210ce7577fSVaclav Hapla   ierr = PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void**)&newarr) : NULL);CHKERRQ(ierr);
27220ce7577fSVaclav Hapla   if (pConesSection) *pConesSection = newcs;
27230ce7577fSVaclav Hapla   if (pCones) {
27240ce7577fSVaclav Hapla     ierr = PetscSectionGetStorageSize(newcs, &n);CHKERRQ(ierr);
27250ce7577fSVaclav Hapla     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones);CHKERRQ(ierr);
27260ce7577fSVaclav Hapla   }
27270ce7577fSVaclav Hapla   PetscFunctionReturn(0);
27280ce7577fSVaclav Hapla }
27290ce7577fSVaclav Hapla 
2730af9eab45SVaclav Hapla /*@
2731af9eab45SVaclav Hapla   DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices.
2732d4636a37SVaclav Hapla 
2733d4636a37SVaclav Hapla   Not collective
2734d4636a37SVaclav Hapla 
2735d4636a37SVaclav Hapla   Input Parameters:
2736d4636a37SVaclav Hapla + dm - The DMPlex
2737af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart()
2738d4636a37SVaclav Hapla 
2739d4636a37SVaclav Hapla   Output Parameter:
2740af9eab45SVaclav Hapla . expandedPoints - An array of vertices recursively expanded from input points
2741d4636a37SVaclav Hapla 
2742d4636a37SVaclav Hapla   Level: advanced
2743d4636a37SVaclav Hapla 
2744af9eab45SVaclav Hapla   Notes:
2745af9eab45SVaclav Hapla   Like DMPlexGetConeRecursive but returns only the 0-depth IS (i.e. vertices only) and no sections.
2746af9eab45SVaclav Hapla   There is no corresponding Restore function, just call ISDestroy() on the returned IS to deallocate.
2747af9eab45SVaclav Hapla 
2748af9eab45SVaclav Hapla .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexGetConeRecursive(), DMPlexRestoreConeRecursive(), DMPlexGetDepth()
2749d4636a37SVaclav Hapla @*/
2750af9eab45SVaclav Hapla PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints)
2751d4636a37SVaclav Hapla {
2752af9eab45SVaclav Hapla   IS                  *expandedPointsAll;
2753af9eab45SVaclav Hapla   PetscInt            depth;
2754d4636a37SVaclav Hapla   PetscErrorCode      ierr;
2755d4636a37SVaclav Hapla 
2756d4636a37SVaclav Hapla   PetscFunctionBegin;
2757af9eab45SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2758af9eab45SVaclav Hapla   PetscValidHeaderSpecific(points, IS_CLASSID, 2);
2759af9eab45SVaclav Hapla   PetscValidPointer(expandedPoints, 3);
2760af9eab45SVaclav Hapla   ierr = DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL);CHKERRQ(ierr);
2761af9eab45SVaclav Hapla   *expandedPoints = expandedPointsAll[0];
27621e1ea65dSPierre Jolivet   ierr = PetscObjectReference((PetscObject)expandedPointsAll[0]);CHKERRQ(ierr);
2763af9eab45SVaclav Hapla   ierr = DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL);CHKERRQ(ierr);
2764af9eab45SVaclav Hapla   PetscFunctionReturn(0);
2765af9eab45SVaclav Hapla }
2766af9eab45SVaclav Hapla 
2767af9eab45SVaclav Hapla /*@
2768af9eab45SVaclav Hapla   DMPlexGetConeRecursive - Expand each given point into its cone points and do that recursively until we end up just with vertices (DAG points of depth 0, i.e. without cones).
2769af9eab45SVaclav Hapla 
2770af9eab45SVaclav Hapla   Not collective
2771af9eab45SVaclav Hapla 
2772af9eab45SVaclav Hapla   Input Parameters:
2773af9eab45SVaclav Hapla + dm - The DMPlex
2774af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart()
2775af9eab45SVaclav Hapla 
2776d8d19677SJose E. Roman   Output Parameters:
2777af9eab45SVaclav Hapla + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth()
2778af9eab45SVaclav Hapla . expandedPoints - (optional) An array of index sets with recursively expanded cones
2779af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points
2780af9eab45SVaclav Hapla 
2781af9eab45SVaclav Hapla   Level: advanced
2782af9eab45SVaclav Hapla 
2783af9eab45SVaclav Hapla   Notes:
2784af9eab45SVaclav Hapla   Like DMPlexGetConeTuple() but recursive.
2785af9eab45SVaclav Hapla 
2786af9eab45SVaclav Hapla   Array expandedPoints has size equal to depth. Each expandedPoints[d] contains DAG points with maximum depth d, recursively cone-wise expanded from the input points.
2787af9eab45SVaclav Hapla   For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc.
2788af9eab45SVaclav Hapla 
2789af9eab45SVaclav Hapla   Array section has size equal to depth.  Each PetscSection sections[d] realizes mapping from expandedPoints[d+1] (section points) to expandedPoints[d] (section dofs) as follows:
2790af9eab45SVaclav Hapla   (1) DAG points in expandedPoints[d+1] with depth d+1 to their cone points in expandedPoints[d];
2791af9eab45SVaclav Hapla   (2) DAG points in expandedPoints[d+1] with depth in [0,d] to the same points in expandedPoints[d].
2792af9eab45SVaclav Hapla 
2793af9eab45SVaclav Hapla .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexRestoreConeRecursive(), DMPlexGetConeRecursiveVertices(), DMPlexGetDepth()
2794af9eab45SVaclav Hapla @*/
2795af9eab45SVaclav Hapla PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[])
2796af9eab45SVaclav Hapla {
2797af9eab45SVaclav Hapla   const PetscInt      *arr0=NULL, *cone=NULL;
2798af9eab45SVaclav Hapla   PetscInt            *arr=NULL, *newarr=NULL;
2799af9eab45SVaclav Hapla   PetscInt            d, depth_, i, n, newn, cn, co, start, end;
2800af9eab45SVaclav Hapla   IS                  *expandedPoints_;
2801af9eab45SVaclav Hapla   PetscSection        *sections_;
2802af9eab45SVaclav Hapla   PetscErrorCode      ierr;
2803af9eab45SVaclav Hapla 
2804af9eab45SVaclav Hapla   PetscFunctionBegin;
2805af9eab45SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2806af9eab45SVaclav Hapla   PetscValidHeaderSpecific(points, IS_CLASSID, 2);
2807af9eab45SVaclav Hapla   if (depth) PetscValidIntPointer(depth, 3);
2808af9eab45SVaclav Hapla   if (expandedPoints) PetscValidPointer(expandedPoints, 4);
2809af9eab45SVaclav Hapla   if (sections) PetscValidPointer(sections, 5);
2810af9eab45SVaclav Hapla   ierr = ISGetLocalSize(points, &n);CHKERRQ(ierr);
2811af9eab45SVaclav Hapla   ierr = ISGetIndices(points, &arr0);CHKERRQ(ierr);
2812af9eab45SVaclav Hapla   ierr = DMPlexGetDepth(dm, &depth_);CHKERRQ(ierr);
2813af9eab45SVaclav Hapla   ierr = PetscCalloc1(depth_, &expandedPoints_);CHKERRQ(ierr);
2814af9eab45SVaclav Hapla   ierr = PetscCalloc1(depth_, &sections_);CHKERRQ(ierr);
2815af9eab45SVaclav Hapla   arr = (PetscInt*) arr0; /* this is ok because first generation of arr is not modified */
2816af9eab45SVaclav Hapla   for (d=depth_-1; d>=0; d--) {
2817af9eab45SVaclav Hapla     ierr = PetscSectionCreate(PETSC_COMM_SELF, &sections_[d]);CHKERRQ(ierr);
2818af9eab45SVaclav Hapla     ierr = PetscSectionSetChart(sections_[d], 0, n);CHKERRQ(ierr);
2819af9eab45SVaclav Hapla     for (i=0; i<n; i++) {
2820af9eab45SVaclav Hapla       ierr = DMPlexGetDepthStratum(dm, d+1, &start, &end);CHKERRQ(ierr);
2821af9eab45SVaclav Hapla       if (arr[i] >= start && arr[i] < end) {
2822af9eab45SVaclav Hapla         ierr = DMPlexGetConeSize(dm, arr[i], &cn);CHKERRQ(ierr);
2823af9eab45SVaclav Hapla         ierr = PetscSectionSetDof(sections_[d], i, cn);CHKERRQ(ierr);
2824af9eab45SVaclav Hapla       } else {
2825af9eab45SVaclav Hapla         ierr = PetscSectionSetDof(sections_[d], i, 1);CHKERRQ(ierr);
2826af9eab45SVaclav Hapla       }
2827af9eab45SVaclav Hapla     }
2828af9eab45SVaclav Hapla     ierr = PetscSectionSetUp(sections_[d]);CHKERRQ(ierr);
2829af9eab45SVaclav Hapla     ierr = PetscSectionGetStorageSize(sections_[d], &newn);CHKERRQ(ierr);
2830af9eab45SVaclav Hapla     ierr = PetscMalloc1(newn, &newarr);CHKERRQ(ierr);
2831af9eab45SVaclav Hapla     for (i=0; i<n; i++) {
2832af9eab45SVaclav Hapla       ierr = PetscSectionGetDof(sections_[d], i, &cn);CHKERRQ(ierr);
2833af9eab45SVaclav Hapla       ierr = PetscSectionGetOffset(sections_[d], i, &co);CHKERRQ(ierr);
2834af9eab45SVaclav Hapla       if (cn > 1) {
2835af9eab45SVaclav Hapla         ierr = DMPlexGetCone(dm, arr[i], &cone);CHKERRQ(ierr);
2836af9eab45SVaclav Hapla         ierr = PetscMemcpy(&newarr[co], cone, cn*sizeof(PetscInt));CHKERRQ(ierr);
2837af9eab45SVaclav Hapla       } else {
2838af9eab45SVaclav Hapla         newarr[co] = arr[i];
2839af9eab45SVaclav Hapla       }
2840af9eab45SVaclav Hapla     }
2841af9eab45SVaclav Hapla     ierr = ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d]);CHKERRQ(ierr);
2842af9eab45SVaclav Hapla     arr = newarr;
2843af9eab45SVaclav Hapla     n = newn;
2844af9eab45SVaclav Hapla   }
2845ba2698f1SMatthew G. Knepley   ierr = ISRestoreIndices(points, &arr0);CHKERRQ(ierr);
2846af9eab45SVaclav Hapla   *depth = depth_;
2847af9eab45SVaclav Hapla   if (expandedPoints) *expandedPoints = expandedPoints_;
2848af9eab45SVaclav Hapla   else {
2849af9eab45SVaclav Hapla     for (d=0; d<depth_; d++) {ierr = ISDestroy(&expandedPoints_[d]);CHKERRQ(ierr);}
2850af9eab45SVaclav Hapla     ierr = PetscFree(expandedPoints_);CHKERRQ(ierr);
2851af9eab45SVaclav Hapla   }
2852af9eab45SVaclav Hapla   if (sections) *sections = sections_;
2853af9eab45SVaclav Hapla   else {
2854af9eab45SVaclav Hapla     for (d=0; d<depth_; d++) {ierr = PetscSectionDestroy(&sections_[d]);CHKERRQ(ierr);}
2855af9eab45SVaclav Hapla     ierr = PetscFree(sections_);CHKERRQ(ierr);
2856af9eab45SVaclav Hapla   }
2857af9eab45SVaclav Hapla   PetscFunctionReturn(0);
2858af9eab45SVaclav Hapla }
2859af9eab45SVaclav Hapla 
2860af9eab45SVaclav Hapla /*@
2861af9eab45SVaclav Hapla   DMPlexRestoreConeRecursive - Deallocates arrays created by DMPlexGetConeRecursive
2862af9eab45SVaclav Hapla 
2863af9eab45SVaclav Hapla   Not collective
2864af9eab45SVaclav Hapla 
2865af9eab45SVaclav Hapla   Input Parameters:
2866af9eab45SVaclav Hapla + dm - The DMPlex
2867af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart()
2868af9eab45SVaclav Hapla 
2869d8d19677SJose E. Roman   Output Parameters:
2870af9eab45SVaclav Hapla + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth()
2871af9eab45SVaclav Hapla . expandedPoints - (optional) An array of recursively expanded cones
2872af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points
2873af9eab45SVaclav Hapla 
2874af9eab45SVaclav Hapla   Level: advanced
2875af9eab45SVaclav Hapla 
2876af9eab45SVaclav Hapla   Notes:
2877af9eab45SVaclav Hapla   See DMPlexGetConeRecursive() for details.
2878af9eab45SVaclav Hapla 
2879af9eab45SVaclav Hapla .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexGetConeRecursive(), DMPlexGetConeRecursiveVertices(), DMPlexGetDepth()
2880af9eab45SVaclav Hapla @*/
2881af9eab45SVaclav Hapla PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[])
2882af9eab45SVaclav Hapla {
2883af9eab45SVaclav Hapla   PetscInt            d, depth_;
2884af9eab45SVaclav Hapla   PetscErrorCode      ierr;
2885af9eab45SVaclav Hapla 
2886af9eab45SVaclav Hapla   PetscFunctionBegin;
2887af9eab45SVaclav Hapla   ierr = DMPlexGetDepth(dm, &depth_);CHKERRQ(ierr);
28882c71b3e2SJacob Faibussowitsch   PetscCheckFalse(depth && *depth != depth_,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive");
2889af9eab45SVaclav Hapla   if (depth) *depth = 0;
2890af9eab45SVaclav Hapla   if (expandedPoints) {
2891af9eab45SVaclav Hapla     for (d=0; d<depth_; d++) {ierr = ISDestroy(&((*expandedPoints)[d]));CHKERRQ(ierr);}
2892af9eab45SVaclav Hapla     ierr = PetscFree(*expandedPoints);CHKERRQ(ierr);
2893af9eab45SVaclav Hapla   }
2894af9eab45SVaclav Hapla   if (sections)  {
2895af9eab45SVaclav Hapla     for (d=0; d<depth_; d++) {ierr = PetscSectionDestroy(&((*sections)[d]));CHKERRQ(ierr);}
2896af9eab45SVaclav Hapla     ierr = PetscFree(*sections);CHKERRQ(ierr);
2897af9eab45SVaclav Hapla   }
2898d4636a37SVaclav Hapla   PetscFunctionReturn(0);
2899d4636a37SVaclav Hapla }
2900d4636a37SVaclav Hapla 
2901552f7358SJed Brown /*@
290292371b87SBarry Smith   DMPlexSetCone - Set the points on the in-edges for this point in the DAG; that is these are the points that cover the specific point
2903552f7358SJed Brown 
2904552f7358SJed Brown   Not collective
2905552f7358SJed Brown 
2906552f7358SJed Brown   Input Parameters:
2907552f7358SJed Brown + mesh - The DMPlex
2908eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
2909552f7358SJed Brown - cone - An array of points which are on the in-edges for point p
2910552f7358SJed Brown 
2911552f7358SJed Brown   Output Parameter:
2912552f7358SJed Brown 
2913552f7358SJed Brown   Note:
2914552f7358SJed Brown   This should be called after all calls to DMPlexSetConeSize() and DMSetUp().
2915552f7358SJed Brown 
2916552f7358SJed Brown   Level: beginner
2917552f7358SJed Brown 
291892371b87SBarry Smith .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp(), DMPlexSetSupport(), DMPlexSetSupportSize()
2919552f7358SJed Brown @*/
2920552f7358SJed Brown PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[])
2921552f7358SJed Brown {
2922552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2923552f7358SJed Brown   PetscInt       pStart, pEnd;
2924552f7358SJed Brown   PetscInt       dof, off, c;
2925552f7358SJed Brown   PetscErrorCode ierr;
2926552f7358SJed Brown 
2927552f7358SJed Brown   PetscFunctionBegin;
2928552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2929552f7358SJed Brown   ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr);
2930552f7358SJed Brown   ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr);
2931552f7358SJed Brown   if (dof) PetscValidPointer(cone, 3);
2932552f7358SJed Brown   ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr);
29332c71b3e2SJacob Faibussowitsch   PetscCheckFalse((p < pStart) || (p >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd);
2934552f7358SJed Brown   for (c = 0; c < dof; ++c) {
29352c71b3e2SJacob Faibussowitsch     PetscCheckFalse((cone[c] < pStart) || (cone[c] >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", cone[c], pStart, pEnd);
2936552f7358SJed Brown     mesh->cones[off+c] = cone[c];
2937552f7358SJed Brown   }
2938552f7358SJed Brown   PetscFunctionReturn(0);
2939552f7358SJed Brown }
2940552f7358SJed Brown 
2941552f7358SJed Brown /*@C
2942eaf898f9SPatrick Sanan   DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG
2943552f7358SJed Brown 
2944552f7358SJed Brown   Not collective
2945552f7358SJed Brown 
2946552f7358SJed Brown   Input Parameters:
2947552f7358SJed Brown + mesh - The DMPlex
2948eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
2949552f7358SJed Brown 
2950552f7358SJed Brown   Output Parameter:
2951552f7358SJed Brown . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an
2952b5a892a1SMatthew G. Knepley                     integer giving the prescription for cone traversal.
2953552f7358SJed Brown 
2954552f7358SJed Brown   Level: beginner
2955552f7358SJed Brown 
2956b5a892a1SMatthew G. Knepley   Notes:
2957b5a892a1SMatthew G. Knepley   The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always
2958b5a892a1SMatthew G. Knepley   the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection
2959b5a892a1SMatthew G. Knepley   of o, however it is not necessarily the inverse. To get the inverse, use DMPolytopeTypeComposeOrientationInv()
2960b5a892a1SMatthew G. Knepley   with the identity.
2961b5a892a1SMatthew G. Knepley 
29623813dfbdSMatthew G Knepley   Fortran Notes:
29633813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
29643813dfbdSMatthew G Knepley   include petsc.h90 in your code.
29653b12b3d8SVaclav Hapla   You must also call DMPlexRestoreConeOrientation() after you finish using the returned array.
2966922102d1SVaclav Hapla   DMPlexRestoreConeOrientation() is not needed/available in C.
29673813dfbdSMatthew G Knepley 
2968b5a892a1SMatthew G. Knepley .seealso: DMPolytopeTypeComposeOrientation(), DMPolytopeTypeComposeOrientationInv(), DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart()
2969552f7358SJed Brown @*/
2970552f7358SJed Brown PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[])
2971552f7358SJed Brown {
2972552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2973552f7358SJed Brown   PetscInt       off;
2974552f7358SJed Brown   PetscErrorCode ierr;
2975552f7358SJed Brown 
2976552f7358SJed Brown   PetscFunctionBegin;
2977552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
297876bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
2979552f7358SJed Brown     PetscInt dof;
2980552f7358SJed Brown     ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr);
2981552f7358SJed Brown     if (dof) PetscValidPointer(coneOrientation, 3);
2982552f7358SJed Brown   }
2983552f7358SJed Brown   ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr);
29840d644c17SKarl Rupp 
2985552f7358SJed Brown   *coneOrientation = &mesh->coneOrientations[off];
2986552f7358SJed Brown   PetscFunctionReturn(0);
2987552f7358SJed Brown }
2988552f7358SJed Brown 
2989552f7358SJed Brown /*@
2990eaf898f9SPatrick Sanan   DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG
2991552f7358SJed Brown 
2992552f7358SJed Brown   Not collective
2993552f7358SJed Brown 
2994552f7358SJed Brown   Input Parameters:
2995552f7358SJed Brown + mesh - The DMPlex
2996eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
2997b5a892a1SMatthew G. Knepley - coneOrientation - An array of orientations
2998552f7358SJed Brown   Output Parameter:
2999552f7358SJed Brown 
3000b5a892a1SMatthew G. Knepley   Notes:
3001552f7358SJed Brown   This should be called after all calls to DMPlexSetConeSize() and DMSetUp().
3002552f7358SJed Brown 
3003b5a892a1SMatthew G. Knepley   The meaning of coneOrientation is detailed in DMPlexGetConeOrientation().
3004b5a892a1SMatthew G. Knepley 
3005552f7358SJed Brown   Level: beginner
3006552f7358SJed Brown 
3007552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp()
3008552f7358SJed Brown @*/
3009552f7358SJed Brown PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[])
3010552f7358SJed Brown {
3011552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3012552f7358SJed Brown   PetscInt       pStart, pEnd;
3013552f7358SJed Brown   PetscInt       dof, off, c;
3014552f7358SJed Brown   PetscErrorCode ierr;
3015552f7358SJed Brown 
3016552f7358SJed Brown   PetscFunctionBegin;
3017552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3018552f7358SJed Brown   ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr);
3019552f7358SJed Brown   ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr);
3020552f7358SJed Brown   if (dof) PetscValidPointer(coneOrientation, 3);
3021552f7358SJed Brown   ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr);
30222c71b3e2SJacob Faibussowitsch   PetscCheckFalse((p < pStart) || (p >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd);
3023552f7358SJed Brown   for (c = 0; c < dof; ++c) {
3024552f7358SJed Brown     PetscInt cdof, o = coneOrientation[c];
3025552f7358SJed Brown 
3026552f7358SJed Brown     ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr);
30272c71b3e2SJacob Faibussowitsch     PetscCheckFalse(o && ((o < -(cdof+1)) || (o >= cdof)),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone orientation %D is not in the valid range [%D. %D)", o, -(cdof+1), cdof);
3028552f7358SJed Brown     mesh->coneOrientations[off+c] = o;
3029552f7358SJed Brown   }
3030552f7358SJed Brown   PetscFunctionReturn(0);
3031552f7358SJed Brown }
3032552f7358SJed Brown 
30337cd05799SMatthew G. Knepley /*@
3034eaf898f9SPatrick Sanan   DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG
30357cd05799SMatthew G. Knepley 
30367cd05799SMatthew G. Knepley   Not collective
30377cd05799SMatthew G. Knepley 
30387cd05799SMatthew G. Knepley   Input Parameters:
30397cd05799SMatthew G. Knepley + mesh - The DMPlex
3040eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
30417cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put
30427cd05799SMatthew G. Knepley - conePoint - The mesh point to insert
30437cd05799SMatthew G. Knepley 
30447cd05799SMatthew G. Knepley   Level: beginner
30457cd05799SMatthew G. Knepley 
30467cd05799SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp()
30477cd05799SMatthew G. Knepley @*/
3048552f7358SJed Brown PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint)
3049552f7358SJed Brown {
3050552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3051552f7358SJed Brown   PetscInt       pStart, pEnd;
3052552f7358SJed Brown   PetscInt       dof, off;
3053552f7358SJed Brown   PetscErrorCode ierr;
3054552f7358SJed Brown 
3055552f7358SJed Brown   PetscFunctionBegin;
3056552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3057552f7358SJed Brown   ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr);
30582c71b3e2SJacob Faibussowitsch   PetscCheckFalse((p < pStart) || (p >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd);
30592c71b3e2SJacob Faibussowitsch   PetscCheckFalse((conePoint < pStart) || (conePoint >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", conePoint, pStart, pEnd);
306077c88f5bSMatthew G Knepley   ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr);
306177c88f5bSMatthew G Knepley   ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr);
30622c71b3e2SJacob Faibussowitsch   PetscCheckFalse((conePos < 0) || (conePos >= dof),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %D of point %D is not in the valid range [0, %D)", conePos, p, dof);
3063552f7358SJed Brown   mesh->cones[off+conePos] = conePoint;
3064552f7358SJed Brown   PetscFunctionReturn(0);
3065552f7358SJed Brown }
3066552f7358SJed Brown 
30677cd05799SMatthew G. Knepley /*@
3068eaf898f9SPatrick Sanan   DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG
30697cd05799SMatthew G. Knepley 
30707cd05799SMatthew G. Knepley   Not collective
30717cd05799SMatthew G. Knepley 
30727cd05799SMatthew G. Knepley   Input Parameters:
30737cd05799SMatthew G. Knepley + mesh - The DMPlex
3074eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
30757cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put
30767cd05799SMatthew G. Knepley - coneOrientation - The point orientation to insert
30777cd05799SMatthew G. Knepley 
30787cd05799SMatthew G. Knepley   Level: beginner
30797cd05799SMatthew G. Knepley 
3080b5a892a1SMatthew G. Knepley   Notes:
3081b5a892a1SMatthew G. Knepley   The meaning of coneOrientation values is detailed in DMPlexGetConeOrientation().
3082b5a892a1SMatthew G. Knepley 
30837cd05799SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp()
30847cd05799SMatthew G. Knepley @*/
308577c88f5bSMatthew G Knepley PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation)
308677c88f5bSMatthew G Knepley {
308777c88f5bSMatthew G Knepley   DM_Plex       *mesh = (DM_Plex*) dm->data;
308877c88f5bSMatthew G Knepley   PetscInt       pStart, pEnd;
308977c88f5bSMatthew G Knepley   PetscInt       dof, off;
309077c88f5bSMatthew G Knepley   PetscErrorCode ierr;
309177c88f5bSMatthew G Knepley 
309277c88f5bSMatthew G Knepley   PetscFunctionBegin;
309377c88f5bSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
309477c88f5bSMatthew G Knepley   ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr);
30952c71b3e2SJacob Faibussowitsch   PetscCheckFalse((p < pStart) || (p >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd);
309677c88f5bSMatthew G Knepley   ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr);
309777c88f5bSMatthew G Knepley   ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr);
30982c71b3e2SJacob Faibussowitsch   PetscCheckFalse((conePos < 0) || (conePos >= dof),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %D of point %D is not in the valid range [0, %D)", conePos, p, dof);
309977c88f5bSMatthew G Knepley   mesh->coneOrientations[off+conePos] = coneOrientation;
310077c88f5bSMatthew G Knepley   PetscFunctionReturn(0);
310177c88f5bSMatthew G Knepley }
310277c88f5bSMatthew G Knepley 
3103552f7358SJed Brown /*@
3104eaf898f9SPatrick Sanan   DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG
3105552f7358SJed Brown 
3106552f7358SJed Brown   Not collective
3107552f7358SJed Brown 
3108552f7358SJed Brown   Input Parameters:
3109552f7358SJed Brown + mesh - The DMPlex
3110eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
3111552f7358SJed Brown 
3112552f7358SJed Brown   Output Parameter:
3113552f7358SJed Brown . size - The support size for point p
3114552f7358SJed Brown 
3115552f7358SJed Brown   Level: beginner
3116552f7358SJed Brown 
3117552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize()
3118552f7358SJed Brown @*/
3119552f7358SJed Brown PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size)
3120552f7358SJed Brown {
3121552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3122552f7358SJed Brown   PetscErrorCode ierr;
3123552f7358SJed Brown 
3124552f7358SJed Brown   PetscFunctionBegin;
3125552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3126552f7358SJed Brown   PetscValidPointer(size, 3);
3127552f7358SJed Brown   ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr);
3128552f7358SJed Brown   PetscFunctionReturn(0);
3129552f7358SJed Brown }
3130552f7358SJed Brown 
3131552f7358SJed Brown /*@
3132eaf898f9SPatrick Sanan   DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG
3133552f7358SJed Brown 
3134552f7358SJed Brown   Not collective
3135552f7358SJed Brown 
3136552f7358SJed Brown   Input Parameters:
3137552f7358SJed Brown + mesh - The DMPlex
3138eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
3139552f7358SJed Brown - size - The support size for point p
3140552f7358SJed Brown 
3141552f7358SJed Brown   Output Parameter:
3142552f7358SJed Brown 
3143552f7358SJed Brown   Note:
3144552f7358SJed Brown   This should be called after DMPlexSetChart().
3145552f7358SJed Brown 
3146552f7358SJed Brown   Level: beginner
3147552f7358SJed Brown 
3148552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart()
3149552f7358SJed Brown @*/
3150552f7358SJed Brown PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size)
3151552f7358SJed Brown {
3152552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3153552f7358SJed Brown   PetscErrorCode ierr;
3154552f7358SJed Brown 
3155552f7358SJed Brown   PetscFunctionBegin;
3156552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3157552f7358SJed Brown   ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr);
31580d644c17SKarl Rupp 
3159552f7358SJed Brown   mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size);
3160552f7358SJed Brown   PetscFunctionReturn(0);
3161552f7358SJed Brown }
3162552f7358SJed Brown 
3163552f7358SJed Brown /*@C
3164eaf898f9SPatrick Sanan   DMPlexGetSupport - Return the points on the out-edges for this point in the DAG
3165552f7358SJed Brown 
3166552f7358SJed Brown   Not collective
3167552f7358SJed Brown 
3168552f7358SJed Brown   Input Parameters:
3169552f7358SJed Brown + mesh - The DMPlex
3170eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
3171552f7358SJed Brown 
3172552f7358SJed Brown   Output Parameter:
3173552f7358SJed Brown . support - An array of points which are on the out-edges for point p
3174552f7358SJed Brown 
3175552f7358SJed Brown   Level: beginner
3176552f7358SJed Brown 
31773813dfbdSMatthew G Knepley   Fortran Notes:
31783813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
31793813dfbdSMatthew G Knepley   include petsc.h90 in your code.
31803b12b3d8SVaclav Hapla   You must also call DMPlexRestoreSupport() after you finish using the returned array.
3181922102d1SVaclav Hapla   DMPlexRestoreSupport() is not needed/available in C.
31823813dfbdSMatthew G Knepley 
3183e45f02b0SMatthew G. Knepley .seealso: DMPlexGetSupportSize(), DMPlexSetSupport(), DMPlexGetCone(), DMPlexSetChart()
3184552f7358SJed Brown @*/
3185552f7358SJed Brown PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[])
3186552f7358SJed Brown {
3187552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3188552f7358SJed Brown   PetscInt       off;
3189552f7358SJed Brown   PetscErrorCode ierr;
3190552f7358SJed Brown 
3191552f7358SJed Brown   PetscFunctionBegin;
3192552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3193552f7358SJed Brown   PetscValidPointer(support, 3);
3194552f7358SJed Brown   ierr     = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr);
3195552f7358SJed Brown   *support = &mesh->supports[off];
3196552f7358SJed Brown   PetscFunctionReturn(0);
3197552f7358SJed Brown }
3198552f7358SJed Brown 
3199552f7358SJed Brown /*@
320092371b87SBarry Smith   DMPlexSetSupport - Set the points on the out-edges for this point in the DAG, that is the list of points that this point covers
3201552f7358SJed Brown 
3202552f7358SJed Brown   Not collective
3203552f7358SJed Brown 
3204552f7358SJed Brown   Input Parameters:
3205552f7358SJed Brown + mesh - The DMPlex
3206eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
320792371b87SBarry Smith - support - An array of points which are on the out-edges for point p
3208552f7358SJed Brown 
3209552f7358SJed Brown   Output Parameter:
3210552f7358SJed Brown 
3211552f7358SJed Brown   Note:
3212552f7358SJed Brown   This should be called after all calls to DMPlexSetSupportSize() and DMSetUp().
3213552f7358SJed Brown 
3214552f7358SJed Brown   Level: beginner
3215552f7358SJed Brown 
321692371b87SBarry Smith .seealso: DMPlexSetCone(), DMPlexSetConeSize(), DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp()
3217552f7358SJed Brown @*/
3218552f7358SJed Brown PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[])
3219552f7358SJed Brown {
3220552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3221552f7358SJed Brown   PetscInt       pStart, pEnd;
3222552f7358SJed Brown   PetscInt       dof, off, c;
3223552f7358SJed Brown   PetscErrorCode ierr;
3224552f7358SJed Brown 
3225552f7358SJed Brown   PetscFunctionBegin;
3226552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3227552f7358SJed Brown   ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr);
3228552f7358SJed Brown   ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr);
3229552f7358SJed Brown   if (dof) PetscValidPointer(support, 3);
3230552f7358SJed Brown   ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr);
32312c71b3e2SJacob Faibussowitsch   PetscCheckFalse((p < pStart) || (p >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd);
3232552f7358SJed Brown   for (c = 0; c < dof; ++c) {
32332c71b3e2SJacob Faibussowitsch     PetscCheckFalse((support[c] < pStart) || (support[c] >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", support[c], pStart, pEnd);
3234552f7358SJed Brown     mesh->supports[off+c] = support[c];
3235552f7358SJed Brown   }
3236552f7358SJed Brown   PetscFunctionReturn(0);
3237552f7358SJed Brown }
3238552f7358SJed Brown 
32397cd05799SMatthew G. Knepley /*@
3240eaf898f9SPatrick Sanan   DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG
32417cd05799SMatthew G. Knepley 
32427cd05799SMatthew G. Knepley   Not collective
32437cd05799SMatthew G. Knepley 
32447cd05799SMatthew G. Knepley   Input Parameters:
32457cd05799SMatthew G. Knepley + mesh - The DMPlex
3246eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
32477cd05799SMatthew G. Knepley . supportPos - The local index in the cone where the point should be put
32487cd05799SMatthew G. Knepley - supportPoint - The mesh point to insert
32497cd05799SMatthew G. Knepley 
32507cd05799SMatthew G. Knepley   Level: beginner
32517cd05799SMatthew G. Knepley 
32527cd05799SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp()
32537cd05799SMatthew G. Knepley @*/
3254552f7358SJed Brown PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint)
3255552f7358SJed Brown {
3256552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3257552f7358SJed Brown   PetscInt       pStart, pEnd;
3258552f7358SJed Brown   PetscInt       dof, off;
3259552f7358SJed Brown   PetscErrorCode ierr;
3260552f7358SJed Brown 
3261552f7358SJed Brown   PetscFunctionBegin;
3262552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3263552f7358SJed Brown   ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr);
3264552f7358SJed Brown   ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr);
3265552f7358SJed Brown   ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr);
32662c71b3e2SJacob Faibussowitsch   PetscCheckFalse((p < pStart) || (p >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd);
32672c71b3e2SJacob Faibussowitsch   PetscCheckFalse((supportPoint < pStart) || (supportPoint >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", supportPoint, pStart, pEnd);
32682c71b3e2SJacob Faibussowitsch   PetscCheckFalse(supportPos >= dof,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support position %D of point %D is not in the valid range [0, %D)", supportPos, p, dof);
3269552f7358SJed Brown   mesh->supports[off+supportPos] = supportPoint;
3270552f7358SJed Brown   PetscFunctionReturn(0);
3271552f7358SJed Brown }
3272552f7358SJed Brown 
3273b5a892a1SMatthew G. Knepley /* Converts an orientation o in the current numbering to the previous scheme used in Plex */
3274b5a892a1SMatthew G. Knepley PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o)
3275b5a892a1SMatthew G. Knepley {
3276b5a892a1SMatthew G. Knepley   switch (ct) {
3277b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:
3278b5a892a1SMatthew G. Knepley       if (o == -1) return -2;
3279b5a892a1SMatthew G. Knepley       break;
3280b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:
3281b5a892a1SMatthew G. Knepley       if (o == -3) return -1;
3282b5a892a1SMatthew G. Knepley       if (o == -2) return -3;
3283b5a892a1SMatthew G. Knepley       if (o == -1) return -2;
3284b5a892a1SMatthew G. Knepley       break;
3285b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:
3286b5a892a1SMatthew G. Knepley       if (o == -4) return -2;
3287b5a892a1SMatthew G. Knepley       if (o == -3) return -1;
3288b5a892a1SMatthew G. Knepley       if (o == -2) return -4;
3289b5a892a1SMatthew G. Knepley       if (o == -1) return -3;
3290b5a892a1SMatthew G. Knepley       break;
3291b5a892a1SMatthew G. Knepley     default: return o;
3292b5a892a1SMatthew G. Knepley   }
3293b5a892a1SMatthew G. Knepley   return o;
3294b5a892a1SMatthew G. Knepley }
3295b5a892a1SMatthew G. Knepley 
3296b5a892a1SMatthew G. Knepley /* Converts an orientation o in the previous scheme used in Plex to the current numbering */
3297b5a892a1SMatthew G. Knepley PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o)
3298b5a892a1SMatthew G. Knepley {
3299b5a892a1SMatthew G. Knepley   switch (ct) {
3300b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:
3301b5a892a1SMatthew G. Knepley       if ((o == -2) || (o == 1)) return -1;
3302b5a892a1SMatthew G. Knepley       if (o == -1) return 0;
3303b5a892a1SMatthew G. Knepley       break;
3304b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:
3305b5a892a1SMatthew G. Knepley       if (o == -3) return -2;
3306b5a892a1SMatthew G. Knepley       if (o == -2) return -1;
3307b5a892a1SMatthew G. Knepley       if (o == -1) return -3;
3308b5a892a1SMatthew G. Knepley       break;
3309b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:
3310b5a892a1SMatthew G. Knepley       if (o == -4) return -2;
3311b5a892a1SMatthew G. Knepley       if (o == -3) return -1;
3312b5a892a1SMatthew G. Knepley       if (o == -2) return -4;
3313b5a892a1SMatthew G. Knepley       if (o == -1) return -3;
3314b5a892a1SMatthew G. Knepley       break;
3315b5a892a1SMatthew G. Knepley     default: return o;
3316b5a892a1SMatthew G. Knepley   }
3317b5a892a1SMatthew G. Knepley   return o;
3318b5a892a1SMatthew G. Knepley }
3319b5a892a1SMatthew G. Knepley 
3320b5a892a1SMatthew G. Knepley /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */
3321b5a892a1SMatthew G. Knepley PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm)
3322b5a892a1SMatthew G. Knepley {
3323b5a892a1SMatthew G. Knepley   PetscInt       pStart, pEnd, p;
3324b5a892a1SMatthew G. Knepley   PetscErrorCode ierr;
3325b5a892a1SMatthew G. Knepley 
3326b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
3327b5a892a1SMatthew G. Knepley   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
3328b5a892a1SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
3329b5a892a1SMatthew G. Knepley     const PetscInt *cone, *ornt;
3330b5a892a1SMatthew G. Knepley     PetscInt        coneSize, c;
3331b5a892a1SMatthew G. Knepley 
3332b5a892a1SMatthew G. Knepley     ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
3333b5a892a1SMatthew G. Knepley     ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr);
3334b5a892a1SMatthew G. Knepley     ierr = DMPlexGetConeOrientation(dm, p, &ornt);CHKERRQ(ierr);
3335b5a892a1SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
3336b5a892a1SMatthew G. Knepley       DMPolytopeType ct;
3337b5a892a1SMatthew G. Knepley       const PetscInt o = ornt[c];
3338b5a892a1SMatthew G. Knepley 
3339b5a892a1SMatthew G. Knepley       ierr = DMPlexGetCellType(dm, cone[c], &ct);CHKERRQ(ierr);
3340b5a892a1SMatthew G. Knepley       switch (ct) {
3341b5a892a1SMatthew G. Knepley         case DM_POLYTOPE_SEGMENT:
3342b5a892a1SMatthew G. Knepley           if ((o == -2) || (o == 1)) {ierr = DMPlexInsertConeOrientation(dm, p, c, -1);CHKERRQ(ierr);}
3343b5a892a1SMatthew G. Knepley           if (o == -1) {ierr = DMPlexInsertConeOrientation(dm, p, c, 0);CHKERRQ(ierr);}
3344b5a892a1SMatthew G. Knepley           break;
3345b5a892a1SMatthew G. Knepley         case DM_POLYTOPE_TRIANGLE:
3346b5a892a1SMatthew G. Knepley           if (o == -3) {ierr = DMPlexInsertConeOrientation(dm, p, c, -2);CHKERRQ(ierr);}
3347b5a892a1SMatthew G. Knepley           if (o == -2) {ierr = DMPlexInsertConeOrientation(dm, p, c, -1);CHKERRQ(ierr);}
3348b5a892a1SMatthew G. Knepley           if (o == -1) {ierr = DMPlexInsertConeOrientation(dm, p, c, -3);CHKERRQ(ierr);}
3349b5a892a1SMatthew G. Knepley           break;
3350b5a892a1SMatthew G. Knepley         case DM_POLYTOPE_QUADRILATERAL:
3351b5a892a1SMatthew G. Knepley           if (o == -4) {ierr = DMPlexInsertConeOrientation(dm, p, c, -2);CHKERRQ(ierr);}
3352b5a892a1SMatthew G. Knepley           if (o == -3) {ierr = DMPlexInsertConeOrientation(dm, p, c, -1);CHKERRQ(ierr);}
3353b5a892a1SMatthew G. Knepley           if (o == -2) {ierr = DMPlexInsertConeOrientation(dm, p, c, -4);CHKERRQ(ierr);}
3354b5a892a1SMatthew G. Knepley           if (o == -1) {ierr = DMPlexInsertConeOrientation(dm, p, c, -3);CHKERRQ(ierr);}
3355b5a892a1SMatthew G. Knepley           break;
3356b5a892a1SMatthew G. Knepley         default: break;
3357b5a892a1SMatthew G. Knepley       }
3358b5a892a1SMatthew G. Knepley     }
3359b5a892a1SMatthew G. Knepley   }
3360b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
3361b5a892a1SMatthew G. Knepley }
3362b5a892a1SMatthew G. Knepley 
3363012bc364SMatthew G. Knepley static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3364b5a892a1SMatthew G. Knepley {
3365b5a892a1SMatthew G. Knepley   DMPolytopeType  ct = DM_POLYTOPE_UNKNOWN;
3366b5a892a1SMatthew G. Knepley   PetscInt       *closure;
3367b5a892a1SMatthew G. Knepley   const PetscInt *tmp = NULL, *tmpO = NULL;
3368b5a892a1SMatthew G. Knepley   PetscInt        off = 0, tmpSize, t;
3369b5a892a1SMatthew G. Knepley   PetscErrorCode  ierr;
3370b5a892a1SMatthew G. Knepley 
3371b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3372b5a892a1SMatthew G. Knepley   if (ornt) {
3373b5a892a1SMatthew G. Knepley     ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
3374b5a892a1SMatthew G. Knepley     if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN;
3375b5a892a1SMatthew G. Knepley   }
3376b5a892a1SMatthew G. Knepley   if (*points) {
3377b5a892a1SMatthew G. Knepley     closure = *points;
3378b5a892a1SMatthew G. Knepley   } else {
3379b5a892a1SMatthew G. Knepley     PetscInt maxConeSize, maxSupportSize;
3380b5a892a1SMatthew G. Knepley     ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr);
3381b5a892a1SMatthew G. Knepley     ierr = DMGetWorkArray(dm, 2*(PetscMax(maxConeSize, maxSupportSize)+1), MPIU_INT, &closure);CHKERRQ(ierr);
3382b5a892a1SMatthew G. Knepley   }
3383b5a892a1SMatthew G. Knepley   if (useCone) {
3384b5a892a1SMatthew G. Knepley     ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr);
3385b5a892a1SMatthew G. Knepley     ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr);
3386b5a892a1SMatthew G. Knepley     ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr);
3387b5a892a1SMatthew G. Knepley   } else {
3388b5a892a1SMatthew G. Knepley     ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr);
3389b5a892a1SMatthew G. Knepley     ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr);
3390b5a892a1SMatthew G. Knepley   }
3391b5a892a1SMatthew G. Knepley   if (ct == DM_POLYTOPE_UNKNOWN) {
3392b5a892a1SMatthew G. Knepley     closure[off++] = p;
3393b5a892a1SMatthew G. Knepley     closure[off++] = 0;
3394b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3395b5a892a1SMatthew G. Knepley       closure[off++] = tmp[t];
3396b5a892a1SMatthew G. Knepley       closure[off++] = tmpO ? tmpO[t] : 0;
3397b5a892a1SMatthew G. Knepley     }
3398b5a892a1SMatthew G. Knepley   } else {
3399b5a892a1SMatthew G. Knepley     const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, ornt);CHKERRQ(ierr);
3400b5a892a1SMatthew G. Knepley 
3401b5a892a1SMatthew G. Knepley     /* We assume that cells with a valid type have faces with a valid type */
3402b5a892a1SMatthew G. Knepley     closure[off++] = p;
3403b5a892a1SMatthew G. Knepley     closure[off++] = ornt;
3404b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3405b5a892a1SMatthew G. Knepley       DMPolytopeType ft;
3406b5a892a1SMatthew G. Knepley 
3407b5a892a1SMatthew G. Knepley       ierr = DMPlexGetCellType(dm, tmp[t], &ft);CHKERRQ(ierr);
3408b5a892a1SMatthew G. Knepley       closure[off++] = tmp[arr[t]];
3409b5a892a1SMatthew G. Knepley       closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0;
3410b5a892a1SMatthew G. Knepley     }
3411b5a892a1SMatthew G. Knepley   }
3412b5a892a1SMatthew G. Knepley   if (numPoints) *numPoints = tmpSize+1;
3413b5a892a1SMatthew G. Knepley   if (points)    *points    = closure;
3414b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
3415b5a892a1SMatthew G. Knepley }
3416b5a892a1SMatthew G. Knepley 
3417b5a892a1SMatthew G. Knepley /* We need a special tensor verison becasue we want to allow duplicate points in the endcaps for hybrid cells */
3418b5a892a1SMatthew G. Knepley static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points)
3419b5a892a1SMatthew G. Knepley {
3420b5a892a1SMatthew G. Knepley   const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, o);
3421b5a892a1SMatthew G. Knepley   const PetscInt *cone, *ornt;
3422b5a892a1SMatthew G. Knepley   PetscInt       *pts,  *closure = NULL;
3423b5a892a1SMatthew G. Knepley   DMPolytopeType  ft;
3424b5a892a1SMatthew G. Knepley   PetscInt        maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize;
3425b5a892a1SMatthew G. Knepley   PetscInt        dim, coneSize, c, d, clSize, cl;
3426b5a892a1SMatthew G. Knepley   PetscErrorCode  ierr;
3427b5a892a1SMatthew G. Knepley 
3428b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3429b5a892a1SMatthew G. Knepley   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
3430b5a892a1SMatthew G. Knepley   ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr);
3431b5a892a1SMatthew G. Knepley   ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr);
3432b5a892a1SMatthew G. Knepley   ierr = DMPlexGetConeOrientation(dm, point, &ornt);CHKERRQ(ierr);
3433b5a892a1SMatthew G. Knepley   ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr);
3434b5a892a1SMatthew G. Knepley   coneSeries    = (maxConeSize    > 1) ? ((PetscPowInt(maxConeSize,    dim+1)-1)/(maxConeSize-1))    : dim+1;
3435b5a892a1SMatthew G. Knepley   supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim+1)-1)/(maxSupportSize-1)) : dim+1;
3436b5a892a1SMatthew G. Knepley   maxSize       = PetscMax(coneSeries, supportSeries);
3437b5a892a1SMatthew G. Knepley   if (*points) {pts  = *points;}
3438b5a892a1SMatthew G. Knepley   else         {ierr = DMGetWorkArray(dm, 2*maxSize, MPIU_INT, &pts);CHKERRQ(ierr);}
3439b5a892a1SMatthew G. Knepley   c    = 0;
3440b5a892a1SMatthew G. Knepley   pts[c++] = point;
3441b5a892a1SMatthew G. Knepley   pts[c++] = o;
3442b5a892a1SMatthew G. Knepley   ierr = DMPlexGetCellType(dm, cone[arr[0*2+0]], &ft);CHKERRQ(ierr);
3443b5a892a1SMatthew G. Knepley   ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0*2+0]], DMPolytopeTypeComposeOrientation(ft, arr[0*2+1], ornt[0]), useCone, &clSize, &closure);CHKERRQ(ierr);
3444b5a892a1SMatthew G. Knepley   for (cl = 0; cl < clSize*2; cl += 2) {pts[c++] = closure[cl]; pts[c++] = closure[cl+1];}
3445b5a892a1SMatthew G. Knepley   ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1*2+0]], DMPolytopeTypeComposeOrientation(ft, arr[1*2+1], ornt[1]), useCone, &clSize, &closure);CHKERRQ(ierr);
3446b5a892a1SMatthew G. Knepley   for (cl = 0; cl < clSize*2; cl += 2) {pts[c++] = closure[cl]; pts[c++] = closure[cl+1];}
3447b5a892a1SMatthew G. Knepley   ierr = DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure);CHKERRQ(ierr);
3448b5a892a1SMatthew G. Knepley   for (d = 2; d < coneSize; ++d) {
3449b5a892a1SMatthew G. Knepley     ierr = DMPlexGetCellType(dm, cone[arr[d*2+0]], &ft);CHKERRQ(ierr);
3450b5a892a1SMatthew G. Knepley     pts[c++] = cone[arr[d*2+0]];
3451b5a892a1SMatthew G. Knepley     pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d*2+1], ornt[d]);
3452b5a892a1SMatthew G. Knepley   }
3453b5a892a1SMatthew G. Knepley   if (dim >= 3) {
3454b5a892a1SMatthew G. Knepley     for (d = 2; d < coneSize; ++d) {
3455b5a892a1SMatthew G. Knepley       const PetscInt  fpoint = cone[arr[d*2+0]];
3456b5a892a1SMatthew G. Knepley       const PetscInt *fcone, *fornt;
3457b5a892a1SMatthew G. Knepley       PetscInt        fconeSize, fc, i;
3458b5a892a1SMatthew G. Knepley 
3459b5a892a1SMatthew G. Knepley       ierr = DMPlexGetCellType(dm, fpoint, &ft);CHKERRQ(ierr);
3460b5a892a1SMatthew G. Knepley       const PetscInt *farr = DMPolytopeTypeGetArrangment(ft, DMPolytopeTypeComposeOrientation(ft, arr[d*2+1], ornt[d]));
3461b5a892a1SMatthew G. Knepley       ierr = DMPlexGetConeSize(dm, fpoint, &fconeSize);CHKERRQ(ierr);
3462b5a892a1SMatthew G. Knepley       ierr = DMPlexGetCone(dm, fpoint, &fcone);CHKERRQ(ierr);
3463b5a892a1SMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, fpoint, &fornt);CHKERRQ(ierr);
3464b5a892a1SMatthew G. Knepley       for (fc = 0; fc < fconeSize; ++fc) {
3465b5a892a1SMatthew G. Knepley         const PetscInt cp = fcone[farr[fc*2+0]];
3466b5a892a1SMatthew G. Knepley         const PetscInt co = farr[fc*2+1];
3467b5a892a1SMatthew G. Knepley 
3468b5a892a1SMatthew G. Knepley         for (i = 0; i < c; i += 2) if (pts[i] == cp) break;
3469b5a892a1SMatthew G. Knepley         if (i == c) {
3470b5a892a1SMatthew G. Knepley           ierr = DMPlexGetCellType(dm, cp, &ft);CHKERRQ(ierr);
3471b5a892a1SMatthew G. Knepley           pts[c++] = cp;
3472b5a892a1SMatthew G. Knepley           pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc*2+0]]);
3473b5a892a1SMatthew G. Knepley         }
3474b5a892a1SMatthew G. Knepley       }
3475b5a892a1SMatthew G. Knepley     }
3476b5a892a1SMatthew G. Knepley   }
3477b5a892a1SMatthew G. Knepley   *numPoints = c/2;
3478b5a892a1SMatthew G. Knepley   *points    = pts;
3479b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
3480b5a892a1SMatthew G. Knepley }
3481b5a892a1SMatthew G. Knepley 
3482b5a892a1SMatthew G. Knepley PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3483b5a892a1SMatthew G. Knepley {
3484b5a892a1SMatthew G. Knepley   DMPolytopeType ct;
3485b5a892a1SMatthew G. Knepley   PetscInt      *closure, *fifo;
3486b5a892a1SMatthew G. Knepley   PetscInt       closureSize = 0, fifoStart = 0, fifoSize = 0;
3487b5a892a1SMatthew G. Knepley   PetscInt       maxConeSize, maxSupportSize, coneSeries, supportSeries;
3488b5a892a1SMatthew G. Knepley   PetscInt       depth, maxSize;
3489b5a892a1SMatthew G. Knepley   PetscErrorCode ierr;
3490b5a892a1SMatthew G. Knepley 
3491b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3492b5a892a1SMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
3493b5a892a1SMatthew G. Knepley   if (depth == 1) {
3494012bc364SMatthew G. Knepley     ierr = DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points);CHKERRQ(ierr);
3495b5a892a1SMatthew G. Knepley     PetscFunctionReturn(0);
3496b5a892a1SMatthew G. Knepley   }
3497b5a892a1SMatthew G. Knepley   ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
3498b5a892a1SMatthew G. Knepley   if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN;
3499b5a892a1SMatthew G. Knepley   if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || ct == DM_POLYTOPE_TRI_PRISM_TENSOR || ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) {
3500b5a892a1SMatthew G. Knepley     ierr = DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points);CHKERRQ(ierr);
3501b5a892a1SMatthew G. Knepley     PetscFunctionReturn(0);
3502b5a892a1SMatthew G. Knepley   }
3503b5a892a1SMatthew G. Knepley   ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr);
3504b5a892a1SMatthew G. Knepley   coneSeries    = (maxConeSize    > 1) ? ((PetscPowInt(maxConeSize,    depth+1)-1)/(maxConeSize-1))    : depth+1;
3505b5a892a1SMatthew G. Knepley   supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth+1)-1)/(maxSupportSize-1)) : depth+1;
3506b5a892a1SMatthew G. Knepley   maxSize       = PetscMax(coneSeries, supportSeries);
3507b5a892a1SMatthew G. Knepley   ierr = DMGetWorkArray(dm, 3*maxSize, MPIU_INT, &fifo);CHKERRQ(ierr);
3508b5a892a1SMatthew G. Knepley   if (*points) {closure = *points;}
3509b5a892a1SMatthew G. Knepley   else         {ierr = DMGetWorkArray(dm, 2*maxSize, MPIU_INT, &closure);CHKERRQ(ierr);}
3510b5a892a1SMatthew G. Knepley   closure[closureSize++] = p;
3511b5a892a1SMatthew G. Knepley   closure[closureSize++] = ornt;
3512b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = p;
3513b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = ornt;
3514b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = ct;
3515b5a892a1SMatthew G. Knepley   /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */
3516b5a892a1SMatthew G. Knepley   while (fifoSize - fifoStart) {
3517b5a892a1SMatthew G. Knepley     const PetscInt       q    = fifo[fifoStart++];
3518b5a892a1SMatthew G. Knepley     const PetscInt       o    = fifo[fifoStart++];
3519b5a892a1SMatthew G. Knepley     const DMPolytopeType qt   = (DMPolytopeType) fifo[fifoStart++];
3520b5a892a1SMatthew G. Knepley     const PetscInt      *qarr = DMPolytopeTypeGetArrangment(qt, o);
3521b5a892a1SMatthew G. Knepley     const PetscInt      *tmp, *tmpO;
3522b5a892a1SMatthew G. Knepley     PetscInt             tmpSize, t;
3523b5a892a1SMatthew G. Knepley 
3524b5a892a1SMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) {
3525b5a892a1SMatthew G. Knepley       PetscInt nO = DMPolytopeTypeGetNumArrangments(qt)/2;
35262c71b3e2SJacob Faibussowitsch       PetscCheckFalse(o && (o >= nO || o < -nO),PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid orientation %D not in [%D,%D) for %s %D", o, -nO, nO, DMPolytopeTypes[qt], q);
3527b5a892a1SMatthew G. Knepley     }
3528b5a892a1SMatthew G. Knepley     if (useCone) {
3529b5a892a1SMatthew G. Knepley       ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr);
3530b5a892a1SMatthew G. Knepley       ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr);
3531b5a892a1SMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr);
3532b5a892a1SMatthew G. Knepley     } else {
3533b5a892a1SMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr);
3534b5a892a1SMatthew G. Knepley       ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr);
3535b5a892a1SMatthew G. Knepley       tmpO = NULL;
3536b5a892a1SMatthew G. Knepley     }
3537b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3538b5a892a1SMatthew G. Knepley       const PetscInt ip = useCone && qarr ? qarr[t*2]   : t;
3539b5a892a1SMatthew G. Knepley       const PetscInt io = useCone && qarr ? qarr[t*2+1] : 0;
3540b5a892a1SMatthew G. Knepley       const PetscInt cp = tmp[ip];
3541b5a892a1SMatthew G. Knepley       ierr = DMPlexGetCellType(dm, cp, &ct);CHKERRQ(ierr);
3542b5a892a1SMatthew G. Knepley       const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0;
3543b5a892a1SMatthew G. Knepley       PetscInt       c;
3544b5a892a1SMatthew G. Knepley 
3545b5a892a1SMatthew G. Knepley       /* Check for duplicate */
3546b5a892a1SMatthew G. Knepley       for (c = 0; c < closureSize; c += 2) {
3547b5a892a1SMatthew G. Knepley         if (closure[c] == cp) break;
3548b5a892a1SMatthew G. Knepley       }
3549b5a892a1SMatthew G. Knepley       if (c == closureSize) {
3550b5a892a1SMatthew G. Knepley         closure[closureSize++] = cp;
3551b5a892a1SMatthew G. Knepley         closure[closureSize++] = co;
3552b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = cp;
3553b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = co;
3554b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = ct;
3555b5a892a1SMatthew G. Knepley       }
3556b5a892a1SMatthew G. Knepley     }
3557b5a892a1SMatthew G. Knepley   }
3558b5a892a1SMatthew G. Knepley   ierr = DMRestoreWorkArray(dm, 3*maxSize, MPIU_INT, &fifo);CHKERRQ(ierr);
3559b5a892a1SMatthew G. Knepley   if (numPoints) *numPoints = closureSize/2;
3560b5a892a1SMatthew G. Knepley   if (points)    *points    = closure;
3561b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
3562b5a892a1SMatthew G. Knepley }
3563b5a892a1SMatthew G. Knepley 
3564552f7358SJed Brown /*@C
3565eaf898f9SPatrick Sanan   DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG
3566552f7358SJed Brown 
3567552f7358SJed Brown   Not collective
3568552f7358SJed Brown 
3569552f7358SJed Brown   Input Parameters:
3570b5a892a1SMatthew G. Knepley + dm      - The DMPlex
3571b5a892a1SMatthew G. Knepley . p       - The mesh point
35726b867d5aSJose E. Roman - useCone - PETSC_TRUE for the closure, otherwise return the star
3573552f7358SJed Brown 
35746b867d5aSJose E. Roman   Input/Output Parameter:
35756b867d5aSJose E. Roman . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...];
35766b867d5aSJose E. Roman            if NULL on input, internal storage will be returned, otherwise the provided array is used
35776b867d5aSJose E. Roman 
35786b867d5aSJose E. Roman   Output Parameter:
35796b867d5aSJose E. Roman . numPoints - The number of points in the closure, so points[] is of size 2*numPoints
3580552f7358SJed Brown 
3581552f7358SJed Brown   Note:
35820298fd71SBarry Smith   If using internal storage (points is NULL on input), each call overwrites the last output.
3583552f7358SJed Brown 
35843813dfbdSMatthew G Knepley   Fortran Notes:
3585b5a892a1SMatthew G. Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must include petsc.h90 in your code.
35863813dfbdSMatthew G Knepley 
35873813dfbdSMatthew G Knepley   The numPoints argument is not present in the Fortran 90 binding since it is internal to the array.
35883813dfbdSMatthew G Knepley 
3589552f7358SJed Brown   Level: beginner
3590552f7358SJed Brown 
3591552f7358SJed Brown .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone()
3592552f7358SJed Brown @*/
3593552f7358SJed Brown PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3594552f7358SJed Brown {
3595552f7358SJed Brown   PetscErrorCode ierr;
3596552f7358SJed Brown 
3597b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3598552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3599b5a892a1SMatthew G. Knepley   if (numPoints) PetscValidIntPointer(numPoints, 4);
3600b5a892a1SMatthew G. Knepley   if (points)    PetscValidPointer(points, 5);
3601b5a892a1SMatthew G. Knepley   ierr = DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points);CHKERRQ(ierr);
36029bf0dad6SMatthew G. Knepley   PetscFunctionReturn(0);
36039bf0dad6SMatthew G. Knepley }
36049bf0dad6SMatthew G. Knepley 
3605552f7358SJed Brown /*@C
3606eaf898f9SPatrick Sanan   DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG
3607552f7358SJed Brown 
3608552f7358SJed Brown   Not collective
3609552f7358SJed Brown 
3610552f7358SJed Brown   Input Parameters:
3611b5a892a1SMatthew G. Knepley + dm        - The DMPlex
3612b5a892a1SMatthew G. Knepley . p         - The mesh point
3613b5a892a1SMatthew G. Knepley . useCone   - PETSC_TRUE for the closure, otherwise return the star
3614b5a892a1SMatthew G. Knepley . numPoints - The number of points in the closure, so points[] is of size 2*numPoints
3615b5a892a1SMatthew G. Knepley - points    - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]
3616552f7358SJed Brown 
3617552f7358SJed Brown   Note:
36180298fd71SBarry Smith   If not using internal storage (points is not NULL on input), this call is unnecessary
3619552f7358SJed Brown 
36203813dfbdSMatthew G Knepley   Fortran Notes:
3621b5a892a1SMatthew G. Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must include petsc.h90 in your code.
36223813dfbdSMatthew G Knepley 
36233813dfbdSMatthew G Knepley   The numPoints argument is not present in the Fortran 90 binding since it is internal to the array.
36243813dfbdSMatthew G Knepley 
3625552f7358SJed Brown   Level: beginner
3626552f7358SJed Brown 
3627552f7358SJed Brown .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone()
3628552f7358SJed Brown @*/
3629552f7358SJed Brown PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3630552f7358SJed Brown {
3631552f7358SJed Brown   PetscErrorCode ierr;
3632552f7358SJed Brown 
3633b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3634552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36354ff43b2cSJed Brown   if (numPoints) *numPoints = 0;
3636b5a892a1SMatthew G. Knepley   ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, points);CHKERRQ(ierr);
3637552f7358SJed Brown   PetscFunctionReturn(0);
3638552f7358SJed Brown }
3639552f7358SJed Brown 
3640552f7358SJed Brown /*@
3641eaf898f9SPatrick Sanan   DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG
3642552f7358SJed Brown 
3643552f7358SJed Brown   Not collective
3644552f7358SJed Brown 
3645552f7358SJed Brown   Input Parameter:
3646552f7358SJed Brown . mesh - The DMPlex
3647552f7358SJed Brown 
3648552f7358SJed Brown   Output Parameters:
3649552f7358SJed Brown + maxConeSize - The maximum number of in-edges
3650552f7358SJed Brown - maxSupportSize - The maximum number of out-edges
3651552f7358SJed Brown 
3652552f7358SJed Brown   Level: beginner
3653552f7358SJed Brown 
3654552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart()
3655552f7358SJed Brown @*/
3656552f7358SJed Brown PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize)
3657552f7358SJed Brown {
3658552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
3659552f7358SJed Brown 
3660552f7358SJed Brown   PetscFunctionBegin;
3661552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3662552f7358SJed Brown   if (maxConeSize)    *maxConeSize    = mesh->maxConeSize;
3663552f7358SJed Brown   if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize;
3664552f7358SJed Brown   PetscFunctionReturn(0);
3665552f7358SJed Brown }
3666552f7358SJed Brown 
3667552f7358SJed Brown PetscErrorCode DMSetUp_Plex(DM dm)
3668552f7358SJed Brown {
3669552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3670552f7358SJed Brown   PetscInt       size;
3671552f7358SJed Brown   PetscErrorCode ierr;
3672552f7358SJed Brown 
3673552f7358SJed Brown   PetscFunctionBegin;
3674552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3675552f7358SJed Brown   ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr);
3676552f7358SJed Brown   ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr);
36771795a4d1SJed Brown   ierr = PetscMalloc1(size, &mesh->cones);CHKERRQ(ierr);
36781795a4d1SJed Brown   ierr = PetscCalloc1(size, &mesh->coneOrientations);CHKERRQ(ierr);
3679ef1259faSMatthew G. Knepley   ierr = PetscLogObjectMemory((PetscObject) dm, size*2*sizeof(PetscInt));CHKERRQ(ierr);
3680552f7358SJed Brown   if (mesh->maxSupportSize) {
3681552f7358SJed Brown     ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr);
3682552f7358SJed Brown     ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr);
36831795a4d1SJed Brown     ierr = PetscMalloc1(size, &mesh->supports);CHKERRQ(ierr);
3684ef1259faSMatthew G. Knepley     ierr = PetscLogObjectMemory((PetscObject) dm, size*sizeof(PetscInt));CHKERRQ(ierr);
3685552f7358SJed Brown   }
3686552f7358SJed Brown   PetscFunctionReturn(0);
3687552f7358SJed Brown }
3688552f7358SJed Brown 
3689276c5506SMatthew G. Knepley PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm)
3690552f7358SJed Brown {
3691552f7358SJed Brown   PetscErrorCode ierr;
3692552f7358SJed Brown 
3693552f7358SJed Brown   PetscFunctionBegin;
36944d9407bcSMatthew G. Knepley   if (subdm) {ierr = DMClone(dm, subdm);CHKERRQ(ierr);}
3695792b654fSMatthew G. Knepley   ierr = DMCreateSectionSubDM(dm, numFields, fields, is, subdm);CHKERRQ(ierr);
3696c2939958SSatish Balay   if (subdm) {(*subdm)->useNatural = dm->useNatural;}
3697736995cdSBlaise Bourdin   if (dm->useNatural && dm->sfMigration) {
3698f94b4a02SBlaise Bourdin     PetscSF        sfMigrationInv,sfNatural;
3699f94b4a02SBlaise Bourdin     PetscSection   section, sectionSeq;
3700f94b4a02SBlaise Bourdin 
37013dcd263cSBlaise Bourdin     (*subdm)->sfMigration = dm->sfMigration;
37023dcd263cSBlaise Bourdin     ierr = PetscObjectReference((PetscObject) dm->sfMigration);CHKERRQ(ierr);
3703c3b366b1Sprj-     ierr = DMGetLocalSection((*subdm), &section);CHKERRQ(ierr);
3704f94b4a02SBlaise Bourdin     ierr = PetscSFCreateInverseSF((*subdm)->sfMigration, &sfMigrationInv);CHKERRQ(ierr);
3705f94b4a02SBlaise Bourdin     ierr = PetscSectionCreate(PetscObjectComm((PetscObject) (*subdm)), &sectionSeq);CHKERRQ(ierr);
3706f94b4a02SBlaise Bourdin     ierr = PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq);CHKERRQ(ierr);
3707f94b4a02SBlaise Bourdin 
3708f94b4a02SBlaise Bourdin     ierr = DMPlexCreateGlobalToNaturalSF(*subdm, sectionSeq, (*subdm)->sfMigration, &sfNatural);CHKERRQ(ierr);
3709c40e9495SBlaise Bourdin     (*subdm)->sfNatural = sfNatural;
3710f94b4a02SBlaise Bourdin     ierr = PetscSectionDestroy(&sectionSeq);CHKERRQ(ierr);
3711f94b4a02SBlaise Bourdin     ierr = PetscSFDestroy(&sfMigrationInv);CHKERRQ(ierr);
3712f94b4a02SBlaise Bourdin   }
3713552f7358SJed Brown   PetscFunctionReturn(0);
3714552f7358SJed Brown }
3715552f7358SJed Brown 
37162adcc780SMatthew G. Knepley PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm)
37172adcc780SMatthew G. Knepley {
37182adcc780SMatthew G. Knepley   PetscErrorCode ierr;
37193dcd263cSBlaise Bourdin   PetscInt       i = 0;
37202adcc780SMatthew G. Knepley 
37212adcc780SMatthew G. Knepley   PetscFunctionBegin;
3722435bcee1SStefano Zampini   ierr = DMClone(dms[0], superdm);CHKERRQ(ierr);
3723792b654fSMatthew G. Knepley   ierr = DMCreateSectionSuperDM(dms, len, is, superdm);CHKERRQ(ierr);
3724c40e9495SBlaise Bourdin   (*superdm)->useNatural = PETSC_FALSE;
37253dcd263cSBlaise Bourdin   for (i = 0; i < len; i++) {
37263dcd263cSBlaise Bourdin     if (dms[i]->useNatural && dms[i]->sfMigration) {
37273dcd263cSBlaise Bourdin       PetscSF        sfMigrationInv,sfNatural;
37283dcd263cSBlaise Bourdin       PetscSection   section, sectionSeq;
37293dcd263cSBlaise Bourdin 
37303dcd263cSBlaise Bourdin       (*superdm)->sfMigration = dms[i]->sfMigration;
37313dcd263cSBlaise Bourdin       ierr = PetscObjectReference((PetscObject) dms[i]->sfMigration);CHKERRQ(ierr);
3732c40e9495SBlaise Bourdin       (*superdm)->useNatural = PETSC_TRUE;
373392fd8e1eSJed Brown       ierr = DMGetLocalSection((*superdm), &section);CHKERRQ(ierr);
37343dcd263cSBlaise Bourdin       ierr = PetscSFCreateInverseSF((*superdm)->sfMigration, &sfMigrationInv);CHKERRQ(ierr);
37353dcd263cSBlaise Bourdin       ierr = PetscSectionCreate(PetscObjectComm((PetscObject) (*superdm)), &sectionSeq);CHKERRQ(ierr);
37363dcd263cSBlaise Bourdin       ierr = PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq);CHKERRQ(ierr);
37373dcd263cSBlaise Bourdin 
37383dcd263cSBlaise Bourdin       ierr = DMPlexCreateGlobalToNaturalSF(*superdm, sectionSeq, (*superdm)->sfMigration, &sfNatural);CHKERRQ(ierr);
3739c40e9495SBlaise Bourdin       (*superdm)->sfNatural = sfNatural;
37403dcd263cSBlaise Bourdin       ierr = PetscSectionDestroy(&sectionSeq);CHKERRQ(ierr);
37413dcd263cSBlaise Bourdin       ierr = PetscSFDestroy(&sfMigrationInv);CHKERRQ(ierr);
37423dcd263cSBlaise Bourdin       break;
37433dcd263cSBlaise Bourdin     }
37443dcd263cSBlaise Bourdin   }
37452adcc780SMatthew G. Knepley   PetscFunctionReturn(0);
37462adcc780SMatthew G. Knepley }
37472adcc780SMatthew G. Knepley 
3748552f7358SJed Brown /*@
3749eaf898f9SPatrick Sanan   DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information
3750552f7358SJed Brown 
3751552f7358SJed Brown   Not collective
3752552f7358SJed Brown 
3753552f7358SJed Brown   Input Parameter:
3754552f7358SJed Brown . mesh - The DMPlex
3755552f7358SJed Brown 
3756552f7358SJed Brown   Output Parameter:
3757552f7358SJed Brown 
3758552f7358SJed Brown   Note:
3759552f7358SJed Brown   This should be called after all calls to DMPlexSetCone()
3760552f7358SJed Brown 
3761552f7358SJed Brown   Level: beginner
3762552f7358SJed Brown 
3763552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone()
3764552f7358SJed Brown @*/
3765552f7358SJed Brown PetscErrorCode DMPlexSymmetrize(DM dm)
3766552f7358SJed Brown {
3767552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3768552f7358SJed Brown   PetscInt      *offsets;
3769552f7358SJed Brown   PetscInt       supportSize;
3770552f7358SJed Brown   PetscInt       pStart, pEnd, p;
3771552f7358SJed Brown   PetscErrorCode ierr;
3772552f7358SJed Brown 
3773552f7358SJed Brown   PetscFunctionBegin;
3774552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
37752c71b3e2SJacob Faibussowitsch   PetscCheckFalse(mesh->supports,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex");
377630b0ce1bSStefano Zampini   ierr = PetscLogEventBegin(DMPLEX_Symmetrize,dm,0,0,0);CHKERRQ(ierr);
3777552f7358SJed Brown   /* Calculate support sizes */
3778552f7358SJed Brown   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
3779552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
3780552f7358SJed Brown     PetscInt dof, off, c;
3781552f7358SJed Brown 
3782552f7358SJed Brown     ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr);
3783552f7358SJed Brown     ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr);
3784552f7358SJed Brown     for (c = off; c < off+dof; ++c) {
3785552f7358SJed Brown       ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr);
3786552f7358SJed Brown     }
3787552f7358SJed Brown   }
3788552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
3789552f7358SJed Brown     PetscInt dof;
3790552f7358SJed Brown 
3791552f7358SJed Brown     ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr);
37920d644c17SKarl Rupp 
3793552f7358SJed Brown     mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof);
3794552f7358SJed Brown   }
3795552f7358SJed Brown   ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr);
3796552f7358SJed Brown   /* Calculate supports */
3797552f7358SJed Brown   ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr);
37981795a4d1SJed Brown   ierr = PetscMalloc1(supportSize, &mesh->supports);CHKERRQ(ierr);
37991795a4d1SJed Brown   ierr = PetscCalloc1(pEnd - pStart, &offsets);CHKERRQ(ierr);
3800552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
3801552f7358SJed Brown     PetscInt dof, off, c;
3802552f7358SJed Brown 
3803552f7358SJed Brown     ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr);
3804552f7358SJed Brown     ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr);
3805552f7358SJed Brown     for (c = off; c < off+dof; ++c) {
3806552f7358SJed Brown       const PetscInt q = mesh->cones[c];
3807552f7358SJed Brown       PetscInt       offS;
3808552f7358SJed Brown 
3809552f7358SJed Brown       ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr);
38100d644c17SKarl Rupp 
3811552f7358SJed Brown       mesh->supports[offS+offsets[q]] = p;
3812552f7358SJed Brown       ++offsets[q];
3813552f7358SJed Brown     }
3814552f7358SJed Brown   }
3815552f7358SJed Brown   ierr = PetscFree(offsets);CHKERRQ(ierr);
381630b0ce1bSStefano Zampini   ierr = PetscLogEventEnd(DMPLEX_Symmetrize,dm,0,0,0);CHKERRQ(ierr);
3817552f7358SJed Brown   PetscFunctionReturn(0);
3818552f7358SJed Brown }
3819552f7358SJed Brown 
3820277ea44aSLisandro Dalcin static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd)
3821277ea44aSLisandro Dalcin {
3822277ea44aSLisandro Dalcin   IS             stratumIS;
3823277ea44aSLisandro Dalcin   PetscErrorCode ierr;
3824277ea44aSLisandro Dalcin 
3825277ea44aSLisandro Dalcin   PetscFunctionBegin;
3826277ea44aSLisandro Dalcin   if (pStart >= pEnd) PetscFunctionReturn(0);
382776bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
3828277ea44aSLisandro Dalcin     PetscInt  qStart, qEnd, numLevels, level;
3829277ea44aSLisandro Dalcin     PetscBool overlap = PETSC_FALSE;
3830277ea44aSLisandro Dalcin     ierr = DMLabelGetNumValues(label, &numLevels);CHKERRQ(ierr);
3831277ea44aSLisandro Dalcin     for (level = 0; level < numLevels; level++) {
3832277ea44aSLisandro Dalcin       ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr);
3833277ea44aSLisandro Dalcin       if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) {overlap = PETSC_TRUE; break;}
3834277ea44aSLisandro Dalcin     }
38352c71b3e2SJacob Faibussowitsch     PetscCheckFalse(overlap,PETSC_COMM_SELF, PETSC_ERR_PLIB, "New depth %D range [%D,%D) overlaps with depth %D range [%D,%D)", depth, pStart, pEnd, level, qStart, qEnd);
3836277ea44aSLisandro Dalcin   }
3837277ea44aSLisandro Dalcin   ierr = ISCreateStride(PETSC_COMM_SELF, pEnd-pStart, pStart, 1, &stratumIS);CHKERRQ(ierr);
3838277ea44aSLisandro Dalcin   ierr = DMLabelSetStratumIS(label, depth, stratumIS);CHKERRQ(ierr);
3839277ea44aSLisandro Dalcin   ierr = ISDestroy(&stratumIS);CHKERRQ(ierr);
3840277ea44aSLisandro Dalcin   PetscFunctionReturn(0);
3841277ea44aSLisandro Dalcin }
3842277ea44aSLisandro Dalcin 
3843552f7358SJed Brown /*@
3844a8d69d7bSBarry Smith   DMPlexStratify - The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and
38456dd80730SBarry Smith   can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the
3846552f7358SJed Brown   same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in
3847552f7358SJed Brown   the DAG.
3848552f7358SJed Brown 
3849bf4602e4SToby Isaac   Collective on dm
3850552f7358SJed Brown 
3851552f7358SJed Brown   Input Parameter:
3852552f7358SJed Brown . mesh - The DMPlex
3853552f7358SJed Brown 
3854552f7358SJed Brown   Output Parameter:
3855552f7358SJed Brown 
3856552f7358SJed Brown   Notes:
3857b1bb481bSMatthew Knepley   Concretely, DMPlexStratify() creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex
3858b1bb481bSMatthew Knepley   meshes, vertices are depth 0 and cells are depth 1. For fully interpolated meshes, depth 0 for vertices, 1 for edges, and so on
3859b1bb481bSMatthew Knepley   until cells have depth equal to the dimension of the mesh. The depth label can be accessed through DMPlexGetDepthLabel() or DMPlexGetDepthStratum(), or
3860c58f1c22SToby Isaac   manually via DMGetLabel().  The height is defined implicitly by height = maxDimension - depth, and can be accessed
3861150b719bSJed Brown   via DMPlexGetHeightStratum().  For example, cells have height 0 and faces have height 1.
3862552f7358SJed Brown 
3863b1bb481bSMatthew Knepley   The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results
3864b1bb481bSMatthew Knepley   if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that
3865b1bb481bSMatthew Knepley   we had a mesh consisting of one triangle (c0) and three vertices (v0, v1, v2), and only one edge is on the boundary so we choose
3866b1bb481bSMatthew Knepley   to interpolate only that one (e0), so that
3867b1bb481bSMatthew Knepley $  cone(c0) = {e0, v2}
3868b1bb481bSMatthew Knepley $  cone(e0) = {v0, v1}
3869b1bb481bSMatthew Knepley   If DMPlexStratify() is run on this mesh, it will give depths
3870b1bb481bSMatthew Knepley $  depth 0 = {v0, v1, v2}
3871b1bb481bSMatthew Knepley $  depth 1 = {e0, c0}
3872b1bb481bSMatthew Knepley   where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2.
3873b1bb481bSMatthew Knepley 
3874150b719bSJed Brown   DMPlexStratify() should be called after all calls to DMPlexSymmetrize()
3875552f7358SJed Brown 
3876552f7358SJed Brown   Level: beginner
3877552f7358SJed Brown 
3878ba2698f1SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexSymmetrize(), DMPlexComputeCellTypes()
3879552f7358SJed Brown @*/
3880552f7358SJed Brown PetscErrorCode DMPlexStratify(DM dm)
3881552f7358SJed Brown {
3882df0420ecSMatthew G. Knepley   DM_Plex       *mesh = (DM_Plex*) dm->data;
3883aa50250dSMatthew G. Knepley   DMLabel        label;
3884552f7358SJed Brown   PetscInt       pStart, pEnd, p;
3885552f7358SJed Brown   PetscInt       numRoots = 0, numLeaves = 0;
3886552f7358SJed Brown   PetscErrorCode ierr;
3887552f7358SJed Brown 
3888552f7358SJed Brown   PetscFunctionBegin;
3889552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3890552f7358SJed Brown   ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr);
3891277ea44aSLisandro Dalcin 
3892277ea44aSLisandro Dalcin   /* Create depth label */
3893aa50250dSMatthew G. Knepley   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
3894c58f1c22SToby Isaac   ierr = DMCreateLabel(dm, "depth");CHKERRQ(ierr);
3895aa50250dSMatthew G. Knepley   ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr);
3896277ea44aSLisandro Dalcin 
3897277ea44aSLisandro Dalcin   {
3898552f7358SJed Brown     /* Initialize roots and count leaves */
3899277ea44aSLisandro Dalcin     PetscInt sMin = PETSC_MAX_INT;
3900277ea44aSLisandro Dalcin     PetscInt sMax = PETSC_MIN_INT;
3901552f7358SJed Brown     PetscInt coneSize, supportSize;
3902552f7358SJed Brown 
3903277ea44aSLisandro Dalcin     for (p = pStart; p < pEnd; ++p) {
3904552f7358SJed Brown       ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
3905552f7358SJed Brown       ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr);
3906552f7358SJed Brown       if (!coneSize && supportSize) {
3907277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
3908277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
3909552f7358SJed Brown         ++numRoots;
3910552f7358SJed Brown       } else if (!supportSize && coneSize) {
3911552f7358SJed Brown         ++numLeaves;
3912552f7358SJed Brown       } else if (!supportSize && !coneSize) {
3913552f7358SJed Brown         /* Isolated points */
3914277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
3915277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
3916552f7358SJed Brown       }
3917552f7358SJed Brown     }
3918277ea44aSLisandro Dalcin     ierr = DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax+1);CHKERRQ(ierr);
3919277ea44aSLisandro Dalcin   }
3920277ea44aSLisandro Dalcin 
3921552f7358SJed Brown   if (numRoots + numLeaves == (pEnd - pStart)) {
3922277ea44aSLisandro Dalcin     PetscInt sMin = PETSC_MAX_INT;
3923277ea44aSLisandro Dalcin     PetscInt sMax = PETSC_MIN_INT;
3924552f7358SJed Brown     PetscInt coneSize, supportSize;
3925552f7358SJed Brown 
3926277ea44aSLisandro Dalcin     for (p = pStart; p < pEnd; ++p) {
3927552f7358SJed Brown       ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
3928552f7358SJed Brown       ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr);
3929552f7358SJed Brown       if (!supportSize && coneSize) {
3930277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
3931277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
3932552f7358SJed Brown       }
3933552f7358SJed Brown     }
3934277ea44aSLisandro Dalcin     ierr = DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax+1);CHKERRQ(ierr);
3935552f7358SJed Brown   } else {
3936277ea44aSLisandro Dalcin     PetscInt level = 0;
3937277ea44aSLisandro Dalcin     PetscInt qStart, qEnd, q;
3938552f7358SJed Brown 
3939277ea44aSLisandro Dalcin     ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr);
3940277ea44aSLisandro Dalcin     while (qEnd > qStart) {
3941277ea44aSLisandro Dalcin       PetscInt sMin = PETSC_MAX_INT;
3942277ea44aSLisandro Dalcin       PetscInt sMax = PETSC_MIN_INT;
394374ef644bSMatthew G. Knepley 
3944277ea44aSLisandro Dalcin       for (q = qStart; q < qEnd; ++q) {
394574ef644bSMatthew G. Knepley         const PetscInt *support;
394674ef644bSMatthew G. Knepley         PetscInt        supportSize, s;
394774ef644bSMatthew G. Knepley 
3948277ea44aSLisandro Dalcin         ierr = DMPlexGetSupportSize(dm, q, &supportSize);CHKERRQ(ierr);
3949277ea44aSLisandro Dalcin         ierr = DMPlexGetSupport(dm, q, &support);CHKERRQ(ierr);
395074ef644bSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
3951277ea44aSLisandro Dalcin           sMin = PetscMin(support[s], sMin);
3952277ea44aSLisandro Dalcin           sMax = PetscMax(support[s], sMax);
3953552f7358SJed Brown         }
3954552f7358SJed Brown       }
3955277ea44aSLisandro Dalcin       ierr = DMLabelGetNumValues(label, &level);CHKERRQ(ierr);
3956277ea44aSLisandro Dalcin       ierr = DMPlexCreateDepthStratum(dm, label, level, sMin, sMax+1);CHKERRQ(ierr);
3957277ea44aSLisandro Dalcin       ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr);
395874ef644bSMatthew G. Knepley     }
395974ef644bSMatthew G. Knepley   }
3960bf4602e4SToby Isaac   { /* just in case there is an empty process */
3961bf4602e4SToby Isaac     PetscInt numValues, maxValues = 0, v;
3962bf4602e4SToby Isaac 
3963bf4602e4SToby Isaac     ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr);
3964ffc4695bSBarry Smith     ierr = MPI_Allreduce(&numValues,&maxValues,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr);
3965bf4602e4SToby Isaac     for (v = numValues; v < maxValues; v++) {
3966367003a6SStefano Zampini       ierr = DMLabelAddStratum(label, v);CHKERRQ(ierr);
3967bf4602e4SToby Isaac     }
3968bf4602e4SToby Isaac   }
3969d67d17b1SMatthew G. Knepley   ierr = PetscObjectStateGet((PetscObject) label, &mesh->depthState);CHKERRQ(ierr);
3970552f7358SJed Brown   ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr);
3971552f7358SJed Brown   PetscFunctionReturn(0);
3972552f7358SJed Brown }
3973552f7358SJed Brown 
3974412e9a14SMatthew G. Knepley PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt)
3975ba2698f1SMatthew G. Knepley {
3976412e9a14SMatthew G. Knepley   DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
3977412e9a14SMatthew G. Knepley   PetscInt       dim, depth, pheight, coneSize;
3978ba2698f1SMatthew G. Knepley   PetscErrorCode ierr;
3979ba2698f1SMatthew G. Knepley 
3980412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
3981ba2698f1SMatthew G. Knepley   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
3982ba2698f1SMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
3983ba2698f1SMatthew G. Knepley   ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
3984ba2698f1SMatthew G. Knepley   pheight = depth - pdepth;
3985ba2698f1SMatthew G. Knepley   if (depth <= 1) {
3986ba2698f1SMatthew G. Knepley     switch (pdepth) {
3987ba2698f1SMatthew G. Knepley       case 0: ct = DM_POLYTOPE_POINT;break;
3988ba2698f1SMatthew G. Knepley       case 1:
3989ba2698f1SMatthew G. Knepley         switch (coneSize) {
3990ba2698f1SMatthew G. Knepley           case 2: ct = DM_POLYTOPE_SEGMENT;break;
3991ba2698f1SMatthew G. Knepley           case 3: ct = DM_POLYTOPE_TRIANGLE;break;
3992ba2698f1SMatthew G. Knepley           case 4:
3993ba2698f1SMatthew G. Knepley           switch (dim) {
3994ba2698f1SMatthew G. Knepley             case 2: ct = DM_POLYTOPE_QUADRILATERAL;break;
3995ba2698f1SMatthew G. Knepley             case 3: ct = DM_POLYTOPE_TETRAHEDRON;break;
3996ba2698f1SMatthew G. Knepley             default: break;
3997ba2698f1SMatthew G. Knepley           }
3998ba2698f1SMatthew G. Knepley           break;
3999da9060c4SMatthew G. Knepley         case 5: ct = DM_POLYTOPE_PYRAMID;break;
4000ba2698f1SMatthew G. Knepley         case 6: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break;
4001ba2698f1SMatthew G. Knepley         case 8: ct = DM_POLYTOPE_HEXAHEDRON;break;
4002ba2698f1SMatthew G. Knepley         default: break;
4003ba2698f1SMatthew G. Knepley       }
4004ba2698f1SMatthew G. Knepley     }
4005ba2698f1SMatthew G. Knepley   } else {
4006ba2698f1SMatthew G. Knepley     if (pdepth == 0) {
4007ba2698f1SMatthew G. Knepley       ct = DM_POLYTOPE_POINT;
4008ba2698f1SMatthew G. Knepley     } else if (pheight == 0) {
4009ba2698f1SMatthew G. Knepley       switch (dim) {
4010ba2698f1SMatthew G. Knepley         case 1:
4011ba2698f1SMatthew G. Knepley           switch (coneSize) {
4012ba2698f1SMatthew G. Knepley             case 2: ct = DM_POLYTOPE_SEGMENT;break;
4013ba2698f1SMatthew G. Knepley             default: break;
4014ba2698f1SMatthew G. Knepley           }
4015ba2698f1SMatthew G. Knepley           break;
4016ba2698f1SMatthew G. Knepley         case 2:
4017ba2698f1SMatthew G. Knepley           switch (coneSize) {
4018ba2698f1SMatthew G. Knepley             case 3: ct = DM_POLYTOPE_TRIANGLE;break;
4019ba2698f1SMatthew G. Knepley             case 4: ct = DM_POLYTOPE_QUADRILATERAL;break;
4020ba2698f1SMatthew G. Knepley             default: break;
4021ba2698f1SMatthew G. Knepley           }
4022ba2698f1SMatthew G. Knepley           break;
4023ba2698f1SMatthew G. Knepley         case 3:
4024ba2698f1SMatthew G. Knepley           switch (coneSize) {
4025ba2698f1SMatthew G. Knepley             case 4: ct = DM_POLYTOPE_TETRAHEDRON;break;
4026da9060c4SMatthew G. Knepley             case 5:
4027da9060c4SMatthew G. Knepley             {
4028da9060c4SMatthew G. Knepley               const PetscInt *cone;
4029da9060c4SMatthew G. Knepley               PetscInt        faceConeSize;
4030da9060c4SMatthew G. Knepley 
4031da9060c4SMatthew G. Knepley               ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr);
4032da9060c4SMatthew G. Knepley               ierr = DMPlexGetConeSize(dm, cone[0], &faceConeSize);CHKERRQ(ierr);
4033da9060c4SMatthew G. Knepley               switch (faceConeSize) {
4034da9060c4SMatthew G. Knepley                 case 3: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break;
4035da9060c4SMatthew G. Knepley                 case 4: ct = DM_POLYTOPE_PYRAMID;break;
4036da9060c4SMatthew G. Knepley               }
4037da9060c4SMatthew G. Knepley             }
4038da9060c4SMatthew G. Knepley             break;
4039ba2698f1SMatthew G. Knepley             case 6: ct = DM_POLYTOPE_HEXAHEDRON;break;
4040ba2698f1SMatthew G. Knepley             default: break;
4041ba2698f1SMatthew G. Knepley           }
4042ba2698f1SMatthew G. Knepley           break;
4043ba2698f1SMatthew G. Knepley         default: break;
4044ba2698f1SMatthew G. Knepley       }
4045ba2698f1SMatthew G. Knepley     } else if (pheight > 0) {
4046ba2698f1SMatthew G. Knepley       switch (coneSize) {
4047ba2698f1SMatthew G. Knepley         case 2: ct = DM_POLYTOPE_SEGMENT;break;
4048ba2698f1SMatthew G. Knepley         case 3: ct = DM_POLYTOPE_TRIANGLE;break;
4049ba2698f1SMatthew G. Knepley         case 4: ct = DM_POLYTOPE_QUADRILATERAL;break;
4050ba2698f1SMatthew G. Knepley         default: break;
4051ba2698f1SMatthew G. Knepley       }
4052ba2698f1SMatthew G. Knepley     }
4053ba2698f1SMatthew G. Knepley   }
4054412e9a14SMatthew G. Knepley   *pt = ct;
4055412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
4056ba2698f1SMatthew G. Knepley }
4057412e9a14SMatthew G. Knepley 
4058412e9a14SMatthew G. Knepley /*@
4059412e9a14SMatthew G. Knepley   DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size.
4060412e9a14SMatthew G. Knepley 
4061412e9a14SMatthew G. Knepley   Collective on dm
4062412e9a14SMatthew G. Knepley 
4063412e9a14SMatthew G. Knepley   Input Parameter:
4064412e9a14SMatthew G. Knepley . mesh - The DMPlex
4065412e9a14SMatthew G. Knepley 
4066412e9a14SMatthew G. Knepley   DMPlexComputeCellTypes() should be called after all calls to DMPlexSymmetrize() and DMPlexStratify()
4067412e9a14SMatthew G. Knepley 
4068412e9a14SMatthew G. Knepley   Level: developer
4069412e9a14SMatthew G. Knepley 
4070412e9a14SMatthew G. Knepley   Note: This function is normally called automatically by Plex when a cell type is requested. It creates an
4071412e9a14SMatthew G. Knepley   internal DMLabel named "celltype" which can be directly accessed using DMGetLabel(). A user may disable
4072412e9a14SMatthew G. Knepley   automatic creation by creating the label manually, using DMCreateLabel(dm, "celltype").
4073412e9a14SMatthew G. Knepley 
4074412e9a14SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexSymmetrize(), DMPlexStratify(), DMGetLabel(), DMCreateLabel()
4075412e9a14SMatthew G. Knepley @*/
4076412e9a14SMatthew G. Knepley PetscErrorCode DMPlexComputeCellTypes(DM dm)
4077412e9a14SMatthew G. Knepley {
4078412e9a14SMatthew G. Knepley   DM_Plex       *mesh;
4079412e9a14SMatthew G. Knepley   DMLabel        ctLabel;
4080412e9a14SMatthew G. Knepley   PetscInt       pStart, pEnd, p;
4081412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
4082412e9a14SMatthew G. Knepley 
4083412e9a14SMatthew G. Knepley   PetscFunctionBegin;
4084412e9a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4085412e9a14SMatthew G. Knepley   mesh = (DM_Plex *) dm->data;
4086412e9a14SMatthew G. Knepley   ierr = DMCreateLabel(dm, "celltype");CHKERRQ(ierr);
4087412e9a14SMatthew G. Knepley   ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr);
4088412e9a14SMatthew G. Knepley   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
4089412e9a14SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
4090327c2912SStefano Zampini     DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
4091412e9a14SMatthew G. Knepley     PetscInt       pdepth;
4092412e9a14SMatthew G. Knepley 
4093412e9a14SMatthew G. Knepley     ierr = DMPlexGetPointDepth(dm, p, &pdepth);CHKERRQ(ierr);
4094412e9a14SMatthew G. Knepley     ierr = DMPlexComputeCellType_Internal(dm, p, pdepth, &ct);CHKERRQ(ierr);
40952c71b3e2SJacob Faibussowitsch     PetscCheckFalse(ct == DM_POLYTOPE_UNKNOWN,PETSC_COMM_SELF, PETSC_ERR_SUP, "Point %D is screwed up", p);
4096412e9a14SMatthew G. Knepley     ierr = DMLabelSetValue(ctLabel, p, ct);CHKERRQ(ierr);
4097412e9a14SMatthew G. Knepley   }
4098412e9a14SMatthew G. Knepley   ierr = PetscObjectStateGet((PetscObject) ctLabel, &mesh->celltypeState);CHKERRQ(ierr);
4099412e9a14SMatthew G. Knepley   ierr = PetscObjectViewFromOptions((PetscObject) ctLabel, NULL, "-dm_plex_celltypes_view");CHKERRQ(ierr);
4100ba2698f1SMatthew G. Knepley   PetscFunctionReturn(0);
4101ba2698f1SMatthew G. Knepley }
4102ba2698f1SMatthew G. Knepley 
4103552f7358SJed Brown /*@C
4104552f7358SJed Brown   DMPlexGetJoin - Get an array for the join of the set of points
4105552f7358SJed Brown 
4106552f7358SJed Brown   Not Collective
4107552f7358SJed Brown 
4108552f7358SJed Brown   Input Parameters:
4109552f7358SJed Brown + dm - The DMPlex object
4110552f7358SJed Brown . numPoints - The number of input points for the join
4111552f7358SJed Brown - points - The input points
4112552f7358SJed Brown 
4113552f7358SJed Brown   Output Parameters:
4114552f7358SJed Brown + numCoveredPoints - The number of points in the join
4115552f7358SJed Brown - coveredPoints - The points in the join
4116552f7358SJed Brown 
4117552f7358SJed Brown   Level: intermediate
4118552f7358SJed Brown 
4119552f7358SJed Brown   Note: Currently, this is restricted to a single level join
4120552f7358SJed Brown 
41213813dfbdSMatthew G Knepley   Fortran Notes:
41223813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
41233813dfbdSMatthew G Knepley   include petsc.h90 in your code.
41243813dfbdSMatthew G Knepley 
41253813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
41263813dfbdSMatthew G Knepley 
4127552f7358SJed Brown .seealso: DMPlexRestoreJoin(), DMPlexGetMeet()
4128552f7358SJed Brown @*/
4129552f7358SJed Brown PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4130552f7358SJed Brown {
4131552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
4132552f7358SJed Brown   PetscInt      *join[2];
4133552f7358SJed Brown   PetscInt       joinSize, i = 0;
4134552f7358SJed Brown   PetscInt       dof, off, p, c, m;
4135552f7358SJed Brown   PetscErrorCode ierr;
4136552f7358SJed Brown 
4137552f7358SJed Brown   PetscFunctionBegin;
4138552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
413948bb261cSVaclav Hapla   PetscValidIntPointer(points, 3);
414048bb261cSVaclav Hapla   PetscValidIntPointer(numCoveredPoints, 4);
414148bb261cSVaclav Hapla   PetscValidPointer(coveredPoints, 5);
414269291d52SBarry Smith   ierr = DMGetWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[0]);CHKERRQ(ierr);
414369291d52SBarry Smith   ierr = DMGetWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1]);CHKERRQ(ierr);
4144552f7358SJed Brown   /* Copy in support of first point */
4145552f7358SJed Brown   ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr);
4146552f7358SJed Brown   ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr);
4147552f7358SJed Brown   for (joinSize = 0; joinSize < dof; ++joinSize) {
4148552f7358SJed Brown     join[i][joinSize] = mesh->supports[off+joinSize];
4149552f7358SJed Brown   }
4150552f7358SJed Brown   /* Check each successive support */
4151552f7358SJed Brown   for (p = 1; p < numPoints; ++p) {
4152552f7358SJed Brown     PetscInt newJoinSize = 0;
4153552f7358SJed Brown 
4154552f7358SJed Brown     ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr);
4155552f7358SJed Brown     ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr);
4156552f7358SJed Brown     for (c = 0; c < dof; ++c) {
4157552f7358SJed Brown       const PetscInt point = mesh->supports[off+c];
4158552f7358SJed Brown 
4159552f7358SJed Brown       for (m = 0; m < joinSize; ++m) {
4160552f7358SJed Brown         if (point == join[i][m]) {
4161552f7358SJed Brown           join[1-i][newJoinSize++] = point;
4162552f7358SJed Brown           break;
4163552f7358SJed Brown         }
4164552f7358SJed Brown       }
4165552f7358SJed Brown     }
4166552f7358SJed Brown     joinSize = newJoinSize;
4167552f7358SJed Brown     i        = 1-i;
4168552f7358SJed Brown   }
4169552f7358SJed Brown   *numCoveredPoints = joinSize;
4170552f7358SJed Brown   *coveredPoints    = join[i];
417169291d52SBarry Smith   ierr              = DMRestoreWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1-i]);CHKERRQ(ierr);
4172552f7358SJed Brown   PetscFunctionReturn(0);
4173552f7358SJed Brown }
4174552f7358SJed Brown 
4175552f7358SJed Brown /*@C
4176552f7358SJed Brown   DMPlexRestoreJoin - Restore an array for the join of the set of points
4177552f7358SJed Brown 
4178552f7358SJed Brown   Not Collective
4179552f7358SJed Brown 
4180552f7358SJed Brown   Input Parameters:
4181552f7358SJed Brown + dm - The DMPlex object
4182552f7358SJed Brown . numPoints - The number of input points for the join
4183552f7358SJed Brown - points - The input points
4184552f7358SJed Brown 
4185552f7358SJed Brown   Output Parameters:
4186552f7358SJed Brown + numCoveredPoints - The number of points in the join
4187552f7358SJed Brown - coveredPoints - The points in the join
4188552f7358SJed Brown 
41893813dfbdSMatthew G Knepley   Fortran Notes:
41903813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
41913813dfbdSMatthew G Knepley   include petsc.h90 in your code.
41923813dfbdSMatthew G Knepley 
41933813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
41943813dfbdSMatthew G Knepley 
4195552f7358SJed Brown   Level: intermediate
4196552f7358SJed Brown 
4197552f7358SJed Brown .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet()
4198552f7358SJed Brown @*/
4199552f7358SJed Brown PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4200552f7358SJed Brown {
4201552f7358SJed Brown   PetscErrorCode ierr;
4202552f7358SJed Brown 
4203552f7358SJed Brown   PetscFunctionBegin;
4204552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4205d7902bd2SMatthew G. Knepley   if (points) PetscValidIntPointer(points,3);
4206d7902bd2SMatthew G. Knepley   if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4);
4207d7902bd2SMatthew G. Knepley   PetscValidPointer(coveredPoints, 5);
420869291d52SBarry Smith   ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints);CHKERRQ(ierr);
4209d7902bd2SMatthew G. Knepley   if (numCoveredPoints) *numCoveredPoints = 0;
4210552f7358SJed Brown   PetscFunctionReturn(0);
4211552f7358SJed Brown }
4212552f7358SJed Brown 
4213552f7358SJed Brown /*@C
4214552f7358SJed Brown   DMPlexGetFullJoin - Get an array for the join of the set of points
4215552f7358SJed Brown 
4216552f7358SJed Brown   Not Collective
4217552f7358SJed Brown 
4218552f7358SJed Brown   Input Parameters:
4219552f7358SJed Brown + dm - The DMPlex object
4220552f7358SJed Brown . numPoints - The number of input points for the join
4221552f7358SJed Brown - points - The input points
4222552f7358SJed Brown 
4223552f7358SJed Brown   Output Parameters:
4224552f7358SJed Brown + numCoveredPoints - The number of points in the join
4225552f7358SJed Brown - coveredPoints - The points in the join
4226552f7358SJed Brown 
42273813dfbdSMatthew G Knepley   Fortran Notes:
42283813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
42293813dfbdSMatthew G Knepley   include petsc.h90 in your code.
42303813dfbdSMatthew G Knepley 
42313813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
42323813dfbdSMatthew G Knepley 
4233552f7358SJed Brown   Level: intermediate
4234552f7358SJed Brown 
4235552f7358SJed Brown .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet()
4236552f7358SJed Brown @*/
4237552f7358SJed Brown PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4238552f7358SJed Brown {
4239552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
4240552f7358SJed Brown   PetscInt      *offsets, **closures;
4241552f7358SJed Brown   PetscInt      *join[2];
4242552f7358SJed Brown   PetscInt       depth = 0, maxSize, joinSize = 0, i = 0;
424324c766afSToby Isaac   PetscInt       p, d, c, m, ms;
4244552f7358SJed Brown   PetscErrorCode ierr;
4245552f7358SJed Brown 
4246552f7358SJed Brown   PetscFunctionBegin;
4247552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
424848bb261cSVaclav Hapla   PetscValidIntPointer(points, 3);
424948bb261cSVaclav Hapla   PetscValidIntPointer(numCoveredPoints, 4);
425048bb261cSVaclav Hapla   PetscValidPointer(coveredPoints, 5);
4251552f7358SJed Brown 
4252552f7358SJed Brown   ierr    = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
42531795a4d1SJed Brown   ierr    = PetscCalloc1(numPoints, &closures);CHKERRQ(ierr);
425469291d52SBarry Smith   ierr    = DMGetWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets);CHKERRQ(ierr);
425524c766afSToby Isaac   ms      = mesh->maxSupportSize;
425624c766afSToby Isaac   maxSize = (ms > 1) ? ((PetscPowInt(ms,depth+1)-1)/(ms-1)) : depth + 1;
425769291d52SBarry Smith   ierr    = DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0]);CHKERRQ(ierr);
425869291d52SBarry Smith   ierr    = DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1]);CHKERRQ(ierr);
4259552f7358SJed Brown 
4260552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
4261552f7358SJed Brown     PetscInt closureSize;
4262552f7358SJed Brown 
4263552f7358SJed Brown     ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr);
42640d644c17SKarl Rupp 
4265552f7358SJed Brown     offsets[p*(depth+2)+0] = 0;
4266552f7358SJed Brown     for (d = 0; d < depth+1; ++d) {
4267552f7358SJed Brown       PetscInt pStart, pEnd, i;
4268552f7358SJed Brown 
4269552f7358SJed Brown       ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr);
4270552f7358SJed Brown       for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) {
4271552f7358SJed Brown         if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) {
4272552f7358SJed Brown           offsets[p*(depth+2)+d+1] = i;
4273552f7358SJed Brown           break;
4274552f7358SJed Brown         }
4275552f7358SJed Brown       }
4276552f7358SJed Brown       if (i == closureSize) offsets[p*(depth+2)+d+1] = i;
4277552f7358SJed Brown     }
42782c71b3e2SJacob Faibussowitsch     PetscCheckFalse(offsets[p*(depth+2)+depth+1] != closureSize,PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(depth+2)+depth+1], closureSize);
4279552f7358SJed Brown   }
4280552f7358SJed Brown   for (d = 0; d < depth+1; ++d) {
4281552f7358SJed Brown     PetscInt dof;
4282552f7358SJed Brown 
4283552f7358SJed Brown     /* Copy in support of first point */
4284552f7358SJed Brown     dof = offsets[d+1] - offsets[d];
4285552f7358SJed Brown     for (joinSize = 0; joinSize < dof; ++joinSize) {
4286552f7358SJed Brown       join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2];
4287552f7358SJed Brown     }
4288552f7358SJed Brown     /* Check each successive cone */
4289552f7358SJed Brown     for (p = 1; p < numPoints && joinSize; ++p) {
4290552f7358SJed Brown       PetscInt newJoinSize = 0;
4291552f7358SJed Brown 
4292552f7358SJed Brown       dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d];
4293552f7358SJed Brown       for (c = 0; c < dof; ++c) {
4294552f7358SJed Brown         const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2];
4295552f7358SJed Brown 
4296552f7358SJed Brown         for (m = 0; m < joinSize; ++m) {
4297552f7358SJed Brown           if (point == join[i][m]) {
4298552f7358SJed Brown             join[1-i][newJoinSize++] = point;
4299552f7358SJed Brown             break;
4300552f7358SJed Brown           }
4301552f7358SJed Brown         }
4302552f7358SJed Brown       }
4303552f7358SJed Brown       joinSize = newJoinSize;
4304552f7358SJed Brown       i        = 1-i;
4305552f7358SJed Brown     }
4306552f7358SJed Brown     if (joinSize) break;
4307552f7358SJed Brown   }
4308552f7358SJed Brown   *numCoveredPoints = joinSize;
4309552f7358SJed Brown   *coveredPoints    = join[i];
4310552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
43110298fd71SBarry Smith     ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]);CHKERRQ(ierr);
4312552f7358SJed Brown   }
4313552f7358SJed Brown   ierr = PetscFree(closures);CHKERRQ(ierr);
431469291d52SBarry Smith   ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets);CHKERRQ(ierr);
431569291d52SBarry Smith   ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1-i]);CHKERRQ(ierr);
4316552f7358SJed Brown   PetscFunctionReturn(0);
4317552f7358SJed Brown }
4318552f7358SJed Brown 
4319552f7358SJed Brown /*@C
4320552f7358SJed Brown   DMPlexGetMeet - Get an array for the meet of the set of points
4321552f7358SJed Brown 
4322552f7358SJed Brown   Not Collective
4323552f7358SJed Brown 
4324552f7358SJed Brown   Input Parameters:
4325552f7358SJed Brown + dm - The DMPlex object
4326552f7358SJed Brown . numPoints - The number of input points for the meet
4327552f7358SJed Brown - points - The input points
4328552f7358SJed Brown 
4329552f7358SJed Brown   Output Parameters:
4330552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4331552f7358SJed Brown - coveredPoints - The points in the meet
4332552f7358SJed Brown 
4333552f7358SJed Brown   Level: intermediate
4334552f7358SJed Brown 
4335552f7358SJed Brown   Note: Currently, this is restricted to a single level meet
4336552f7358SJed Brown 
43373813dfbdSMatthew G Knepley   Fortran Notes:
43383813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
43393813dfbdSMatthew G Knepley   include petsc.h90 in your code.
43403813dfbdSMatthew G Knepley 
43413813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
43423813dfbdSMatthew G Knepley 
4343552f7358SJed Brown .seealso: DMPlexRestoreMeet(), DMPlexGetJoin()
4344552f7358SJed Brown @*/
4345552f7358SJed Brown PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints)
4346552f7358SJed Brown {
4347552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
4348552f7358SJed Brown   PetscInt      *meet[2];
4349552f7358SJed Brown   PetscInt       meetSize, i = 0;
4350552f7358SJed Brown   PetscInt       dof, off, p, c, m;
4351552f7358SJed Brown   PetscErrorCode ierr;
4352552f7358SJed Brown 
4353552f7358SJed Brown   PetscFunctionBegin;
4354552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4355064a246eSJacob Faibussowitsch   PetscValidPointer(points, 3);
4356064a246eSJacob Faibussowitsch   PetscValidPointer(numCoveringPoints, 4);
4357064a246eSJacob Faibussowitsch   PetscValidPointer(coveringPoints, 5);
435869291d52SBarry Smith   ierr = DMGetWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[0]);CHKERRQ(ierr);
435969291d52SBarry Smith   ierr = DMGetWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1]);CHKERRQ(ierr);
4360552f7358SJed Brown   /* Copy in cone of first point */
4361552f7358SJed Brown   ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr);
4362552f7358SJed Brown   ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr);
4363552f7358SJed Brown   for (meetSize = 0; meetSize < dof; ++meetSize) {
4364552f7358SJed Brown     meet[i][meetSize] = mesh->cones[off+meetSize];
4365552f7358SJed Brown   }
4366552f7358SJed Brown   /* Check each successive cone */
4367552f7358SJed Brown   for (p = 1; p < numPoints; ++p) {
4368552f7358SJed Brown     PetscInt newMeetSize = 0;
4369552f7358SJed Brown 
4370552f7358SJed Brown     ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr);
4371552f7358SJed Brown     ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr);
4372552f7358SJed Brown     for (c = 0; c < dof; ++c) {
4373552f7358SJed Brown       const PetscInt point = mesh->cones[off+c];
4374552f7358SJed Brown 
4375552f7358SJed Brown       for (m = 0; m < meetSize; ++m) {
4376552f7358SJed Brown         if (point == meet[i][m]) {
4377552f7358SJed Brown           meet[1-i][newMeetSize++] = point;
4378552f7358SJed Brown           break;
4379552f7358SJed Brown         }
4380552f7358SJed Brown       }
4381552f7358SJed Brown     }
4382552f7358SJed Brown     meetSize = newMeetSize;
4383552f7358SJed Brown     i        = 1-i;
4384552f7358SJed Brown   }
4385552f7358SJed Brown   *numCoveringPoints = meetSize;
4386552f7358SJed Brown   *coveringPoints    = meet[i];
438769291d52SBarry Smith   ierr               = DMRestoreWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1-i]);CHKERRQ(ierr);
4388552f7358SJed Brown   PetscFunctionReturn(0);
4389552f7358SJed Brown }
4390552f7358SJed Brown 
4391552f7358SJed Brown /*@C
4392552f7358SJed Brown   DMPlexRestoreMeet - Restore an array for the meet of the set of points
4393552f7358SJed Brown 
4394552f7358SJed Brown   Not Collective
4395552f7358SJed Brown 
4396552f7358SJed Brown   Input Parameters:
4397552f7358SJed Brown + dm - The DMPlex object
4398552f7358SJed Brown . numPoints - The number of input points for the meet
4399552f7358SJed Brown - points - The input points
4400552f7358SJed Brown 
4401552f7358SJed Brown   Output Parameters:
4402552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4403552f7358SJed Brown - coveredPoints - The points in the meet
4404552f7358SJed Brown 
4405552f7358SJed Brown   Level: intermediate
4406552f7358SJed Brown 
44073813dfbdSMatthew G Knepley   Fortran Notes:
44083813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
44093813dfbdSMatthew G Knepley   include petsc.h90 in your code.
44103813dfbdSMatthew G Knepley 
44113813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
44123813dfbdSMatthew G Knepley 
4413552f7358SJed Brown .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin()
4414552f7358SJed Brown @*/
4415552f7358SJed Brown PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4416552f7358SJed Brown {
4417552f7358SJed Brown   PetscErrorCode ierr;
4418552f7358SJed Brown 
4419552f7358SJed Brown   PetscFunctionBegin;
4420552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4421d7902bd2SMatthew G. Knepley   if (points) PetscValidIntPointer(points,3);
4422d7902bd2SMatthew G. Knepley   if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4);
4423d7902bd2SMatthew G. Knepley   PetscValidPointer(coveredPoints,5);
442469291d52SBarry Smith   ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints);CHKERRQ(ierr);
4425d7902bd2SMatthew G. Knepley   if (numCoveredPoints) *numCoveredPoints = 0;
4426552f7358SJed Brown   PetscFunctionReturn(0);
4427552f7358SJed Brown }
4428552f7358SJed Brown 
4429552f7358SJed Brown /*@C
4430552f7358SJed Brown   DMPlexGetFullMeet - Get an array for the meet of the set of points
4431552f7358SJed Brown 
4432552f7358SJed Brown   Not Collective
4433552f7358SJed Brown 
4434552f7358SJed Brown   Input Parameters:
4435552f7358SJed Brown + dm - The DMPlex object
4436552f7358SJed Brown . numPoints - The number of input points for the meet
4437552f7358SJed Brown - points - The input points
4438552f7358SJed Brown 
4439552f7358SJed Brown   Output Parameters:
4440552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4441552f7358SJed Brown - coveredPoints - The points in the meet
4442552f7358SJed Brown 
4443552f7358SJed Brown   Level: intermediate
4444552f7358SJed Brown 
44453813dfbdSMatthew G Knepley   Fortran Notes:
44463813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
44473813dfbdSMatthew G Knepley   include petsc.h90 in your code.
44483813dfbdSMatthew G Knepley 
44493813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
44503813dfbdSMatthew G Knepley 
4451552f7358SJed Brown .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin()
4452552f7358SJed Brown @*/
4453552f7358SJed Brown PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4454552f7358SJed Brown {
4455552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
4456552f7358SJed Brown   PetscInt      *offsets, **closures;
4457552f7358SJed Brown   PetscInt      *meet[2];
4458552f7358SJed Brown   PetscInt       height = 0, maxSize, meetSize = 0, i = 0;
445924c766afSToby Isaac   PetscInt       p, h, c, m, mc;
4460552f7358SJed Brown   PetscErrorCode ierr;
4461552f7358SJed Brown 
4462552f7358SJed Brown   PetscFunctionBegin;
4463552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4464064a246eSJacob Faibussowitsch   PetscValidPointer(points, 3);
4465064a246eSJacob Faibussowitsch   PetscValidPointer(numCoveredPoints, 4);
4466064a246eSJacob Faibussowitsch   PetscValidPointer(coveredPoints, 5);
4467552f7358SJed Brown 
4468552f7358SJed Brown   ierr    = DMPlexGetDepth(dm, &height);CHKERRQ(ierr);
4469785e854fSJed Brown   ierr    = PetscMalloc1(numPoints, &closures);CHKERRQ(ierr);
447069291d52SBarry Smith   ierr    = DMGetWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets);CHKERRQ(ierr);
447124c766afSToby Isaac   mc      = mesh->maxConeSize;
447224c766afSToby Isaac   maxSize = (mc > 1) ? ((PetscPowInt(mc,height+1)-1)/(mc-1)) : height + 1;
447369291d52SBarry Smith   ierr    = DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0]);CHKERRQ(ierr);
447469291d52SBarry Smith   ierr    = DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1]);CHKERRQ(ierr);
4475552f7358SJed Brown 
4476552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
4477552f7358SJed Brown     PetscInt closureSize;
4478552f7358SJed Brown 
4479552f7358SJed Brown     ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr);
44800d644c17SKarl Rupp 
4481552f7358SJed Brown     offsets[p*(height+2)+0] = 0;
4482552f7358SJed Brown     for (h = 0; h < height+1; ++h) {
4483552f7358SJed Brown       PetscInt pStart, pEnd, i;
4484552f7358SJed Brown 
4485552f7358SJed Brown       ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr);
4486552f7358SJed Brown       for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) {
4487552f7358SJed Brown         if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) {
4488552f7358SJed Brown           offsets[p*(height+2)+h+1] = i;
4489552f7358SJed Brown           break;
4490552f7358SJed Brown         }
4491552f7358SJed Brown       }
4492552f7358SJed Brown       if (i == closureSize) offsets[p*(height+2)+h+1] = i;
4493552f7358SJed Brown     }
44942c71b3e2SJacob Faibussowitsch     PetscCheckFalse(offsets[p*(height+2)+height+1] != closureSize,PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(height+2)+height+1], closureSize);
4495552f7358SJed Brown   }
4496552f7358SJed Brown   for (h = 0; h < height+1; ++h) {
4497552f7358SJed Brown     PetscInt dof;
4498552f7358SJed Brown 
4499552f7358SJed Brown     /* Copy in cone of first point */
4500552f7358SJed Brown     dof = offsets[h+1] - offsets[h];
4501552f7358SJed Brown     for (meetSize = 0; meetSize < dof; ++meetSize) {
4502552f7358SJed Brown       meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2];
4503552f7358SJed Brown     }
4504552f7358SJed Brown     /* Check each successive cone */
4505552f7358SJed Brown     for (p = 1; p < numPoints && meetSize; ++p) {
4506552f7358SJed Brown       PetscInt newMeetSize = 0;
4507552f7358SJed Brown 
4508552f7358SJed Brown       dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h];
4509552f7358SJed Brown       for (c = 0; c < dof; ++c) {
4510552f7358SJed Brown         const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2];
4511552f7358SJed Brown 
4512552f7358SJed Brown         for (m = 0; m < meetSize; ++m) {
4513552f7358SJed Brown           if (point == meet[i][m]) {
4514552f7358SJed Brown             meet[1-i][newMeetSize++] = point;
4515552f7358SJed Brown             break;
4516552f7358SJed Brown           }
4517552f7358SJed Brown         }
4518552f7358SJed Brown       }
4519552f7358SJed Brown       meetSize = newMeetSize;
4520552f7358SJed Brown       i        = 1-i;
4521552f7358SJed Brown     }
4522552f7358SJed Brown     if (meetSize) break;
4523552f7358SJed Brown   }
4524552f7358SJed Brown   *numCoveredPoints = meetSize;
4525552f7358SJed Brown   *coveredPoints    = meet[i];
4526552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
45270298fd71SBarry Smith     ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]);CHKERRQ(ierr);
4528552f7358SJed Brown   }
4529552f7358SJed Brown   ierr = PetscFree(closures);CHKERRQ(ierr);
453069291d52SBarry Smith   ierr = DMRestoreWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets);CHKERRQ(ierr);
453169291d52SBarry Smith   ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1-i]);CHKERRQ(ierr);
4532552f7358SJed Brown   PetscFunctionReturn(0);
4533552f7358SJed Brown }
4534552f7358SJed Brown 
45354e3744c5SMatthew G. Knepley /*@C
45364e3744c5SMatthew G. Knepley   DMPlexEqual - Determine if two DMs have the same topology
45374e3744c5SMatthew G. Knepley 
45384e3744c5SMatthew G. Knepley   Not Collective
45394e3744c5SMatthew G. Knepley 
45404e3744c5SMatthew G. Knepley   Input Parameters:
45414e3744c5SMatthew G. Knepley + dmA - A DMPlex object
45424e3744c5SMatthew G. Knepley - dmB - A DMPlex object
45434e3744c5SMatthew G. Knepley 
45444e3744c5SMatthew G. Knepley   Output Parameters:
45454e3744c5SMatthew G. Knepley . equal - PETSC_TRUE if the topologies are identical
45464e3744c5SMatthew G. Knepley 
45474e3744c5SMatthew G. Knepley   Level: intermediate
45484e3744c5SMatthew G. Knepley 
45494e3744c5SMatthew G. Knepley   Notes:
45504e3744c5SMatthew G. Knepley   We are not solving graph isomorphism, so we do not permutation.
45514e3744c5SMatthew G. Knepley 
45524e3744c5SMatthew G. Knepley .seealso: DMPlexGetCone()
45534e3744c5SMatthew G. Knepley @*/
45544e3744c5SMatthew G. Knepley PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal)
45554e3744c5SMatthew G. Knepley {
45564e3744c5SMatthew G. Knepley   PetscInt       depth, depthB, pStart, pEnd, pStartB, pEndB, p;
45574e3744c5SMatthew G. Knepley   PetscErrorCode ierr;
45584e3744c5SMatthew G. Knepley 
45594e3744c5SMatthew G. Knepley   PetscFunctionBegin;
45604e3744c5SMatthew G. Knepley   PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
45614e3744c5SMatthew G. Knepley   PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
45624e3744c5SMatthew G. Knepley   PetscValidPointer(equal, 3);
45634e3744c5SMatthew G. Knepley 
45644e3744c5SMatthew G. Knepley   *equal = PETSC_FALSE;
45654e3744c5SMatthew G. Knepley   ierr = DMPlexGetDepth(dmA, &depth);CHKERRQ(ierr);
45664e3744c5SMatthew G. Knepley   ierr = DMPlexGetDepth(dmB, &depthB);CHKERRQ(ierr);
45674e3744c5SMatthew G. Knepley   if (depth != depthB) PetscFunctionReturn(0);
45684e3744c5SMatthew G. Knepley   ierr = DMPlexGetChart(dmA, &pStart,  &pEnd);CHKERRQ(ierr);
45694e3744c5SMatthew G. Knepley   ierr = DMPlexGetChart(dmB, &pStartB, &pEndB);CHKERRQ(ierr);
45704e3744c5SMatthew G. Knepley   if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(0);
45714e3744c5SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
45724e3744c5SMatthew G. Knepley     const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB;
45734e3744c5SMatthew G. Knepley     PetscInt        coneSize, coneSizeB, c, supportSize, supportSizeB, s;
45744e3744c5SMatthew G. Knepley 
45754e3744c5SMatthew G. Knepley     ierr = DMPlexGetConeSize(dmA, p, &coneSize);CHKERRQ(ierr);
45764e3744c5SMatthew G. Knepley     ierr = DMPlexGetCone(dmA, p, &cone);CHKERRQ(ierr);
45774e3744c5SMatthew G. Knepley     ierr = DMPlexGetConeOrientation(dmA, p, &ornt);CHKERRQ(ierr);
45784e3744c5SMatthew G. Knepley     ierr = DMPlexGetConeSize(dmB, p, &coneSizeB);CHKERRQ(ierr);
45794e3744c5SMatthew G. Knepley     ierr = DMPlexGetCone(dmB, p, &coneB);CHKERRQ(ierr);
45804e3744c5SMatthew G. Knepley     ierr = DMPlexGetConeOrientation(dmB, p, &orntB);CHKERRQ(ierr);
45814e3744c5SMatthew G. Knepley     if (coneSize != coneSizeB) PetscFunctionReturn(0);
45824e3744c5SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
45834e3744c5SMatthew G. Knepley       if (cone[c] != coneB[c]) PetscFunctionReturn(0);
45844e3744c5SMatthew G. Knepley       if (ornt[c] != orntB[c]) PetscFunctionReturn(0);
45854e3744c5SMatthew G. Knepley     }
45864e3744c5SMatthew G. Knepley     ierr = DMPlexGetSupportSize(dmA, p, &supportSize);CHKERRQ(ierr);
45874e3744c5SMatthew G. Knepley     ierr = DMPlexGetSupport(dmA, p, &support);CHKERRQ(ierr);
45884e3744c5SMatthew G. Knepley     ierr = DMPlexGetSupportSize(dmB, p, &supportSizeB);CHKERRQ(ierr);
45894e3744c5SMatthew G. Knepley     ierr = DMPlexGetSupport(dmB, p, &supportB);CHKERRQ(ierr);
45904e3744c5SMatthew G. Knepley     if (supportSize != supportSizeB) PetscFunctionReturn(0);
45914e3744c5SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
45924e3744c5SMatthew G. Knepley       if (support[s] != supportB[s]) PetscFunctionReturn(0);
45934e3744c5SMatthew G. Knepley     }
45944e3744c5SMatthew G. Knepley   }
45954e3744c5SMatthew G. Knepley   *equal = PETSC_TRUE;
45964e3744c5SMatthew G. Knepley   PetscFunctionReturn(0);
45974e3744c5SMatthew G. Knepley }
45984e3744c5SMatthew G. Knepley 
45997cd05799SMatthew G. Knepley /*@C
46007cd05799SMatthew G. Knepley   DMPlexGetNumFaceVertices - Returns the number of vertices on a face
46017cd05799SMatthew G. Knepley 
46027cd05799SMatthew G. Knepley   Not Collective
46037cd05799SMatthew G. Knepley 
46047cd05799SMatthew G. Knepley   Input Parameters:
46057cd05799SMatthew G. Knepley + dm         - The DMPlex
46067cd05799SMatthew G. Knepley . cellDim    - The cell dimension
46077cd05799SMatthew G. Knepley - numCorners - The number of vertices on a cell
46087cd05799SMatthew G. Knepley 
46097cd05799SMatthew G. Knepley   Output Parameters:
46107cd05799SMatthew G. Knepley . numFaceVertices - The number of vertices on a face
46117cd05799SMatthew G. Knepley 
46127cd05799SMatthew G. Knepley   Level: developer
46137cd05799SMatthew G. Knepley 
46147cd05799SMatthew G. Knepley   Notes:
46157cd05799SMatthew G. Knepley   Of course this can only work for a restricted set of symmetric shapes
46167cd05799SMatthew G. Knepley 
46177cd05799SMatthew G. Knepley .seealso: DMPlexGetCone()
46187cd05799SMatthew G. Knepley @*/
461918ad9376SMatthew G. Knepley PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices)
4620a6dfd86eSKarl Rupp {
462182f516ccSBarry Smith   MPI_Comm       comm;
4622552f7358SJed Brown   PetscErrorCode ierr;
4623552f7358SJed Brown 
4624552f7358SJed Brown   PetscFunctionBegin;
462582f516ccSBarry Smith   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
4626064a246eSJacob Faibussowitsch   PetscValidPointer(numFaceVertices,4);
4627552f7358SJed Brown   switch (cellDim) {
4628552f7358SJed Brown   case 0:
4629552f7358SJed Brown     *numFaceVertices = 0;
4630552f7358SJed Brown     break;
4631552f7358SJed Brown   case 1:
4632552f7358SJed Brown     *numFaceVertices = 1;
4633552f7358SJed Brown     break;
4634552f7358SJed Brown   case 2:
4635552f7358SJed Brown     switch (numCorners) {
463619436ca2SJed Brown     case 3: /* triangle */
463719436ca2SJed Brown       *numFaceVertices = 2; /* Edge has 2 vertices */
4638552f7358SJed Brown       break;
463919436ca2SJed Brown     case 4: /* quadrilateral */
464019436ca2SJed Brown       *numFaceVertices = 2; /* Edge has 2 vertices */
4641552f7358SJed Brown       break;
464219436ca2SJed Brown     case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */
464319436ca2SJed Brown       *numFaceVertices = 3; /* Edge has 3 vertices */
4644552f7358SJed Brown       break;
464519436ca2SJed Brown     case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */
464619436ca2SJed Brown       *numFaceVertices = 3; /* Edge has 3 vertices */
4647552f7358SJed Brown       break;
4648552f7358SJed Brown     default:
464998921bdaSJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim);
4650552f7358SJed Brown     }
4651552f7358SJed Brown     break;
4652552f7358SJed Brown   case 3:
4653552f7358SJed Brown     switch (numCorners) {
465419436ca2SJed Brown     case 4: /* tetradehdron */
465519436ca2SJed Brown       *numFaceVertices = 3; /* Face has 3 vertices */
4656552f7358SJed Brown       break;
465719436ca2SJed Brown     case 6: /* tet cohesive cells */
465819436ca2SJed Brown       *numFaceVertices = 4; /* Face has 4 vertices */
4659552f7358SJed Brown       break;
466019436ca2SJed Brown     case 8: /* hexahedron */
466119436ca2SJed Brown       *numFaceVertices = 4; /* Face has 4 vertices */
4662552f7358SJed Brown       break;
466319436ca2SJed Brown     case 9: /* tet cohesive Lagrange cells */
466419436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4665552f7358SJed Brown       break;
466619436ca2SJed Brown     case 10: /* quadratic tetrahedron */
466719436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4668552f7358SJed Brown       break;
466919436ca2SJed Brown     case 12: /* hex cohesive Lagrange cells */
467019436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4671552f7358SJed Brown       break;
467219436ca2SJed Brown     case 18: /* quadratic tet cohesive Lagrange cells */
467319436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4674552f7358SJed Brown       break;
467519436ca2SJed Brown     case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */
467619436ca2SJed Brown       *numFaceVertices = 9; /* Face has 9 vertices */
4677552f7358SJed Brown       break;
4678552f7358SJed Brown     default:
467998921bdaSJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim);
4680552f7358SJed Brown     }
4681552f7358SJed Brown     break;
4682552f7358SJed Brown   default:
468398921bdaSJacob Faibussowitsch     SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %D", cellDim);
4684552f7358SJed Brown   }
4685552f7358SJed Brown   PetscFunctionReturn(0);
4686552f7358SJed Brown }
4687552f7358SJed Brown 
4688552f7358SJed Brown /*@
4689aa50250dSMatthew G. Knepley   DMPlexGetDepthLabel - Get the DMLabel recording the depth of each point
4690552f7358SJed Brown 
4691552f7358SJed Brown   Not Collective
4692552f7358SJed Brown 
4693aa50250dSMatthew G. Knepley   Input Parameter:
4694552f7358SJed Brown . dm    - The DMPlex object
4695552f7358SJed Brown 
4696aa50250dSMatthew G. Knepley   Output Parameter:
4697aa50250dSMatthew G. Knepley . depthLabel - The DMLabel recording point depth
4698552f7358SJed Brown 
4699552f7358SJed Brown   Level: developer
4700552f7358SJed Brown 
4701dc287ab2SVaclav Hapla .seealso: DMPlexGetDepth(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum(), DMPlexGetPointDepth(),
4702aa50250dSMatthew G. Knepley @*/
4703aa50250dSMatthew G. Knepley PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel)
4704aa50250dSMatthew G. Knepley {
4705aa50250dSMatthew G. Knepley   PetscFunctionBegin;
4706aa50250dSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4707aa50250dSMatthew G. Knepley   PetscValidPointer(depthLabel, 2);
4708c58f1c22SToby Isaac   *depthLabel = dm->depthLabel;
4709aa50250dSMatthew G. Knepley   PetscFunctionReturn(0);
4710aa50250dSMatthew G. Knepley }
4711aa50250dSMatthew G. Knepley 
4712aa50250dSMatthew G. Knepley /*@
4713aa50250dSMatthew G. Knepley   DMPlexGetDepth - Get the depth of the DAG representing this mesh
4714aa50250dSMatthew G. Knepley 
4715aa50250dSMatthew G. Knepley   Not Collective
4716aa50250dSMatthew G. Knepley 
4717aa50250dSMatthew G. Knepley   Input Parameter:
4718aa50250dSMatthew G. Knepley . dm    - The DMPlex object
4719aa50250dSMatthew G. Knepley 
4720aa50250dSMatthew G. Knepley   Output Parameter:
4721aa50250dSMatthew G. Knepley . depth - The number of strata (breadth first levels) in the DAG
4722aa50250dSMatthew G. Knepley 
4723aa50250dSMatthew G. Knepley   Level: developer
4724552f7358SJed Brown 
4725b1bb481bSMatthew Knepley   Notes:
4726b1bb481bSMatthew Knepley   This returns maximum of point depths over all points, i.e. maximum value of the label returned by DMPlexGetDepthLabel().
4727dc287ab2SVaclav Hapla   The point depth is described more in detail in DMPlexGetDepthStratum().
4728dc287ab2SVaclav Hapla   An empty mesh gives -1.
4729b1bb481bSMatthew Knepley 
4730dc287ab2SVaclav Hapla .seealso: DMPlexGetDepthLabel(), DMPlexGetDepthStratum(), DMPlexGetPointDepth(), DMPlexSymmetrize()
4731552f7358SJed Brown @*/
4732552f7358SJed Brown PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth)
4733552f7358SJed Brown {
4734aa50250dSMatthew G. Knepley   DMLabel        label;
4735aa50250dSMatthew G. Knepley   PetscInt       d = 0;
4736552f7358SJed Brown   PetscErrorCode ierr;
4737552f7358SJed Brown 
4738552f7358SJed Brown   PetscFunctionBegin;
4739552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4740552f7358SJed Brown   PetscValidPointer(depth, 2);
4741aa50250dSMatthew G. Knepley   ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr);
4742aa50250dSMatthew G. Knepley   if (label) {ierr = DMLabelGetNumValues(label, &d);CHKERRQ(ierr);}
4743552f7358SJed Brown   *depth = d-1;
4744552f7358SJed Brown   PetscFunctionReturn(0);
4745552f7358SJed Brown }
4746552f7358SJed Brown 
4747552f7358SJed Brown /*@
4748552f7358SJed Brown   DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth.
4749552f7358SJed Brown 
4750552f7358SJed Brown   Not Collective
4751552f7358SJed Brown 
4752552f7358SJed Brown   Input Parameters:
4753552f7358SJed Brown + dm           - The DMPlex object
4754552f7358SJed Brown - stratumValue - The requested depth
4755552f7358SJed Brown 
4756552f7358SJed Brown   Output Parameters:
4757552f7358SJed Brown + start - The first point at this depth
4758552f7358SJed Brown - end   - One beyond the last point at this depth
4759552f7358SJed Brown 
4760647867b2SJed Brown   Notes:
4761647867b2SJed Brown   Depth indexing is related to topological dimension.  Depth stratum 0 contains the lowest topological dimension points,
4762647867b2SJed Brown   often "vertices".  If the mesh is "interpolated" (see DMPlexInterpolate()), then depth stratum 1 contains the next
4763647867b2SJed Brown   higher dimension, e.g., "edges".
4764647867b2SJed Brown 
4765552f7358SJed Brown   Level: developer
4766552f7358SJed Brown 
4767dc287ab2SVaclav Hapla .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth(), DMPlexGetDepthLabel(), DMPlexGetPointDepth(), DMPlexSymmetrize(), DMPlexInterpolate()
4768552f7358SJed Brown @*/
47690adebc6cSBarry Smith PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end)
47700adebc6cSBarry Smith {
4771aa50250dSMatthew G. Knepley   DMLabel        label;
477263d1a920SMatthew G. Knepley   PetscInt       pStart, pEnd;
4773552f7358SJed Brown   PetscErrorCode ierr;
4774552f7358SJed Brown 
4775552f7358SJed Brown   PetscFunctionBegin;
4776552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
477763d1a920SMatthew G. Knepley   if (start) {PetscValidPointer(start, 3); *start = 0;}
477863d1a920SMatthew G. Knepley   if (end)   {PetscValidPointer(end,   4); *end   = 0;}
4779552f7358SJed Brown   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
47800d644c17SKarl Rupp   if (pStart == pEnd) PetscFunctionReturn(0);
478163d1a920SMatthew G. Knepley   if (stratumValue < 0) {
478263d1a920SMatthew G. Knepley     if (start) *start = pStart;
478363d1a920SMatthew G. Knepley     if (end)   *end   = pEnd;
478463d1a920SMatthew G. Knepley     PetscFunctionReturn(0);
4785552f7358SJed Brown   }
4786aa50250dSMatthew G. Knepley   ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr);
47872c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");
478863d1a920SMatthew G. Knepley   ierr = DMLabelGetStratumBounds(label, stratumValue, start, end);CHKERRQ(ierr);
4789552f7358SJed Brown   PetscFunctionReturn(0);
4790552f7358SJed Brown }
4791552f7358SJed Brown 
4792552f7358SJed Brown /*@
4793552f7358SJed Brown   DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height.
4794552f7358SJed Brown 
4795552f7358SJed Brown   Not Collective
4796552f7358SJed Brown 
4797552f7358SJed Brown   Input Parameters:
4798552f7358SJed Brown + dm           - The DMPlex object
4799552f7358SJed Brown - stratumValue - The requested height
4800552f7358SJed Brown 
4801552f7358SJed Brown   Output Parameters:
4802552f7358SJed Brown + start - The first point at this height
4803552f7358SJed Brown - end   - One beyond the last point at this height
4804552f7358SJed Brown 
4805647867b2SJed Brown   Notes:
4806647867b2SJed Brown   Height indexing is related to topological codimension.  Height stratum 0 contains the highest topological dimension
4807647867b2SJed Brown   points, often called "cells" or "elements".  If the mesh is "interpolated" (see DMPlexInterpolate()), then height
4808647867b2SJed Brown   stratum 1 contains the boundary of these "cells", often called "faces" or "facets".
4809647867b2SJed Brown 
4810552f7358SJed Brown   Level: developer
4811552f7358SJed Brown 
48123dc9a465SVaclav Hapla .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth(), DMPlexGetPointHeight()
4813552f7358SJed Brown @*/
48140adebc6cSBarry Smith PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end)
48150adebc6cSBarry Smith {
4816aa50250dSMatthew G. Knepley   DMLabel        label;
481763d1a920SMatthew G. Knepley   PetscInt       depth, pStart, pEnd;
4818552f7358SJed Brown   PetscErrorCode ierr;
4819552f7358SJed Brown 
4820552f7358SJed Brown   PetscFunctionBegin;
4821552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
482263d1a920SMatthew G. Knepley   if (start) {PetscValidPointer(start, 3); *start = 0;}
482363d1a920SMatthew G. Knepley   if (end)   {PetscValidPointer(end,   4); *end   = 0;}
4824552f7358SJed Brown   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
48250d644c17SKarl Rupp   if (pStart == pEnd) PetscFunctionReturn(0);
482663d1a920SMatthew G. Knepley   if (stratumValue < 0) {
482763d1a920SMatthew G. Knepley     if (start) *start = pStart;
482863d1a920SMatthew G. Knepley     if (end)   *end   = pEnd;
482963d1a920SMatthew G. Knepley     PetscFunctionReturn(0);
4830552f7358SJed Brown   }
4831aa50250dSMatthew G. Knepley   ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr);
48322c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");
483363d1a920SMatthew G. Knepley   ierr = DMLabelGetNumValues(label, &depth);CHKERRQ(ierr);
483463d1a920SMatthew G. Knepley   ierr = DMLabelGetStratumBounds(label, depth-1-stratumValue, start, end);CHKERRQ(ierr);
4835552f7358SJed Brown   PetscFunctionReturn(0);
4836552f7358SJed Brown }
4837552f7358SJed Brown 
4838ba2698f1SMatthew G. Knepley /*@
4839ba2698f1SMatthew G. Knepley   DMPlexGetPointDepth - Get the depth of a given point
4840ba2698f1SMatthew G. Knepley 
4841ba2698f1SMatthew G. Knepley   Not Collective
4842ba2698f1SMatthew G. Knepley 
4843d8d19677SJose E. Roman   Input Parameters:
4844ba2698f1SMatthew G. Knepley + dm    - The DMPlex object
4845ba2698f1SMatthew G. Knepley - point - The point
4846ba2698f1SMatthew G. Knepley 
4847ba2698f1SMatthew G. Knepley   Output Parameter:
4848ba2698f1SMatthew G. Knepley . depth - The depth of the point
4849ba2698f1SMatthew G. Knepley 
4850ba2698f1SMatthew G. Knepley   Level: intermediate
4851ba2698f1SMatthew G. Knepley 
48523dc9a465SVaclav Hapla .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexGetPointHeight()
4853ba2698f1SMatthew G. Knepley @*/
4854ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth)
4855ba2698f1SMatthew G. Knepley {
4856ba2698f1SMatthew G. Knepley   PetscErrorCode ierr;
4857ba2698f1SMatthew G. Knepley 
4858ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
4859ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
486040a2aa30SMatthew G. Knepley   PetscValidIntPointer(depth, 3);
4861ba2698f1SMatthew G. Knepley   ierr = DMLabelGetValue(dm->depthLabel, point, depth);CHKERRQ(ierr);
4862ba2698f1SMatthew G. Knepley   PetscFunctionReturn(0);
4863ba2698f1SMatthew G. Knepley }
4864ba2698f1SMatthew G. Knepley 
4865ba2698f1SMatthew G. Knepley /*@
48660c0a32dcSVaclav Hapla   DMPlexGetPointHeight - Get the height of a given point
48670c0a32dcSVaclav Hapla 
48680c0a32dcSVaclav Hapla   Not Collective
48690c0a32dcSVaclav Hapla 
4870d8d19677SJose E. Roman   Input Parameters:
48710c0a32dcSVaclav Hapla + dm    - The DMPlex object
48720c0a32dcSVaclav Hapla - point - The point
48730c0a32dcSVaclav Hapla 
48740c0a32dcSVaclav Hapla   Output Parameter:
48750c0a32dcSVaclav Hapla . height - The height of the point
48760c0a32dcSVaclav Hapla 
48770c0a32dcSVaclav Hapla   Level: intermediate
48780c0a32dcSVaclav Hapla 
48793dc9a465SVaclav Hapla .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexGetPointDepth()
48800c0a32dcSVaclav Hapla @*/
48810c0a32dcSVaclav Hapla PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height)
48820c0a32dcSVaclav Hapla {
48830c0a32dcSVaclav Hapla   PetscInt       n, pDepth;
48840c0a32dcSVaclav Hapla   PetscErrorCode ierr;
48850c0a32dcSVaclav Hapla 
48860c0a32dcSVaclav Hapla   PetscFunctionBegin;
48870c0a32dcSVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
48880c0a32dcSVaclav Hapla   PetscValidIntPointer(height, 3);
48890c0a32dcSVaclav Hapla   ierr = DMLabelGetNumValues(dm->depthLabel, &n);CHKERRQ(ierr);
48900c0a32dcSVaclav Hapla   ierr = DMLabelGetValue(dm->depthLabel, point, &pDepth);CHKERRQ(ierr);
48910c0a32dcSVaclav Hapla   *height = n - 1 - pDepth;  /* DAG depth is n-1 */
48920c0a32dcSVaclav Hapla   PetscFunctionReturn(0);
48930c0a32dcSVaclav Hapla }
48940c0a32dcSVaclav Hapla 
48950c0a32dcSVaclav Hapla /*@
4896ba2698f1SMatthew G. Knepley   DMPlexGetCellTypeLabel - Get the DMLabel recording the polytope type of each cell
4897ba2698f1SMatthew G. Knepley 
4898ba2698f1SMatthew G. Knepley   Not Collective
4899ba2698f1SMatthew G. Knepley 
4900ba2698f1SMatthew G. Knepley   Input Parameter:
4901ba2698f1SMatthew G. Knepley . dm - The DMPlex object
4902ba2698f1SMatthew G. Knepley 
4903ba2698f1SMatthew G. Knepley   Output Parameter:
4904ba2698f1SMatthew G. Knepley . celltypeLabel - The DMLabel recording cell polytope type
4905ba2698f1SMatthew G. Knepley 
4906412e9a14SMatthew G. Knepley   Note: This function will trigger automatica computation of cell types. This can be disabled by calling
4907412e9a14SMatthew G. Knepley   DMCreateLabel(dm, "celltype") beforehand.
4908412e9a14SMatthew G. Knepley 
4909ba2698f1SMatthew G. Knepley   Level: developer
4910ba2698f1SMatthew G. Knepley 
4911dc287ab2SVaclav Hapla .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMCreateLabel()
4912ba2698f1SMatthew G. Knepley @*/
4913ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel)
4914ba2698f1SMatthew G. Knepley {
4915ba2698f1SMatthew G. Knepley   PetscErrorCode ierr;
4916ba2698f1SMatthew G. Knepley 
4917ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
4918ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4919ba2698f1SMatthew G. Knepley   PetscValidPointer(celltypeLabel, 2);
4920ba2698f1SMatthew G. Knepley   if (!dm->celltypeLabel) {ierr = DMPlexComputeCellTypes(dm);CHKERRQ(ierr);}
4921ba2698f1SMatthew G. Knepley   *celltypeLabel = dm->celltypeLabel;
4922ba2698f1SMatthew G. Knepley   PetscFunctionReturn(0);
4923ba2698f1SMatthew G. Knepley }
4924ba2698f1SMatthew G. Knepley 
4925ba2698f1SMatthew G. Knepley /*@
4926ba2698f1SMatthew G. Knepley   DMPlexGetCellType - Get the polytope type of a given cell
4927ba2698f1SMatthew G. Knepley 
4928ba2698f1SMatthew G. Knepley   Not Collective
4929ba2698f1SMatthew G. Knepley 
4930d8d19677SJose E. Roman   Input Parameters:
4931ba2698f1SMatthew G. Knepley + dm   - The DMPlex object
4932ba2698f1SMatthew G. Knepley - cell - The cell
4933ba2698f1SMatthew G. Knepley 
4934ba2698f1SMatthew G. Knepley   Output Parameter:
4935ba2698f1SMatthew G. Knepley . celltype - The polytope type of the cell
4936ba2698f1SMatthew G. Knepley 
4937ba2698f1SMatthew G. Knepley   Level: intermediate
4938ba2698f1SMatthew G. Knepley 
4939ba2698f1SMatthew G. Knepley .seealso: DMPlexGetCellTypeLabel(), DMPlexGetDepthLabel(), DMPlexGetDepth()
4940ba2698f1SMatthew G. Knepley @*/
4941ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype)
4942ba2698f1SMatthew G. Knepley {
4943ba2698f1SMatthew G. Knepley   DMLabel        label;
4944ba2698f1SMatthew G. Knepley   PetscInt       ct;
4945ba2698f1SMatthew G. Knepley   PetscErrorCode ierr;
4946ba2698f1SMatthew G. Knepley 
4947ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
4948ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4949ba2698f1SMatthew G. Knepley   PetscValidPointer(celltype, 3);
4950ba2698f1SMatthew G. Knepley   ierr = DMPlexGetCellTypeLabel(dm, &label);CHKERRQ(ierr);
4951ba2698f1SMatthew G. Knepley   ierr = DMLabelGetValue(label, cell, &ct);CHKERRQ(ierr);
49522c71b3e2SJacob Faibussowitsch   PetscCheckFalse(ct < 0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %D has not been assigned a cell type", cell);
4953ba2698f1SMatthew G. Knepley   *celltype = (DMPolytopeType) ct;
4954ba2698f1SMatthew G. Knepley   PetscFunctionReturn(0);
4955ba2698f1SMatthew G. Knepley }
4956ba2698f1SMatthew G. Knepley 
4957412e9a14SMatthew G. Knepley /*@
4958412e9a14SMatthew G. Knepley   DMPlexSetCellType - Set the polytope type of a given cell
4959412e9a14SMatthew G. Knepley 
4960412e9a14SMatthew G. Knepley   Not Collective
4961412e9a14SMatthew G. Knepley 
4962412e9a14SMatthew G. Knepley   Input Parameters:
4963412e9a14SMatthew G. Knepley + dm   - The DMPlex object
4964412e9a14SMatthew G. Knepley . cell - The cell
4965412e9a14SMatthew G. Knepley - celltype - The polytope type of the cell
4966412e9a14SMatthew G. Knepley 
4967412e9a14SMatthew G. Knepley   Note: By default, cell types will be automatically computed using DMPlexComputeCellTypes() before this function
4968412e9a14SMatthew G. Knepley   is executed. This function will override the computed type. However, if automatic classification will not succeed
4969412e9a14SMatthew G. Knepley   and a user wants to manually specify all types, the classification must be disabled by calling
4970412e9a14SMatthew G. Knepley   DMCreaateLabel(dm, "celltype") before getting or setting any cell types.
4971412e9a14SMatthew G. Knepley 
4972412e9a14SMatthew G. Knepley   Level: advanced
4973412e9a14SMatthew G. Knepley 
4974412e9a14SMatthew G. Knepley .seealso: DMPlexGetCellTypeLabel(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexComputeCellTypes(), DMCreateLabel()
4975412e9a14SMatthew G. Knepley @*/
4976412e9a14SMatthew G. Knepley PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype)
4977412e9a14SMatthew G. Knepley {
4978412e9a14SMatthew G. Knepley   DMLabel        label;
4979412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
4980412e9a14SMatthew G. Knepley 
4981412e9a14SMatthew G. Knepley   PetscFunctionBegin;
4982412e9a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4983412e9a14SMatthew G. Knepley   ierr = DMPlexGetCellTypeLabel(dm, &label);CHKERRQ(ierr);
4984412e9a14SMatthew G. Knepley   ierr = DMLabelSetValue(label, cell, celltype);CHKERRQ(ierr);
4985412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
4986412e9a14SMatthew G. Knepley }
4987412e9a14SMatthew G. Knepley 
49880adebc6cSBarry Smith PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm)
49890adebc6cSBarry Smith {
4990efe440bfSMatthew G. Knepley   PetscSection   section, s;
4991efe440bfSMatthew G. Knepley   Mat            m;
49923e922f36SToby Isaac   PetscInt       maxHeight;
4993552f7358SJed Brown   PetscErrorCode ierr;
4994552f7358SJed Brown 
4995552f7358SJed Brown   PetscFunctionBegin;
499638221697SMatthew G. Knepley   ierr = DMClone(dm, cdm);CHKERRQ(ierr);
49973e922f36SToby Isaac   ierr = DMPlexGetMaxProjectionHeight(dm, &maxHeight);CHKERRQ(ierr);
49983e922f36SToby Isaac   ierr = DMPlexSetMaxProjectionHeight(*cdm, maxHeight);CHKERRQ(ierr);
499982f516ccSBarry Smith   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section);CHKERRQ(ierr);
500092fd8e1eSJed Brown   ierr = DMSetLocalSection(*cdm, section);CHKERRQ(ierr);
50011d799100SJed Brown   ierr = PetscSectionDestroy(&section);CHKERRQ(ierr);
5002efe440bfSMatthew G. Knepley   ierr = PetscSectionCreate(PETSC_COMM_SELF, &s);CHKERRQ(ierr);
5003efe440bfSMatthew G. Knepley   ierr = MatCreate(PETSC_COMM_SELF, &m);CHKERRQ(ierr);
500479769bd5SJed Brown   ierr = DMSetDefaultConstraints(*cdm, s, m, NULL);CHKERRQ(ierr);
5005efe440bfSMatthew G. Knepley   ierr = PetscSectionDestroy(&s);CHKERRQ(ierr);
5006efe440bfSMatthew G. Knepley   ierr = MatDestroy(&m);CHKERRQ(ierr);
50078f4c458bSMatthew G. Knepley 
50088f4c458bSMatthew G. Knepley   ierr = DMSetNumFields(*cdm, 1);CHKERRQ(ierr);
50098f4c458bSMatthew G. Knepley   ierr = DMCreateDS(*cdm);CHKERRQ(ierr);
5010552f7358SJed Brown   PetscFunctionReturn(0);
5011552f7358SJed Brown }
5012552f7358SJed Brown 
5013f19dbd58SToby Isaac PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field)
5014f19dbd58SToby Isaac {
5015f19dbd58SToby Isaac   Vec            coordsLocal;
5016f19dbd58SToby Isaac   DM             coordsDM;
5017f19dbd58SToby Isaac   PetscErrorCode ierr;
5018f19dbd58SToby Isaac 
5019f19dbd58SToby Isaac   PetscFunctionBegin;
5020f19dbd58SToby Isaac   *field = NULL;
5021f19dbd58SToby Isaac   ierr = DMGetCoordinatesLocal(dm,&coordsLocal);CHKERRQ(ierr);
5022f19dbd58SToby Isaac   ierr = DMGetCoordinateDM(dm,&coordsDM);CHKERRQ(ierr);
5023f19dbd58SToby Isaac   if (coordsLocal && coordsDM) {
5024f19dbd58SToby Isaac     ierr = DMFieldCreateDS(coordsDM, 0, coordsLocal, field);CHKERRQ(ierr);
5025f19dbd58SToby Isaac   }
5026f19dbd58SToby Isaac   PetscFunctionReturn(0);
5027f19dbd58SToby Isaac }
5028f19dbd58SToby Isaac 
50297cd05799SMatthew G. Knepley /*@C
50307cd05799SMatthew G. Knepley   DMPlexGetConeSection - Return a section which describes the layout of cone data
50317cd05799SMatthew G. Knepley 
50327cd05799SMatthew G. Knepley   Not Collective
50337cd05799SMatthew G. Knepley 
50347cd05799SMatthew G. Knepley   Input Parameters:
50357cd05799SMatthew G. Knepley . dm        - The DMPlex object
50367cd05799SMatthew G. Knepley 
50377cd05799SMatthew G. Knepley   Output Parameter:
50387cd05799SMatthew G. Knepley . section - The PetscSection object
50397cd05799SMatthew G. Knepley 
50407cd05799SMatthew G. Knepley   Level: developer
50417cd05799SMatthew G. Knepley 
50427cd05799SMatthew G. Knepley .seealso: DMPlexGetSupportSection(), DMPlexGetCones(), DMPlexGetConeOrientations()
50437cd05799SMatthew G. Knepley @*/
50440adebc6cSBarry Smith PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section)
50450adebc6cSBarry Smith {
5046552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
5047552f7358SJed Brown 
5048552f7358SJed Brown   PetscFunctionBegin;
5049552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5050552f7358SJed Brown   if (section) *section = mesh->coneSection;
5051552f7358SJed Brown   PetscFunctionReturn(0);
5052552f7358SJed Brown }
5053552f7358SJed Brown 
50547cd05799SMatthew G. Knepley /*@C
50557cd05799SMatthew G. Knepley   DMPlexGetSupportSection - Return a section which describes the layout of support data
50567cd05799SMatthew G. Knepley 
50577cd05799SMatthew G. Knepley   Not Collective
50587cd05799SMatthew G. Knepley 
50597cd05799SMatthew G. Knepley   Input Parameters:
50607cd05799SMatthew G. Knepley . dm        - The DMPlex object
50617cd05799SMatthew G. Knepley 
50627cd05799SMatthew G. Knepley   Output Parameter:
50637cd05799SMatthew G. Knepley . section - The PetscSection object
50647cd05799SMatthew G. Knepley 
50657cd05799SMatthew G. Knepley   Level: developer
50667cd05799SMatthew G. Knepley 
50677cd05799SMatthew G. Knepley .seealso: DMPlexGetConeSection()
50687cd05799SMatthew G. Knepley @*/
50698cb4d582SMatthew G. Knepley PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section)
50708cb4d582SMatthew G. Knepley {
50718cb4d582SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
50728cb4d582SMatthew G. Knepley 
50738cb4d582SMatthew G. Knepley   PetscFunctionBegin;
50748cb4d582SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
50758cb4d582SMatthew G. Knepley   if (section) *section = mesh->supportSection;
50768cb4d582SMatthew G. Knepley   PetscFunctionReturn(0);
50778cb4d582SMatthew G. Knepley }
50788cb4d582SMatthew G. Knepley 
50797cd05799SMatthew G. Knepley /*@C
50807cd05799SMatthew G. Knepley   DMPlexGetCones - Return cone data
50817cd05799SMatthew G. Knepley 
50827cd05799SMatthew G. Knepley   Not Collective
50837cd05799SMatthew G. Knepley 
50847cd05799SMatthew G. Knepley   Input Parameters:
50857cd05799SMatthew G. Knepley . dm        - The DMPlex object
50867cd05799SMatthew G. Knepley 
50877cd05799SMatthew G. Knepley   Output Parameter:
50887cd05799SMatthew G. Knepley . cones - The cone for each point
50897cd05799SMatthew G. Knepley 
50907cd05799SMatthew G. Knepley   Level: developer
50917cd05799SMatthew G. Knepley 
50927cd05799SMatthew G. Knepley .seealso: DMPlexGetConeSection()
50937cd05799SMatthew G. Knepley @*/
5094a6dfd86eSKarl Rupp PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[])
5095a6dfd86eSKarl Rupp {
5096552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
5097552f7358SJed Brown 
5098552f7358SJed Brown   PetscFunctionBegin;
5099552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5100552f7358SJed Brown   if (cones) *cones = mesh->cones;
5101552f7358SJed Brown   PetscFunctionReturn(0);
5102552f7358SJed Brown }
5103552f7358SJed Brown 
51047cd05799SMatthew G. Knepley /*@C
51057cd05799SMatthew G. Knepley   DMPlexGetConeOrientations - Return cone orientation data
51067cd05799SMatthew G. Knepley 
51077cd05799SMatthew G. Knepley   Not Collective
51087cd05799SMatthew G. Knepley 
51097cd05799SMatthew G. Knepley   Input Parameters:
51107cd05799SMatthew G. Knepley . dm        - The DMPlex object
51117cd05799SMatthew G. Knepley 
51127cd05799SMatthew G. Knepley   Output Parameter:
5113b5a892a1SMatthew G. Knepley . coneOrientations - The array of cone orientations for all points
51147cd05799SMatthew G. Knepley 
51157cd05799SMatthew G. Knepley   Level: developer
51167cd05799SMatthew G. Knepley 
5117b5a892a1SMatthew G. Knepley   Notes:
5118b5a892a1SMatthew G. Knepley   The PetscSection returned by DMPlexGetConeSection() partitions coneOrientations into cone orientations of particular points as returned by DMPlexGetConeOrientation().
5119b5a892a1SMatthew G. Knepley 
5120b5a892a1SMatthew G. Knepley   The meaning of coneOrientations values is detailed in DMPlexGetConeOrientation().
5121b5a892a1SMatthew G. Knepley 
5122b5a892a1SMatthew G. Knepley .seealso: DMPlexGetConeSection(), DMPlexGetConeOrientation()
51237cd05799SMatthew G. Knepley @*/
5124a6dfd86eSKarl Rupp PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[])
5125a6dfd86eSKarl Rupp {
5126552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
5127552f7358SJed Brown 
5128552f7358SJed Brown   PetscFunctionBegin;
5129552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5130552f7358SJed Brown   if (coneOrientations) *coneOrientations = mesh->coneOrientations;
5131552f7358SJed Brown   PetscFunctionReturn(0);
5132552f7358SJed Brown }
5133552f7358SJed Brown 
5134552f7358SJed Brown /******************************** FEM Support **********************************/
5135552f7358SJed Brown 
51369e8305c2SJed Brown /*
51379e8305c2SJed Brown  Returns number of components and tensor degree for the field.  For interpolated meshes, line should be a point
51389e8305c2SJed Brown  representing a line in the section.
51399e8305c2SJed Brown */
51409e8305c2SJed Brown static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(PetscSection section,PetscInt field,PetscInt line,PetscBool vertexchart,PetscInt *Nc,PetscInt *k)
51419e8305c2SJed Brown {
51429e8305c2SJed Brown   PetscErrorCode ierr;
51439e8305c2SJed Brown 
51449e8305c2SJed Brown   PetscFunctionBeginHot;
51459e8305c2SJed Brown   ierr = PetscSectionGetFieldComponents(section, field, Nc);CHKERRQ(ierr);
5146a433471fSStefano Zampini   if (line < 0) {
5147a433471fSStefano Zampini     *k = 0;
5148a433471fSStefano Zampini     *Nc = 0;
5149a433471fSStefano Zampini   } else if (vertexchart) {            /* If we only have a vertex chart, we must have degree k=1 */
51509e8305c2SJed Brown     *k = 1;
51519e8305c2SJed Brown   } else {                      /* Assume the full interpolated mesh is in the chart; lines in particular */
51529e8305c2SJed Brown     /* An order k SEM disc has k-1 dofs on an edge */
51539e8305c2SJed Brown     ierr = PetscSectionGetFieldDof(section, line, field, k);CHKERRQ(ierr);
51549e8305c2SJed Brown     *k = *k / *Nc + 1;
51559e8305c2SJed Brown   }
51569e8305c2SJed Brown   PetscFunctionReturn(0);
51579e8305c2SJed Brown }
51589e8305c2SJed Brown 
5159a4355906SMatthew Knepley /*@
5160bc1eb3faSJed Brown 
5161bc1eb3faSJed Brown   DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a
5162bc1eb3faSJed Brown   lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the
51631bb6d2a8SBarry Smith   section provided (or the section of the DM).
5164a4355906SMatthew Knepley 
5165a4355906SMatthew Knepley   Input Parameters:
5166a4355906SMatthew Knepley + dm      - The DM
5167a4355906SMatthew Knepley . point   - Either a cell (highest dim point) or an edge (dim 1 point), or PETSC_DETERMINE
5168a4355906SMatthew Knepley - section - The PetscSection to reorder, or NULL for the default section
5169a4355906SMatthew Knepley 
5170a4355906SMatthew Knepley   Note: The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial
5171a4355906SMatthew Knepley   degree of the basis.
5172a4355906SMatthew Knepley 
5173bc1eb3faSJed Brown   Example:
5174bc1eb3faSJed Brown   A typical interpolated single-quad mesh might order points as
5175bc1eb3faSJed Brown .vb
5176bc1eb3faSJed Brown   [c0, v1, v2, v3, v4, e5, e6, e7, e8]
5177bc1eb3faSJed Brown 
5178bc1eb3faSJed Brown   v4 -- e6 -- v3
5179bc1eb3faSJed Brown   |           |
5180bc1eb3faSJed Brown   e7    c0    e8
5181bc1eb3faSJed Brown   |           |
5182bc1eb3faSJed Brown   v1 -- e5 -- v2
5183bc1eb3faSJed Brown .ve
5184bc1eb3faSJed Brown 
5185bc1eb3faSJed Brown   (There is no significance to the ordering described here.)  The default section for a Q3 quad might typically assign
5186bc1eb3faSJed Brown   dofs in the order of points, e.g.,
5187bc1eb3faSJed Brown .vb
5188bc1eb3faSJed Brown     c0 -> [0,1,2,3]
5189bc1eb3faSJed Brown     v1 -> [4]
5190bc1eb3faSJed Brown     ...
5191bc1eb3faSJed Brown     e5 -> [8, 9]
5192bc1eb3faSJed Brown .ve
5193bc1eb3faSJed Brown 
5194bc1eb3faSJed Brown   which corresponds to the dofs
5195bc1eb3faSJed Brown .vb
5196bc1eb3faSJed Brown     6   10  11  7
5197bc1eb3faSJed Brown     13  2   3   15
5198bc1eb3faSJed Brown     12  0   1   14
5199bc1eb3faSJed Brown     4   8   9   5
5200bc1eb3faSJed Brown .ve
5201bc1eb3faSJed Brown 
5202bc1eb3faSJed Brown   The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering
5203bc1eb3faSJed Brown .vb
5204bc1eb3faSJed Brown   0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6
5205bc1eb3faSJed Brown .ve
5206bc1eb3faSJed Brown 
5207bc1eb3faSJed Brown   After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically,
5208bc1eb3faSJed Brown .vb
5209bc1eb3faSJed Brown    4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7
5210bc1eb3faSJed Brown .ve
5211bc1eb3faSJed Brown 
5212a4355906SMatthew Knepley   Level: developer
5213a4355906SMatthew Knepley 
52149df75925SJed Brown .seealso: DMGetLocalSection(), PetscSectionSetClosurePermutation(), DMSetGlobalSection()
5215a4355906SMatthew Knepley @*/
5216bc1eb3faSJed Brown PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section)
52173194fc30SMatthew G. Knepley {
52187391a63aSMatthew G. Knepley   DMLabel        label;
5219bb197d40SJed Brown   PetscInt       dim, depth = -1, eStart = -1, Nf;
52209e8305c2SJed Brown   PetscBool      vertexchart;
52213194fc30SMatthew G. Knepley   PetscErrorCode ierr;
52223194fc30SMatthew G. Knepley 
52233194fc30SMatthew G. Knepley   PetscFunctionBegin;
52243194fc30SMatthew G. Knepley   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
5225a433471fSStefano Zampini   if (dim < 1) PetscFunctionReturn(0);
5226a433471fSStefano Zampini   if (point < 0) {
5227a433471fSStefano Zampini     PetscInt sStart,sEnd;
5228a433471fSStefano Zampini 
5229a433471fSStefano Zampini     ierr = DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd);CHKERRQ(ierr);
5230a433471fSStefano Zampini     point = sEnd-sStart ? sStart : point;
5231a433471fSStefano Zampini   }
52327391a63aSMatthew G. Knepley   ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr);
5233a433471fSStefano Zampini   if (point >= 0) { ierr = DMLabelGetValue(label, point, &depth);CHKERRQ(ierr); }
5234a433471fSStefano Zampini   if (!section) {ierr = DMGetLocalSection(dm, &section);CHKERRQ(ierr);}
52357391a63aSMatthew G. Knepley   if (depth == 1) {eStart = point;}
52367391a63aSMatthew G. Knepley   else if  (depth == dim) {
52377391a63aSMatthew G. Knepley     const PetscInt *cone;
52387391a63aSMatthew G. Knepley 
52397391a63aSMatthew G. Knepley     ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr);
5240d4e6627bSStefano Zampini     if (dim == 2) eStart = cone[0];
5241d4e6627bSStefano Zampini     else if (dim == 3) {
5242d4e6627bSStefano Zampini       const PetscInt *cone2;
5243d4e6627bSStefano Zampini       ierr = DMPlexGetCone(dm, cone[0], &cone2);CHKERRQ(ierr);
5244d4e6627bSStefano Zampini       eStart = cone2[0];
524598921bdaSJacob Faibussowitsch     } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Point %D of depth %D cannot be used to bootstrap spectral ordering for dim %D", point, depth, dim);
52462c71b3e2SJacob Faibussowitsch   } else PetscCheckFalse(depth >= 0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Point %D of depth %D cannot be used to bootstrap spectral ordering for dim %D", point, depth, dim);
52479e8305c2SJed Brown   {                             /* Determine whether the chart covers all points or just vertices. */
52489e8305c2SJed Brown     PetscInt pStart,pEnd,cStart,cEnd;
52499e8305c2SJed Brown     ierr = DMPlexGetDepthStratum(dm,0,&pStart,&pEnd);CHKERRQ(ierr);
52509e8305c2SJed Brown     ierr = PetscSectionGetChart(section,&cStart,&cEnd);CHKERRQ(ierr);
5251796d0a68SJed Brown     if (pStart == cStart && pEnd == cEnd) vertexchart = PETSC_TRUE;      /* Only vertices are in the chart */
5252796d0a68SJed Brown     else if (cStart <= point && point < cEnd) vertexchart = PETSC_FALSE; /* Some interpolated points exist in the chart */
5253796d0a68SJed Brown     else vertexchart = PETSC_TRUE;                                       /* Some interpolated points are not in chart; assume dofs only at cells and vertices */
52549e8305c2SJed Brown   }
52553194fc30SMatthew G. Knepley   ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr);
5256bb197d40SJed Brown   for (PetscInt d=1; d<=dim; d++) {
5257bb197d40SJed Brown     PetscInt k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0;
5258bb197d40SJed Brown     PetscInt *perm;
5259bb197d40SJed Brown 
52603194fc30SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
52619e8305c2SJed Brown       ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr);
5262bb197d40SJed Brown       size += PetscPowInt(k+1, d)*Nc;
52633194fc30SMatthew G. Knepley     }
52643194fc30SMatthew G. Knepley     ierr = PetscMalloc1(size, &perm);CHKERRQ(ierr);
52653194fc30SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
5266bb197d40SJed Brown       switch (d) {
5267babf31e0SJed Brown       case 1:
52689e8305c2SJed Brown         ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr);
5269babf31e0SJed Brown         /*
5270babf31e0SJed Brown          Original ordering is [ edge of length k-1; vtx0; vtx1 ]
5271babf31e0SJed Brown          We want              [ vtx0; edge of length k-1; vtx1 ]
5272babf31e0SJed Brown          */
5273babf31e0SJed Brown         for (c=0; c<Nc; c++,offset++) perm[offset] = (k-1)*Nc + c + foffset;
5274babf31e0SJed Brown         for (i=0; i<k-1; i++) for (c=0; c<Nc; c++,offset++) perm[offset] = i*Nc + c + foffset;
5275babf31e0SJed Brown         for (c=0; c<Nc; c++,offset++) perm[offset] = k*Nc + c + foffset;
5276babf31e0SJed Brown         foffset = offset;
5277babf31e0SJed Brown         break;
527889eabcffSMatthew G. Knepley       case 2:
52793194fc30SMatthew G. Knepley         /* The original quad closure is oriented clockwise, {f, e_b, e_r, e_t, e_l, v_lb, v_rb, v_tr, v_tl} */
52809e8305c2SJed Brown         ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr);
52813194fc30SMatthew G. Knepley         /* The SEM order is
52823194fc30SMatthew G. Knepley 
52833194fc30SMatthew G. Knepley          v_lb, {e_b}, v_rb,
528489eabcffSMatthew G. Knepley          e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r,
52853194fc30SMatthew G. Knepley          v_lt, reverse {e_t}, v_rt
52863194fc30SMatthew G. Knepley          */
52873194fc30SMatthew G. Knepley         {
52883194fc30SMatthew G. Knepley           const PetscInt of   = 0;
52893194fc30SMatthew G. Knepley           const PetscInt oeb  = of   + PetscSqr(k-1);
52903194fc30SMatthew G. Knepley           const PetscInt oer  = oeb  + (k-1);
52913194fc30SMatthew G. Knepley           const PetscInt oet  = oer  + (k-1);
52923194fc30SMatthew G. Knepley           const PetscInt oel  = oet  + (k-1);
52933194fc30SMatthew G. Knepley           const PetscInt ovlb = oel  + (k-1);
52943194fc30SMatthew G. Knepley           const PetscInt ovrb = ovlb + 1;
52953194fc30SMatthew G. Knepley           const PetscInt ovrt = ovrb + 1;
52963194fc30SMatthew G. Knepley           const PetscInt ovlt = ovrt + 1;
52973194fc30SMatthew G. Knepley           PetscInt       o;
52983194fc30SMatthew G. Knepley 
52993194fc30SMatthew G. Knepley           /* bottom */
53003194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb*Nc + c + foffset;
53013194fc30SMatthew G. Knepley           for (o = oeb; o < oer; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
53023194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb*Nc + c + foffset;
53033194fc30SMatthew G. Knepley           /* middle */
53043194fc30SMatthew G. Knepley           for (i = 0; i < k-1; ++i) {
53053194fc30SMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel+(k-2)-i)*Nc + c + foffset;
53063194fc30SMatthew G. Knepley             for (o = of+(k-1)*i; o < of+(k-1)*(i+1); ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
53073194fc30SMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer+i)*Nc + c + foffset;
53083194fc30SMatthew G. Knepley           }
53093194fc30SMatthew G. Knepley           /* top */
53103194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt*Nc + c + foffset;
53113194fc30SMatthew G. Knepley           for (o = oel-1; o >= oet; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
53123194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt*Nc + c + foffset;
53133194fc30SMatthew G. Knepley           foffset = offset;
53143194fc30SMatthew G. Knepley         }
531589eabcffSMatthew G. Knepley         break;
531689eabcffSMatthew G. Knepley       case 3:
531789eabcffSMatthew G. Knepley         /* The original hex closure is
531889eabcffSMatthew G. Knepley 
531989eabcffSMatthew G. Knepley          {c,
532089eabcffSMatthew G. Knepley          f_b, f_t, f_f, f_b, f_r, f_l,
532189eabcffSMatthew G. Knepley          e_bl, e_bb, e_br, e_bf,  e_tf, e_tr, e_tb, e_tl,  e_rf, e_lf, e_lb, e_rb,
532289eabcffSMatthew G. Knepley          v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb}
532389eabcffSMatthew G. Knepley          */
53249e8305c2SJed Brown         ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr);
532589eabcffSMatthew G. Knepley         /* The SEM order is
532689eabcffSMatthew G. Knepley          Bottom Slice
532789eabcffSMatthew G. Knepley          v_blf, {e^{(k-1)-n}_bf}, v_brf,
532889eabcffSMatthew G. Knepley          e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br,
532989eabcffSMatthew G. Knepley          v_blb, {e_bb}, v_brb,
533089eabcffSMatthew G. Knepley 
533189eabcffSMatthew G. Knepley          Middle Slice (j)
533289eabcffSMatthew G. Knepley          {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf,
533389eabcffSMatthew G. Knepley          f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r,
533489eabcffSMatthew G. Knepley          e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb,
533589eabcffSMatthew G. Knepley 
533689eabcffSMatthew G. Knepley          Top Slice
533789eabcffSMatthew G. Knepley          v_tlf, {e_tf}, v_trf,
533889eabcffSMatthew G. Knepley          e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr,
533989eabcffSMatthew G. Knepley          v_tlb, {e^{(k-1)-n}_tb}, v_trb,
534089eabcffSMatthew G. Knepley          */
534189eabcffSMatthew G. Knepley         {
534289eabcffSMatthew G. Knepley           const PetscInt oc    = 0;
534389eabcffSMatthew G. Knepley           const PetscInt ofb   = oc    + PetscSqr(k-1)*(k-1);
534489eabcffSMatthew G. Knepley           const PetscInt oft   = ofb   + PetscSqr(k-1);
534589eabcffSMatthew G. Knepley           const PetscInt off   = oft   + PetscSqr(k-1);
534689eabcffSMatthew G. Knepley           const PetscInt ofk   = off   + PetscSqr(k-1);
534789eabcffSMatthew G. Knepley           const PetscInt ofr   = ofk   + PetscSqr(k-1);
534889eabcffSMatthew G. Knepley           const PetscInt ofl   = ofr   + PetscSqr(k-1);
534989eabcffSMatthew G. Knepley           const PetscInt oebl  = ofl   + PetscSqr(k-1);
535089eabcffSMatthew G. Knepley           const PetscInt oebb  = oebl  + (k-1);
535189eabcffSMatthew G. Knepley           const PetscInt oebr  = oebb  + (k-1);
535289eabcffSMatthew G. Knepley           const PetscInt oebf  = oebr  + (k-1);
535389eabcffSMatthew G. Knepley           const PetscInt oetf  = oebf  + (k-1);
535489eabcffSMatthew G. Knepley           const PetscInt oetr  = oetf  + (k-1);
535589eabcffSMatthew G. Knepley           const PetscInt oetb  = oetr  + (k-1);
535689eabcffSMatthew G. Knepley           const PetscInt oetl  = oetb  + (k-1);
535789eabcffSMatthew G. Knepley           const PetscInt oerf  = oetl  + (k-1);
535889eabcffSMatthew G. Knepley           const PetscInt oelf  = oerf  + (k-1);
535989eabcffSMatthew G. Knepley           const PetscInt oelb  = oelf  + (k-1);
536089eabcffSMatthew G. Knepley           const PetscInt oerb  = oelb  + (k-1);
536189eabcffSMatthew G. Knepley           const PetscInt ovblf = oerb  + (k-1);
536289eabcffSMatthew G. Knepley           const PetscInt ovblb = ovblf + 1;
536389eabcffSMatthew G. Knepley           const PetscInt ovbrb = ovblb + 1;
536489eabcffSMatthew G. Knepley           const PetscInt ovbrf = ovbrb + 1;
536589eabcffSMatthew G. Knepley           const PetscInt ovtlf = ovbrf + 1;
536689eabcffSMatthew G. Knepley           const PetscInt ovtrf = ovtlf + 1;
536789eabcffSMatthew G. Knepley           const PetscInt ovtrb = ovtrf + 1;
536889eabcffSMatthew G. Knepley           const PetscInt ovtlb = ovtrb + 1;
536989eabcffSMatthew G. Knepley           PetscInt       o, n;
537089eabcffSMatthew G. Knepley 
537189eabcffSMatthew G. Knepley           /* Bottom Slice */
537289eabcffSMatthew G. Knepley           /*   bottom */
537389eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf*Nc + c + foffset;
537489eabcffSMatthew G. Knepley           for (o = oetf-1; o >= oebf; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
537589eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf*Nc + c + foffset;
537689eabcffSMatthew G. Knepley           /*   middle */
537789eabcffSMatthew G. Knepley           for (i = 0; i < k-1; ++i) {
537889eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl+i)*Nc + c + foffset;
5379316b7f87SMax Rietmann             for (n = 0; n < k-1; ++n) {o = ofb+n*(k-1)+i; for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;}
538089eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr+(k-2)-i)*Nc + c + foffset;
53813194fc30SMatthew G. Knepley           }
538289eabcffSMatthew G. Knepley           /*   top */
538389eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb*Nc + c + foffset;
538489eabcffSMatthew G. Knepley           for (o = oebb; o < oebr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
538589eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb*Nc + c + foffset;
538689eabcffSMatthew G. Knepley 
538789eabcffSMatthew G. Knepley           /* Middle Slice */
538889eabcffSMatthew G. Knepley           for (j = 0; j < k-1; ++j) {
538989eabcffSMatthew G. Knepley             /*   bottom */
539089eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf+(k-2)-j)*Nc + c + foffset;
539189eabcffSMatthew G. Knepley             for (o = off+j*(k-1); o < off+(j+1)*(k-1); ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
539289eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf+j)*Nc + c + foffset;
539389eabcffSMatthew G. Knepley             /*   middle */
539489eabcffSMatthew G. Knepley             for (i = 0; i < k-1; ++i) {
539589eabcffSMatthew G. Knepley               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl+i*(k-1)+j)*Nc + c + foffset;
539689eabcffSMatthew G. Knepley               for (n = 0; n < k-1; ++n) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oc+(j*(k-1)+i)*(k-1)+n)*Nc + c + foffset;
539789eabcffSMatthew G. Knepley               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr+j*(k-1)+i)*Nc + c + foffset;
539889eabcffSMatthew G. Knepley             }
539989eabcffSMatthew G. Knepley             /*   top */
540089eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb+j)*Nc + c + foffset;
540189eabcffSMatthew G. Knepley             for (o = ofk+j*(k-1)+(k-2); o >= ofk+j*(k-1); --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
540289eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb+(k-2)-j)*Nc + c + foffset;
540389eabcffSMatthew G. Knepley           }
540489eabcffSMatthew G. Knepley 
540589eabcffSMatthew G. Knepley           /* Top Slice */
540689eabcffSMatthew G. Knepley           /*   bottom */
540789eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf*Nc + c + foffset;
540889eabcffSMatthew G. Knepley           for (o = oetf; o < oetr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
540989eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf*Nc + c + foffset;
541089eabcffSMatthew G. Knepley           /*   middle */
541189eabcffSMatthew G. Knepley           for (i = 0; i < k-1; ++i) {
541289eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl+(k-2)-i)*Nc + c + foffset;
541389eabcffSMatthew G. Knepley             for (n = 0; n < k-1; ++n) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft+i*(k-1)+n)*Nc + c + foffset;
541489eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr+i)*Nc + c + foffset;
541589eabcffSMatthew G. Knepley           }
541689eabcffSMatthew G. Knepley           /*   top */
541789eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb*Nc + c + foffset;
541889eabcffSMatthew G. Knepley           for (o = oetl-1; o >= oetb; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
541989eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb*Nc + c + foffset;
542089eabcffSMatthew G. Knepley 
542189eabcffSMatthew G. Knepley           foffset = offset;
542289eabcffSMatthew G. Knepley         }
542389eabcffSMatthew G. Knepley         break;
542498921bdaSJacob Faibussowitsch       default: SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %D", d);
542589eabcffSMatthew G. Knepley       }
542689eabcffSMatthew G. Knepley     }
54272c71b3e2SJacob Faibussowitsch     PetscCheckFalse(offset != size,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Number of permutation entries %D != %D", offset, size);
54283194fc30SMatthew G. Knepley     /* Check permutation */
54293194fc30SMatthew G. Knepley     {
54303194fc30SMatthew G. Knepley       PetscInt *check;
54313194fc30SMatthew G. Knepley 
54323194fc30SMatthew G. Knepley       ierr = PetscMalloc1(size, &check);CHKERRQ(ierr);
54332c71b3e2SJacob Faibussowitsch       for (i = 0; i < size; ++i) {check[i] = -1; PetscCheckFalse(perm[i] < 0 || perm[i] >= size,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid permutation index p[%D] = %D", i, perm[i]);}
54343194fc30SMatthew G. Knepley       for (i = 0; i < size; ++i) check[perm[i]] = i;
54352c71b3e2SJacob Faibussowitsch       for (i = 0; i < size; ++i) {PetscCheckFalse(check[i] < 0,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Missing permutation index %D", i);}
54363194fc30SMatthew G. Knepley       ierr = PetscFree(check);CHKERRQ(ierr);
54373194fc30SMatthew G. Knepley     }
5438bb197d40SJed Brown     ierr = PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size, PETSC_OWN_POINTER, perm);CHKERRQ(ierr);
5439a05c9aa3SJed Brown     if (d == dim) { // Add permutation for localized (in case this is a coordinate DM)
5440a05c9aa3SJed Brown       PetscInt *loc_perm;
5441a05c9aa3SJed Brown       ierr = PetscMalloc1(size*2, &loc_perm);CHKERRQ(ierr);
5442a05c9aa3SJed Brown       for (PetscInt i=0; i<size; i++) {
5443a05c9aa3SJed Brown         loc_perm[i] = perm[i];
5444a05c9aa3SJed Brown         loc_perm[size+i] = size + perm[i];
5445a05c9aa3SJed Brown       }
5446a05c9aa3SJed Brown       ierr = PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size*2, PETSC_OWN_POINTER, loc_perm);CHKERRQ(ierr);
5447a05c9aa3SJed Brown     }
5448bb197d40SJed Brown   }
54493194fc30SMatthew G. Knepley   PetscFunctionReturn(0);
54503194fc30SMatthew G. Knepley }
54513194fc30SMatthew G. Knepley 
5452e071409bSToby Isaac PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace)
5453e071409bSToby Isaac {
5454e071409bSToby Isaac   PetscDS        prob;
5455e071409bSToby Isaac   PetscInt       depth, Nf, h;
5456e071409bSToby Isaac   DMLabel        label;
5457e071409bSToby Isaac   PetscErrorCode ierr;
5458e071409bSToby Isaac 
5459e071409bSToby Isaac   PetscFunctionBeginHot;
5460e5e52638SMatthew G. Knepley   ierr = DMGetDS(dm, &prob);CHKERRQ(ierr);
5461e071409bSToby Isaac   Nf      = prob->Nf;
5462e071409bSToby Isaac   label   = dm->depthLabel;
5463e071409bSToby Isaac   *dspace = NULL;
5464e071409bSToby Isaac   if (field < Nf) {
5465e071409bSToby Isaac     PetscObject disc = prob->disc[field];
5466e071409bSToby Isaac 
5467e071409bSToby Isaac     if (disc->classid == PETSCFE_CLASSID) {
5468e071409bSToby Isaac       PetscDualSpace dsp;
5469e071409bSToby Isaac 
5470e071409bSToby Isaac       ierr = PetscFEGetDualSpace((PetscFE)disc,&dsp);CHKERRQ(ierr);
5471e071409bSToby Isaac       ierr = DMLabelGetNumValues(label,&depth);CHKERRQ(ierr);
5472e071409bSToby Isaac       ierr = DMLabelGetValue(label,point,&h);CHKERRQ(ierr);
5473e071409bSToby Isaac       h    = depth - 1 - h;
5474e071409bSToby Isaac       if (h) {
5475e071409bSToby Isaac         ierr = PetscDualSpaceGetHeightSubspace(dsp,h,dspace);CHKERRQ(ierr);
5476e071409bSToby Isaac       } else {
5477e071409bSToby Isaac         *dspace = dsp;
5478e071409bSToby Isaac       }
5479e071409bSToby Isaac     }
5480e071409bSToby Isaac   }
5481e071409bSToby Isaac   PetscFunctionReturn(0);
5482e071409bSToby Isaac }
5483e071409bSToby Isaac 
54849fbee547SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
5485a6dfd86eSKarl Rupp {
5486552f7358SJed Brown   PetscScalar    *array, *vArray;
5487d9917b9dSMatthew G. Knepley   const PetscInt *cone, *coneO;
54881a271a75SMatthew G. Knepley   PetscInt        pStart, pEnd, p, numPoints, size = 0, offset = 0;
5489552f7358SJed Brown   PetscErrorCode  ierr;
5490552f7358SJed Brown 
54911b406b76SMatthew G. Knepley   PetscFunctionBeginHot;
54922a3aaacfSMatthew G. Knepley   ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr);
54935a1bb5cfSMatthew G. Knepley   ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr);
54945a1bb5cfSMatthew G. Knepley   ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr);
54955a1bb5cfSMatthew G. Knepley   ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr);
54963f7cbbe7SMatthew G. Knepley   if (!values || !*values) {
54979df71ca4SMatthew G. Knepley     if ((point >= pStart) && (point < pEnd)) {
54989df71ca4SMatthew G. Knepley       PetscInt dof;
5499d9917b9dSMatthew G. Knepley 
55009df71ca4SMatthew G. Knepley       ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr);
55019df71ca4SMatthew G. Knepley       size += dof;
55029df71ca4SMatthew G. Knepley     }
55039df71ca4SMatthew G. Knepley     for (p = 0; p < numPoints; ++p) {
55049df71ca4SMatthew G. Knepley       const PetscInt cp = cone[p];
55052a3aaacfSMatthew G. Knepley       PetscInt       dof;
55065a1bb5cfSMatthew G. Knepley 
55075a1bb5cfSMatthew G. Knepley       if ((cp < pStart) || (cp >= pEnd)) continue;
55082a3aaacfSMatthew G. Knepley       ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr);
55095a1bb5cfSMatthew G. Knepley       size += dof;
55105a1bb5cfSMatthew G. Knepley     }
55113f7cbbe7SMatthew G. Knepley     if (!values) {
55123f7cbbe7SMatthew G. Knepley       if (csize) *csize = size;
55133f7cbbe7SMatthew G. Knepley       PetscFunctionReturn(0);
55143f7cbbe7SMatthew G. Knepley     }
551569291d52SBarry Smith     ierr = DMGetWorkArray(dm, size, MPIU_SCALAR, &array);CHKERRQ(ierr);
5516982e9ed1SMatthew G. Knepley   } else {
5517982e9ed1SMatthew G. Knepley     array = *values;
5518982e9ed1SMatthew G. Knepley   }
55199df71ca4SMatthew G. Knepley   size = 0;
55205a1bb5cfSMatthew G. Knepley   ierr = VecGetArray(v, &vArray);CHKERRQ(ierr);
55219df71ca4SMatthew G. Knepley   if ((point >= pStart) && (point < pEnd)) {
55229df71ca4SMatthew G. Knepley     PetscInt     dof, off, d;
55239df71ca4SMatthew G. Knepley     PetscScalar *varr;
5524d9917b9dSMatthew G. Knepley 
55259df71ca4SMatthew G. Knepley     ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr);
55269df71ca4SMatthew G. Knepley     ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr);
55279df71ca4SMatthew G. Knepley     varr = &vArray[off];
55281a271a75SMatthew G. Knepley     for (d = 0; d < dof; ++d, ++offset) {
55291a271a75SMatthew G. Knepley       array[offset] = varr[d];
55309df71ca4SMatthew G. Knepley     }
55319df71ca4SMatthew G. Knepley     size += dof;
55329df71ca4SMatthew G. Knepley   }
55339df71ca4SMatthew G. Knepley   for (p = 0; p < numPoints; ++p) {
55349df71ca4SMatthew G. Knepley     const PetscInt cp = cone[p];
55359df71ca4SMatthew G. Knepley     PetscInt       o  = coneO[p];
55365a1bb5cfSMatthew G. Knepley     PetscInt       dof, off, d;
55375a1bb5cfSMatthew G. Knepley     PetscScalar   *varr;
55385a1bb5cfSMatthew G. Knepley 
553952ed52e8SMatthew G. Knepley     if ((cp < pStart) || (cp >= pEnd)) continue;
55405a1bb5cfSMatthew G. Knepley     ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr);
55415a1bb5cfSMatthew G. Knepley     ierr = PetscSectionGetOffset(section, cp, &off);CHKERRQ(ierr);
55425a1bb5cfSMatthew G. Knepley     varr = &vArray[off];
55435a1bb5cfSMatthew G. Knepley     if (o >= 0) {
55441a271a75SMatthew G. Knepley       for (d = 0; d < dof; ++d, ++offset) {
55451a271a75SMatthew G. Knepley         array[offset] = varr[d];
55465a1bb5cfSMatthew G. Knepley       }
55475a1bb5cfSMatthew G. Knepley     } else {
55481a271a75SMatthew G. Knepley       for (d = dof-1; d >= 0; --d, ++offset) {
55491a271a75SMatthew G. Knepley         array[offset] = varr[d];
55505a1bb5cfSMatthew G. Knepley       }
55515a1bb5cfSMatthew G. Knepley     }
55529df71ca4SMatthew G. Knepley     size += dof;
55535a1bb5cfSMatthew G. Knepley   }
55545a1bb5cfSMatthew G. Knepley   ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr);
55559df71ca4SMatthew G. Knepley   if (!*values) {
55565a1bb5cfSMatthew G. Knepley     if (csize) *csize = size;
55575a1bb5cfSMatthew G. Knepley     *values = array;
55589df71ca4SMatthew G. Knepley   } else {
55592c71b3e2SJacob Faibussowitsch     PetscCheckFalse(size > *csize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size);
55608c312ff3SMatthew G. Knepley     *csize = size;
55619df71ca4SMatthew G. Knepley   }
55625a1bb5cfSMatthew G. Knepley   PetscFunctionReturn(0);
55635a1bb5cfSMatthew G. Knepley }
5564d9917b9dSMatthew G. Knepley 
556527f02ce8SMatthew G. Knepley /* Compress out points not in the section */
55669fbee547SJacob Faibussowitsch static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[])
556727f02ce8SMatthew G. Knepley {
556827f02ce8SMatthew G. Knepley   const PetscInt np = *numPoints;
556927f02ce8SMatthew G. Knepley   PetscInt       pStart, pEnd, p, q;
557027f02ce8SMatthew G. Knepley   PetscErrorCode ierr;
557127f02ce8SMatthew G. Knepley 
557227f02ce8SMatthew G. Knepley   ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr);
557327f02ce8SMatthew G. Knepley   for (p = 0, q = 0; p < np; ++p) {
557427f02ce8SMatthew G. Knepley     const PetscInt r = points[p*2];
557527f02ce8SMatthew G. Knepley     if ((r >= pStart) && (r < pEnd)) {
557627f02ce8SMatthew G. Knepley       points[q*2]   = r;
557727f02ce8SMatthew G. Knepley       points[q*2+1] = points[p*2+1];
557827f02ce8SMatthew G. Knepley       ++q;
557927f02ce8SMatthew G. Knepley     }
558027f02ce8SMatthew G. Knepley   }
558127f02ce8SMatthew G. Knepley   *numPoints = q;
558227f02ce8SMatthew G. Knepley   return 0;
558327f02ce8SMatthew G. Knepley }
558427f02ce8SMatthew G. Knepley 
558597529cf3SJed Brown /* Compressed closure does not apply closure permutation */
55861dc59d61SMatthew G. Knepley PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp)
5587923c78e0SToby Isaac {
558827f02ce8SMatthew G. Knepley   const PetscInt *cla = NULL;
5589923c78e0SToby Isaac   PetscInt       np, *pts = NULL;
5590923c78e0SToby Isaac   PetscErrorCode ierr;
5591923c78e0SToby Isaac 
5592923c78e0SToby Isaac   PetscFunctionBeginHot;
5593923c78e0SToby Isaac   ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, clSec, clPoints);CHKERRQ(ierr);
559427f02ce8SMatthew G. Knepley   if (*clPoints) {
5595923c78e0SToby Isaac     PetscInt dof, off;
5596923c78e0SToby Isaac 
5597923c78e0SToby Isaac     ierr = PetscSectionGetDof(*clSec, point, &dof);CHKERRQ(ierr);
5598923c78e0SToby Isaac     ierr = PetscSectionGetOffset(*clSec, point, &off);CHKERRQ(ierr);
5599923c78e0SToby Isaac     ierr = ISGetIndices(*clPoints, &cla);CHKERRQ(ierr);
5600923c78e0SToby Isaac     np   = dof/2;
5601923c78e0SToby Isaac     pts  = (PetscInt *) &cla[off];
560227f02ce8SMatthew G. Knepley   } else {
560327f02ce8SMatthew G. Knepley     ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &np, &pts);CHKERRQ(ierr);
560427f02ce8SMatthew G. Knepley     ierr = CompressPoints_Private(section, &np, pts);CHKERRQ(ierr);
5605923c78e0SToby Isaac   }
5606923c78e0SToby Isaac   *numPoints = np;
5607923c78e0SToby Isaac   *points    = pts;
5608923c78e0SToby Isaac   *clp       = cla;
5609923c78e0SToby Isaac   PetscFunctionReturn(0);
5610923c78e0SToby Isaac }
5611923c78e0SToby Isaac 
56121dc59d61SMatthew G. Knepley PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp)
5613923c78e0SToby Isaac {
5614923c78e0SToby Isaac   PetscErrorCode ierr;
5615923c78e0SToby Isaac 
5616923c78e0SToby Isaac   PetscFunctionBeginHot;
5617923c78e0SToby Isaac   if (!*clPoints) {
5618923c78e0SToby Isaac     ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points);CHKERRQ(ierr);
5619923c78e0SToby Isaac   } else {
5620923c78e0SToby Isaac     ierr = ISRestoreIndices(*clPoints, clp);CHKERRQ(ierr);
5621923c78e0SToby Isaac   }
5622923c78e0SToby Isaac   *numPoints = 0;
5623923c78e0SToby Isaac   *points    = NULL;
5624923c78e0SToby Isaac   *clSec     = NULL;
5625923c78e0SToby Isaac   *clPoints  = NULL;
5626923c78e0SToby Isaac   *clp       = NULL;
5627923c78e0SToby Isaac   PetscFunctionReturn(0);
5628923c78e0SToby Isaac }
5629923c78e0SToby Isaac 
56309fbee547SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Static(DM dm, PetscSection section, PetscInt numPoints, const PetscInt points[], const PetscInt clperm[], const PetscScalar vArray[], PetscInt *size, PetscScalar array[])
56311a271a75SMatthew G. Knepley {
56321a271a75SMatthew G. Knepley   PetscInt          offset = 0, p;
563397e99dd9SToby Isaac   const PetscInt    **perms = NULL;
563497e99dd9SToby Isaac   const PetscScalar **flips = NULL;
56351a271a75SMatthew G. Knepley   PetscErrorCode    ierr;
56361a271a75SMatthew G. Knepley 
56371a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
5638fe02ba77SJed Brown   *size = 0;
563997e99dd9SToby Isaac   ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr);
564097e99dd9SToby Isaac   for (p = 0; p < numPoints; p++) {
564197e99dd9SToby Isaac     const PetscInt    point = points[2*p];
564297e99dd9SToby Isaac     const PetscInt    *perm = perms ? perms[p] : NULL;
564397e99dd9SToby Isaac     const PetscScalar *flip = flips ? flips[p] : NULL;
56441a271a75SMatthew G. Knepley     PetscInt          dof, off, d;
56451a271a75SMatthew G. Knepley     const PetscScalar *varr;
56461a271a75SMatthew G. Knepley 
56471a271a75SMatthew G. Knepley     ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr);
56481a271a75SMatthew G. Knepley     ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr);
56491a271a75SMatthew G. Knepley     varr = &vArray[off];
565097e99dd9SToby Isaac     if (clperm) {
565197e99dd9SToby Isaac       if (perm) {
565297e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]]  = varr[d];
56531a271a75SMatthew G. Knepley       } else {
565497e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset +      d ]]  = varr[d];
565597e99dd9SToby Isaac       }
565697e99dd9SToby Isaac       if (flip) {
565797e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset +      d ]] *= flip[d];
565897e99dd9SToby Isaac       }
565997e99dd9SToby Isaac     } else {
566097e99dd9SToby Isaac       if (perm) {
566197e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset + perm[d]]  = varr[d];
566297e99dd9SToby Isaac       } else {
566397e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset +      d ]  = varr[d];
566497e99dd9SToby Isaac       }
566597e99dd9SToby Isaac       if (flip) {
566697e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset +      d ] *= flip[d];
56671a271a75SMatthew G. Knepley       }
56681a271a75SMatthew G. Knepley     }
566997e99dd9SToby Isaac     offset += dof;
567097e99dd9SToby Isaac   }
567197e99dd9SToby Isaac   ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr);
56721a271a75SMatthew G. Knepley   *size = offset;
56731a271a75SMatthew G. Knepley   PetscFunctionReturn(0);
56741a271a75SMatthew G. Knepley }
56751a271a75SMatthew G. Knepley 
56769fbee547SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Fields_Static(DM dm, PetscSection section, PetscInt numPoints, const PetscInt points[], PetscInt numFields, const PetscInt clperm[], const PetscScalar vArray[], PetscInt *size, PetscScalar array[])
56771a271a75SMatthew G. Knepley {
56781a271a75SMatthew G. Knepley   PetscInt          offset = 0, f;
56791a271a75SMatthew G. Knepley   PetscErrorCode    ierr;
56801a271a75SMatthew G. Knepley 
56811a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
5682fe02ba77SJed Brown   *size = 0;
56831a271a75SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
568497e99dd9SToby Isaac     PetscInt          p;
568597e99dd9SToby Isaac     const PetscInt    **perms = NULL;
568697e99dd9SToby Isaac     const PetscScalar **flips = NULL;
56871a271a75SMatthew G. Knepley 
568897e99dd9SToby Isaac     ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr);
568997e99dd9SToby Isaac     for (p = 0; p < numPoints; p++) {
569097e99dd9SToby Isaac       const PetscInt    point = points[2*p];
569197e99dd9SToby Isaac       PetscInt          fdof, foff, b;
56921a271a75SMatthew G. Knepley       const PetscScalar *varr;
569397e99dd9SToby Isaac       const PetscInt    *perm = perms ? perms[p] : NULL;
569497e99dd9SToby Isaac       const PetscScalar *flip = flips ? flips[p] : NULL;
56951a271a75SMatthew G. Knepley 
56961a271a75SMatthew G. Knepley       ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr);
56971a271a75SMatthew G. Knepley       ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr);
56981a271a75SMatthew G. Knepley       varr = &vArray[foff];
569997e99dd9SToby Isaac       if (clperm) {
570097e99dd9SToby Isaac         if (perm) {for (b = 0; b < fdof; b++) {array[clperm[offset + perm[b]]]  = varr[b];}}
570197e99dd9SToby Isaac         else      {for (b = 0; b < fdof; b++) {array[clperm[offset +      b ]]  = varr[b];}}
570297e99dd9SToby Isaac         if (flip) {for (b = 0; b < fdof; b++) {array[clperm[offset +      b ]] *= flip[b];}}
57031a271a75SMatthew G. Knepley       } else {
570497e99dd9SToby Isaac         if (perm) {for (b = 0; b < fdof; b++) {array[offset + perm[b]]  = varr[b];}}
570597e99dd9SToby Isaac         else      {for (b = 0; b < fdof; b++) {array[offset +      b ]  = varr[b];}}
570697e99dd9SToby Isaac         if (flip) {for (b = 0; b < fdof; b++) {array[offset +      b ] *= flip[b];}}
57071a271a75SMatthew G. Knepley       }
570897e99dd9SToby Isaac       offset += fdof;
57091a271a75SMatthew G. Knepley     }
571097e99dd9SToby Isaac     ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr);
57111a271a75SMatthew G. Knepley   }
57121a271a75SMatthew G. Knepley   *size = offset;
57131a271a75SMatthew G. Knepley   PetscFunctionReturn(0);
57141a271a75SMatthew G. Knepley }
57151a271a75SMatthew G. Knepley 
5716552f7358SJed Brown /*@C
5717552f7358SJed Brown   DMPlexVecGetClosure - Get an array of the values on the closure of 'point'
5718552f7358SJed Brown 
5719552f7358SJed Brown   Not collective
5720552f7358SJed Brown 
5721552f7358SJed Brown   Input Parameters:
5722552f7358SJed Brown + dm - The DM
5723552f7358SJed Brown . section - The section describing the layout in v, or NULL to use the default section
5724552f7358SJed Brown . v - The local vector
57256b867d5aSJose E. Roman - point - The point in the DM
5726552f7358SJed Brown 
57276b867d5aSJose E. Roman   Input/Output Parameters:
57286b867d5aSJose E. Roman + csize  - The size of the input values array, or NULL; on output the number of values in the closure
57296b867d5aSJose E. Roman - values - An array to use for the values, or NULL to have it allocated automatically;
57306b867d5aSJose E. Roman            if the user provided NULL, it is a borrowed array and should not be freed
573122c1ee49SMatthew G. Knepley 
573222c1ee49SMatthew G. Knepley $ Note that DMPlexVecGetClosure/DMPlexVecRestoreClosure only allocates the values array if it set to NULL in the
573322c1ee49SMatthew G. Knepley $ calling function. This is because DMPlexVecGetClosure() is typically called in the inner loop of a Vec or Mat
573422c1ee49SMatthew G. Knepley $ assembly function, and a user may already have allocated storage for this operation.
573522c1ee49SMatthew G. Knepley $
573622c1ee49SMatthew G. Knepley $ A typical use could be
573722c1ee49SMatthew G. Knepley $
573822c1ee49SMatthew G. Knepley $  values = NULL;
573922c1ee49SMatthew G. Knepley $  ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr);
574022c1ee49SMatthew G. Knepley $  for (cl = 0; cl < clSize; ++cl) {
574122c1ee49SMatthew G. Knepley $    <Compute on closure>
574222c1ee49SMatthew G. Knepley $  }
574322c1ee49SMatthew G. Knepley $  ierr = DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr);
574422c1ee49SMatthew G. Knepley $
574522c1ee49SMatthew G. Knepley $ or
574622c1ee49SMatthew G. Knepley $
574722c1ee49SMatthew G. Knepley $  PetscMalloc1(clMaxSize, &values);
574822c1ee49SMatthew G. Knepley $  for (p = pStart; p < pEnd; ++p) {
574922c1ee49SMatthew G. Knepley $    clSize = clMaxSize;
575022c1ee49SMatthew G. Knepley $    ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr);
575122c1ee49SMatthew G. Knepley $    for (cl = 0; cl < clSize; ++cl) {
575222c1ee49SMatthew G. Knepley $      <Compute on closure>
575322c1ee49SMatthew G. Knepley $    }
575422c1ee49SMatthew G. Knepley $  }
575522c1ee49SMatthew G. Knepley $  PetscFree(values);
5756552f7358SJed Brown 
5757552f7358SJed Brown   Fortran Notes:
5758552f7358SJed Brown   Since it returns an array, this routine is only available in Fortran 90, and you must
5759552f7358SJed Brown   include petsc.h90 in your code.
5760552f7358SJed Brown 
5761552f7358SJed Brown   The csize argument is not present in the Fortran 90 binding since it is internal to the array.
5762552f7358SJed Brown 
5763552f7358SJed Brown   Level: intermediate
5764552f7358SJed Brown 
5765552f7358SJed Brown .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure()
5766552f7358SJed Brown @*/
5767552f7358SJed Brown PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
5768552f7358SJed Brown {
5769552f7358SJed Brown   PetscSection       clSection;
5770d9917b9dSMatthew G. Knepley   IS                 clPoints;
5771552f7358SJed Brown   PetscInt          *points = NULL;
5772c459fbc1SJed Brown   const PetscInt    *clp, *perm;
5773c459fbc1SJed Brown   PetscInt           depth, numFields, numPoints, asize;
5774552f7358SJed Brown   PetscErrorCode     ierr;
5775552f7358SJed Brown 
5776d9917b9dSMatthew G. Knepley   PetscFunctionBeginHot;
5777552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
577892fd8e1eSJed Brown   if (!section) {ierr = DMGetLocalSection(dm, &section);CHKERRQ(ierr);}
57791a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
57801a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
5781552f7358SJed Brown   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
5782552f7358SJed Brown   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
5783552f7358SJed Brown   if (depth == 1 && numFields < 2) {
57841a271a75SMatthew G. Knepley     ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr);
5785552f7358SJed Brown     PetscFunctionReturn(0);
5786552f7358SJed Brown   }
57871a271a75SMatthew G. Knepley   /* Get points */
5788923c78e0SToby Isaac   ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr);
5789c459fbc1SJed Brown   /* Get sizes */
5790c459fbc1SJed Brown   asize = 0;
5791c459fbc1SJed Brown   for (PetscInt p = 0; p < numPoints*2; p += 2) {
5792c459fbc1SJed Brown     PetscInt dof;
5793552f7358SJed Brown     ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr);
57941a271a75SMatthew G. Knepley     asize += dof;
5795552f7358SJed Brown   }
5796c459fbc1SJed Brown   if (values) {
5797c459fbc1SJed Brown     const PetscScalar *vArray;
5798c459fbc1SJed Brown     PetscInt          size;
5799c459fbc1SJed Brown 
5800c459fbc1SJed Brown     if (*values) {
58012c71b3e2SJacob Faibussowitsch       PetscCheckFalse(*csize < asize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Provided array size %D not sufficient to hold closure size %D", *csize, asize);
5802c459fbc1SJed Brown     } else {ierr = DMGetWorkArray(dm, asize, MPIU_SCALAR, values);CHKERRQ(ierr);}
5803c459fbc1SJed Brown     ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, asize, &perm);CHKERRQ(ierr);
58048a84db2dSMatthew G. Knepley     ierr = VecGetArrayRead(v, &vArray);CHKERRQ(ierr);
58051a271a75SMatthew G. Knepley     /* Get values */
5806c459fbc1SJed Brown     if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values);CHKERRQ(ierr);}
5807c459fbc1SJed Brown     else               {ierr = DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values);CHKERRQ(ierr);}
58082c71b3e2SJacob Faibussowitsch     PetscCheckFalse(asize != size,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Section size %D does not match Vec closure size %D", asize, size);
58091a271a75SMatthew G. Knepley     /* Cleanup array */
58108a84db2dSMatthew G. Knepley     ierr = VecRestoreArrayRead(v, &vArray);CHKERRQ(ierr);
5811d0f6b257SMatthew G. Knepley   }
5812c459fbc1SJed Brown   if (csize) *csize = asize;
5813c459fbc1SJed Brown   /* Cleanup points */
5814c459fbc1SJed Brown   ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr);
5815552f7358SJed Brown   PetscFunctionReturn(0);
5816552f7358SJed Brown }
5817552f7358SJed Brown 
5818e5c487bfSMatthew G. Knepley PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[])
5819e5c487bfSMatthew G. Knepley {
5820e5c487bfSMatthew G. Knepley   DMLabel            depthLabel;
5821e5c487bfSMatthew G. Knepley   PetscSection       clSection;
5822e5c487bfSMatthew G. Knepley   IS                 clPoints;
5823e5c487bfSMatthew G. Knepley   PetscScalar       *array;
5824e5c487bfSMatthew G. Knepley   const PetscScalar *vArray;
5825e5c487bfSMatthew G. Knepley   PetscInt          *points = NULL;
5826c459fbc1SJed Brown   const PetscInt    *clp, *perm = NULL;
5827c459fbc1SJed Brown   PetscInt           mdepth, numFields, numPoints, Np = 0, p, clsize, size;
5828e5c487bfSMatthew G. Knepley   PetscErrorCode     ierr;
5829e5c487bfSMatthew G. Knepley 
5830e5c487bfSMatthew G. Knepley   PetscFunctionBeginHot;
5831e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5832e5c487bfSMatthew G. Knepley   if (!section) {ierr = DMGetLocalSection(dm, &section);CHKERRQ(ierr);}
5833e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
5834e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
5835e5c487bfSMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &mdepth);CHKERRQ(ierr);
5836e5c487bfSMatthew G. Knepley   ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr);
5837e5c487bfSMatthew G. Knepley   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
5838e5c487bfSMatthew G. Knepley   if (mdepth == 1 && numFields < 2) {
5839e5c487bfSMatthew G. Knepley     ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr);
5840e5c487bfSMatthew G. Knepley     PetscFunctionReturn(0);
5841e5c487bfSMatthew G. Knepley   }
5842e5c487bfSMatthew G. Knepley   /* Get points */
5843e5c487bfSMatthew G. Knepley   ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr);
5844c459fbc1SJed Brown   for (clsize=0,p=0; p<Np; p++) {
5845c459fbc1SJed Brown     PetscInt dof;
5846c459fbc1SJed Brown     ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr);
5847c459fbc1SJed Brown     clsize += dof;
5848c459fbc1SJed Brown   }
5849c459fbc1SJed Brown   ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &perm);CHKERRQ(ierr);
5850e5c487bfSMatthew G. Knepley   /* Filter points */
5851e5c487bfSMatthew G. Knepley   for (p = 0; p < numPoints*2; p += 2) {
5852e5c487bfSMatthew G. Knepley     PetscInt dep;
5853e5c487bfSMatthew G. Knepley 
5854e5c487bfSMatthew G. Knepley     ierr = DMLabelGetValue(depthLabel, points[p], &dep);CHKERRQ(ierr);
5855e5c487bfSMatthew G. Knepley     if (dep != depth) continue;
5856e5c487bfSMatthew G. Knepley     points[Np*2+0] = points[p];
5857e5c487bfSMatthew G. Knepley     points[Np*2+1] = points[p+1];
5858e5c487bfSMatthew G. Knepley     ++Np;
5859e5c487bfSMatthew G. Knepley   }
5860e5c487bfSMatthew G. Knepley   /* Get array */
5861e5c487bfSMatthew G. Knepley   if (!values || !*values) {
5862e5c487bfSMatthew G. Knepley     PetscInt asize = 0, dof;
5863e5c487bfSMatthew G. Knepley 
5864e5c487bfSMatthew G. Knepley     for (p = 0; p < Np*2; p += 2) {
5865e5c487bfSMatthew G. Knepley       ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr);
5866e5c487bfSMatthew G. Knepley       asize += dof;
5867e5c487bfSMatthew G. Knepley     }
5868e5c487bfSMatthew G. Knepley     if (!values) {
5869e5c487bfSMatthew G. Knepley       ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr);
5870e5c487bfSMatthew G. Knepley       if (csize) *csize = asize;
5871e5c487bfSMatthew G. Knepley       PetscFunctionReturn(0);
5872e5c487bfSMatthew G. Knepley     }
5873e5c487bfSMatthew G. Knepley     ierr = DMGetWorkArray(dm, asize, MPIU_SCALAR, &array);CHKERRQ(ierr);
5874e5c487bfSMatthew G. Knepley   } else {
5875e5c487bfSMatthew G. Knepley     array = *values;
5876e5c487bfSMatthew G. Knepley   }
5877e5c487bfSMatthew G. Knepley   ierr = VecGetArrayRead(v, &vArray);CHKERRQ(ierr);
5878e5c487bfSMatthew G. Knepley   /* Get values */
5879e5c487bfSMatthew G. Knepley   if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array);CHKERRQ(ierr);}
5880e5c487bfSMatthew G. Knepley   else               {ierr = DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array);CHKERRQ(ierr);}
5881e5c487bfSMatthew G. Knepley   /* Cleanup points */
5882e5c487bfSMatthew G. Knepley   ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr);
5883e5c487bfSMatthew G. Knepley   /* Cleanup array */
5884e5c487bfSMatthew G. Knepley   ierr = VecRestoreArrayRead(v, &vArray);CHKERRQ(ierr);
5885e5c487bfSMatthew G. Knepley   if (!*values) {
5886e5c487bfSMatthew G. Knepley     if (csize) *csize = size;
5887e5c487bfSMatthew G. Knepley     *values = array;
5888e5c487bfSMatthew G. Knepley   } else {
58892c71b3e2SJacob Faibussowitsch     PetscCheckFalse(size > *csize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size);
5890e5c487bfSMatthew G. Knepley     *csize = size;
5891e5c487bfSMatthew G. Knepley   }
5892e5c487bfSMatthew G. Knepley   PetscFunctionReturn(0);
5893e5c487bfSMatthew G. Knepley }
5894e5c487bfSMatthew G. Knepley 
5895552f7358SJed Brown /*@C
5896552f7358SJed Brown   DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point'
5897552f7358SJed Brown 
5898552f7358SJed Brown   Not collective
5899552f7358SJed Brown 
5900552f7358SJed Brown   Input Parameters:
5901552f7358SJed Brown + dm - The DM
59020298fd71SBarry Smith . section - The section describing the layout in v, or NULL to use the default section
5903552f7358SJed Brown . v - The local vector
5904eaf898f9SPatrick Sanan . point - The point in the DM
59050298fd71SBarry Smith . csize - The number of values in the closure, or NULL
5906552f7358SJed Brown - values - The array of values, which is a borrowed array and should not be freed
5907552f7358SJed Brown 
590822c1ee49SMatthew G. Knepley   Note that the array values are discarded and not copied back into v. In order to copy values back to v, use DMPlexVecSetClosure()
590922c1ee49SMatthew G. Knepley 
59103813dfbdSMatthew G Knepley   Fortran Notes:
59113813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
59123813dfbdSMatthew G Knepley   include petsc.h90 in your code.
59133813dfbdSMatthew G Knepley 
59143813dfbdSMatthew G Knepley   The csize argument is not present in the Fortran 90 binding since it is internal to the array.
59153813dfbdSMatthew G Knepley 
5916552f7358SJed Brown   Level: intermediate
5917552f7358SJed Brown 
5918552f7358SJed Brown .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure()
5919552f7358SJed Brown @*/
59207c1f9639SMatthew G Knepley PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
5921a6dfd86eSKarl Rupp {
5922552f7358SJed Brown   PetscInt       size = 0;
5923552f7358SJed Brown   PetscErrorCode ierr;
5924552f7358SJed Brown 
5925552f7358SJed Brown   PetscFunctionBegin;
5926552f7358SJed Brown   /* Should work without recalculating size */
592769291d52SBarry Smith   ierr = DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void*) values);CHKERRQ(ierr);
5928c9fdaa05SMatthew G. Knepley   *values = NULL;
5929552f7358SJed Brown   PetscFunctionReturn(0);
5930552f7358SJed Brown }
5931552f7358SJed Brown 
59329fbee547SJacob Faibussowitsch static inline void add   (PetscScalar *x, PetscScalar y) {*x += y;}
59339fbee547SJacob Faibussowitsch static inline void insert(PetscScalar *x, PetscScalar y) {*x  = y;}
5934552f7358SJed Brown 
59359fbee547SJacob Faibussowitsch static inline PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, const PetscInt perm[], const PetscScalar flip[], const PetscInt clperm[], const PetscScalar values[], PetscInt offset, PetscScalar array[])
5936552f7358SJed Brown {
5937552f7358SJed Brown   PetscInt        cdof;   /* The number of constraints on this point */
5938552f7358SJed Brown   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
5939552f7358SJed Brown   PetscScalar    *a;
5940552f7358SJed Brown   PetscInt        off, cind = 0, k;
5941552f7358SJed Brown   PetscErrorCode  ierr;
5942552f7358SJed Brown 
5943552f7358SJed Brown   PetscFunctionBegin;
5944552f7358SJed Brown   ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr);
5945552f7358SJed Brown   ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr);
5946552f7358SJed Brown   a    = &array[off];
5947552f7358SJed Brown   if (!cdof || setBC) {
594897e99dd9SToby Isaac     if (clperm) {
594997e99dd9SToby Isaac       if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));}}
595097e99dd9SToby Isaac       else      {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+     k ]] * (flip ? flip[     k ] : 1.));}}
5951552f7358SJed Brown     } else {
595297e99dd9SToby Isaac       if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));}}
595397e99dd9SToby Isaac       else      {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+     k ] * (flip ? flip[     k ] : 1.));}}
5954552f7358SJed Brown     }
5955552f7358SJed Brown   } else {
5956552f7358SJed Brown     ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr);
595797e99dd9SToby Isaac     if (clperm) {
595897e99dd9SToby Isaac       if (perm) {for (k = 0; k < dof; ++k) {
5959552f7358SJed Brown           if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
596097e99dd9SToby Isaac           fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));
5961552f7358SJed Brown         }
5962552f7358SJed Brown       } else {
5963552f7358SJed Brown         for (k = 0; k < dof; ++k) {
5964552f7358SJed Brown           if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
596597e99dd9SToby Isaac           fuse(&a[k], values[clperm[offset+     k ]] * (flip ? flip[     k ] : 1.));
596697e99dd9SToby Isaac         }
596797e99dd9SToby Isaac       }
596897e99dd9SToby Isaac     } else {
596997e99dd9SToby Isaac       if (perm) {
597097e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
597197e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
597297e99dd9SToby Isaac           fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));
597397e99dd9SToby Isaac         }
597497e99dd9SToby Isaac       } else {
597597e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
597697e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
597797e99dd9SToby Isaac           fuse(&a[k], values[offset+     k ] * (flip ? flip[     k ] : 1.));
597897e99dd9SToby Isaac         }
5979552f7358SJed Brown       }
5980552f7358SJed Brown     }
5981552f7358SJed Brown   }
5982552f7358SJed Brown   PetscFunctionReturn(0);
5983552f7358SJed Brown }
5984552f7358SJed Brown 
59859fbee547SJacob Faibussowitsch static inline PetscErrorCode updatePointBC_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), const PetscInt perm[], const PetscScalar flip[], const PetscInt clperm[], const PetscScalar values[], PetscInt offset, PetscScalar array[])
5986a5e93ea8SMatthew G. Knepley {
5987a5e93ea8SMatthew G. Knepley   PetscInt        cdof;   /* The number of constraints on this point */
5988a5e93ea8SMatthew G. Knepley   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
5989a5e93ea8SMatthew G. Knepley   PetscScalar    *a;
5990a5e93ea8SMatthew G. Knepley   PetscInt        off, cind = 0, k;
5991a5e93ea8SMatthew G. Knepley   PetscErrorCode  ierr;
5992a5e93ea8SMatthew G. Knepley 
5993a5e93ea8SMatthew G. Knepley   PetscFunctionBegin;
5994a5e93ea8SMatthew G. Knepley   ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr);
5995a5e93ea8SMatthew G. Knepley   ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr);
5996a5e93ea8SMatthew G. Knepley   a    = &array[off];
5997a5e93ea8SMatthew G. Knepley   if (cdof) {
5998a5e93ea8SMatthew G. Knepley     ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr);
599997e99dd9SToby Isaac     if (clperm) {
600097e99dd9SToby Isaac       if (perm) {
6001a5e93ea8SMatthew G. Knepley         for (k = 0; k < dof; ++k) {
6002a5e93ea8SMatthew G. Knepley           if ((cind < cdof) && (k == cdofs[cind])) {
600397e99dd9SToby Isaac             fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));
600497e99dd9SToby Isaac             cind++;
6005a5e93ea8SMatthew G. Knepley           }
6006a5e93ea8SMatthew G. Knepley         }
6007a5e93ea8SMatthew G. Knepley       } else {
6008a5e93ea8SMatthew G. Knepley         for (k = 0; k < dof; ++k) {
6009a5e93ea8SMatthew G. Knepley           if ((cind < cdof) && (k == cdofs[cind])) {
601097e99dd9SToby Isaac             fuse(&a[k], values[clperm[offset+     k ]] * (flip ? flip[     k ] : 1.));
601197e99dd9SToby Isaac             cind++;
601297e99dd9SToby Isaac           }
601397e99dd9SToby Isaac         }
601497e99dd9SToby Isaac       }
601597e99dd9SToby Isaac     } else {
601697e99dd9SToby Isaac       if (perm) {
601797e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
601897e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {
601997e99dd9SToby Isaac             fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));
602097e99dd9SToby Isaac             cind++;
602197e99dd9SToby Isaac           }
602297e99dd9SToby Isaac         }
602397e99dd9SToby Isaac       } else {
602497e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
602597e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {
602697e99dd9SToby Isaac             fuse(&a[k], values[offset+     k ] * (flip ? flip[     k ] : 1.));
602797e99dd9SToby Isaac             cind++;
602897e99dd9SToby Isaac           }
6029a5e93ea8SMatthew G. Knepley         }
6030a5e93ea8SMatthew G. Knepley       }
6031a5e93ea8SMatthew G. Knepley     }
6032a5e93ea8SMatthew G. Knepley   }
6033a5e93ea8SMatthew G. Knepley   PetscFunctionReturn(0);
6034a5e93ea8SMatthew G. Knepley }
6035a5e93ea8SMatthew G. Knepley 
60369fbee547SJacob Faibussowitsch static inline PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, const PetscInt *perm, const PetscScalar *flip, PetscInt f, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, const PetscInt clperm[], const PetscScalar values[], PetscInt *offset, PetscScalar array[])
6037a6dfd86eSKarl Rupp {
6038552f7358SJed Brown   PetscScalar    *a;
60391a271a75SMatthew G. Knepley   PetscInt        fdof, foff, fcdof, foffset = *offset;
60401a271a75SMatthew G. Knepley   const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
604197e99dd9SToby Isaac   PetscInt        cind = 0, b;
6042552f7358SJed Brown   PetscErrorCode  ierr;
6043552f7358SJed Brown 
6044552f7358SJed Brown   PetscFunctionBegin;
6045552f7358SJed Brown   ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr);
6046552f7358SJed Brown   ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr);
60471a271a75SMatthew G. Knepley   ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr);
60481a271a75SMatthew G. Knepley   a    = &array[foff];
6049552f7358SJed Brown   if (!fcdof || setBC) {
605097e99dd9SToby Isaac     if (clperm) {
605197e99dd9SToby Isaac       if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));}}
605297e99dd9SToby Isaac       else      {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+     b ]] * (flip ? flip[     b ] : 1.));}}
6053552f7358SJed Brown     } else {
605497e99dd9SToby Isaac       if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));}}
605597e99dd9SToby Isaac       else      {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+     b ] * (flip ? flip[     b ] : 1.));}}
6056552f7358SJed Brown     }
6057552f7358SJed Brown   } else {
6058552f7358SJed Brown     ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr);
605997e99dd9SToby Isaac     if (clperm) {
606097e99dd9SToby Isaac       if (perm) {
606197e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
606297e99dd9SToby Isaac           if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;}
606397e99dd9SToby Isaac           fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));
6064552f7358SJed Brown         }
6065552f7358SJed Brown       } else {
606697e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
606797e99dd9SToby Isaac           if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;}
606897e99dd9SToby Isaac           fuse(&a[b], values[clperm[foffset+     b ]] * (flip ? flip[     b ] : 1.));
606997e99dd9SToby Isaac         }
607097e99dd9SToby Isaac       }
607197e99dd9SToby Isaac     } else {
607297e99dd9SToby Isaac       if (perm) {
607397e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
607497e99dd9SToby Isaac           if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;}
607597e99dd9SToby Isaac           fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));
607697e99dd9SToby Isaac         }
607797e99dd9SToby Isaac       } else {
607897e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
607997e99dd9SToby Isaac           if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;}
608097e99dd9SToby Isaac           fuse(&a[b], values[foffset+     b ] * (flip ? flip[     b ] : 1.));
6081552f7358SJed Brown         }
6082552f7358SJed Brown       }
6083552f7358SJed Brown     }
6084552f7358SJed Brown   }
60851a271a75SMatthew G. Knepley   *offset += fdof;
6086552f7358SJed Brown   PetscFunctionReturn(0);
6087552f7358SJed Brown }
6088552f7358SJed Brown 
60899fbee547SJacob Faibussowitsch static inline PetscErrorCode updatePointFieldsBC_private(PetscSection section, PetscInt point, const PetscInt perm[], const PetscScalar flip[], PetscInt f, PetscInt Ncc, const PetscInt comps[], void (*fuse)(PetscScalar*, PetscScalar), const PetscInt clperm[], const PetscScalar values[], PetscInt *offset, PetscScalar array[])
6090a5e93ea8SMatthew G. Knepley {
6091a5e93ea8SMatthew G. Knepley   PetscScalar    *a;
60921a271a75SMatthew G. Knepley   PetscInt        fdof, foff, fcdof, foffset = *offset;
60931a271a75SMatthew G. Knepley   const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
60945da9d227SMatthew G. Knepley   PetscInt        Nc, cind = 0, ncind = 0, b;
6095ba322698SMatthew G. Knepley   PetscBool       ncSet, fcSet;
6096a5e93ea8SMatthew G. Knepley   PetscErrorCode  ierr;
6097a5e93ea8SMatthew G. Knepley 
6098a5e93ea8SMatthew G. Knepley   PetscFunctionBegin;
60995da9d227SMatthew G. Knepley   ierr = PetscSectionGetFieldComponents(section, f, &Nc);CHKERRQ(ierr);
6100a5e93ea8SMatthew G. Knepley   ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr);
6101a5e93ea8SMatthew G. Knepley   ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr);
61021a271a75SMatthew G. Knepley   ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr);
61031a271a75SMatthew G. Knepley   a    = &array[foff];
6104a5e93ea8SMatthew G. Knepley   if (fcdof) {
6105ba322698SMatthew G. Knepley     /* We just override fcdof and fcdofs with Ncc and comps */
6106a5e93ea8SMatthew G. Knepley     ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr);
610797e99dd9SToby Isaac     if (clperm) {
610897e99dd9SToby Isaac       if (perm) {
6109ba322698SMatthew G. Knepley         if (comps) {
6110ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6111ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
61125da9d227SMatthew G. Knepley             if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;}
6113ba322698SMatthew G. Knepley             if ((cind < fcdof) && (b == fcdofs[cind])) {++cind;  fcSet = PETSC_TRUE;}
6114ba322698SMatthew G. Knepley             if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));}
6115ba322698SMatthew G. Knepley           }
6116ba322698SMatthew G. Knepley         } else {
611797e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
611897e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
611997e99dd9SToby Isaac               fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));
6120a5e93ea8SMatthew G. Knepley               ++cind;
6121a5e93ea8SMatthew G. Knepley             }
6122a5e93ea8SMatthew G. Knepley           }
6123ba322698SMatthew G. Knepley         }
6124ba322698SMatthew G. Knepley       } else {
6125ba322698SMatthew G. Knepley         if (comps) {
6126ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6127ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
61285da9d227SMatthew G. Knepley             if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;}
6129ba322698SMatthew G. Knepley             if ((cind < fcdof) && (b == fcdofs[cind])) {++cind;  fcSet = PETSC_TRUE;}
6130ba322698SMatthew G. Knepley             if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+     b ]] * (flip ? flip[     b ] : 1.));}
6131ba322698SMatthew G. Knepley           }
6132a5e93ea8SMatthew G. Knepley         } else {
613397e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
613497e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
613597e99dd9SToby Isaac               fuse(&a[b], values[clperm[foffset+     b ]] * (flip ? flip[     b ] : 1.));
613697e99dd9SToby Isaac               ++cind;
613797e99dd9SToby Isaac             }
613897e99dd9SToby Isaac           }
613997e99dd9SToby Isaac         }
6140ba322698SMatthew G. Knepley       }
614197e99dd9SToby Isaac     } else {
614297e99dd9SToby Isaac       if (perm) {
6143ba322698SMatthew G. Knepley         if (comps) {
6144ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6145ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
61465da9d227SMatthew G. Knepley             if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;}
6147ba322698SMatthew G. Knepley             if ((cind < fcdof) && (b == fcdofs[cind])) {++cind;  fcSet = PETSC_TRUE;}
6148ba322698SMatthew G. Knepley             if (ncSet && fcSet) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));}
6149ba322698SMatthew G. Knepley           }
6150ba322698SMatthew G. Knepley         } else {
615197e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
615297e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
615397e99dd9SToby Isaac               fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));
615497e99dd9SToby Isaac               ++cind;
615597e99dd9SToby Isaac             }
615697e99dd9SToby Isaac           }
6157ba322698SMatthew G. Knepley         }
6158ba322698SMatthew G. Knepley       } else {
6159ba322698SMatthew G. Knepley         if (comps) {
6160ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6161ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
61625da9d227SMatthew G. Knepley             if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;}
6163ba322698SMatthew G. Knepley             if ((cind < fcdof) && (b == fcdofs[cind])) {++cind;  fcSet = PETSC_TRUE;}
6164ba322698SMatthew G. Knepley             if (ncSet && fcSet) {fuse(&a[b], values[foffset+     b ] * (flip ? flip[     b ] : 1.));}
6165ba322698SMatthew G. Knepley           }
616697e99dd9SToby Isaac         } else {
616797e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
616897e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
616997e99dd9SToby Isaac               fuse(&a[b], values[foffset+     b ] * (flip ? flip[     b ] : 1.));
6170a5e93ea8SMatthew G. Knepley               ++cind;
6171a5e93ea8SMatthew G. Knepley             }
6172a5e93ea8SMatthew G. Knepley           }
6173a5e93ea8SMatthew G. Knepley         }
6174a5e93ea8SMatthew G. Knepley       }
6175a5e93ea8SMatthew G. Knepley     }
6176ba322698SMatthew G. Knepley   }
61771a271a75SMatthew G. Knepley   *offset += fdof;
6178a5e93ea8SMatthew G. Knepley   PetscFunctionReturn(0);
6179a5e93ea8SMatthew G. Knepley }
6180a5e93ea8SMatthew G. Knepley 
61819fbee547SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode)
6182a6dfd86eSKarl Rupp {
6183552f7358SJed Brown   PetscScalar    *array;
61841b406b76SMatthew G. Knepley   const PetscInt *cone, *coneO;
61851b406b76SMatthew G. Knepley   PetscInt        pStart, pEnd, p, numPoints, off, dof;
6186552f7358SJed Brown   PetscErrorCode  ierr;
6187552f7358SJed Brown 
61881b406b76SMatthew G. Knepley   PetscFunctionBeginHot;
6189b6ebb6e6SMatthew G. Knepley   ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr);
6190b6ebb6e6SMatthew G. Knepley   ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr);
6191b6ebb6e6SMatthew G. Knepley   ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr);
6192b6ebb6e6SMatthew G. Knepley   ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr);
6193b6ebb6e6SMatthew G. Knepley   ierr = VecGetArray(v, &array);CHKERRQ(ierr);
6194b6ebb6e6SMatthew G. Knepley   for (p = 0, off = 0; p <= numPoints; ++p, off += dof) {
6195b6ebb6e6SMatthew G. Knepley     const PetscInt cp = !p ? point : cone[p-1];
6196b6ebb6e6SMatthew G. Knepley     const PetscInt o  = !p ? 0     : coneO[p-1];
6197b6ebb6e6SMatthew G. Knepley 
6198b6ebb6e6SMatthew G. Knepley     if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;}
6199b6ebb6e6SMatthew G. Knepley     ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr);
6200b6ebb6e6SMatthew G. Knepley     /* ADD_VALUES */
6201b6ebb6e6SMatthew G. Knepley     {
6202b6ebb6e6SMatthew G. Knepley       const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6203b6ebb6e6SMatthew G. Knepley       PetscScalar    *a;
6204b6ebb6e6SMatthew G. Knepley       PetscInt        cdof, coff, cind = 0, k;
6205b6ebb6e6SMatthew G. Knepley 
6206b6ebb6e6SMatthew G. Knepley       ierr = PetscSectionGetConstraintDof(section, cp, &cdof);CHKERRQ(ierr);
6207b6ebb6e6SMatthew G. Knepley       ierr = PetscSectionGetOffset(section, cp, &coff);CHKERRQ(ierr);
6208b6ebb6e6SMatthew G. Knepley       a    = &array[coff];
6209b6ebb6e6SMatthew G. Knepley       if (!cdof) {
6210b6ebb6e6SMatthew G. Knepley         if (o >= 0) {
6211b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
6212b6ebb6e6SMatthew G. Knepley             a[k] += values[off+k];
6213b6ebb6e6SMatthew G. Knepley           }
6214b6ebb6e6SMatthew G. Knepley         } else {
6215b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
6216b6ebb6e6SMatthew G. Knepley             a[k] += values[off+dof-k-1];
6217b6ebb6e6SMatthew G. Knepley           }
6218b6ebb6e6SMatthew G. Knepley         }
6219b6ebb6e6SMatthew G. Knepley       } else {
6220b6ebb6e6SMatthew G. Knepley         ierr = PetscSectionGetConstraintIndices(section, cp, &cdofs);CHKERRQ(ierr);
6221b6ebb6e6SMatthew G. Knepley         if (o >= 0) {
6222b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
6223b6ebb6e6SMatthew G. Knepley             if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
6224b6ebb6e6SMatthew G. Knepley             a[k] += values[off+k];
6225b6ebb6e6SMatthew G. Knepley           }
6226b6ebb6e6SMatthew G. Knepley         } else {
6227b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
6228b6ebb6e6SMatthew G. Knepley             if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
6229b6ebb6e6SMatthew G. Knepley             a[k] += values[off+dof-k-1];
6230b6ebb6e6SMatthew G. Knepley           }
6231b6ebb6e6SMatthew G. Knepley         }
6232b6ebb6e6SMatthew G. Knepley       }
6233b6ebb6e6SMatthew G. Knepley     }
6234b6ebb6e6SMatthew G. Knepley   }
6235b6ebb6e6SMatthew G. Knepley   ierr = VecRestoreArray(v, &array);CHKERRQ(ierr);
6236b6ebb6e6SMatthew G. Knepley   PetscFunctionReturn(0);
6237b6ebb6e6SMatthew G. Knepley }
62381b406b76SMatthew G. Knepley 
62391b406b76SMatthew G. Knepley /*@C
62401b406b76SMatthew G. Knepley   DMPlexVecSetClosure - Set an array of the values on the closure of 'point'
62411b406b76SMatthew G. Knepley 
62421b406b76SMatthew G. Knepley   Not collective
62431b406b76SMatthew G. Knepley 
62441b406b76SMatthew G. Knepley   Input Parameters:
62451b406b76SMatthew G. Knepley + dm - The DM
62461b406b76SMatthew G. Knepley . section - The section describing the layout in v, or NULL to use the default section
62471b406b76SMatthew G. Knepley . v - The local vector
6248eaf898f9SPatrick Sanan . point - The point in the DM
62491b406b76SMatthew G. Knepley . values - The array of values
625022c1ee49SMatthew G. Knepley - mode - The insert mode. One of INSERT_ALL_VALUES, ADD_ALL_VALUES, INSERT_VALUES, ADD_VALUES, INSERT_BC_VALUES, and ADD_BC_VALUES,
625122c1ee49SMatthew G. Knepley          where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions.
62521b406b76SMatthew G. Knepley 
62531b406b76SMatthew G. Knepley   Fortran Notes:
62541b406b76SMatthew G. Knepley   This routine is only available in Fortran 90, and you must include petsc.h90 in your code.
62551b406b76SMatthew G. Knepley 
62561b406b76SMatthew G. Knepley   Level: intermediate
62571b406b76SMatthew G. Knepley 
62581b406b76SMatthew G. Knepley .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure()
62591b406b76SMatthew G. Knepley @*/
62601b406b76SMatthew G. Knepley PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode)
62611b406b76SMatthew G. Knepley {
62621b406b76SMatthew G. Knepley   PetscSection    clSection;
62631b406b76SMatthew G. Knepley   IS              clPoints;
62641b406b76SMatthew G. Knepley   PetscScalar    *array;
62651b406b76SMatthew G. Knepley   PetscInt       *points = NULL;
626627f02ce8SMatthew G. Knepley   const PetscInt *clp, *clperm = NULL;
6267c459fbc1SJed Brown   PetscInt        depth, numFields, numPoints, p, clsize;
62681b406b76SMatthew G. Knepley   PetscErrorCode  ierr;
62691b406b76SMatthew G. Knepley 
62701a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
62711b406b76SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
627292fd8e1eSJed Brown   if (!section) {ierr = DMGetLocalSection(dm, &section);CHKERRQ(ierr);}
62731a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
62741a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
62751b406b76SMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
62761b406b76SMatthew G. Knepley   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
62771b406b76SMatthew G. Knepley   if (depth == 1 && numFields < 2 && mode == ADD_VALUES) {
62788f3be42fSMatthew G. Knepley     ierr = DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode);CHKERRQ(ierr);
62791b406b76SMatthew G. Knepley     PetscFunctionReturn(0);
62801b406b76SMatthew G. Knepley   }
62811a271a75SMatthew G. Knepley   /* Get points */
6282923c78e0SToby Isaac   ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr);
6283c459fbc1SJed Brown   for (clsize=0,p=0; p<numPoints; p++) {
6284c459fbc1SJed Brown     PetscInt dof;
6285c459fbc1SJed Brown     ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr);
6286c459fbc1SJed Brown     clsize += dof;
6287c459fbc1SJed Brown   }
6288c459fbc1SJed Brown   ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm);CHKERRQ(ierr);
62891a271a75SMatthew G. Knepley   /* Get array */
6290552f7358SJed Brown   ierr = VecGetArray(v, &array);CHKERRQ(ierr);
62911a271a75SMatthew G. Knepley   /* Get values */
6292ef90cfe2SMatthew G. Knepley   if (numFields > 0) {
629397e99dd9SToby Isaac     PetscInt offset = 0, f;
6294552f7358SJed Brown     for (f = 0; f < numFields; ++f) {
629597e99dd9SToby Isaac       const PetscInt    **perms = NULL;
629697e99dd9SToby Isaac       const PetscScalar **flips = NULL;
629797e99dd9SToby Isaac 
629897e99dd9SToby Isaac       ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr);
6299552f7358SJed Brown       switch (mode) {
6300552f7358SJed Brown       case INSERT_VALUES:
630197e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
630297e99dd9SToby Isaac           const PetscInt    point = points[2*p];
630397e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
630497e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
630597e99dd9SToby Isaac           updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array);
6306552f7358SJed Brown         } break;
6307552f7358SJed Brown       case INSERT_ALL_VALUES:
630897e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
630997e99dd9SToby Isaac           const PetscInt    point = points[2*p];
631097e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
631197e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
631297e99dd9SToby Isaac           updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array);
6313552f7358SJed Brown         } break;
6314a5e93ea8SMatthew G. Knepley       case INSERT_BC_VALUES:
631597e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
631697e99dd9SToby Isaac           const PetscInt    point = points[2*p];
631797e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
631897e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
6319ba322698SMatthew G. Knepley           updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array);
6320a5e93ea8SMatthew G. Knepley         } break;
6321552f7358SJed Brown       case ADD_VALUES:
632297e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
632397e99dd9SToby Isaac           const PetscInt    point = points[2*p];
632497e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
632597e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
632697e99dd9SToby Isaac           updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array);
6327552f7358SJed Brown         } break;
6328552f7358SJed Brown       case ADD_ALL_VALUES:
632997e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
633097e99dd9SToby Isaac           const PetscInt    point = points[2*p];
633197e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
633297e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
633397e99dd9SToby Isaac           updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array);
6334552f7358SJed Brown         } break;
6335304ab55fSMatthew G. Knepley       case ADD_BC_VALUES:
633697e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
633797e99dd9SToby Isaac           const PetscInt    point = points[2*p];
633897e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
633997e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
6340ba322698SMatthew G. Knepley           updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array);
6341304ab55fSMatthew G. Knepley         } break;
6342552f7358SJed Brown       default:
634398921bdaSJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
6344552f7358SJed Brown       }
634597e99dd9SToby Isaac       ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr);
63461a271a75SMatthew G. Knepley     }
6347552f7358SJed Brown   } else {
63481a271a75SMatthew G. Knepley     PetscInt dof, off;
634997e99dd9SToby Isaac     const PetscInt    **perms = NULL;
635097e99dd9SToby Isaac     const PetscScalar **flips = NULL;
63511a271a75SMatthew G. Knepley 
635297e99dd9SToby Isaac     ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr);
6353552f7358SJed Brown     switch (mode) {
6354552f7358SJed Brown     case INSERT_VALUES:
635597e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
635697e99dd9SToby Isaac         const PetscInt    point = points[2*p];
635797e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
635897e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
635997e99dd9SToby Isaac         ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr);
636097e99dd9SToby Isaac         updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array);
6361552f7358SJed Brown       } break;
6362552f7358SJed Brown     case INSERT_ALL_VALUES:
636397e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
636497e99dd9SToby Isaac         const PetscInt    point = points[2*p];
636597e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
636697e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
636797e99dd9SToby Isaac         ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr);
636897e99dd9SToby Isaac         updatePoint_private(section, point, dof, insert, PETSC_TRUE,  perm, flip, clperm, values, off, array);
6369552f7358SJed Brown       } break;
6370a5e93ea8SMatthew G. Knepley     case INSERT_BC_VALUES:
637197e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
637297e99dd9SToby Isaac         const PetscInt    point = points[2*p];
637397e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
637497e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
637597e99dd9SToby Isaac         ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr);
637697e99dd9SToby Isaac         updatePointBC_private(section, point, dof, insert,  perm, flip, clperm, values, off, array);
6377a5e93ea8SMatthew G. Knepley       } break;
6378552f7358SJed Brown     case ADD_VALUES:
637997e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
638097e99dd9SToby Isaac         const PetscInt    point = points[2*p];
638197e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
638297e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
638397e99dd9SToby Isaac         ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr);
638497e99dd9SToby Isaac         updatePoint_private(section, point, dof, add,    PETSC_FALSE, perm, flip, clperm, values, off, array);
6385552f7358SJed Brown       } break;
6386552f7358SJed Brown     case ADD_ALL_VALUES:
638797e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
638897e99dd9SToby Isaac         const PetscInt    point = points[2*p];
638997e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
639097e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
639197e99dd9SToby Isaac         ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr);
639297e99dd9SToby Isaac         updatePoint_private(section, point, dof, add,    PETSC_TRUE,  perm, flip, clperm, values, off, array);
6393552f7358SJed Brown       } break;
6394304ab55fSMatthew G. Knepley     case ADD_BC_VALUES:
639597e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
639697e99dd9SToby Isaac         const PetscInt    point = points[2*p];
639797e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
639897e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
639997e99dd9SToby Isaac         ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr);
640097e99dd9SToby Isaac         updatePointBC_private(section, point, dof, add,  perm, flip, clperm, values, off, array);
6401304ab55fSMatthew G. Knepley       } break;
6402552f7358SJed Brown     default:
640398921bdaSJacob Faibussowitsch       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
6404552f7358SJed Brown     }
640597e99dd9SToby Isaac     ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr);
6406552f7358SJed Brown   }
64071a271a75SMatthew G. Knepley   /* Cleanup points */
6408923c78e0SToby Isaac   ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr);
64091a271a75SMatthew G. Knepley   /* Cleanup array */
6410552f7358SJed Brown   ierr = VecRestoreArray(v, &array);CHKERRQ(ierr);
6411552f7358SJed Brown   PetscFunctionReturn(0);
6412552f7358SJed Brown }
6413552f7358SJed Brown 
64145f790a90SMatthew G. Knepley /* Check whether the given point is in the label. If not, update the offset to skip this point */
64159fbee547SJacob Faibussowitsch static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset)
64165f790a90SMatthew G. Knepley {
64175f790a90SMatthew G. Knepley   PetscFunctionBegin;
64185f790a90SMatthew G. Knepley   if (label) {
64195f790a90SMatthew G. Knepley     PetscInt       val, fdof;
64205f790a90SMatthew G. Knepley     PetscErrorCode ierr;
64215f790a90SMatthew G. Knepley 
64225f790a90SMatthew G. Knepley     /* There is a problem with this:
64235f790a90SMatthew G. Knepley          Suppose we have two label values, defining surfaces, interecting along a line in 3D. When we add cells to the label, the cells that
64245f790a90SMatthew G. Knepley        touch both surfaces must pick a label value. Thus we miss setting values for the surface with that other value intersecting that cell.
64255f790a90SMatthew G. Knepley        Thus I am only going to check val != -1, not val != labelId
64265f790a90SMatthew G. Knepley     */
64275f790a90SMatthew G. Knepley     ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr);
64285f790a90SMatthew G. Knepley     if (val < 0) {
64295f790a90SMatthew G. Knepley       ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr);
64305f790a90SMatthew G. Knepley       *offset += fdof;
64315f790a90SMatthew G. Knepley       PetscFunctionReturn(1);
64325f790a90SMatthew G. Knepley     }
64335f790a90SMatthew G. Knepley   }
64345f790a90SMatthew G. Knepley   PetscFunctionReturn(0);
64355f790a90SMatthew G. Knepley }
64365f790a90SMatthew G. Knepley 
643797529cf3SJed Brown /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */
64385f790a90SMatthew G. Knepley PetscErrorCode DMPlexVecSetFieldClosure_Internal(DM dm, PetscSection section, Vec v, PetscBool fieldActive[], PetscInt point, PetscInt Ncc, const PetscInt comps[], DMLabel label, PetscInt labelId, const PetscScalar values[], InsertMode mode)
6439e07394fbSMatthew G. Knepley {
6440e07394fbSMatthew G. Knepley   PetscSection      clSection;
6441e07394fbSMatthew G. Knepley   IS                clPoints;
6442e07394fbSMatthew G. Knepley   PetscScalar       *array;
6443e07394fbSMatthew G. Knepley   PetscInt          *points = NULL;
644497529cf3SJed Brown   const PetscInt    *clp;
6445e07394fbSMatthew G. Knepley   PetscInt          numFields, numPoints, p;
644697e99dd9SToby Isaac   PetscInt          offset = 0, f;
6447e07394fbSMatthew G. Knepley   PetscErrorCode    ierr;
6448e07394fbSMatthew G. Knepley 
6449e07394fbSMatthew G. Knepley   PetscFunctionBeginHot;
6450e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
645192fd8e1eSJed Brown   if (!section) {ierr = DMGetLocalSection(dm, &section);CHKERRQ(ierr);}
6452e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
6453e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
6454e07394fbSMatthew G. Knepley   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
6455e07394fbSMatthew G. Knepley   /* Get points */
6456923c78e0SToby Isaac   ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr);
6457e07394fbSMatthew G. Knepley   /* Get array */
6458e07394fbSMatthew G. Knepley   ierr = VecGetArray(v, &array);CHKERRQ(ierr);
6459e07394fbSMatthew G. Knepley   /* Get values */
6460e07394fbSMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
646197e99dd9SToby Isaac     const PetscInt    **perms = NULL;
646297e99dd9SToby Isaac     const PetscScalar **flips = NULL;
646397e99dd9SToby Isaac 
6464e07394fbSMatthew G. Knepley     if (!fieldActive[f]) {
6465e07394fbSMatthew G. Knepley       for (p = 0; p < numPoints*2; p += 2) {
6466e07394fbSMatthew G. Knepley         PetscInt fdof;
6467e07394fbSMatthew G. Knepley         ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr);
6468e07394fbSMatthew G. Knepley         offset += fdof;
6469e07394fbSMatthew G. Knepley       }
6470e07394fbSMatthew G. Knepley       continue;
6471e07394fbSMatthew G. Knepley     }
647297e99dd9SToby Isaac     ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr);
6473e07394fbSMatthew G. Knepley     switch (mode) {
6474e07394fbSMatthew G. Knepley     case INSERT_VALUES:
647597e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
647697e99dd9SToby Isaac         const PetscInt    point = points[2*p];
647797e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
647897e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
64795f790a90SMatthew G. Knepley         ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue;
648097529cf3SJed Brown         updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array);
6481e07394fbSMatthew G. Knepley       } break;
6482e07394fbSMatthew G. Knepley     case INSERT_ALL_VALUES:
648397e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
648497e99dd9SToby Isaac         const PetscInt    point = points[2*p];
648597e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
648697e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
64875f790a90SMatthew G. Knepley         ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue;
648897529cf3SJed Brown         updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array);
6489e07394fbSMatthew G. Knepley       } break;
6490e07394fbSMatthew G. Knepley     case INSERT_BC_VALUES:
649197e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
649297e99dd9SToby Isaac         const PetscInt    point = points[2*p];
649397e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
649497e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
64955f790a90SMatthew G. Knepley         ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue;
649697529cf3SJed Brown         updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array);
6497e07394fbSMatthew G. Knepley       } break;
6498e07394fbSMatthew G. Knepley     case ADD_VALUES:
649997e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
650097e99dd9SToby Isaac         const PetscInt    point = points[2*p];
650197e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
650297e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
65035f790a90SMatthew G. Knepley         ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue;
650497529cf3SJed Brown         updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array);
6505e07394fbSMatthew G. Knepley       } break;
6506e07394fbSMatthew G. Knepley     case ADD_ALL_VALUES:
650797e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
650897e99dd9SToby Isaac         const PetscInt    point = points[2*p];
650997e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
651097e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
65115f790a90SMatthew G. Knepley         ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue;
651297529cf3SJed Brown         updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array);
6513e07394fbSMatthew G. Knepley       } break;
6514e07394fbSMatthew G. Knepley     default:
651598921bdaSJacob Faibussowitsch       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
6516e07394fbSMatthew G. Knepley     }
651797e99dd9SToby Isaac     ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr);
6518e07394fbSMatthew G. Knepley   }
6519e07394fbSMatthew G. Knepley   /* Cleanup points */
6520923c78e0SToby Isaac   ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr);
6521e07394fbSMatthew G. Knepley   /* Cleanup array */
6522e07394fbSMatthew G. Knepley   ierr = VecRestoreArray(v, &array);CHKERRQ(ierr);
6523e07394fbSMatthew G. Knepley   PetscFunctionReturn(0);
6524e07394fbSMatthew G. Knepley }
6525e07394fbSMatthew G. Knepley 
65267cd05799SMatthew G. Knepley static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[])
6527552f7358SJed Brown {
6528552f7358SJed Brown   PetscMPIInt    rank;
6529552f7358SJed Brown   PetscInt       i, j;
6530552f7358SJed Brown   PetscErrorCode ierr;
6531552f7358SJed Brown 
6532552f7358SJed Brown   PetscFunctionBegin;
6533ffc4695bSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr);
6534eaf898f9SPatrick Sanan   ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat for point %D\n", rank, point);CHKERRQ(ierr);
6535e4b003c7SBarry Smith   for (i = 0; i < numRIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%D] = %D\n", rank, i, rindices[i]);CHKERRQ(ierr);}
6536e4b003c7SBarry Smith   for (i = 0; i < numCIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%D] = %D\n", rank, i, cindices[i]);CHKERRQ(ierr);}
6537b0ecff45SMatthew G. Knepley   numCIndices = numCIndices ? numCIndices : numRIndices;
6538557cf195SMatthew G. Knepley   if (!values) PetscFunctionReturn(0);
6539b0ecff45SMatthew G. Knepley   for (i = 0; i < numRIndices; i++) {
6540e4b003c7SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer, "[%d]", rank);CHKERRQ(ierr);
6541b0ecff45SMatthew G. Knepley     for (j = 0; j < numCIndices; j++) {
6542519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX)
65437eba1a17SMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j]));CHKERRQ(ierr);
6544552f7358SJed Brown #else
6545b0ecff45SMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j]);CHKERRQ(ierr);
6546552f7358SJed Brown #endif
6547552f7358SJed Brown     }
654877a6746dSMatthew G Knepley     ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr);
6549552f7358SJed Brown   }
6550552f7358SJed Brown   PetscFunctionReturn(0);
6551552f7358SJed Brown }
6552552f7358SJed Brown 
655305586334SMatthew G. Knepley /*
655405586334SMatthew G. Knepley   DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array
655505586334SMatthew G. Knepley 
655605586334SMatthew G. Knepley   Input Parameters:
655705586334SMatthew G. Knepley + section - The section for this data layout
655836fa2b79SJed Brown . islocal - Is the section (and thus indices being requested) local or global?
655905586334SMatthew G. Knepley . point   - The point contributing dofs with these indices
656005586334SMatthew G. Knepley . off     - The global offset of this point
656105586334SMatthew G. Knepley . loff    - The local offset of each field
6562a5b23f4aSJose E. Roman . setBC   - The flag determining whether to include indices of boundary values
656305586334SMatthew G. Knepley . perm    - A permutation of the dofs on this point, or NULL
656405586334SMatthew G. Knepley - indperm - A permutation of the entire indices array, or NULL
656505586334SMatthew G. Knepley 
656605586334SMatthew G. Knepley   Output Parameter:
656705586334SMatthew G. Knepley . indices - Indices for dofs on this point
656805586334SMatthew G. Knepley 
656905586334SMatthew G. Knepley   Level: developer
657005586334SMatthew G. Knepley 
657105586334SMatthew G. Knepley   Note: The indices could be local or global, depending on the value of 'off'.
657205586334SMatthew G. Knepley */
657336fa2b79SJed Brown PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal,PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[])
6574a6dfd86eSKarl Rupp {
6575e6ccafaeSMatthew G Knepley   PetscInt        dof;   /* The number of unknowns on this point */
6576552f7358SJed Brown   PetscInt        cdof;  /* The number of constraints on this point */
6577552f7358SJed Brown   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6578552f7358SJed Brown   PetscInt        cind = 0, k;
6579552f7358SJed Brown   PetscErrorCode  ierr;
6580552f7358SJed Brown 
6581552f7358SJed Brown   PetscFunctionBegin;
65822c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!islocal && setBC,PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC");
6583552f7358SJed Brown   ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr);
6584552f7358SJed Brown   ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr);
6585552f7358SJed Brown   if (!cdof || setBC) {
658605586334SMatthew G. Knepley     for (k = 0; k < dof; ++k) {
658705586334SMatthew G. Knepley       const PetscInt preind = perm ? *loff+perm[k] : *loff+k;
658805586334SMatthew G. Knepley       const PetscInt ind    = indperm ? indperm[preind] : preind;
658905586334SMatthew G. Knepley 
659005586334SMatthew G. Knepley       indices[ind] = off + k;
6591552f7358SJed Brown     }
6592552f7358SJed Brown   } else {
6593552f7358SJed Brown     ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr);
65944acb8e1eSToby Isaac     for (k = 0; k < dof; ++k) {
659505586334SMatthew G. Knepley       const PetscInt preind = perm ? *loff+perm[k] : *loff+k;
659605586334SMatthew G. Knepley       const PetscInt ind    = indperm ? indperm[preind] : preind;
659705586334SMatthew G. Knepley 
65984acb8e1eSToby Isaac       if ((cind < cdof) && (k == cdofs[cind])) {
65994acb8e1eSToby Isaac         /* Insert check for returning constrained indices */
660005586334SMatthew G. Knepley         indices[ind] = -(off+k+1);
66014acb8e1eSToby Isaac         ++cind;
66024acb8e1eSToby Isaac       } else {
660336fa2b79SJed Brown         indices[ind] = off + k - (islocal ? 0 : cind);
6604552f7358SJed Brown       }
6605552f7358SJed Brown     }
6606552f7358SJed Brown   }
6607e6ccafaeSMatthew G Knepley   *loff += dof;
6608552f7358SJed Brown   PetscFunctionReturn(0);
6609552f7358SJed Brown }
6610552f7358SJed Brown 
66117e29afd2SMatthew G. Knepley /*
661236fa2b79SJed Brown  DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering.
66137e29afd2SMatthew G. Knepley 
661436fa2b79SJed Brown  Input Parameters:
661536fa2b79SJed Brown + section - a section (global or local)
661636fa2b79SJed Brown - islocal - PETSC_TRUE if requesting local indices (i.e., section is local); PETSC_FALSE for global
661736fa2b79SJed Brown . point - point within section
661836fa2b79SJed Brown . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section
661936fa2b79SJed Brown . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field
662036fa2b79SJed Brown . setBC - identify constrained (boundary condition) points via involution.
662136fa2b79SJed Brown . perms - perms[f][permsoff][:] is a permutation of dofs within each field
662236fa2b79SJed Brown . permsoff - offset
662336fa2b79SJed Brown - indperm - index permutation
662436fa2b79SJed Brown 
662536fa2b79SJed Brown  Output Parameter:
662636fa2b79SJed Brown . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field
662736fa2b79SJed Brown . indices - array to hold indices (as defined by section) of each dof associated with point
662836fa2b79SJed Brown 
662936fa2b79SJed Brown  Notes:
663036fa2b79SJed Brown  If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs.
663136fa2b79SJed Brown  If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position
663236fa2b79SJed Brown  in the local vector.
663336fa2b79SJed Brown 
663436fa2b79SJed Brown  If section is global and setBC=false, the indices for constrained points are negative (and their value is not
663536fa2b79SJed Brown  significant).  It is invalid to call with a global section and setBC=true.
663636fa2b79SJed Brown 
663736fa2b79SJed Brown  Developer Note:
663836fa2b79SJed Brown  The section is only used for field layout, so islocal is technically a statement about the offset (off).  At some point
663936fa2b79SJed Brown  in the future, global sections may have fields set, in which case we could pass the global section and obtain the
664036fa2b79SJed Brown  offset could be obtained from the section instead of passing it explicitly as we do now.
664136fa2b79SJed Brown 
664236fa2b79SJed Brown  Example:
664336fa2b79SJed Brown  Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}.
664436fa2b79SJed Brown  When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE).
664536fa2b79SJed Brown  Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices.
664636fa2b79SJed Brown  The global vector does not store constrained dofs, so when this function returns global indices, say {110, -112, 111}, the value of -112 is an arbitrary flag that should not be interpreted beyond its sign.
664736fa2b79SJed Brown 
664836fa2b79SJed Brown  Level: developer
66497e29afd2SMatthew G. Knepley */
665036fa2b79SJed Brown PetscErrorCode DMPlexGetIndicesPointFields_Internal(PetscSection section, PetscBool islocal, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[])
6651a6dfd86eSKarl Rupp {
6652552f7358SJed Brown   PetscInt       numFields, foff, f;
6653552f7358SJed Brown   PetscErrorCode ierr;
6654552f7358SJed Brown 
6655552f7358SJed Brown   PetscFunctionBegin;
66562c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!islocal && setBC,PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC");
6657552f7358SJed Brown   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
6658552f7358SJed Brown   for (f = 0, foff = 0; f < numFields; ++f) {
66594acb8e1eSToby Isaac     PetscInt        fdof, cfdof;
6660552f7358SJed Brown     const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
66614acb8e1eSToby Isaac     PetscInt        cind = 0, b;
66624acb8e1eSToby Isaac     const PetscInt  *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL;
6663552f7358SJed Brown 
6664552f7358SJed Brown     ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr);
6665552f7358SJed Brown     ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr);
6666552f7358SJed Brown     if (!cfdof || setBC) {
666705586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
666805586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b;
666905586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
667005586334SMatthew G. Knepley 
667105586334SMatthew G. Knepley         indices[ind] = off+foff+b;
667205586334SMatthew G. Knepley       }
6673552f7358SJed Brown     } else {
6674552f7358SJed Brown       ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr);
667505586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
667605586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b;
667705586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
667805586334SMatthew G. Knepley 
66794acb8e1eSToby Isaac         if ((cind < cfdof) && (b == fcdofs[cind])) {
668005586334SMatthew G. Knepley           indices[ind] = -(off+foff+b+1);
6681552f7358SJed Brown           ++cind;
6682552f7358SJed Brown         } else {
668336fa2b79SJed Brown           indices[ind] = off + foff + b - (islocal ? 0 : cind);
6684552f7358SJed Brown         }
6685552f7358SJed Brown       }
6686552f7358SJed Brown     }
668736fa2b79SJed Brown     foff     += (setBC || islocal ? fdof : (fdof - cfdof));
6688552f7358SJed Brown     foffs[f] += fdof;
6689552f7358SJed Brown   }
6690552f7358SJed Brown   PetscFunctionReturn(0);
6691552f7358SJed Brown }
6692552f7358SJed Brown 
66937e29afd2SMatthew G. Knepley /*
66947e29afd2SMatthew G. Knepley   This version believes the globalSection offsets for each field, rather than just the point offset
66957e29afd2SMatthew G. Knepley 
66967e29afd2SMatthew G. Knepley  . foffs - The offset into 'indices' for each field, since it is segregated by field
6697645102dcSJed Brown 
6698645102dcSJed Brown  Notes:
6699645102dcSJed Brown  The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal.
6700645102dcSJed Brown  Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists.
67017e29afd2SMatthew G. Knepley */
6702645102dcSJed Brown static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[])
67037e29afd2SMatthew G. Knepley {
67047e29afd2SMatthew G. Knepley   PetscInt       numFields, foff, f;
67057e29afd2SMatthew G. Knepley   PetscErrorCode ierr;
67067e29afd2SMatthew G. Knepley 
67077e29afd2SMatthew G. Knepley   PetscFunctionBegin;
67087e29afd2SMatthew G. Knepley   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
67097e29afd2SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
67107e29afd2SMatthew G. Knepley     PetscInt        fdof, cfdof;
67117e29afd2SMatthew G. Knepley     const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
67127e29afd2SMatthew G. Knepley     PetscInt        cind = 0, b;
67137e29afd2SMatthew G. Knepley     const PetscInt  *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL;
67147e29afd2SMatthew G. Knepley 
67157e29afd2SMatthew G. Knepley     ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr);
67167e29afd2SMatthew G. Knepley     ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr);
67177e29afd2SMatthew G. Knepley     ierr = PetscSectionGetFieldOffset(globalSection, point, f, &foff);CHKERRQ(ierr);
6718645102dcSJed Brown     if (!cfdof) {
671905586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
672005586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b;
672105586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
672205586334SMatthew G. Knepley 
672305586334SMatthew G. Knepley         indices[ind] = foff+b;
672405586334SMatthew G. Knepley       }
67257e29afd2SMatthew G. Knepley     } else {
67267e29afd2SMatthew G. Knepley       ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr);
672705586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
672805586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b;
672905586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
673005586334SMatthew G. Knepley 
67317e29afd2SMatthew G. Knepley         if ((cind < cfdof) && (b == fcdofs[cind])) {
673205586334SMatthew G. Knepley           indices[ind] = -(foff+b+1);
67337e29afd2SMatthew G. Knepley           ++cind;
67347e29afd2SMatthew G. Knepley         } else {
673505586334SMatthew G. Knepley           indices[ind] = foff+b-cind;
67367e29afd2SMatthew G. Knepley         }
67377e29afd2SMatthew G. Knepley       }
67387e29afd2SMatthew G. Knepley     }
67397e29afd2SMatthew G. Knepley     foffs[f] += fdof;
67407e29afd2SMatthew G. Knepley   }
67417e29afd2SMatthew G. Knepley   PetscFunctionReturn(0);
67427e29afd2SMatthew G. Knepley }
67437e29afd2SMatthew G. Knepley 
67444acb8e1eSToby Isaac PetscErrorCode DMPlexAnchorsModifyMat(DM dm, PetscSection section, PetscInt numPoints, PetscInt numIndices, const PetscInt points[], const PetscInt ***perms, const PetscScalar values[], PetscInt *outNumPoints, PetscInt *outNumIndices, PetscInt *outPoints[], PetscScalar *outValues[], PetscInt offsets[], PetscBool multiplyLeft)
6745d3d1a6afSToby Isaac {
6746d3d1a6afSToby Isaac   Mat             cMat;
6747d3d1a6afSToby Isaac   PetscSection    aSec, cSec;
6748d3d1a6afSToby Isaac   IS              aIS;
6749d3d1a6afSToby Isaac   PetscInt        aStart = -1, aEnd = -1;
6750d3d1a6afSToby Isaac   const PetscInt  *anchors;
6751e17c06e0SMatthew G. Knepley   PetscInt        numFields, f, p, q, newP = 0;
6752d3d1a6afSToby Isaac   PetscInt        newNumPoints = 0, newNumIndices = 0;
6753d3d1a6afSToby Isaac   PetscInt        *newPoints, *indices, *newIndices;
6754d3d1a6afSToby Isaac   PetscInt        maxAnchor, maxDof;
6755d3d1a6afSToby Isaac   PetscInt        newOffsets[32];
6756d3d1a6afSToby Isaac   PetscInt        *pointMatOffsets[32];
6757d3d1a6afSToby Isaac   PetscInt        *newPointOffsets[32];
6758d3d1a6afSToby Isaac   PetscScalar     *pointMat[32];
67596ecaa68aSToby Isaac   PetscScalar     *newValues=NULL,*tmpValues;
6760d3d1a6afSToby Isaac   PetscBool       anyConstrained = PETSC_FALSE;
6761d3d1a6afSToby Isaac   PetscErrorCode  ierr;
6762d3d1a6afSToby Isaac 
6763d3d1a6afSToby Isaac   PetscFunctionBegin;
6764d3d1a6afSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6765d3d1a6afSToby Isaac   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
6766d3d1a6afSToby Isaac   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
6767d3d1a6afSToby Isaac 
6768a17985deSToby Isaac   ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr);
6769d3d1a6afSToby Isaac   /* if there are point-to-point constraints */
6770d3d1a6afSToby Isaac   if (aSec) {
6771580bdb30SBarry Smith     ierr = PetscArrayzero(newOffsets, 32);CHKERRQ(ierr);
6772d3d1a6afSToby Isaac     ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr);
6773d3d1a6afSToby Isaac     ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr);
6774d3d1a6afSToby Isaac     /* figure out how many points are going to be in the new element matrix
6775d3d1a6afSToby Isaac      * (we allow double counting, because it's all just going to be summed
6776d3d1a6afSToby Isaac      * into the global matrix anyway) */
6777d3d1a6afSToby Isaac     for (p = 0; p < 2*numPoints; p+=2) {
6778d3d1a6afSToby Isaac       PetscInt b    = points[p];
67794b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
6780d3d1a6afSToby Isaac 
67814b2f2278SToby Isaac       ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr);
67824b2f2278SToby Isaac       if (!bSecDof) {
67834b2f2278SToby Isaac         continue;
67844b2f2278SToby Isaac       }
6785d3d1a6afSToby Isaac       if (b >= aStart && b < aEnd) {
6786d3d1a6afSToby Isaac         ierr = PetscSectionGetDof(aSec,b,&bDof);CHKERRQ(ierr);
6787d3d1a6afSToby Isaac       }
6788d3d1a6afSToby Isaac       if (bDof) {
6789d3d1a6afSToby Isaac         /* this point is constrained */
6790d3d1a6afSToby Isaac         /* it is going to be replaced by its anchors */
6791d3d1a6afSToby Isaac         PetscInt bOff, q;
6792d3d1a6afSToby Isaac 
6793d3d1a6afSToby Isaac         anyConstrained = PETSC_TRUE;
6794d3d1a6afSToby Isaac         newNumPoints  += bDof;
6795d3d1a6afSToby Isaac         ierr = PetscSectionGetOffset(aSec,b,&bOff);CHKERRQ(ierr);
6796d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
6797d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q];
6798d3d1a6afSToby Isaac           PetscInt aDof;
6799d3d1a6afSToby Isaac 
6800d3d1a6afSToby Isaac           ierr           = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr);
6801d3d1a6afSToby Isaac           newNumIndices += aDof;
6802d3d1a6afSToby Isaac           for (f = 0; f < numFields; ++f) {
6803d3d1a6afSToby Isaac             PetscInt fDof;
6804d3d1a6afSToby Isaac 
6805d3d1a6afSToby Isaac             ierr             = PetscSectionGetFieldDof(section, a, f, &fDof);CHKERRQ(ierr);
6806d3d1a6afSToby Isaac             newOffsets[f+1] += fDof;
6807d3d1a6afSToby Isaac           }
6808d3d1a6afSToby Isaac         }
6809d3d1a6afSToby Isaac       }
6810d3d1a6afSToby Isaac       else {
6811d3d1a6afSToby Isaac         /* this point is not constrained */
6812d3d1a6afSToby Isaac         newNumPoints++;
68134b2f2278SToby Isaac         newNumIndices += bSecDof;
6814d3d1a6afSToby Isaac         for (f = 0; f < numFields; ++f) {
6815d3d1a6afSToby Isaac           PetscInt fDof;
6816d3d1a6afSToby Isaac 
6817d3d1a6afSToby Isaac           ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr);
6818d3d1a6afSToby Isaac           newOffsets[f+1] += fDof;
6819d3d1a6afSToby Isaac         }
6820d3d1a6afSToby Isaac       }
6821d3d1a6afSToby Isaac     }
6822d3d1a6afSToby Isaac   }
6823d3d1a6afSToby Isaac   if (!anyConstrained) {
682472b80496SMatthew G. Knepley     if (outNumPoints)  *outNumPoints  = 0;
682572b80496SMatthew G. Knepley     if (outNumIndices) *outNumIndices = 0;
682672b80496SMatthew G. Knepley     if (outPoints)     *outPoints     = NULL;
682772b80496SMatthew G. Knepley     if (outValues)     *outValues     = NULL;
682872b80496SMatthew G. Knepley     if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);}
6829d3d1a6afSToby Isaac     PetscFunctionReturn(0);
6830d3d1a6afSToby Isaac   }
6831d3d1a6afSToby Isaac 
68326ecaa68aSToby Isaac   if (outNumPoints)  *outNumPoints  = newNumPoints;
68336ecaa68aSToby Isaac   if (outNumIndices) *outNumIndices = newNumIndices;
68346ecaa68aSToby Isaac 
6835f13f9184SToby Isaac   for (f = 0; f < numFields; ++f) newOffsets[f+1] += newOffsets[f];
6836d3d1a6afSToby Isaac 
68376ecaa68aSToby Isaac   if (!outPoints && !outValues) {
68386ecaa68aSToby Isaac     if (offsets) {
68396ecaa68aSToby Isaac       for (f = 0; f <= numFields; f++) {
68406ecaa68aSToby Isaac         offsets[f] = newOffsets[f];
68416ecaa68aSToby Isaac       }
68426ecaa68aSToby Isaac     }
68436ecaa68aSToby Isaac     if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);}
68446ecaa68aSToby Isaac     PetscFunctionReturn(0);
68456ecaa68aSToby Isaac   }
68466ecaa68aSToby Isaac 
68472c71b3e2SJacob Faibussowitsch   PetscCheckFalse(numFields && newOffsets[numFields] != newNumIndices,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", newOffsets[numFields], newNumIndices);
6848d3d1a6afSToby Isaac 
684979769bd5SJed Brown   ierr = DMGetDefaultConstraints(dm, &cSec, &cMat, NULL);CHKERRQ(ierr);
6850d3d1a6afSToby Isaac 
6851d3d1a6afSToby Isaac   /* workspaces */
6852d3d1a6afSToby Isaac   if (numFields) {
6853d3d1a6afSToby Isaac     for (f = 0; f < numFields; f++) {
685469291d52SBarry Smith       ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr);
685569291d52SBarry Smith       ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr);
6856d3d1a6afSToby Isaac     }
6857d3d1a6afSToby Isaac   }
6858d3d1a6afSToby Isaac   else {
685969291d52SBarry Smith     ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr);
686069291d52SBarry Smith     ierr = DMGetWorkArray(dm,numPoints,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr);
6861d3d1a6afSToby Isaac   }
6862d3d1a6afSToby Isaac 
6863d3d1a6afSToby Isaac   /* get workspaces for the point-to-point matrices */
6864d3d1a6afSToby Isaac   if (numFields) {
68654b2f2278SToby Isaac     PetscInt totalOffset, totalMatOffset;
68664b2f2278SToby Isaac 
6867d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
6868d3d1a6afSToby Isaac       PetscInt b    = points[2*p];
68694b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
6870d3d1a6afSToby Isaac 
68714b2f2278SToby Isaac       ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr);
68724b2f2278SToby Isaac       if (!bSecDof) {
68734b2f2278SToby Isaac         for (f = 0; f < numFields; f++) {
68744b2f2278SToby Isaac           newPointOffsets[f][p + 1] = 0;
68754b2f2278SToby Isaac           pointMatOffsets[f][p + 1] = 0;
68764b2f2278SToby Isaac         }
68774b2f2278SToby Isaac         continue;
68784b2f2278SToby Isaac       }
6879d3d1a6afSToby Isaac       if (b >= aStart && b < aEnd) {
6880d3d1a6afSToby Isaac         ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr);
6881d3d1a6afSToby Isaac       }
6882d3d1a6afSToby Isaac       if (bDof) {
6883d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
6884d3d1a6afSToby Isaac           PetscInt fDof, q, bOff, allFDof = 0;
6885d3d1a6afSToby Isaac 
6886d3d1a6afSToby Isaac           ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr);
6887d3d1a6afSToby Isaac           ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr);
6888d3d1a6afSToby Isaac           for (q = 0; q < bDof; q++) {
6889d3d1a6afSToby Isaac             PetscInt a = anchors[bOff + q];
6890d3d1a6afSToby Isaac             PetscInt aFDof;
6891d3d1a6afSToby Isaac 
6892d3d1a6afSToby Isaac             ierr     = PetscSectionGetFieldDof(section, a, f, &aFDof);CHKERRQ(ierr);
6893d3d1a6afSToby Isaac             allFDof += aFDof;
6894d3d1a6afSToby Isaac           }
6895d3d1a6afSToby Isaac           newPointOffsets[f][p+1] = allFDof;
6896d3d1a6afSToby Isaac           pointMatOffsets[f][p+1] = fDof * allFDof;
6897d3d1a6afSToby Isaac         }
6898d3d1a6afSToby Isaac       }
6899d3d1a6afSToby Isaac       else {
6900d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
6901d3d1a6afSToby Isaac           PetscInt fDof;
6902d3d1a6afSToby Isaac 
6903d3d1a6afSToby Isaac           ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr);
6904d3d1a6afSToby Isaac           newPointOffsets[f][p+1] = fDof;
6905d3d1a6afSToby Isaac           pointMatOffsets[f][p+1] = 0;
6906d3d1a6afSToby Isaac         }
6907d3d1a6afSToby Isaac       }
6908d3d1a6afSToby Isaac     }
69094b2f2278SToby Isaac     for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) {
69104b2f2278SToby Isaac       newPointOffsets[f][0] = totalOffset;
69114b2f2278SToby Isaac       pointMatOffsets[f][0] = totalMatOffset;
6912d3d1a6afSToby Isaac       for (p = 0; p < numPoints; p++) {
6913d3d1a6afSToby Isaac         newPointOffsets[f][p+1] += newPointOffsets[f][p];
6914d3d1a6afSToby Isaac         pointMatOffsets[f][p+1] += pointMatOffsets[f][p];
6915d3d1a6afSToby Isaac       }
691619f70fd5SToby Isaac       totalOffset    = newPointOffsets[f][numPoints];
691719f70fd5SToby Isaac       totalMatOffset = pointMatOffsets[f][numPoints];
691869291d52SBarry Smith       ierr = DMGetWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr);
6919d3d1a6afSToby Isaac     }
6920d3d1a6afSToby Isaac   }
6921d3d1a6afSToby Isaac   else {
6922d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
6923d3d1a6afSToby Isaac       PetscInt b    = points[2*p];
69244b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
6925d3d1a6afSToby Isaac 
69264b2f2278SToby Isaac       ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr);
69274b2f2278SToby Isaac       if (!bSecDof) {
69284b2f2278SToby Isaac         newPointOffsets[0][p + 1] = 0;
69294b2f2278SToby Isaac         pointMatOffsets[0][p + 1] = 0;
69304b2f2278SToby Isaac         continue;
69314b2f2278SToby Isaac       }
6932d3d1a6afSToby Isaac       if (b >= aStart && b < aEnd) {
6933d3d1a6afSToby Isaac         ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr);
6934d3d1a6afSToby Isaac       }
6935d3d1a6afSToby Isaac       if (bDof) {
69364b2f2278SToby Isaac         PetscInt bOff, q, allDof = 0;
6937d3d1a6afSToby Isaac 
6938d3d1a6afSToby Isaac         ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr);
6939d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
6940d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aDof;
6941d3d1a6afSToby Isaac 
6942d3d1a6afSToby Isaac           ierr    = PetscSectionGetDof(section, a, &aDof);CHKERRQ(ierr);
6943d3d1a6afSToby Isaac           allDof += aDof;
6944d3d1a6afSToby Isaac         }
6945d3d1a6afSToby Isaac         newPointOffsets[0][p+1] = allDof;
69464b2f2278SToby Isaac         pointMatOffsets[0][p+1] = bSecDof * allDof;
6947d3d1a6afSToby Isaac       }
6948d3d1a6afSToby Isaac       else {
69494b2f2278SToby Isaac         newPointOffsets[0][p+1] = bSecDof;
6950d3d1a6afSToby Isaac         pointMatOffsets[0][p+1] = 0;
6951d3d1a6afSToby Isaac       }
6952d3d1a6afSToby Isaac     }
6953d3d1a6afSToby Isaac     newPointOffsets[0][0] = 0;
6954d3d1a6afSToby Isaac     pointMatOffsets[0][0] = 0;
6955d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
6956d3d1a6afSToby Isaac       newPointOffsets[0][p+1] += newPointOffsets[0][p];
6957d3d1a6afSToby Isaac       pointMatOffsets[0][p+1] += pointMatOffsets[0][p];
6958d3d1a6afSToby Isaac     }
695969291d52SBarry Smith     ierr = DMGetWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr);
6960d3d1a6afSToby Isaac   }
6961d3d1a6afSToby Isaac 
69626ecaa68aSToby Isaac   /* output arrays */
696369291d52SBarry Smith   ierr = DMGetWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr);
69646ecaa68aSToby Isaac 
6965d3d1a6afSToby Isaac   /* get the point-to-point matrices; construct newPoints */
6966d3d1a6afSToby Isaac   ierr = PetscSectionGetMaxDof(aSec, &maxAnchor);CHKERRQ(ierr);
6967d3d1a6afSToby Isaac   ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr);
696869291d52SBarry Smith   ierr = DMGetWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr);
696969291d52SBarry Smith   ierr = DMGetWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr);
6970d3d1a6afSToby Isaac   if (numFields) {
6971d3d1a6afSToby Isaac     for (p = 0, newP = 0; p < numPoints; p++) {
6972d3d1a6afSToby Isaac       PetscInt b    = points[2*p];
6973d3d1a6afSToby Isaac       PetscInt o    = points[2*p+1];
69744b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
6975d3d1a6afSToby Isaac 
69764b2f2278SToby Isaac       ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr);
69774b2f2278SToby Isaac       if (!bSecDof) {
69784b2f2278SToby Isaac         continue;
69794b2f2278SToby Isaac       }
6980d3d1a6afSToby Isaac       if (b >= aStart && b < aEnd) {
6981d3d1a6afSToby Isaac         ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr);
6982d3d1a6afSToby Isaac       }
6983d3d1a6afSToby Isaac       if (bDof) {
6984d3d1a6afSToby Isaac         PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q;
6985d3d1a6afSToby Isaac 
6986d3d1a6afSToby Isaac         fStart[0] = 0;
6987d3d1a6afSToby Isaac         fEnd[0]   = 0;
6988d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
6989d3d1a6afSToby Isaac           PetscInt fDof;
6990d3d1a6afSToby Isaac 
6991d3d1a6afSToby Isaac           ierr        = PetscSectionGetFieldDof(cSec, b, f, &fDof);CHKERRQ(ierr);
6992d3d1a6afSToby Isaac           fStart[f+1] = fStart[f] + fDof;
6993d3d1a6afSToby Isaac           fEnd[f+1]   = fStart[f+1];
6994d3d1a6afSToby Isaac         }
6995d3d1a6afSToby Isaac         ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr);
699636fa2b79SJed Brown         ierr = DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices);CHKERRQ(ierr);
6997d3d1a6afSToby Isaac 
6998d3d1a6afSToby Isaac         fAnchorStart[0] = 0;
6999d3d1a6afSToby Isaac         fAnchorEnd[0]   = 0;
7000d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7001d3d1a6afSToby Isaac           PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p];
7002d3d1a6afSToby Isaac 
7003d3d1a6afSToby Isaac           fAnchorStart[f+1] = fAnchorStart[f] + fDof;
7004d3d1a6afSToby Isaac           fAnchorEnd[f+1]   = fAnchorStart[f + 1];
7005d3d1a6afSToby Isaac         }
7006d3d1a6afSToby Isaac         ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr);
7007d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7008d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aOff;
7009d3d1a6afSToby Isaac 
7010d3d1a6afSToby Isaac           /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */
7011d3d1a6afSToby Isaac           newPoints[2*(newP + q)]     = a;
7012d3d1a6afSToby Isaac           newPoints[2*(newP + q) + 1] = 0;
7013302440fdSBarry Smith           ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr);
701436fa2b79SJed Brown           ierr = DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices);CHKERRQ(ierr);
7015d3d1a6afSToby Isaac         }
7016d3d1a6afSToby Isaac         newP += bDof;
7017d3d1a6afSToby Isaac 
70186ecaa68aSToby Isaac         if (outValues) {
7019d3d1a6afSToby Isaac           /* get the point-to-point submatrix */
7020d3d1a6afSToby Isaac           for (f = 0; f < numFields; f++) {
7021d3d1a6afSToby Isaac             ierr = MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p]);CHKERRQ(ierr);
7022d3d1a6afSToby Isaac           }
7023d3d1a6afSToby Isaac         }
70246ecaa68aSToby Isaac       }
7025d3d1a6afSToby Isaac       else {
7026d3d1a6afSToby Isaac         newPoints[2 * newP]     = b;
7027d3d1a6afSToby Isaac         newPoints[2 * newP + 1] = o;
7028d3d1a6afSToby Isaac         newP++;
7029d3d1a6afSToby Isaac       }
7030d3d1a6afSToby Isaac     }
7031d3d1a6afSToby Isaac   } else {
7032d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
7033d3d1a6afSToby Isaac       PetscInt b    = points[2*p];
7034d3d1a6afSToby Isaac       PetscInt o    = points[2*p+1];
70354b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7036d3d1a6afSToby Isaac 
70374b2f2278SToby Isaac       ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr);
70384b2f2278SToby Isaac       if (!bSecDof) {
70394b2f2278SToby Isaac         continue;
70404b2f2278SToby Isaac       }
7041d3d1a6afSToby Isaac       if (b >= aStart && b < aEnd) {
7042d3d1a6afSToby Isaac         ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr);
7043d3d1a6afSToby Isaac       }
7044d3d1a6afSToby Isaac       if (bDof) {
7045d3d1a6afSToby Isaac         PetscInt bEnd = 0, bAnchorEnd = 0, bOff;
7046d3d1a6afSToby Isaac 
7047d3d1a6afSToby Isaac         ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr);
704836fa2b79SJed Brown         ierr = DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices);CHKERRQ(ierr);
7049d3d1a6afSToby Isaac 
7050d3d1a6afSToby Isaac         ierr = PetscSectionGetOffset (aSec, b, &bOff);CHKERRQ(ierr);
7051d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7052d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aOff;
7053d3d1a6afSToby Isaac 
7054d3d1a6afSToby Isaac           /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */
7055d3d1a6afSToby Isaac 
7056d3d1a6afSToby Isaac           newPoints[2*(newP + q)]     = a;
7057d3d1a6afSToby Isaac           newPoints[2*(newP + q) + 1] = 0;
7058302440fdSBarry Smith           ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr);
705936fa2b79SJed Brown           ierr = DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices);CHKERRQ(ierr);
7060d3d1a6afSToby Isaac         }
7061d3d1a6afSToby Isaac         newP += bDof;
7062d3d1a6afSToby Isaac 
7063d3d1a6afSToby Isaac         /* get the point-to-point submatrix */
70646ecaa68aSToby Isaac         if (outValues) {
7065d3d1a6afSToby Isaac           ierr = MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p]);CHKERRQ(ierr);
7066d3d1a6afSToby Isaac         }
70676ecaa68aSToby Isaac       }
7068d3d1a6afSToby Isaac       else {
7069d3d1a6afSToby Isaac         newPoints[2 * newP]     = b;
7070d3d1a6afSToby Isaac         newPoints[2 * newP + 1] = o;
7071d3d1a6afSToby Isaac         newP++;
7072d3d1a6afSToby Isaac       }
7073d3d1a6afSToby Isaac     }
7074d3d1a6afSToby Isaac   }
7075d3d1a6afSToby Isaac 
70766ecaa68aSToby Isaac   if (outValues) {
707769291d52SBarry Smith     ierr = DMGetWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr);
7078580bdb30SBarry Smith     ierr = PetscArrayzero(tmpValues,newNumIndices*numIndices);CHKERRQ(ierr);
7079d3d1a6afSToby Isaac     /* multiply constraints on the right */
7080d3d1a6afSToby Isaac     if (numFields) {
7081d3d1a6afSToby Isaac       for (f = 0; f < numFields; f++) {
7082d3d1a6afSToby Isaac         PetscInt oldOff = offsets[f];
7083d3d1a6afSToby Isaac 
7084d3d1a6afSToby Isaac         for (p = 0; p < numPoints; p++) {
7085d3d1a6afSToby Isaac           PetscInt cStart = newPointOffsets[f][p];
7086d3d1a6afSToby Isaac           PetscInt b      = points[2 * p];
7087d3d1a6afSToby Isaac           PetscInt c, r, k;
7088d3d1a6afSToby Isaac           PetscInt dof;
7089d3d1a6afSToby Isaac 
7090d3d1a6afSToby Isaac           ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr);
70914b2f2278SToby Isaac           if (!dof) {
70924b2f2278SToby Isaac             continue;
70934b2f2278SToby Isaac           }
7094d3d1a6afSToby Isaac           if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) {
7095d3d1a6afSToby Isaac             PetscInt nCols         = newPointOffsets[f][p+1]-cStart;
7096d3d1a6afSToby Isaac             const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p];
7097d3d1a6afSToby Isaac 
7098d3d1a6afSToby Isaac             for (r = 0; r < numIndices; r++) {
7099d3d1a6afSToby Isaac               for (c = 0; c < nCols; c++) {
7100d3d1a6afSToby Isaac                 for (k = 0; k < dof; k++) {
71014acb8e1eSToby Isaac                   tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c];
7102d3d1a6afSToby Isaac                 }
7103d3d1a6afSToby Isaac               }
7104d3d1a6afSToby Isaac             }
7105d3d1a6afSToby Isaac           }
7106d3d1a6afSToby Isaac           else {
7107d3d1a6afSToby Isaac             /* copy this column as is */
7108d3d1a6afSToby Isaac             for (r = 0; r < numIndices; r++) {
7109d3d1a6afSToby Isaac               for (c = 0; c < dof; c++) {
7110d3d1a6afSToby Isaac                 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c];
7111d3d1a6afSToby Isaac               }
7112d3d1a6afSToby Isaac             }
7113d3d1a6afSToby Isaac           }
7114d3d1a6afSToby Isaac           oldOff += dof;
7115d3d1a6afSToby Isaac         }
7116d3d1a6afSToby Isaac       }
7117d3d1a6afSToby Isaac     }
7118d3d1a6afSToby Isaac     else {
7119d3d1a6afSToby Isaac       PetscInt oldOff = 0;
7120d3d1a6afSToby Isaac       for (p = 0; p < numPoints; p++) {
7121d3d1a6afSToby Isaac         PetscInt cStart = newPointOffsets[0][p];
7122d3d1a6afSToby Isaac         PetscInt b      = points[2 * p];
7123d3d1a6afSToby Isaac         PetscInt c, r, k;
7124d3d1a6afSToby Isaac         PetscInt dof;
7125d3d1a6afSToby Isaac 
7126d3d1a6afSToby Isaac         ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr);
71274b2f2278SToby Isaac         if (!dof) {
71284b2f2278SToby Isaac           continue;
71294b2f2278SToby Isaac         }
7130d3d1a6afSToby Isaac         if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) {
7131d3d1a6afSToby Isaac           PetscInt nCols         = newPointOffsets[0][p+1]-cStart;
7132d3d1a6afSToby Isaac           const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p];
7133d3d1a6afSToby Isaac 
7134d3d1a6afSToby Isaac           for (r = 0; r < numIndices; r++) {
7135d3d1a6afSToby Isaac             for (c = 0; c < nCols; c++) {
7136d3d1a6afSToby Isaac               for (k = 0; k < dof; k++) {
7137d3d1a6afSToby Isaac                 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k];
7138d3d1a6afSToby Isaac               }
7139d3d1a6afSToby Isaac             }
7140d3d1a6afSToby Isaac           }
7141d3d1a6afSToby Isaac         }
7142d3d1a6afSToby Isaac         else {
7143d3d1a6afSToby Isaac           /* copy this column as is */
7144d3d1a6afSToby Isaac           for (r = 0; r < numIndices; r++) {
7145d3d1a6afSToby Isaac             for (c = 0; c < dof; c++) {
7146d3d1a6afSToby Isaac               tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c];
7147d3d1a6afSToby Isaac             }
7148d3d1a6afSToby Isaac           }
7149d3d1a6afSToby Isaac         }
7150d3d1a6afSToby Isaac         oldOff += dof;
7151d3d1a6afSToby Isaac       }
7152d3d1a6afSToby Isaac     }
7153d3d1a6afSToby Isaac 
71546ecaa68aSToby Isaac     if (multiplyLeft) {
715569291d52SBarry Smith       ierr = DMGetWorkArray(dm,newNumIndices*newNumIndices,MPIU_SCALAR,&newValues);CHKERRQ(ierr);
7156580bdb30SBarry Smith       ierr = PetscArrayzero(newValues,newNumIndices*newNumIndices);CHKERRQ(ierr);
7157d3d1a6afSToby Isaac       /* multiply constraints transpose on the left */
7158d3d1a6afSToby Isaac       if (numFields) {
7159d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7160d3d1a6afSToby Isaac           PetscInt oldOff = offsets[f];
7161d3d1a6afSToby Isaac 
7162d3d1a6afSToby Isaac           for (p = 0; p < numPoints; p++) {
7163d3d1a6afSToby Isaac             PetscInt rStart = newPointOffsets[f][p];
7164d3d1a6afSToby Isaac             PetscInt b      = points[2 * p];
7165d3d1a6afSToby Isaac             PetscInt c, r, k;
7166d3d1a6afSToby Isaac             PetscInt dof;
7167d3d1a6afSToby Isaac 
7168d3d1a6afSToby Isaac             ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr);
7169d3d1a6afSToby Isaac             if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) {
7170d3d1a6afSToby Isaac               PetscInt nRows                        = newPointOffsets[f][p+1]-rStart;
7171d3d1a6afSToby Isaac               const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p];
7172d3d1a6afSToby Isaac 
7173d3d1a6afSToby Isaac               for (r = 0; r < nRows; r++) {
7174d3d1a6afSToby Isaac                 for (c = 0; c < newNumIndices; c++) {
7175d3d1a6afSToby Isaac                   for (k = 0; k < dof; k++) {
7176d3d1a6afSToby Isaac                     newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c];
7177d3d1a6afSToby Isaac                   }
7178d3d1a6afSToby Isaac                 }
7179d3d1a6afSToby Isaac               }
7180d3d1a6afSToby Isaac             }
7181d3d1a6afSToby Isaac             else {
7182d3d1a6afSToby Isaac               /* copy this row as is */
7183d3d1a6afSToby Isaac               for (r = 0; r < dof; r++) {
7184d3d1a6afSToby Isaac                 for (c = 0; c < newNumIndices; c++) {
7185d3d1a6afSToby Isaac                   newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c];
7186d3d1a6afSToby Isaac                 }
7187d3d1a6afSToby Isaac               }
7188d3d1a6afSToby Isaac             }
7189d3d1a6afSToby Isaac             oldOff += dof;
7190d3d1a6afSToby Isaac           }
7191d3d1a6afSToby Isaac         }
7192d3d1a6afSToby Isaac       }
7193d3d1a6afSToby Isaac       else {
7194d3d1a6afSToby Isaac         PetscInt oldOff = 0;
7195d3d1a6afSToby Isaac 
7196d3d1a6afSToby Isaac         for (p = 0; p < numPoints; p++) {
7197d3d1a6afSToby Isaac           PetscInt rStart = newPointOffsets[0][p];
7198d3d1a6afSToby Isaac           PetscInt b      = points[2 * p];
7199d3d1a6afSToby Isaac           PetscInt c, r, k;
7200d3d1a6afSToby Isaac           PetscInt dof;
7201d3d1a6afSToby Isaac 
7202d3d1a6afSToby Isaac           ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr);
7203d3d1a6afSToby Isaac           if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) {
7204d3d1a6afSToby Isaac             PetscInt nRows                        = newPointOffsets[0][p+1]-rStart;
7205d3d1a6afSToby Isaac             const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p];
7206d3d1a6afSToby Isaac 
7207d3d1a6afSToby Isaac             for (r = 0; r < nRows; r++) {
7208d3d1a6afSToby Isaac               for (c = 0; c < newNumIndices; c++) {
7209d3d1a6afSToby Isaac                 for (k = 0; k < dof; k++) {
7210d3d1a6afSToby Isaac                   newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c];
7211d3d1a6afSToby Isaac                 }
7212d3d1a6afSToby Isaac               }
7213d3d1a6afSToby Isaac             }
7214d3d1a6afSToby Isaac           }
7215d3d1a6afSToby Isaac           else {
7216d3d1a6afSToby Isaac             /* copy this row as is */
72179fc93327SToby Isaac             for (r = 0; r < dof; r++) {
7218d3d1a6afSToby Isaac               for (c = 0; c < newNumIndices; c++) {
7219d3d1a6afSToby Isaac                 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c];
7220d3d1a6afSToby Isaac               }
7221d3d1a6afSToby Isaac             }
7222d3d1a6afSToby Isaac           }
7223d3d1a6afSToby Isaac           oldOff += dof;
7224d3d1a6afSToby Isaac         }
7225d3d1a6afSToby Isaac       }
7226d3d1a6afSToby Isaac 
722769291d52SBarry Smith       ierr = DMRestoreWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr);
72286ecaa68aSToby Isaac     }
72296ecaa68aSToby Isaac     else {
72306ecaa68aSToby Isaac       newValues = tmpValues;
72316ecaa68aSToby Isaac     }
72326ecaa68aSToby Isaac   }
72336ecaa68aSToby Isaac 
7234d3d1a6afSToby Isaac   /* clean up */
723569291d52SBarry Smith   ierr = DMRestoreWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr);
723669291d52SBarry Smith   ierr = DMRestoreWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr);
72376ecaa68aSToby Isaac 
7238d3d1a6afSToby Isaac   if (numFields) {
7239d3d1a6afSToby Isaac     for (f = 0; f < numFields; f++) {
724069291d52SBarry Smith       ierr = DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr);
724169291d52SBarry Smith       ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr);
724269291d52SBarry Smith       ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr);
7243d3d1a6afSToby Isaac     }
7244d3d1a6afSToby Isaac   }
7245d3d1a6afSToby Isaac   else {
724669291d52SBarry Smith     ierr = DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr);
724769291d52SBarry Smith     ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr);
724869291d52SBarry Smith     ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr);
7249d3d1a6afSToby Isaac   }
7250d3d1a6afSToby Isaac   ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);
7251d3d1a6afSToby Isaac 
7252d3d1a6afSToby Isaac   /* output */
72536ecaa68aSToby Isaac   if (outPoints) {
7254d3d1a6afSToby Isaac     *outPoints = newPoints;
72556ecaa68aSToby Isaac   }
72566ecaa68aSToby Isaac   else {
725769291d52SBarry Smith     ierr = DMRestoreWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr);
72586ecaa68aSToby Isaac   }
725931620726SToby Isaac   if (outValues) {
7260d3d1a6afSToby Isaac     *outValues = newValues;
72616ecaa68aSToby Isaac   }
72626ecaa68aSToby Isaac   for (f = 0; f <= numFields; f++) {
7263d3d1a6afSToby Isaac     offsets[f] = newOffsets[f];
7264d3d1a6afSToby Isaac   }
7265d3d1a6afSToby Isaac   PetscFunctionReturn(0);
7266d3d1a6afSToby Isaac }
7267d3d1a6afSToby Isaac 
72684a1e0b3eSMatthew G. Knepley /*@C
726971f0bbf9SMatthew G. Knepley   DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections.
72707cd05799SMatthew G. Knepley 
72717cd05799SMatthew G. Knepley   Not collective
72727cd05799SMatthew G. Knepley 
72737cd05799SMatthew G. Knepley   Input Parameters:
72747cd05799SMatthew G. Knepley + dm         - The DM
727571f0bbf9SMatthew G. Knepley . section    - The PetscSection describing the points (a local section)
727671f0bbf9SMatthew G. Knepley . idxSection - The PetscSection from which to obtain indices (may be local or global)
727771f0bbf9SMatthew G. Knepley . point      - The point defining the closure
727871f0bbf9SMatthew G. Knepley - useClPerm  - Use the closure point permutation if available
72797cd05799SMatthew G. Knepley 
728071f0bbf9SMatthew G. Knepley   Output Parameters:
728171f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections
728271f0bbf9SMatthew G. Knepley . indices    - The dof indices
728371f0bbf9SMatthew G. Knepley . outOffsets - Array to write the field offsets into, or NULL
728471f0bbf9SMatthew G. Knepley - values     - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL
72857cd05799SMatthew G. Knepley 
728636fa2b79SJed Brown   Notes:
728736fa2b79SJed Brown   Must call DMPlexRestoreClosureIndices() to free allocated memory
728836fa2b79SJed Brown 
728936fa2b79SJed Brown   If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices.  The value
729036fa2b79SJed Brown   of those indices is not significant.  If idxSection is local, the constrained dofs will yield the involution -(idx+1)
729136fa2b79SJed Brown   of their index in a local vector.  A caller who does not wish to distinguish those points may recover the nonnegative
729236fa2b79SJed Brown   indices via involution, -(-(idx+1)+1)==idx.  Local indices are provided when idxSection == section, otherwise global
729336fa2b79SJed Brown   indices (with the above semantics) are implied.
72947cd05799SMatthew G. Knepley 
72957cd05799SMatthew G. Knepley   Level: advanced
72967cd05799SMatthew G. Knepley 
729736fa2b79SJed Brown .seealso DMPlexRestoreClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure(), DMGetLocalSection(), DMGetGlobalSection()
72984a1e0b3eSMatthew G. Knepley @*/
729971f0bbf9SMatthew G. Knepley PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm,
730071f0bbf9SMatthew G. Knepley                                        PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[])
73017773e69fSMatthew G. Knepley {
730271f0bbf9SMatthew G. Knepley   /* Closure ordering */
73037773e69fSMatthew G. Knepley   PetscSection        clSection;
73047773e69fSMatthew G. Knepley   IS                  clPoints;
730571f0bbf9SMatthew G. Knepley   const PetscInt     *clp;
730671f0bbf9SMatthew G. Knepley   PetscInt           *points;
730771f0bbf9SMatthew G. Knepley   const PetscInt     *clperm = NULL;
730871f0bbf9SMatthew G. Knepley   /* Dof permutation and sign flips */
73094acb8e1eSToby Isaac   const PetscInt    **perms[32] = {NULL};
731071f0bbf9SMatthew G. Knepley   const PetscScalar **flips[32] = {NULL};
731171f0bbf9SMatthew G. Knepley   PetscScalar        *valCopy   = NULL;
731271f0bbf9SMatthew G. Knepley   /* Hanging node constraints */
731371f0bbf9SMatthew G. Knepley   PetscInt           *pointsC = NULL;
731471f0bbf9SMatthew G. Knepley   PetscScalar        *valuesC = NULL;
731571f0bbf9SMatthew G. Knepley   PetscInt            NclC, NiC;
731671f0bbf9SMatthew G. Knepley 
731771f0bbf9SMatthew G. Knepley   PetscInt           *idx;
731871f0bbf9SMatthew G. Knepley   PetscInt            Nf, Ncl, Ni = 0, offsets[32], p, f;
731971f0bbf9SMatthew G. Knepley   PetscBool           isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE;
73207773e69fSMatthew G. Knepley   PetscErrorCode      ierr;
73217773e69fSMatthew G. Knepley 
732271f0bbf9SMatthew G. Knepley   PetscFunctionBeginHot;
73237773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
73247773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
732536fa2b79SJed Brown   PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3);
732671f0bbf9SMatthew G. Knepley   if (numIndices) PetscValidPointer(numIndices, 6);
732771f0bbf9SMatthew G. Knepley   if (indices)    PetscValidPointer(indices, 7);
732871f0bbf9SMatthew G. Knepley   if (outOffsets) PetscValidPointer(outOffsets, 8);
732971f0bbf9SMatthew G. Knepley   if (values)     PetscValidPointer(values, 9);
73307773e69fSMatthew G. Knepley   ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr);
73312c71b3e2SJacob Faibussowitsch   PetscCheckFalse(Nf > 31,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", Nf);
7332580bdb30SBarry Smith   ierr = PetscArrayzero(offsets, 32);CHKERRQ(ierr);
733371f0bbf9SMatthew G. Knepley   /* 1) Get points in closure */
733471f0bbf9SMatthew G. Knepley   ierr = DMPlexGetCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr);
7335c459fbc1SJed Brown   if (useClPerm) {
7336c459fbc1SJed Brown     PetscInt depth, clsize;
7337c459fbc1SJed Brown     ierr = DMPlexGetPointDepth(dm, point, &depth);CHKERRQ(ierr);
7338c459fbc1SJed Brown     for (clsize=0,p=0; p<Ncl; p++) {
7339c459fbc1SJed Brown       PetscInt dof;
7340c459fbc1SJed Brown       ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr);
7341c459fbc1SJed Brown       clsize += dof;
7342c459fbc1SJed Brown     }
7343c459fbc1SJed Brown     ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm);CHKERRQ(ierr);
7344c459fbc1SJed Brown   }
734571f0bbf9SMatthew G. Knepley   /* 2) Get number of indices on these points and field offsets from section */
734671f0bbf9SMatthew G. Knepley   for (p = 0; p < Ncl*2; p += 2) {
73477773e69fSMatthew G. Knepley     PetscInt dof, fdof;
73487773e69fSMatthew G. Knepley 
73497773e69fSMatthew G. Knepley     ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr);
73507773e69fSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
73517773e69fSMatthew G. Knepley       ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr);
73527773e69fSMatthew G. Knepley       offsets[f+1] += fdof;
73537773e69fSMatthew G. Knepley     }
735471f0bbf9SMatthew G. Knepley     Ni += dof;
73557773e69fSMatthew G. Knepley   }
73567773e69fSMatthew G. Knepley   for (f = 1; f < Nf; ++f) offsets[f+1] += offsets[f];
73572c71b3e2SJacob Faibussowitsch   PetscCheckFalse(Nf && offsets[Nf] != Ni,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", offsets[Nf], Ni);
735871f0bbf9SMatthew G. Knepley   /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */
735971f0bbf9SMatthew G. Knepley   for (f = 0; f < PetscMax(1, Nf); ++f) {
736071f0bbf9SMatthew G. Knepley     if (Nf) {ierr = PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);}
736171f0bbf9SMatthew G. Knepley     else    {ierr = PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);}
736271f0bbf9SMatthew G. Knepley     /* may need to apply sign changes to the element matrix */
736371f0bbf9SMatthew G. Knepley     if (values && flips[f]) {
736471f0bbf9SMatthew G. Knepley       PetscInt foffset = offsets[f];
73656ecaa68aSToby Isaac 
736671f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
736771f0bbf9SMatthew G. Knepley         PetscInt           pnt  = points[2*p], fdof;
736871f0bbf9SMatthew G. Knepley         const PetscScalar *flip = flips[f] ? flips[f][p] : NULL;
736971f0bbf9SMatthew G. Knepley 
737071f0bbf9SMatthew G. Knepley         if (!Nf) {ierr = PetscSectionGetDof(section, pnt, &fdof);CHKERRQ(ierr);}
737171f0bbf9SMatthew G. Knepley         else     {ierr = PetscSectionGetFieldDof(section, pnt, f, &fdof);CHKERRQ(ierr);}
737271f0bbf9SMatthew G. Knepley         if (flip) {
737371f0bbf9SMatthew G. Knepley           PetscInt i, j, k;
737471f0bbf9SMatthew G. Knepley 
737571f0bbf9SMatthew G. Knepley           if (!valCopy) {
737671f0bbf9SMatthew G. Knepley             ierr = DMGetWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy);CHKERRQ(ierr);
737771f0bbf9SMatthew G. Knepley             for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j];
737871f0bbf9SMatthew G. Knepley             *values = valCopy;
737971f0bbf9SMatthew G. Knepley           }
738071f0bbf9SMatthew G. Knepley           for (i = 0; i < fdof; ++i) {
738171f0bbf9SMatthew G. Knepley             PetscScalar fval = flip[i];
738271f0bbf9SMatthew G. Knepley 
738371f0bbf9SMatthew G. Knepley             for (k = 0; k < Ni; ++k) {
738471f0bbf9SMatthew G. Knepley               valCopy[Ni * (foffset + i) + k] *= fval;
738571f0bbf9SMatthew G. Knepley               valCopy[Ni * k + (foffset + i)] *= fval;
73866ecaa68aSToby Isaac             }
73876ecaa68aSToby Isaac           }
738871f0bbf9SMatthew G. Knepley         }
738971f0bbf9SMatthew G. Knepley         foffset += fdof;
739071f0bbf9SMatthew G. Knepley       }
739171f0bbf9SMatthew G. Knepley     }
739271f0bbf9SMatthew G. Knepley   }
739371f0bbf9SMatthew G. Knepley   /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */
739471f0bbf9SMatthew G. Knepley   ierr = DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE);CHKERRQ(ierr);
739571f0bbf9SMatthew G. Knepley   if (NclC) {
739671f0bbf9SMatthew G. Knepley     if (valCopy) {ierr = DMRestoreWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy);CHKERRQ(ierr);}
739771f0bbf9SMatthew G. Knepley     for (f = 0; f < PetscMax(1, Nf); ++f) {
739871f0bbf9SMatthew G. Knepley       if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);}
739971f0bbf9SMatthew G. Knepley       else    {ierr = PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);}
740071f0bbf9SMatthew G. Knepley     }
740171f0bbf9SMatthew G. Knepley     for (f = 0; f < PetscMax(1, Nf); ++f) {
740271f0bbf9SMatthew G. Knepley       if (Nf) {ierr = PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f]);CHKERRQ(ierr);}
740371f0bbf9SMatthew G. Knepley       else    {ierr = PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f]);CHKERRQ(ierr);}
740471f0bbf9SMatthew G. Knepley     }
740571f0bbf9SMatthew G. Knepley     ierr = DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr);
740671f0bbf9SMatthew G. Knepley     Ncl     = NclC;
740771f0bbf9SMatthew G. Knepley     Ni      = NiC;
740871f0bbf9SMatthew G. Knepley     points  = pointsC;
740971f0bbf9SMatthew G. Knepley     if (values) *values = valuesC;
741071f0bbf9SMatthew G. Knepley   }
741171f0bbf9SMatthew G. Knepley   /* 5) Calculate indices */
741271f0bbf9SMatthew G. Knepley   ierr = DMGetWorkArray(dm, Ni, MPIU_INT, &idx);CHKERRQ(ierr);
741371f0bbf9SMatthew G. Knepley   if (Nf) {
741471f0bbf9SMatthew G. Knepley     PetscInt  idxOff;
741571f0bbf9SMatthew G. Knepley     PetscBool useFieldOffsets;
741671f0bbf9SMatthew G. Knepley 
741771f0bbf9SMatthew G. Knepley     if (outOffsets) {for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f];}
741871f0bbf9SMatthew G. Knepley     ierr = PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets);CHKERRQ(ierr);
741971f0bbf9SMatthew G. Knepley     if (useFieldOffsets) {
742071f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
742171f0bbf9SMatthew G. Knepley         const PetscInt pnt = points[p*2];
742271f0bbf9SMatthew G. Knepley 
742371f0bbf9SMatthew G. Knepley         ierr = DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx);CHKERRQ(ierr);
74247773e69fSMatthew G. Knepley       }
74257773e69fSMatthew G. Knepley     } else {
742671f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
742771f0bbf9SMatthew G. Knepley         const PetscInt pnt = points[p*2];
742871f0bbf9SMatthew G. Knepley 
742971f0bbf9SMatthew G. Knepley         ierr = PetscSectionGetOffset(idxSection, pnt, &idxOff);CHKERRQ(ierr);
743071f0bbf9SMatthew G. Knepley         /* Note that we pass a local section even though we're using global offsets.  This is because global sections do
743171f0bbf9SMatthew G. Knepley          * not (at the time of this writing) have fields set. They probably should, in which case we would pass the
743271f0bbf9SMatthew G. Knepley          * global section. */
743371f0bbf9SMatthew G. Knepley         ierr = DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx);CHKERRQ(ierr);
743471f0bbf9SMatthew G. Knepley       }
743571f0bbf9SMatthew G. Knepley     }
743671f0bbf9SMatthew G. Knepley   } else {
743771f0bbf9SMatthew G. Knepley     PetscInt off = 0, idxOff;
743871f0bbf9SMatthew G. Knepley 
743971f0bbf9SMatthew G. Knepley     for (p = 0; p < Ncl; ++p) {
744071f0bbf9SMatthew G. Knepley       const PetscInt  pnt  = points[p*2];
74414acb8e1eSToby Isaac       const PetscInt *perm = perms[0] ? perms[0][p] : NULL;
74424acb8e1eSToby Isaac 
744371f0bbf9SMatthew G. Knepley       ierr = PetscSectionGetOffset(idxSection, pnt, &idxOff);CHKERRQ(ierr);
744471f0bbf9SMatthew G. Knepley       /* Note that we pass a local section even though we're using global offsets.  This is because global sections do
744571f0bbf9SMatthew G. Knepley        * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */
744671f0bbf9SMatthew G. Knepley       ierr = DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx);CHKERRQ(ierr);
74477773e69fSMatthew G. Knepley     }
74487773e69fSMatthew G. Knepley   }
744971f0bbf9SMatthew G. Knepley   /* 6) Cleanup */
745071f0bbf9SMatthew G. Knepley   for (f = 0; f < PetscMax(1, Nf); ++f) {
745171f0bbf9SMatthew G. Knepley     if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);}
745271f0bbf9SMatthew G. Knepley     else    {ierr = PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);}
74534acb8e1eSToby Isaac   }
745471f0bbf9SMatthew G. Knepley   if (NclC) {
745571f0bbf9SMatthew G. Knepley     ierr = DMRestoreWorkArray(dm, NclC*2, MPIU_INT, &pointsC);CHKERRQ(ierr);
74567773e69fSMatthew G. Knepley   } else {
745771f0bbf9SMatthew G. Knepley     ierr = DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr);
74587773e69fSMatthew G. Knepley   }
745971f0bbf9SMatthew G. Knepley 
746071f0bbf9SMatthew G. Knepley   if (numIndices) *numIndices = Ni;
746171f0bbf9SMatthew G. Knepley   if (indices)    *indices    = idx;
74627773e69fSMatthew G. Knepley   PetscFunctionReturn(0);
74637773e69fSMatthew G. Knepley }
74647773e69fSMatthew G. Knepley 
74657cd05799SMatthew G. Knepley /*@C
746671f0bbf9SMatthew G. Knepley   DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections.
74677cd05799SMatthew G. Knepley 
74687cd05799SMatthew G. Knepley   Not collective
74697cd05799SMatthew G. Knepley 
74707cd05799SMatthew G. Knepley   Input Parameters:
74717cd05799SMatthew G. Knepley + dm         - The DM
747271f0bbf9SMatthew G. Knepley . section    - The PetscSection describing the points (a local section)
747371f0bbf9SMatthew G. Knepley . idxSection - The PetscSection from which to obtain indices (may be local or global)
747471f0bbf9SMatthew G. Knepley . point      - The point defining the closure
747571f0bbf9SMatthew G. Knepley - useClPerm  - Use the closure point permutation if available
747671f0bbf9SMatthew G. Knepley 
747771f0bbf9SMatthew G. Knepley   Output Parameters:
747871f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections
747971f0bbf9SMatthew G. Knepley . indices    - The dof indices
748071f0bbf9SMatthew G. Knepley . outOffsets - Array to write the field offsets into, or NULL
748171f0bbf9SMatthew G. Knepley - values     - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL
748271f0bbf9SMatthew G. Knepley 
748371f0bbf9SMatthew G. Knepley   Notes:
748471f0bbf9SMatthew G. Knepley   If values were modified, the user is responsible for calling DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values).
748571f0bbf9SMatthew G. Knepley 
748671f0bbf9SMatthew G. Knepley   If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices.  The value
748771f0bbf9SMatthew G. Knepley   of those indices is not significant.  If idxSection is local, the constrained dofs will yield the involution -(idx+1)
748871f0bbf9SMatthew G. Knepley   of their index in a local vector.  A caller who does not wish to distinguish those points may recover the nonnegative
748971f0bbf9SMatthew G. Knepley   indices via involution, -(-(idx+1)+1)==idx.  Local indices are provided when idxSection == section, otherwise global
749071f0bbf9SMatthew G. Knepley   indices (with the above semantics) are implied.
74917cd05799SMatthew G. Knepley 
74927cd05799SMatthew G. Knepley   Level: advanced
74937cd05799SMatthew G. Knepley 
749471f0bbf9SMatthew G. Knepley .seealso DMPlexGetClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure(), DMGetLocalSection(), DMGetGlobalSection()
74957cd05799SMatthew G. Knepley @*/
749671f0bbf9SMatthew G. Knepley PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm,
749771f0bbf9SMatthew G. Knepley                                            PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[])
74987773e69fSMatthew G. Knepley {
74997773e69fSMatthew G. Knepley   PetscErrorCode ierr;
75007773e69fSMatthew G. Knepley 
75017773e69fSMatthew G. Knepley   PetscFunctionBegin;
75027773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7503064a246eSJacob Faibussowitsch   PetscValidPointer(indices, 7);
750469291d52SBarry Smith   ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, indices);CHKERRQ(ierr);
75057773e69fSMatthew G. Knepley   PetscFunctionReturn(0);
75067773e69fSMatthew G. Knepley }
75077773e69fSMatthew G. Knepley 
75087f5d1fdeSMatthew G. Knepley /*@C
75097f5d1fdeSMatthew G. Knepley   DMPlexMatSetClosure - Set an array of the values on the closure of 'point'
75107f5d1fdeSMatthew G. Knepley 
75117f5d1fdeSMatthew G. Knepley   Not collective
75127f5d1fdeSMatthew G. Knepley 
75137f5d1fdeSMatthew G. Knepley   Input Parameters:
75147f5d1fdeSMatthew G. Knepley + dm - The DM
7515ebd6d717SJed Brown . section - The section describing the layout in v, or NULL to use the default section
7516ebd6d717SJed Brown . globalSection - The section describing the layout in v, or NULL to use the default global section
75177f5d1fdeSMatthew G. Knepley . A - The matrix
7518eaf898f9SPatrick Sanan . point - The point in the DM
75197f5d1fdeSMatthew G. Knepley . values - The array of values
75207f5d1fdeSMatthew G. Knepley - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions
75217f5d1fdeSMatthew G. Knepley 
75227f5d1fdeSMatthew G. Knepley   Fortran Notes:
75237f5d1fdeSMatthew G. Knepley   This routine is only available in Fortran 90, and you must include petsc.h90 in your code.
75247f5d1fdeSMatthew G. Knepley 
75257f5d1fdeSMatthew G. Knepley   Level: intermediate
75267f5d1fdeSMatthew G. Knepley 
75274a1e0b3eSMatthew G. Knepley .seealso DMPlexMatSetClosureGeneral(), DMPlexVecGetClosure(), DMPlexVecSetClosure()
75287f5d1fdeSMatthew G. Knepley @*/
75297c1f9639SMatthew G Knepley PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
7530552f7358SJed Brown {
7531552f7358SJed Brown   DM_Plex           *mesh = (DM_Plex*) dm->data;
7532552f7358SJed Brown   PetscInt          *indices;
753371f0bbf9SMatthew G. Knepley   PetscInt           numIndices;
753471f0bbf9SMatthew G. Knepley   const PetscScalar *valuesOrig = values;
7535552f7358SJed Brown   PetscErrorCode     ierr;
7536552f7358SJed Brown 
7537552f7358SJed Brown   PetscFunctionBegin;
7538552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
753992fd8e1eSJed Brown   if (!section) {ierr = DMGetLocalSection(dm, &section);CHKERRQ(ierr);}
75403dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
7541e87a4003SBarry Smith   if (!globalSection) {ierr = DMGetGlobalSection(dm, &globalSection);CHKERRQ(ierr);}
75423dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3);
75433dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 4);
7544552f7358SJed Brown 
754571f0bbf9SMatthew G. Knepley   ierr = DMPlexGetClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr);
75460d644c17SKarl Rupp 
7547b0ecff45SMatthew G. Knepley   if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr);}
75484a1e0b3eSMatthew G. Knepley   ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode);
7549552f7358SJed Brown   if (ierr) {
7550552f7358SJed Brown     PetscMPIInt    rank;
7551552f7358SJed Brown     PetscErrorCode ierr2;
7552552f7358SJed Brown 
755355b25c41SPierre Jolivet     ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2);
7554e4b003c7SBarry Smith     ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2);
7555b0ecff45SMatthew G. Knepley     ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr2);
755671f0bbf9SMatthew G. Knepley     ierr2 = DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr2);
755771f0bbf9SMatthew G. Knepley     if (values != valuesOrig) {ierr2 = DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values);CHKERRQ(ierr2);}
7558c3e24edfSBarry Smith     SETERRQ(PetscObjectComm((PetscObject)dm),ierr,"Not possible to set matrix values");
7559552f7358SJed Brown   }
75604a1e0b3eSMatthew G. Knepley   if (mesh->printFEM > 1) {
75614a1e0b3eSMatthew G. Knepley     PetscInt i;
75624a1e0b3eSMatthew G. Knepley     ierr = PetscPrintf(PETSC_COMM_SELF, "  Indices:");CHKERRQ(ierr);
75634a1e0b3eSMatthew G. Knepley     for (i = 0; i < numIndices; ++i) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", indices[i]);CHKERRQ(ierr);}
75644a1e0b3eSMatthew G. Knepley     ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr);
75654a1e0b3eSMatthew G. Knepley   }
756671f0bbf9SMatthew G. Knepley 
756771f0bbf9SMatthew G. Knepley   ierr = DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr);
756871f0bbf9SMatthew G. Knepley   if (values != valuesOrig) {ierr = DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values);CHKERRQ(ierr);}
756971f0bbf9SMatthew G. Knepley   PetscFunctionReturn(0);
75704acb8e1eSToby Isaac }
757171f0bbf9SMatthew G. Knepley 
75724a1e0b3eSMatthew G. Knepley /*@C
75734a1e0b3eSMatthew G. Knepley   DMPlexMatSetClosure - Set an array of the values on the closure of 'point' using a different row and column section
75744a1e0b3eSMatthew G. Knepley 
75754a1e0b3eSMatthew G. Knepley   Not collective
75764a1e0b3eSMatthew G. Knepley 
75774a1e0b3eSMatthew G. Knepley   Input Parameters:
75784a1e0b3eSMatthew G. Knepley + dmRow - The DM for the row fields
75794a1e0b3eSMatthew G. Knepley . sectionRow - The section describing the layout, or NULL to use the default section in dmRow
75804a1e0b3eSMatthew G. Knepley . globalSectionRow - The section describing the layout, or NULL to use the default global section in dmRow
75814a1e0b3eSMatthew G. Knepley . dmCol - The DM for the column fields
75824a1e0b3eSMatthew G. Knepley . sectionCol - The section describing the layout, or NULL to use the default section in dmCol
75834a1e0b3eSMatthew G. Knepley . globalSectionCol - The section describing the layout, or NULL to use the default global section in dmCol
75844a1e0b3eSMatthew G. Knepley . A - The matrix
75854a1e0b3eSMatthew G. Knepley . point - The point in the DMs
75864a1e0b3eSMatthew G. Knepley . values - The array of values
75874a1e0b3eSMatthew G. Knepley - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions
75884a1e0b3eSMatthew G. Knepley 
75894a1e0b3eSMatthew G. Knepley   Level: intermediate
75904a1e0b3eSMatthew G. Knepley 
75914a1e0b3eSMatthew G. Knepley .seealso DMPlexMatSetClosure(), DMPlexVecGetClosure(), DMPlexVecSetClosure()
75924a1e0b3eSMatthew G. Knepley @*/
759371f0bbf9SMatthew G. Knepley PetscErrorCode DMPlexMatSetClosureGeneral(DM dmRow, PetscSection sectionRow, PetscSection globalSectionRow, DM dmCol, PetscSection sectionCol, PetscSection globalSectionCol, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
759471f0bbf9SMatthew G. Knepley {
759571f0bbf9SMatthew G. Knepley   DM_Plex           *mesh = (DM_Plex*) dmRow->data;
759671f0bbf9SMatthew G. Knepley   PetscInt          *indicesRow, *indicesCol;
759771f0bbf9SMatthew G. Knepley   PetscInt           numIndicesRow, numIndicesCol;
759871f0bbf9SMatthew G. Knepley   const PetscScalar *valuesOrig = values;
759971f0bbf9SMatthew G. Knepley   PetscErrorCode     ierr;
760071f0bbf9SMatthew G. Knepley 
760171f0bbf9SMatthew G. Knepley   PetscFunctionBegin;
760271f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1);
760371f0bbf9SMatthew G. Knepley   if (!sectionRow) {ierr = DMGetLocalSection(dmRow, &sectionRow);CHKERRQ(ierr);}
760471f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2);
760571f0bbf9SMatthew G. Knepley   if (!globalSectionRow) {ierr = DMGetGlobalSection(dmRow, &globalSectionRow);CHKERRQ(ierr);}
760671f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3);
760771f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(dmCol, DM_CLASSID, 4);
760871f0bbf9SMatthew G. Knepley   if (!sectionCol) {ierr = DMGetLocalSection(dmCol, &sectionCol);CHKERRQ(ierr);}
760971f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 5);
761071f0bbf9SMatthew G. Knepley   if (!globalSectionCol) {ierr = DMGetGlobalSection(dmCol, &globalSectionCol);CHKERRQ(ierr);}
761171f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 6);
761271f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 7);
761371f0bbf9SMatthew G. Knepley 
761471f0bbf9SMatthew G. Knepley   ierr = DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr);
761571f0bbf9SMatthew G. Knepley   ierr = DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values);CHKERRQ(ierr);
761671f0bbf9SMatthew G. Knepley 
761771f0bbf9SMatthew G. Knepley   if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values);CHKERRQ(ierr);}
76184a1e0b3eSMatthew G. Knepley   ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode);
761971f0bbf9SMatthew G. Knepley   if (ierr) {
762071f0bbf9SMatthew G. Knepley     PetscMPIInt    rank;
762171f0bbf9SMatthew G. Knepley     PetscErrorCode ierr2;
762271f0bbf9SMatthew G. Knepley 
762355b25c41SPierre Jolivet     ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2);
762471f0bbf9SMatthew G. Knepley     ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2);
762571f0bbf9SMatthew G. Knepley     ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values);CHKERRQ(ierr2);
762671f0bbf9SMatthew G. Knepley     ierr2 = DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr2);
762771f0bbf9SMatthew G. Knepley     ierr2 = DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr2);
762871f0bbf9SMatthew G. Knepley     if (values != valuesOrig) {ierr2 = DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values);CHKERRQ(ierr2);}
762971f0bbf9SMatthew G. Knepley     CHKERRQ(ierr);
7630d3d1a6afSToby Isaac   }
763171f0bbf9SMatthew G. Knepley 
763271f0bbf9SMatthew G. Knepley   ierr = DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr);
763371f0bbf9SMatthew G. Knepley   ierr = DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values);CHKERRQ(ierr);
763471f0bbf9SMatthew G. Knepley   if (values != valuesOrig) {ierr = DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values);CHKERRQ(ierr);}
7635552f7358SJed Brown   PetscFunctionReturn(0);
7636552f7358SJed Brown }
7637552f7358SJed Brown 
7638de41b84cSMatthew G. Knepley PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
7639de41b84cSMatthew G. Knepley {
7640de41b84cSMatthew G. Knepley   DM_Plex        *mesh   = (DM_Plex*) dmf->data;
7641de41b84cSMatthew G. Knepley   PetscInt       *fpoints = NULL, *ftotpoints = NULL;
7642de41b84cSMatthew G. Knepley   PetscInt       *cpoints = NULL;
7643de41b84cSMatthew G. Knepley   PetscInt       *findices, *cindices;
764417c0192bSMatthew G. Knepley   const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */
7645de41b84cSMatthew G. Knepley   PetscInt        foffsets[32], coffsets[32];
7646412e9a14SMatthew G. Knepley   DMPolytopeType  ct;
76474ca5e9f5SMatthew G. Knepley   PetscInt        numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f;
7648de41b84cSMatthew G. Knepley   PetscErrorCode  ierr;
7649de41b84cSMatthew G. Knepley 
7650de41b84cSMatthew G. Knepley   PetscFunctionBegin;
7651de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 1);
7652de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 4);
765392fd8e1eSJed Brown   if (!fsection) {ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);}
7654de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2);
765592fd8e1eSJed Brown   if (!csection) {ierr = DMGetLocalSection(dmc, &csection);CHKERRQ(ierr);}
7656de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5);
7657e87a4003SBarry Smith   if (!globalFSection) {ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);}
7658de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3);
7659e87a4003SBarry Smith   if (!globalCSection) {ierr = DMGetGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);}
7660de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6);
7661de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 7);
7662de41b84cSMatthew G. Knepley   ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr);
76632c71b3e2SJacob Faibussowitsch   PetscCheckFalse(numFields > 31,PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields);
7664580bdb30SBarry Smith   ierr = PetscArrayzero(foffsets, 32);CHKERRQ(ierr);
7665580bdb30SBarry Smith   ierr = PetscArrayzero(coffsets, 32);CHKERRQ(ierr);
7666de41b84cSMatthew G. Knepley   /* Column indices */
7667de41b84cSMatthew G. Knepley   ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr);
76684ca5e9f5SMatthew G. Knepley   maxFPoints = numCPoints;
7669de41b84cSMatthew G. Knepley   /* Compress out points not in the section */
7670de41b84cSMatthew G. Knepley   /*   TODO: Squeeze out points with 0 dof as well */
7671de41b84cSMatthew G. Knepley   ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr);
7672de41b84cSMatthew G. Knepley   for (p = 0, q = 0; p < numCPoints*2; p += 2) {
7673de41b84cSMatthew G. Knepley     if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) {
7674de41b84cSMatthew G. Knepley       cpoints[q*2]   = cpoints[p];
7675de41b84cSMatthew G. Knepley       cpoints[q*2+1] = cpoints[p+1];
7676de41b84cSMatthew G. Knepley       ++q;
7677de41b84cSMatthew G. Knepley     }
7678de41b84cSMatthew G. Knepley   }
7679de41b84cSMatthew G. Knepley   numCPoints = q;
7680de41b84cSMatthew G. Knepley   for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) {
7681de41b84cSMatthew G. Knepley     PetscInt fdof;
7682de41b84cSMatthew G. Knepley 
7683de41b84cSMatthew G. Knepley     ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr);
76844ca5e9f5SMatthew G. Knepley     if (!dof) continue;
7685de41b84cSMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
7686de41b84cSMatthew G. Knepley       ierr           = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr);
7687de41b84cSMatthew G. Knepley       coffsets[f+1] += fdof;
7688de41b84cSMatthew G. Knepley     }
7689de41b84cSMatthew G. Knepley     numCIndices += dof;
7690de41b84cSMatthew G. Knepley   }
7691de41b84cSMatthew G. Knepley   for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f];
7692de41b84cSMatthew G. Knepley   /* Row indices */
7693412e9a14SMatthew G. Knepley   ierr = DMPlexGetCellType(dmc, point, &ct);CHKERRQ(ierr);
7694412e9a14SMatthew G. Knepley   {
7695012bc364SMatthew G. Knepley     DMPlexTransform tr;
7696012bc364SMatthew G. Knepley     DMPolytopeType *rct;
7697012bc364SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt, Nt;
7698012bc364SMatthew G. Knepley 
7699012bc364SMatthew G. Knepley     ierr = DMPlexTransformCreate(PETSC_COMM_SELF, &tr);CHKERRQ(ierr);
7700012bc364SMatthew G. Knepley     ierr = DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR);CHKERRQ(ierr);
7701012bc364SMatthew G. Knepley     ierr = DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
7702012bc364SMatthew G. Knepley     numSubcells = rsize[Nt-1];
7703012bc364SMatthew G. Knepley     ierr = DMPlexTransformDestroy(&tr);CHKERRQ(ierr);
7704412e9a14SMatthew G. Knepley   }
770569291d52SBarry Smith   ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr);
7706de41b84cSMatthew G. Knepley   for (r = 0, q = 0; r < numSubcells; ++r) {
7707de41b84cSMatthew G. Knepley     /* TODO Map from coarse to fine cells */
7708de41b84cSMatthew G. Knepley     ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr);
7709de41b84cSMatthew G. Knepley     /* Compress out points not in the section */
7710de41b84cSMatthew G. Knepley     ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr);
7711de41b84cSMatthew G. Knepley     for (p = 0; p < numFPoints*2; p += 2) {
7712de41b84cSMatthew G. Knepley       if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) {
77134ca5e9f5SMatthew G. Knepley         ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr);
77144ca5e9f5SMatthew G. Knepley         if (!dof) continue;
77154ca5e9f5SMatthew G. Knepley         for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break;
77164ca5e9f5SMatthew G. Knepley         if (s < q) continue;
7717de41b84cSMatthew G. Knepley         ftotpoints[q*2]   = fpoints[p];
7718de41b84cSMatthew G. Knepley         ftotpoints[q*2+1] = fpoints[p+1];
7719de41b84cSMatthew G. Knepley         ++q;
7720de41b84cSMatthew G. Knepley       }
7721de41b84cSMatthew G. Knepley     }
7722de41b84cSMatthew G. Knepley     ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr);
7723de41b84cSMatthew G. Knepley   }
7724de41b84cSMatthew G. Knepley   numFPoints = q;
7725de41b84cSMatthew G. Knepley   for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) {
7726de41b84cSMatthew G. Knepley     PetscInt fdof;
7727de41b84cSMatthew G. Knepley 
7728de41b84cSMatthew G. Knepley     ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr);
77294ca5e9f5SMatthew G. Knepley     if (!dof) continue;
7730de41b84cSMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
7731de41b84cSMatthew G. Knepley       ierr           = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr);
7732de41b84cSMatthew G. Knepley       foffsets[f+1] += fdof;
7733de41b84cSMatthew G. Knepley     }
7734de41b84cSMatthew G. Knepley     numFIndices += dof;
7735de41b84cSMatthew G. Knepley   }
7736de41b84cSMatthew G. Knepley   for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f];
7737de41b84cSMatthew G. Knepley 
77382c71b3e2SJacob Faibussowitsch   PetscCheckFalse(numFields && foffsets[numFields] != numFIndices,PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices);
77392c71b3e2SJacob Faibussowitsch   PetscCheckFalse(numFields && coffsets[numFields] != numCIndices,PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices);
774069291d52SBarry Smith   ierr = DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr);
774169291d52SBarry Smith   ierr = DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr);
7742de41b84cSMatthew G. Knepley   if (numFields) {
77434acb8e1eSToby Isaac     const PetscInt **permsF[32] = {NULL};
77444acb8e1eSToby Isaac     const PetscInt **permsC[32] = {NULL};
77454acb8e1eSToby Isaac 
77464acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
77474acb8e1eSToby Isaac       ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr);
77484acb8e1eSToby Isaac       ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr);
7749de41b84cSMatthew G. Knepley     }
77504acb8e1eSToby Isaac     for (p = 0; p < numFPoints; p++) {
77514acb8e1eSToby Isaac       ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr);
775236fa2b79SJed Brown       ierr = DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices);CHKERRQ(ierr);
77534acb8e1eSToby Isaac     }
77544acb8e1eSToby Isaac     for (p = 0; p < numCPoints; p++) {
77554acb8e1eSToby Isaac       ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr);
775636fa2b79SJed Brown       ierr = DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices);CHKERRQ(ierr);
77574acb8e1eSToby Isaac     }
77584acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
77594acb8e1eSToby Isaac       ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr);
77604acb8e1eSToby Isaac       ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr);
7761de41b84cSMatthew G. Knepley     }
7762de41b84cSMatthew G. Knepley   } else {
77634acb8e1eSToby Isaac     const PetscInt **permsF = NULL;
77644acb8e1eSToby Isaac     const PetscInt **permsC = NULL;
77654acb8e1eSToby Isaac 
77664acb8e1eSToby Isaac     ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr);
77674acb8e1eSToby Isaac     ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr);
77684acb8e1eSToby Isaac     for (p = 0, off = 0; p < numFPoints; p++) {
77694acb8e1eSToby Isaac       const PetscInt *perm = permsF ? permsF[p] : NULL;
77704acb8e1eSToby Isaac 
77714acb8e1eSToby Isaac       ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr);
777236fa2b79SJed Brown       ierr = DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices);CHKERRQ(ierr);
7773de41b84cSMatthew G. Knepley     }
77744acb8e1eSToby Isaac     for (p = 0, off = 0; p < numCPoints; p++) {
77754acb8e1eSToby Isaac       const PetscInt *perm = permsC ? permsC[p] : NULL;
77764acb8e1eSToby Isaac 
77774acb8e1eSToby Isaac       ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr);
777836fa2b79SJed Brown       ierr = DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices);CHKERRQ(ierr);
7779de41b84cSMatthew G. Knepley     }
77804acb8e1eSToby Isaac     ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr);
77814acb8e1eSToby Isaac     ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr);
7782de41b84cSMatthew G. Knepley   }
7783de41b84cSMatthew G. Knepley   if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr);}
77844acb8e1eSToby Isaac   /* TODO: flips */
7785de41b84cSMatthew G. Knepley   ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode);
7786de41b84cSMatthew G. Knepley   if (ierr) {
7787de41b84cSMatthew G. Knepley     PetscMPIInt    rank;
7788de41b84cSMatthew G. Knepley     PetscErrorCode ierr2;
7789de41b84cSMatthew G. Knepley 
779055b25c41SPierre Jolivet     ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2);
7791e4b003c7SBarry Smith     ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2);
7792de41b84cSMatthew G. Knepley     ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr2);
779369291d52SBarry Smith     ierr2 = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr2);
779469291d52SBarry Smith     ierr2 = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr2);
7795de41b84cSMatthew G. Knepley     CHKERRQ(ierr);
7796de41b84cSMatthew G. Knepley   }
779769291d52SBarry Smith   ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr);
7798de41b84cSMatthew G. Knepley   ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr);
779969291d52SBarry Smith   ierr = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr);
780069291d52SBarry Smith   ierr = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr);
7801de41b84cSMatthew G. Knepley   PetscFunctionReturn(0);
7802de41b84cSMatthew G. Knepley }
7803de41b84cSMatthew G. Knepley 
78047c927364SMatthew G. Knepley PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[])
78057c927364SMatthew G. Knepley {
78067c927364SMatthew G. Knepley   PetscInt      *fpoints = NULL, *ftotpoints = NULL;
78077c927364SMatthew G. Knepley   PetscInt      *cpoints = NULL;
78087c927364SMatthew G. Knepley   PetscInt       foffsets[32], coffsets[32];
780917c0192bSMatthew G. Knepley   const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */
7810412e9a14SMatthew G. Knepley   DMPolytopeType ct;
78117c927364SMatthew G. Knepley   PetscInt       numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f;
78127c927364SMatthew G. Knepley   PetscErrorCode ierr;
78137c927364SMatthew G. Knepley 
78147c927364SMatthew G. Knepley   PetscFunctionBegin;
78157c927364SMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 1);
78167c927364SMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 4);
781792fd8e1eSJed Brown   if (!fsection) {ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);}
78187c927364SMatthew G. Knepley   PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2);
781992fd8e1eSJed Brown   if (!csection) {ierr = DMGetLocalSection(dmc, &csection);CHKERRQ(ierr);}
78207c927364SMatthew G. Knepley   PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5);
7821e87a4003SBarry Smith   if (!globalFSection) {ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);}
78227c927364SMatthew G. Knepley   PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3);
7823e87a4003SBarry Smith   if (!globalCSection) {ierr = DMGetGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);}
78247c927364SMatthew G. Knepley   PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6);
78257c927364SMatthew G. Knepley   ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr);
78262c71b3e2SJacob Faibussowitsch   PetscCheckFalse(numFields > 31,PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields);
7827580bdb30SBarry Smith   ierr = PetscArrayzero(foffsets, 32);CHKERRQ(ierr);
7828580bdb30SBarry Smith   ierr = PetscArrayzero(coffsets, 32);CHKERRQ(ierr);
78297c927364SMatthew G. Knepley   /* Column indices */
78307c927364SMatthew G. Knepley   ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr);
78317c927364SMatthew G. Knepley   maxFPoints = numCPoints;
78327c927364SMatthew G. Knepley   /* Compress out points not in the section */
78337c927364SMatthew G. Knepley   /*   TODO: Squeeze out points with 0 dof as well */
78347c927364SMatthew G. Knepley   ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr);
78357c927364SMatthew G. Knepley   for (p = 0, q = 0; p < numCPoints*2; p += 2) {
78367c927364SMatthew G. Knepley     if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) {
78377c927364SMatthew G. Knepley       cpoints[q*2]   = cpoints[p];
78387c927364SMatthew G. Knepley       cpoints[q*2+1] = cpoints[p+1];
78397c927364SMatthew G. Knepley       ++q;
78407c927364SMatthew G. Knepley     }
78417c927364SMatthew G. Knepley   }
78427c927364SMatthew G. Knepley   numCPoints = q;
78437c927364SMatthew G. Knepley   for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) {
78447c927364SMatthew G. Knepley     PetscInt fdof;
78457c927364SMatthew G. Knepley 
78467c927364SMatthew G. Knepley     ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr);
78477c927364SMatthew G. Knepley     if (!dof) continue;
78487c927364SMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
78497c927364SMatthew G. Knepley       ierr           = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr);
78507c927364SMatthew G. Knepley       coffsets[f+1] += fdof;
78517c927364SMatthew G. Knepley     }
78527c927364SMatthew G. Knepley     numCIndices += dof;
78537c927364SMatthew G. Knepley   }
78547c927364SMatthew G. Knepley   for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f];
78557c927364SMatthew G. Knepley   /* Row indices */
7856412e9a14SMatthew G. Knepley   ierr = DMPlexGetCellType(dmc, point, &ct);CHKERRQ(ierr);
7857412e9a14SMatthew G. Knepley   {
7858012bc364SMatthew G. Knepley     DMPlexTransform tr;
7859012bc364SMatthew G. Knepley     DMPolytopeType *rct;
7860012bc364SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt, Nt;
7861012bc364SMatthew G. Knepley 
7862012bc364SMatthew G. Knepley     ierr = DMPlexTransformCreate(PETSC_COMM_SELF, &tr);CHKERRQ(ierr);
7863012bc364SMatthew G. Knepley     ierr = DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR);CHKERRQ(ierr);
7864012bc364SMatthew G. Knepley     ierr = DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt);CHKERRQ(ierr);
7865012bc364SMatthew G. Knepley     numSubcells = rsize[Nt-1];
7866012bc364SMatthew G. Knepley     ierr = DMPlexTransformDestroy(&tr);CHKERRQ(ierr);
7867412e9a14SMatthew G. Knepley   }
786869291d52SBarry Smith   ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr);
78697c927364SMatthew G. Knepley   for (r = 0, q = 0; r < numSubcells; ++r) {
78707c927364SMatthew G. Knepley     /* TODO Map from coarse to fine cells */
78717c927364SMatthew G. Knepley     ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr);
78727c927364SMatthew G. Knepley     /* Compress out points not in the section */
78737c927364SMatthew G. Knepley     ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr);
78747c927364SMatthew G. Knepley     for (p = 0; p < numFPoints*2; p += 2) {
78757c927364SMatthew G. Knepley       if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) {
78767c927364SMatthew G. Knepley         ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr);
78777c927364SMatthew G. Knepley         if (!dof) continue;
78787c927364SMatthew G. Knepley         for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break;
78797c927364SMatthew G. Knepley         if (s < q) continue;
78807c927364SMatthew G. Knepley         ftotpoints[q*2]   = fpoints[p];
78817c927364SMatthew G. Knepley         ftotpoints[q*2+1] = fpoints[p+1];
78827c927364SMatthew G. Knepley         ++q;
78837c927364SMatthew G. Knepley       }
78847c927364SMatthew G. Knepley     }
78857c927364SMatthew G. Knepley     ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr);
78867c927364SMatthew G. Knepley   }
78877c927364SMatthew G. Knepley   numFPoints = q;
78887c927364SMatthew G. Knepley   for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) {
78897c927364SMatthew G. Knepley     PetscInt fdof;
78907c927364SMatthew G. Knepley 
78917c927364SMatthew G. Knepley     ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr);
78927c927364SMatthew G. Knepley     if (!dof) continue;
78937c927364SMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
78947c927364SMatthew G. Knepley       ierr           = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr);
78957c927364SMatthew G. Knepley       foffsets[f+1] += fdof;
78967c927364SMatthew G. Knepley     }
78977c927364SMatthew G. Knepley     numFIndices += dof;
78987c927364SMatthew G. Knepley   }
78997c927364SMatthew G. Knepley   for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f];
79007c927364SMatthew G. Knepley 
79012c71b3e2SJacob Faibussowitsch   PetscCheckFalse(numFields && foffsets[numFields] != numFIndices,PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices);
79022c71b3e2SJacob Faibussowitsch   PetscCheckFalse(numFields && coffsets[numFields] != numCIndices,PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices);
79037c927364SMatthew G. Knepley   if (numFields) {
79044acb8e1eSToby Isaac     const PetscInt **permsF[32] = {NULL};
79054acb8e1eSToby Isaac     const PetscInt **permsC[32] = {NULL};
79064acb8e1eSToby Isaac 
79074acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
79084acb8e1eSToby Isaac       ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr);
79094acb8e1eSToby Isaac       ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr);
79107c927364SMatthew G. Knepley     }
79114acb8e1eSToby Isaac     for (p = 0; p < numFPoints; p++) {
79124acb8e1eSToby Isaac       ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr);
791336fa2b79SJed Brown       ierr = DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices);CHKERRQ(ierr);
79144acb8e1eSToby Isaac     }
79154acb8e1eSToby Isaac     for (p = 0; p < numCPoints; p++) {
79164acb8e1eSToby Isaac       ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr);
791736fa2b79SJed Brown       ierr = DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices);CHKERRQ(ierr);
79184acb8e1eSToby Isaac     }
79194acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
79204acb8e1eSToby Isaac       ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr);
79214acb8e1eSToby Isaac       ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr);
79227c927364SMatthew G. Knepley     }
79237c927364SMatthew G. Knepley   } else {
79244acb8e1eSToby Isaac     const PetscInt **permsF = NULL;
79254acb8e1eSToby Isaac     const PetscInt **permsC = NULL;
79264acb8e1eSToby Isaac 
79274acb8e1eSToby Isaac     ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr);
79284acb8e1eSToby Isaac     ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr);
79294acb8e1eSToby Isaac     for (p = 0, off = 0; p < numFPoints; p++) {
79304acb8e1eSToby Isaac       const PetscInt *perm = permsF ? permsF[p] : NULL;
79314acb8e1eSToby Isaac 
79324acb8e1eSToby Isaac       ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr);
793336fa2b79SJed Brown       ierr = DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices);CHKERRQ(ierr);
79347c927364SMatthew G. Knepley     }
79354acb8e1eSToby Isaac     for (p = 0, off = 0; p < numCPoints; p++) {
79364acb8e1eSToby Isaac       const PetscInt *perm = permsC ? permsC[p] : NULL;
79374acb8e1eSToby Isaac 
79384acb8e1eSToby Isaac       ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr);
793936fa2b79SJed Brown       ierr = DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices);CHKERRQ(ierr);
79407c927364SMatthew G. Knepley     }
79414acb8e1eSToby Isaac     ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr);
79424acb8e1eSToby Isaac     ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr);
79437c927364SMatthew G. Knepley   }
794469291d52SBarry Smith   ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr);
79457c927364SMatthew G. Knepley   ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr);
79467c927364SMatthew G. Knepley   PetscFunctionReturn(0);
79477c927364SMatthew G. Knepley }
79487c927364SMatthew G. Knepley 
79497cd05799SMatthew G. Knepley /*@C
79507cd05799SMatthew G. Knepley   DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0)
79517cd05799SMatthew G. Knepley 
79527cd05799SMatthew G. Knepley   Input Parameter:
79537cd05799SMatthew G. Knepley . dm   - The DMPlex object
79547cd05799SMatthew G. Knepley 
79557cd05799SMatthew G. Knepley   Output Parameter:
79567cd05799SMatthew G. Knepley . cellHeight - The height of a cell
79577cd05799SMatthew G. Knepley 
79587cd05799SMatthew G. Knepley   Level: developer
79597cd05799SMatthew G. Knepley 
79607cd05799SMatthew G. Knepley .seealso DMPlexSetVTKCellHeight()
79617cd05799SMatthew G. Knepley @*/
7962552f7358SJed Brown PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight)
7963552f7358SJed Brown {
7964552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
7965552f7358SJed Brown 
7966552f7358SJed Brown   PetscFunctionBegin;
7967552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7968552f7358SJed Brown   PetscValidPointer(cellHeight, 2);
7969552f7358SJed Brown   *cellHeight = mesh->vtkCellHeight;
7970552f7358SJed Brown   PetscFunctionReturn(0);
7971552f7358SJed Brown }
7972552f7358SJed Brown 
79737cd05799SMatthew G. Knepley /*@C
79747cd05799SMatthew G. Knepley   DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0)
79757cd05799SMatthew G. Knepley 
79767cd05799SMatthew G. Knepley   Input Parameters:
79777cd05799SMatthew G. Knepley + dm   - The DMPlex object
79787cd05799SMatthew G. Knepley - cellHeight - The height of a cell
79797cd05799SMatthew G. Knepley 
79807cd05799SMatthew G. Knepley   Level: developer
79817cd05799SMatthew G. Knepley 
79827cd05799SMatthew G. Knepley .seealso DMPlexGetVTKCellHeight()
79837cd05799SMatthew G. Knepley @*/
7984552f7358SJed Brown PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight)
7985552f7358SJed Brown {
7986552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
7987552f7358SJed Brown 
7988552f7358SJed Brown   PetscFunctionBegin;
7989552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7990552f7358SJed Brown   mesh->vtkCellHeight = cellHeight;
7991552f7358SJed Brown   PetscFunctionReturn(0);
7992552f7358SJed Brown }
7993552f7358SJed Brown 
7994e6139122SMatthew G. Knepley /*@
7995e6139122SMatthew G. Knepley   DMPlexGetGhostCellStratum - Get the range of cells which are used to enforce FV boundary conditions
7996e6139122SMatthew G. Knepley 
7997e6139122SMatthew G. Knepley   Input Parameter:
7998e6139122SMatthew G. Knepley . dm - The DMPlex object
7999e6139122SMatthew G. Knepley 
8000e6139122SMatthew G. Knepley   Output Parameters:
80012a9f31c0SMatthew G. Knepley + gcStart - The first ghost cell, or NULL
80022a9f31c0SMatthew G. Knepley - gcEnd   - The upper bound on ghost cells, or NULL
8003e6139122SMatthew G. Knepley 
80042a9f31c0SMatthew G. Knepley   Level: advanced
8005e6139122SMatthew G. Knepley 
80068065b584SMatthew Knepley .seealso DMPlexConstructGhostCells(), DMPlexGetGhostCellStratum()
8007e6139122SMatthew G. Knepley @*/
8008e6139122SMatthew G. Knepley PetscErrorCode DMPlexGetGhostCellStratum(DM dm, PetscInt *gcStart, PetscInt *gcEnd)
8009e6139122SMatthew G. Knepley {
8010412e9a14SMatthew G. Knepley   DMLabel        ctLabel;
8011e6139122SMatthew G. Knepley   PetscErrorCode ierr;
8012e6139122SMatthew G. Knepley 
8013e6139122SMatthew G. Knepley   PetscFunctionBegin;
8014e6139122SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8015412e9a14SMatthew G. Knepley   ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr);
8016412e9a14SMatthew G. Knepley   ierr = DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_FV_GHOST, gcStart, gcEnd);CHKERRQ(ierr);
8017e6139122SMatthew G. Knepley   PetscFunctionReturn(0);
8018e6139122SMatthew G. Knepley }
8019e6139122SMatthew G. Knepley 
80209886b8cfSStefano Zampini PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering)
8021552f7358SJed Brown {
8022552f7358SJed Brown   PetscSection   section, globalSection;
8023552f7358SJed Brown   PetscInt      *numbers, p;
8024552f7358SJed Brown   PetscErrorCode ierr;
8025552f7358SJed Brown 
8026552f7358SJed Brown   PetscFunctionBegin;
802782f516ccSBarry Smith   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section);CHKERRQ(ierr);
8028552f7358SJed Brown   ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr);
8029552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
8030552f7358SJed Brown     ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr);
8031552f7358SJed Brown   }
8032552f7358SJed Brown   ierr = PetscSectionSetUp(section);CHKERRQ(ierr);
803315b58121SMatthew G. Knepley   ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection);CHKERRQ(ierr);
8034854ce69bSBarry Smith   ierr = PetscMalloc1(pEnd - pStart, &numbers);CHKERRQ(ierr);
8035552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
8036552f7358SJed Brown     ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr);
8037ef48cebcSMatthew G. Knepley     if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift;
8038ef48cebcSMatthew G. Knepley     else                       numbers[p-pStart] += shift;
8039552f7358SJed Brown   }
804082f516ccSBarry Smith   ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr);
8041ef48cebcSMatthew G. Knepley   if (globalSize) {
8042ef48cebcSMatthew G. Knepley     PetscLayout layout;
8043ef48cebcSMatthew G. Knepley     ierr = PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout);CHKERRQ(ierr);
8044ef48cebcSMatthew G. Knepley     ierr = PetscLayoutGetSize(layout, globalSize);CHKERRQ(ierr);
8045ef48cebcSMatthew G. Knepley     ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr);
8046ef48cebcSMatthew G. Knepley   }
8047552f7358SJed Brown   ierr = PetscSectionDestroy(&section);CHKERRQ(ierr);
8048552f7358SJed Brown   ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr);
8049552f7358SJed Brown   PetscFunctionReturn(0);
8050552f7358SJed Brown }
8051552f7358SJed Brown 
805281ed3555SMatthew G. Knepley PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers)
8053552f7358SJed Brown {
8054412e9a14SMatthew G. Knepley   PetscInt       cellHeight, cStart, cEnd;
8055552f7358SJed Brown   PetscErrorCode ierr;
8056552f7358SJed Brown 
8057552f7358SJed Brown   PetscFunctionBegin;
8058552f7358SJed Brown   ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr);
8059412e9a14SMatthew G. Knepley   if (includeHybrid) {ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);}
8060412e9a14SMatthew G. Knepley   else               {ierr = DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);}
80619886b8cfSStefano Zampini   ierr = DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers);CHKERRQ(ierr);
806281ed3555SMatthew G. Knepley   PetscFunctionReturn(0);
8063552f7358SJed Brown }
806481ed3555SMatthew G. Knepley 
80658dab3259SMatthew G. Knepley /*@
80667cd05799SMatthew G. Knepley   DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process
80677cd05799SMatthew G. Knepley 
80687cd05799SMatthew G. Knepley   Input Parameter:
80697cd05799SMatthew G. Knepley . dm   - The DMPlex object
80707cd05799SMatthew G. Knepley 
80717cd05799SMatthew G. Knepley   Output Parameter:
80727cd05799SMatthew G. Knepley . globalCellNumbers - Global cell numbers for all cells on this process
80737cd05799SMatthew G. Knepley 
80747cd05799SMatthew G. Knepley   Level: developer
80757cd05799SMatthew G. Knepley 
80767cd05799SMatthew G. Knepley .seealso DMPlexGetVertexNumbering()
80777cd05799SMatthew G. Knepley @*/
807881ed3555SMatthew G. Knepley PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers)
807981ed3555SMatthew G. Knepley {
808081ed3555SMatthew G. Knepley   DM_Plex       *mesh = (DM_Plex*) dm->data;
808181ed3555SMatthew G. Knepley   PetscErrorCode ierr;
808281ed3555SMatthew G. Knepley 
808381ed3555SMatthew G. Knepley   PetscFunctionBegin;
808481ed3555SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
808581ed3555SMatthew G. Knepley   if (!mesh->globalCellNumbers) {ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers);CHKERRQ(ierr);}
8086552f7358SJed Brown   *globalCellNumbers = mesh->globalCellNumbers;
8087552f7358SJed Brown   PetscFunctionReturn(0);
8088552f7358SJed Brown }
8089552f7358SJed Brown 
809081ed3555SMatthew G. Knepley PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers)
809181ed3555SMatthew G. Knepley {
8092412e9a14SMatthew G. Knepley   PetscInt       vStart, vEnd;
809381ed3555SMatthew G. Knepley   PetscErrorCode ierr;
809481ed3555SMatthew G. Knepley 
809581ed3555SMatthew G. Knepley   PetscFunctionBegin;
809681ed3555SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
809781ed3555SMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
80989886b8cfSStefano Zampini   ierr = DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers);CHKERRQ(ierr);
809981ed3555SMatthew G. Knepley   PetscFunctionReturn(0);
810081ed3555SMatthew G. Knepley }
810181ed3555SMatthew G. Knepley 
81028dab3259SMatthew G. Knepley /*@
81036aa51ba9SJacob Faibussowitsch   DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process
81047cd05799SMatthew G. Knepley 
81057cd05799SMatthew G. Knepley   Input Parameter:
81067cd05799SMatthew G. Knepley . dm   - The DMPlex object
81077cd05799SMatthew G. Knepley 
81087cd05799SMatthew G. Knepley   Output Parameter:
81097cd05799SMatthew G. Knepley . globalVertexNumbers - Global vertex numbers for all vertices on this process
81107cd05799SMatthew G. Knepley 
81117cd05799SMatthew G. Knepley   Level: developer
81127cd05799SMatthew G. Knepley 
81137cd05799SMatthew G. Knepley .seealso DMPlexGetCellNumbering()
81147cd05799SMatthew G. Knepley @*/
8115552f7358SJed Brown PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers)
8116552f7358SJed Brown {
8117552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
8118552f7358SJed Brown   PetscErrorCode ierr;
8119552f7358SJed Brown 
8120552f7358SJed Brown   PetscFunctionBegin;
8121552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
812281ed3555SMatthew G. Knepley   if (!mesh->globalVertexNumbers) {ierr = DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers);CHKERRQ(ierr);}
8123552f7358SJed Brown   *globalVertexNumbers = mesh->globalVertexNumbers;
8124552f7358SJed Brown   PetscFunctionReturn(0);
8125552f7358SJed Brown }
8126552f7358SJed Brown 
81278dab3259SMatthew G. Knepley /*@
81287cd05799SMatthew G. Knepley   DMPlexCreatePointNumbering - Create a global numbering for all points on this process
81297cd05799SMatthew G. Knepley 
81307cd05799SMatthew G. Knepley   Input Parameter:
81317cd05799SMatthew G. Knepley . dm   - The DMPlex object
81327cd05799SMatthew G. Knepley 
81337cd05799SMatthew G. Knepley   Output Parameter:
81347cd05799SMatthew G. Knepley . globalPointNumbers - Global numbers for all points on this process
81357cd05799SMatthew G. Knepley 
81367cd05799SMatthew G. Knepley   Level: developer
81377cd05799SMatthew G. Knepley 
81387cd05799SMatthew G. Knepley .seealso DMPlexGetCellNumbering()
81397cd05799SMatthew G. Knepley @*/
8140ef48cebcSMatthew G. Knepley PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers)
8141ef48cebcSMatthew G. Knepley {
8142ef48cebcSMatthew G. Knepley   IS             nums[4];
8143862913ffSStefano Zampini   PetscInt       depths[4], gdepths[4], starts[4];
8144ef48cebcSMatthew G. Knepley   PetscInt       depth, d, shift = 0;
8145ef48cebcSMatthew G. Knepley   PetscErrorCode ierr;
8146ef48cebcSMatthew G. Knepley 
8147ef48cebcSMatthew G. Knepley   PetscFunctionBegin;
8148ef48cebcSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8149ef48cebcSMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
81508abc87a0SMichael Lange   /* For unstratified meshes use dim instead of depth */
81518abc87a0SMichael Lange   if (depth < 0) {ierr = DMGetDimension(dm, &depth);CHKERRQ(ierr);}
8152862913ffSStefano Zampini   for (d = 0; d <= depth; ++d) {
8153862913ffSStefano Zampini     PetscInt end;
8154862913ffSStefano Zampini 
8155862913ffSStefano Zampini     depths[d] = depth-d;
8156862913ffSStefano Zampini     ierr = DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end);CHKERRQ(ierr);
8157862913ffSStefano Zampini     if (!(starts[d]-end)) { starts[d] = depths[d] = -1; }
8158862913ffSStefano Zampini   }
8159862913ffSStefano Zampini   ierr = PetscSortIntWithArray(depth+1, starts, depths);CHKERRQ(ierr);
8160820f2d46SBarry Smith   ierr = MPIU_Allreduce(depths, gdepths, depth+1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr);
8161862913ffSStefano Zampini   for (d = 0; d <= depth; ++d) {
81622c71b3e2SJacob Faibussowitsch     PetscCheckFalse(starts[d] >= 0 && depths[d] != gdepths[d],PETSC_COMM_SELF,PETSC_ERR_PLIB,"Expected depth %D, found %D",depths[d],gdepths[d]);
8163862913ffSStefano Zampini   }
8164ef48cebcSMatthew G. Knepley   for (d = 0; d <= depth; ++d) {
8165ef48cebcSMatthew G. Knepley     PetscInt pStart, pEnd, gsize;
8166ef48cebcSMatthew G. Knepley 
8167862913ffSStefano Zampini     ierr = DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd);CHKERRQ(ierr);
81689886b8cfSStefano Zampini     ierr = DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]);CHKERRQ(ierr);
8169ef48cebcSMatthew G. Knepley     shift += gsize;
8170ef48cebcSMatthew G. Knepley   }
8171302440fdSBarry Smith   ierr = ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers);CHKERRQ(ierr);
8172ef48cebcSMatthew G. Knepley   for (d = 0; d <= depth; ++d) {ierr = ISDestroy(&nums[d]);CHKERRQ(ierr);}
8173ef48cebcSMatthew G. Knepley   PetscFunctionReturn(0);
8174ef48cebcSMatthew G. Knepley }
8175ef48cebcSMatthew G. Knepley 
817608a22f4bSMatthew G. Knepley /*@
817708a22f4bSMatthew G. Knepley   DMPlexCreateRankField - Create a cell field whose value is the rank of the owner
817808a22f4bSMatthew G. Knepley 
817908a22f4bSMatthew G. Knepley   Input Parameter:
818008a22f4bSMatthew G. Knepley . dm - The DMPlex object
818108a22f4bSMatthew G. Knepley 
818208a22f4bSMatthew G. Knepley   Output Parameter:
818308a22f4bSMatthew G. Knepley . ranks - The rank field
818408a22f4bSMatthew G. Knepley 
818508a22f4bSMatthew G. Knepley   Options Database Keys:
818608a22f4bSMatthew G. Knepley . -dm_partition_view - Adds the rank field into the DM output from -dm_view using the same viewer
818708a22f4bSMatthew G. Knepley 
818808a22f4bSMatthew G. Knepley   Level: intermediate
818908a22f4bSMatthew G. Knepley 
819008a22f4bSMatthew G. Knepley .seealso: DMView()
819108a22f4bSMatthew G. Knepley @*/
819208a22f4bSMatthew G. Knepley PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks)
819308a22f4bSMatthew G. Knepley {
819408a22f4bSMatthew G. Knepley   DM             rdm;
819508a22f4bSMatthew G. Knepley   PetscFE        fe;
819608a22f4bSMatthew G. Knepley   PetscScalar   *r;
819708a22f4bSMatthew G. Knepley   PetscMPIInt    rank;
8198a55f9a55SMatthew G. Knepley   DMPolytopeType ct;
819908a22f4bSMatthew G. Knepley   PetscInt       dim, cStart, cEnd, c;
8200a55f9a55SMatthew G. Knepley   PetscBool      simplex;
820108a22f4bSMatthew G. Knepley   PetscErrorCode ierr;
820208a22f4bSMatthew G. Knepley 
820308a22f4bSMatthew G. Knepley   PetscFunctionBeginUser;
8204f95ace6aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8205f95ace6aSMatthew G. Knepley   PetscValidPointer(ranks, 2);
8206ffc4695bSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr);
820708a22f4bSMatthew G. Knepley   ierr = DMClone(dm, &rdm);CHKERRQ(ierr);
820808a22f4bSMatthew G. Knepley   ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr);
8209a55f9a55SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr);
8210a55f9a55SMatthew G. Knepley   ierr = DMPlexGetCellType(dm, cStart, &ct);CHKERRQ(ierr);
8211a55f9a55SMatthew G. Knepley   simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE;
8212a55f9a55SMatthew G. Knepley   ierr = PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe);CHKERRQ(ierr);
821308a22f4bSMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) fe, "rank");CHKERRQ(ierr);
8214e5e52638SMatthew G. Knepley   ierr = DMSetField(rdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr);
821508a22f4bSMatthew G. Knepley   ierr = PetscFEDestroy(&fe);CHKERRQ(ierr);
8216e5e52638SMatthew G. Knepley   ierr = DMCreateDS(rdm);CHKERRQ(ierr);
821708a22f4bSMatthew G. Knepley   ierr = DMCreateGlobalVector(rdm, ranks);CHKERRQ(ierr);
821808a22f4bSMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) *ranks, "partition");CHKERRQ(ierr);
821908a22f4bSMatthew G. Knepley   ierr = VecGetArray(*ranks, &r);CHKERRQ(ierr);
822008a22f4bSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
822108a22f4bSMatthew G. Knepley     PetscScalar *lr;
822208a22f4bSMatthew G. Knepley 
822308a22f4bSMatthew G. Knepley     ierr = DMPlexPointGlobalRef(rdm, c, r, &lr);CHKERRQ(ierr);
822471f09efeSPierre Jolivet     if (lr) *lr = rank;
822508a22f4bSMatthew G. Knepley   }
822608a22f4bSMatthew G. Knepley   ierr = VecRestoreArray(*ranks, &r);CHKERRQ(ierr);
822708a22f4bSMatthew G. Knepley   ierr = DMDestroy(&rdm);CHKERRQ(ierr);
822808a22f4bSMatthew G. Knepley   PetscFunctionReturn(0);
822908a22f4bSMatthew G. Knepley }
823008a22f4bSMatthew G. Knepley 
8231ca8062c8SMatthew G. Knepley /*@
823218e14f0cSMatthew G. Knepley   DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell
823318e14f0cSMatthew G. Knepley 
823418e14f0cSMatthew G. Knepley   Input Parameters:
823518e14f0cSMatthew G. Knepley + dm    - The DMPlex
823618e14f0cSMatthew G. Knepley - label - The DMLabel
823718e14f0cSMatthew G. Knepley 
823818e14f0cSMatthew G. Knepley   Output Parameter:
823918e14f0cSMatthew G. Knepley . val - The label value field
824018e14f0cSMatthew G. Knepley 
824118e14f0cSMatthew G. Knepley   Options Database Keys:
824218e14f0cSMatthew G. Knepley . -dm_label_view - Adds the label value field into the DM output from -dm_view using the same viewer
824318e14f0cSMatthew G. Knepley 
824418e14f0cSMatthew G. Knepley   Level: intermediate
824518e14f0cSMatthew G. Knepley 
824618e14f0cSMatthew G. Knepley .seealso: DMView()
824718e14f0cSMatthew G. Knepley @*/
824818e14f0cSMatthew G. Knepley PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val)
824918e14f0cSMatthew G. Knepley {
825018e14f0cSMatthew G. Knepley   DM             rdm;
825118e14f0cSMatthew G. Knepley   PetscFE        fe;
825218e14f0cSMatthew G. Knepley   PetscScalar   *v;
825318e14f0cSMatthew G. Knepley   PetscInt       dim, cStart, cEnd, c;
825418e14f0cSMatthew G. Knepley   PetscErrorCode ierr;
825518e14f0cSMatthew G. Knepley 
825618e14f0cSMatthew G. Knepley   PetscFunctionBeginUser;
825718e14f0cSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
825818e14f0cSMatthew G. Knepley   PetscValidPointer(label, 2);
825918e14f0cSMatthew G. Knepley   PetscValidPointer(val, 3);
826018e14f0cSMatthew G. Knepley   ierr = DMClone(dm, &rdm);CHKERRQ(ierr);
826118e14f0cSMatthew G. Knepley   ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr);
826218e14f0cSMatthew G. Knepley   ierr = PetscFECreateDefault(PetscObjectComm((PetscObject) rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe);CHKERRQ(ierr);
826318e14f0cSMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) fe, "label_value");CHKERRQ(ierr);
8264e5e52638SMatthew G. Knepley   ierr = DMSetField(rdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr);
826518e14f0cSMatthew G. Knepley   ierr = PetscFEDestroy(&fe);CHKERRQ(ierr);
8266e5e52638SMatthew G. Knepley   ierr = DMCreateDS(rdm);CHKERRQ(ierr);
826718e14f0cSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr);
826818e14f0cSMatthew G. Knepley   ierr = DMCreateGlobalVector(rdm, val);CHKERRQ(ierr);
8269effbd7cbSMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) *val, "label_value");CHKERRQ(ierr);
827018e14f0cSMatthew G. Knepley   ierr = VecGetArray(*val, &v);CHKERRQ(ierr);
827118e14f0cSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
827218e14f0cSMatthew G. Knepley     PetscScalar *lv;
827318e14f0cSMatthew G. Knepley     PetscInt     cval;
827418e14f0cSMatthew G. Knepley 
827518e14f0cSMatthew G. Knepley     ierr = DMPlexPointGlobalRef(rdm, c, v, &lv);CHKERRQ(ierr);
827618e14f0cSMatthew G. Knepley     ierr = DMLabelGetValue(label, c, &cval);CHKERRQ(ierr);
827718e14f0cSMatthew G. Knepley     *lv = cval;
827818e14f0cSMatthew G. Knepley   }
827918e14f0cSMatthew G. Knepley   ierr = VecRestoreArray(*val, &v);CHKERRQ(ierr);
828018e14f0cSMatthew G. Knepley   ierr = DMDestroy(&rdm);CHKERRQ(ierr);
828118e14f0cSMatthew G. Knepley   PetscFunctionReturn(0);
828218e14f0cSMatthew G. Knepley }
828318e14f0cSMatthew G. Knepley 
828418e14f0cSMatthew G. Knepley /*@
8285ca8062c8SMatthew G. Knepley   DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric.
8286ca8062c8SMatthew G. Knepley 
828769916449SMatthew G. Knepley   Input Parameter:
828869916449SMatthew G. Knepley . dm - The DMPlex object
8289ca8062c8SMatthew G. Knepley 
829095eb5ee5SVaclav Hapla   Notes:
829195eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
829295eb5ee5SVaclav Hapla 
829395eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
8294ca8062c8SMatthew G. Knepley 
8295ca8062c8SMatthew G. Knepley   Level: developer
8296ca8062c8SMatthew G. Knepley 
829795eb5ee5SVaclav Hapla .seealso: DMCreate(), DMSetFromOptions()
8298ca8062c8SMatthew G. Knepley @*/
8299ca8062c8SMatthew G. Knepley PetscErrorCode DMPlexCheckSymmetry(DM dm)
8300ca8062c8SMatthew G. Knepley {
8301ca8062c8SMatthew G. Knepley   PetscSection    coneSection, supportSection;
8302ca8062c8SMatthew G. Knepley   const PetscInt *cone, *support;
8303ca8062c8SMatthew G. Knepley   PetscInt        coneSize, c, supportSize, s;
830457beb4faSStefano Zampini   PetscInt        pStart, pEnd, p, pp, csize, ssize;
830557beb4faSStefano Zampini   PetscBool       storagecheck = PETSC_TRUE;
8306ca8062c8SMatthew G. Knepley   PetscErrorCode  ierr;
8307ca8062c8SMatthew G. Knepley 
8308ca8062c8SMatthew G. Knepley   PetscFunctionBegin;
8309ca8062c8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8310412e9a14SMatthew G. Knepley   ierr = DMViewFromOptions(dm, NULL, "-sym_dm_view");CHKERRQ(ierr);
8311ca8062c8SMatthew G. Knepley   ierr = DMPlexGetConeSection(dm, &coneSection);CHKERRQ(ierr);
8312ca8062c8SMatthew G. Knepley   ierr = DMPlexGetSupportSection(dm, &supportSection);CHKERRQ(ierr);
8313ca8062c8SMatthew G. Knepley   /* Check that point p is found in the support of its cone points, and vice versa */
8314ca8062c8SMatthew G. Knepley   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
8315ca8062c8SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
8316ca8062c8SMatthew G. Knepley     ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
8317ca8062c8SMatthew G. Knepley     ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr);
8318ca8062c8SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
831942e66dfaSMatthew G. Knepley       PetscBool dup = PETSC_FALSE;
832042e66dfaSMatthew G. Knepley       PetscInt  d;
832142e66dfaSMatthew G. Knepley       for (d = c-1; d >= 0; --d) {
832242e66dfaSMatthew G. Knepley         if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;}
832342e66dfaSMatthew G. Knepley       }
8324ca8062c8SMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, cone[c], &supportSize);CHKERRQ(ierr);
8325ca8062c8SMatthew G. Knepley       ierr = DMPlexGetSupport(dm, cone[c], &support);CHKERRQ(ierr);
8326ca8062c8SMatthew G. Knepley       for (s = 0; s < supportSize; ++s) {
8327ca8062c8SMatthew G. Knepley         if (support[s] == p) break;
8328ca8062c8SMatthew G. Knepley       }
832942e66dfaSMatthew G. Knepley       if ((s >= supportSize) || (dup && (support[s+1] != p))) {
83308ccfff9cSToby Isaac         ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", p);CHKERRQ(ierr);
8331ca8062c8SMatthew G. Knepley         for (s = 0; s < coneSize; ++s) {
83328ccfff9cSToby Isaac           ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[s]);CHKERRQ(ierr);
8333ca8062c8SMatthew G. Knepley         }
8334302440fdSBarry Smith         ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr);
83358ccfff9cSToby Isaac         ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", cone[c]);CHKERRQ(ierr);
8336ca8062c8SMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
83378ccfff9cSToby Isaac           ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[s]);CHKERRQ(ierr);
8338ca8062c8SMatthew G. Knepley         }
8339302440fdSBarry Smith         ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr);
83402c71b3e2SJacob Faibussowitsch         PetscCheckFalse(dup,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not repeatedly found in support of repeated cone point %D", p, cone[c]);
834198921bdaSJacob Faibussowitsch         else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in support of cone point %D", p, cone[c]);
8342ca8062c8SMatthew G. Knepley       }
834342e66dfaSMatthew G. Knepley     }
834457beb4faSStefano Zampini     ierr = DMPlexGetTreeParent(dm, p, &pp, NULL);CHKERRQ(ierr);
834557beb4faSStefano Zampini     if (p != pp) { storagecheck = PETSC_FALSE; continue; }
8346ca8062c8SMatthew G. Knepley     ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr);
8347ca8062c8SMatthew G. Knepley     ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr);
8348ca8062c8SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
8349ca8062c8SMatthew G. Knepley       ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
8350ca8062c8SMatthew G. Knepley       ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
8351ca8062c8SMatthew G. Knepley       for (c = 0; c < coneSize; ++c) {
835257beb4faSStefano Zampini         ierr = DMPlexGetTreeParent(dm, cone[c], &pp, NULL);CHKERRQ(ierr);
835357beb4faSStefano Zampini         if (cone[c] != pp) { c = 0; break; }
8354ca8062c8SMatthew G. Knepley         if (cone[c] == p) break;
8355ca8062c8SMatthew G. Knepley       }
8356ca8062c8SMatthew G. Knepley       if (c >= coneSize) {
83578ccfff9cSToby Isaac         ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", p);CHKERRQ(ierr);
8358ca8062c8SMatthew G. Knepley         for (c = 0; c < supportSize; ++c) {
83598ccfff9cSToby Isaac           ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[c]);CHKERRQ(ierr);
8360ca8062c8SMatthew G. Knepley         }
8361302440fdSBarry Smith         ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr);
83628ccfff9cSToby Isaac         ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", support[s]);CHKERRQ(ierr);
8363ca8062c8SMatthew G. Knepley         for (c = 0; c < coneSize; ++c) {
83648ccfff9cSToby Isaac           ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[c]);CHKERRQ(ierr);
8365ca8062c8SMatthew G. Knepley         }
8366302440fdSBarry Smith         ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr);
836798921bdaSJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in cone of support point %D", p, support[s]);
8368ca8062c8SMatthew G. Knepley       }
8369ca8062c8SMatthew G. Knepley     }
8370ca8062c8SMatthew G. Knepley   }
837157beb4faSStefano Zampini   if (storagecheck) {
8372ca8062c8SMatthew G. Knepley     ierr = PetscSectionGetStorageSize(coneSection, &csize);CHKERRQ(ierr);
8373ca8062c8SMatthew G. Knepley     ierr = PetscSectionGetStorageSize(supportSection, &ssize);CHKERRQ(ierr);
83742c71b3e2SJacob Faibussowitsch     PetscCheckFalse(csize != ssize,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %D != Total support size %D", csize, ssize);
837557beb4faSStefano Zampini   }
8376ca8062c8SMatthew G. Knepley   PetscFunctionReturn(0);
8377ca8062c8SMatthew G. Knepley }
8378ca8062c8SMatthew G. Knepley 
8379412e9a14SMatthew G. Knepley /*
8380412e9a14SMatthew G. Knepley   For submeshes with cohesive cells (see DMPlexConstructCohesiveCells()), we allow a special case where some of the boundary of a face (edges and vertices) are not duplicated. We call these special boundary points "unsplit", since the same edge or vertex appears in both copies of the face. These unsplit points throw off our counting, so we have to explicitly account for them here.
8381412e9a14SMatthew G. Knepley */
8382412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit)
8383412e9a14SMatthew G. Knepley {
8384412e9a14SMatthew G. Knepley   DMPolytopeType  cct;
8385412e9a14SMatthew G. Knepley   PetscInt        ptpoints[4];
8386412e9a14SMatthew G. Knepley   const PetscInt *cone, *ccone, *ptcone;
8387412e9a14SMatthew G. Knepley   PetscInt        coneSize, cp, cconeSize, ccp, npt = 0, pt;
8388412e9a14SMatthew G. Knepley   PetscErrorCode  ierr;
8389412e9a14SMatthew G. Knepley 
8390412e9a14SMatthew G. Knepley   PetscFunctionBegin;
8391412e9a14SMatthew G. Knepley   *unsplit = 0;
8392412e9a14SMatthew G. Knepley   switch (ct) {
8393b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_POINT_PRISM_TENSOR:
8394b5a892a1SMatthew G. Knepley       ptpoints[npt++] = c;
8395b5a892a1SMatthew G. Knepley       break;
8396412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEG_PRISM_TENSOR:
8397412e9a14SMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
8398412e9a14SMatthew G. Knepley       ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr);
8399412e9a14SMatthew G. Knepley       for (cp = 0; cp < coneSize; ++cp) {
8400412e9a14SMatthew G. Knepley         ierr = DMPlexGetCellType(dm, cone[cp], &cct);CHKERRQ(ierr);
8401412e9a14SMatthew G. Knepley         if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp];
8402412e9a14SMatthew G. Knepley       }
8403412e9a14SMatthew G. Knepley       break;
8404412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:
8405412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
8406412e9a14SMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
8407412e9a14SMatthew G. Knepley       ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr);
8408412e9a14SMatthew G. Knepley       for (cp = 0; cp < coneSize; ++cp) {
8409412e9a14SMatthew G. Knepley         ierr = DMPlexGetCone(dm, cone[cp], &ccone);CHKERRQ(ierr);
8410412e9a14SMatthew G. Knepley         ierr = DMPlexGetConeSize(dm, cone[cp], &cconeSize);CHKERRQ(ierr);
8411412e9a14SMatthew G. Knepley         for (ccp = 0; ccp < cconeSize; ++ccp) {
8412412e9a14SMatthew G. Knepley           ierr = DMPlexGetCellType(dm, ccone[ccp], &cct);CHKERRQ(ierr);
8413412e9a14SMatthew G. Knepley           if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) {
8414412e9a14SMatthew G. Knepley             PetscInt p;
8415412e9a14SMatthew G. Knepley             for (p = 0; p < npt; ++p) if (ptpoints[p] == ccone[ccp]) break;
8416412e9a14SMatthew G. Knepley             if (p == npt) ptpoints[npt++] = ccone[ccp];
8417412e9a14SMatthew G. Knepley           }
8418412e9a14SMatthew G. Knepley         }
8419412e9a14SMatthew G. Knepley       }
8420412e9a14SMatthew G. Knepley       break;
8421412e9a14SMatthew G. Knepley     default: break;
8422412e9a14SMatthew G. Knepley   }
8423412e9a14SMatthew G. Knepley   for (pt = 0; pt < npt; ++pt) {
8424412e9a14SMatthew G. Knepley     ierr = DMPlexGetCone(dm, ptpoints[pt], &ptcone);CHKERRQ(ierr);
8425412e9a14SMatthew G. Knepley     if (ptcone[0] == ptcone[1]) ++(*unsplit);
8426412e9a14SMatthew G. Knepley   }
8427412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
8428412e9a14SMatthew G. Knepley }
8429412e9a14SMatthew G. Knepley 
8430ca8062c8SMatthew G. Knepley /*@
8431ca8062c8SMatthew G. Knepley   DMPlexCheckSkeleton - Check that each cell has the correct number of vertices
8432ca8062c8SMatthew G. Knepley 
8433ca8062c8SMatthew G. Knepley   Input Parameters:
8434ca8062c8SMatthew G. Knepley + dm - The DMPlex object
843558723a97SMatthew G. Knepley - cellHeight - Normally 0
8436ca8062c8SMatthew G. Knepley 
843795eb5ee5SVaclav Hapla   Notes:
843895eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
843925c50c26SVaclav Hapla   Currently applicable only to homogeneous simplex or tensor meshes.
8440ca8062c8SMatthew G. Knepley 
844195eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
844295eb5ee5SVaclav Hapla 
8443ca8062c8SMatthew G. Knepley   Level: developer
8444ca8062c8SMatthew G. Knepley 
844595eb5ee5SVaclav Hapla .seealso: DMCreate(), DMSetFromOptions()
8446ca8062c8SMatthew G. Knepley @*/
844725c50c26SVaclav Hapla PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight)
8448ca8062c8SMatthew G. Knepley {
8449412e9a14SMatthew G. Knepley   DMPlexInterpolatedFlag interp;
8450412e9a14SMatthew G. Knepley   DMPolytopeType         ct;
8451412e9a14SMatthew G. Knepley   PetscInt               vStart, vEnd, cStart, cEnd, c;
8452ca8062c8SMatthew G. Knepley   PetscErrorCode         ierr;
8453ca8062c8SMatthew G. Knepley 
8454ca8062c8SMatthew G. Knepley   PetscFunctionBegin;
8455ca8062c8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8456412e9a14SMatthew G. Knepley   ierr = DMPlexIsInterpolated(dm, &interp);CHKERRQ(ierr);
845725c50c26SVaclav Hapla   ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);
845858723a97SMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
8459412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
8460412e9a14SMatthew G. Knepley     PetscInt *closure = NULL;
8461412e9a14SMatthew G. Knepley     PetscInt  coneSize, closureSize, cl, Nv = 0;
846258723a97SMatthew G. Knepley 
8463412e9a14SMatthew G. Knepley     ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr);
84642c71b3e2SJacob Faibussowitsch     PetscCheckFalse((PetscInt) ct < 0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D has no cell type", c);
8465412e9a14SMatthew G. Knepley     if (ct == DM_POLYTOPE_UNKNOWN) continue;
8466412e9a14SMatthew G. Knepley     if (interp == DMPLEX_INTERPOLATED_FULL) {
8467412e9a14SMatthew G. Knepley       ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr);
84682c71b3e2SJacob Faibussowitsch       PetscCheckFalse(coneSize != DMPolytopeTypeGetConeSize(ct),PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D of type %s has cone size %D != %D", c, DMPolytopeTypes[ct], coneSize, DMPolytopeTypeGetConeSize(ct));
8469412e9a14SMatthew G. Knepley     }
847058723a97SMatthew G. Knepley     ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
847158723a97SMatthew G. Knepley     for (cl = 0; cl < closureSize*2; cl += 2) {
847258723a97SMatthew G. Knepley       const PetscInt p = closure[cl];
8473412e9a14SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) ++Nv;
847458723a97SMatthew G. Knepley     }
847558723a97SMatthew G. Knepley     ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
8476412e9a14SMatthew G. Knepley     /* Special Case: Tensor faces with identified vertices */
8477412e9a14SMatthew G. Knepley     if (Nv < DMPolytopeTypeGetNumVertices(ct)) {
8478412e9a14SMatthew G. Knepley       PetscInt unsplit;
847942363296SMatthew G. Knepley 
8480412e9a14SMatthew G. Knepley       ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr);
8481412e9a14SMatthew G. Knepley       if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue;
848242363296SMatthew G. Knepley     }
84832c71b3e2SJacob Faibussowitsch     PetscCheckFalse(Nv != DMPolytopeTypeGetNumVertices(ct),PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D of type %s has %D vertices != %D", c, DMPolytopeTypes[ct], Nv, DMPolytopeTypeGetNumVertices(ct));
848442363296SMatthew G. Knepley   }
8485ca8062c8SMatthew G. Knepley   PetscFunctionReturn(0);
8486ca8062c8SMatthew G. Knepley }
84879bf0dad6SMatthew G. Knepley 
84889bf0dad6SMatthew G. Knepley /*@
84899bf0dad6SMatthew 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
84909bf0dad6SMatthew G. Knepley 
8491899ea2b8SJacob Faibussowitsch   Not Collective
8492899ea2b8SJacob Faibussowitsch 
84939bf0dad6SMatthew G. Knepley   Input Parameters:
84949bf0dad6SMatthew G. Knepley + dm - The DMPlex object
84959bf0dad6SMatthew G. Knepley - cellHeight - Normally 0
84969bf0dad6SMatthew G. Knepley 
849745da879fSVaclav Hapla   Notes:
849845da879fSVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
849945da879fSVaclav Hapla   This routine is only relevant for meshes that are fully interpolated across all ranks.
850045da879fSVaclav Hapla   It will error out if a partially interpolated mesh is given on some rank.
850145da879fSVaclav Hapla   It will do nothing for locally uninterpolated mesh (as there is nothing to check).
85029bf0dad6SMatthew G. Knepley 
850395eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
850495eb5ee5SVaclav Hapla 
85059bf0dad6SMatthew G. Knepley   Level: developer
85069bf0dad6SMatthew G. Knepley 
850795eb5ee5SVaclav Hapla .seealso: DMCreate(), DMPlexGetVTKCellHeight(), DMSetFromOptions()
85089bf0dad6SMatthew G. Knepley @*/
850925c50c26SVaclav Hapla PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight)
85109bf0dad6SMatthew G. Knepley {
8511ab91121cSMatthew G. Knepley   PetscInt       dim, depth, vStart, vEnd, cStart, cEnd, c, h;
85129bf0dad6SMatthew G. Knepley   PetscErrorCode ierr;
8513899ea2b8SJacob Faibussowitsch   DMPlexInterpolatedFlag interpEnum;
85149bf0dad6SMatthew G. Knepley 
85159bf0dad6SMatthew G. Knepley   PetscFunctionBegin;
85169bf0dad6SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8517899ea2b8SJacob Faibussowitsch   ierr = DMPlexIsInterpolated(dm, &interpEnum);CHKERRQ(ierr);
851845da879fSVaclav Hapla   if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(0);
851945da879fSVaclav Hapla   if (interpEnum == DMPLEX_INTERPOLATED_PARTIAL) {
8520899ea2b8SJacob Faibussowitsch     PetscMPIInt rank;
8521899ea2b8SJacob Faibussowitsch     MPI_Comm    comm;
8522899ea2b8SJacob Faibussowitsch 
8523899ea2b8SJacob Faibussowitsch     ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr);
8524ffc4695bSBarry Smith     ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
852598921bdaSJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Mesh is only partially interpolated on rank %d, this is currently not supported", rank);
8526899ea2b8SJacob Faibussowitsch   }
8527899ea2b8SJacob Faibussowitsch 
8528c73cfb54SMatthew G. Knepley   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
8529ab91121cSMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
85309bf0dad6SMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
8531ab91121cSMatthew G. Knepley   for (h = cellHeight; h < PetscMin(depth, dim); ++h) {
85323554e41dSMatthew G. Knepley     ierr = DMPlexGetHeightStratum(dm, h, &cStart, &cEnd);CHKERRQ(ierr);
85333554e41dSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
8534412e9a14SMatthew G. Knepley       const PetscInt      *cone, *ornt, *faceSizes, *faces;
8535412e9a14SMatthew G. Knepley       const DMPolytopeType *faceTypes;
8536ba2698f1SMatthew G. Knepley       DMPolytopeType        ct;
8537412e9a14SMatthew G. Knepley       PetscInt              numFaces, coneSize, f;
8538412e9a14SMatthew G. Knepley       PetscInt             *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit;
85399bf0dad6SMatthew G. Knepley 
8540ba2698f1SMatthew G. Knepley       ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr);
8541412e9a14SMatthew G. Knepley       ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr);
8542412e9a14SMatthew G. Knepley       if (unsplit) continue;
85439bf0dad6SMatthew G. Knepley       ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr);
85449bf0dad6SMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
85459bf0dad6SMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
85469bf0dad6SMatthew G. Knepley       ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
85479bf0dad6SMatthew G. Knepley       for (cl = 0; cl < closureSize*2; cl += 2) {
85489bf0dad6SMatthew G. Knepley         const PetscInt p = closure[cl];
85499bf0dad6SMatthew G. Knepley         if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p;
85509bf0dad6SMatthew G. Knepley       }
8551412e9a14SMatthew G. Knepley       ierr = DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr);
85522c71b3e2SJacob Faibussowitsch       PetscCheckFalse(coneSize != numFaces,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D of type %s has %D faces but should have %D", c, DMPolytopeTypes[ct], coneSize, numFaces);
85539bf0dad6SMatthew G. Knepley       for (f = 0; f < numFaces; ++f) {
8554d4961f80SStefano Zampini         DMPolytopeType fct;
85559bf0dad6SMatthew G. Knepley         PetscInt       *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v;
85569bf0dad6SMatthew G. Knepley 
8557d4961f80SStefano Zampini         ierr = DMPlexGetCellType(dm, cone[f], &fct);CHKERRQ(ierr);
85589bf0dad6SMatthew G. Knepley         ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr);
85599bf0dad6SMatthew G. Knepley         for (cl = 0; cl < fclosureSize*2; cl += 2) {
85609bf0dad6SMatthew G. Knepley           const PetscInt p = fclosure[cl];
85619bf0dad6SMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p;
85629bf0dad6SMatthew G. Knepley         }
85632c71b3e2SJacob Faibussowitsch         PetscCheckFalse(fnumCorners != faceSizes[f],PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %D of type %s (cone idx %D) of cell %D of type %s has %D vertices but should have %D", cone[f], DMPolytopeTypes[fct], f, c, DMPolytopeTypes[ct], fnumCorners, faceSizes[f]);
85649bf0dad6SMatthew G. Knepley         for (v = 0; v < fnumCorners; ++v) {
8565b5a892a1SMatthew G. Knepley           if (fclosure[v] != faces[fOff+v]) {
8566b5a892a1SMatthew G. Knepley             PetscInt v1;
8567b5a892a1SMatthew G. Knepley 
8568b5a892a1SMatthew G. Knepley             ierr = PetscPrintf(PETSC_COMM_SELF, "face closure:");CHKERRQ(ierr);
8569b5a892a1SMatthew G. Knepley             for (v1 = 0; v1 < fnumCorners; ++v1) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", fclosure[v1]);CHKERRQ(ierr);}
8570b5a892a1SMatthew G. Knepley             ierr = PetscPrintf(PETSC_COMM_SELF, "\ncell face:");CHKERRQ(ierr);
8571b5a892a1SMatthew G. Knepley             for (v1 = 0; v1 < fnumCorners; ++v1) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", faces[fOff+v1]);CHKERRQ(ierr);}
8572b5a892a1SMatthew G. Knepley             ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr);
857398921bdaSJacob Faibussowitsch             SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %D of type %s (cone idx %d, ornt %D) of cell %D of type %s vertex %D, %D != %D", cone[f], DMPolytopeTypes[fct], f, ornt[f], c, DMPolytopeTypes[ct], v, fclosure[v], faces[fOff+v]);
8574b5a892a1SMatthew G. Knepley           }
85759bf0dad6SMatthew G. Knepley         }
85769bf0dad6SMatthew G. Knepley         ierr = DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr);
8577412e9a14SMatthew G. Knepley         fOff += faceSizes[f];
85789bf0dad6SMatthew G. Knepley       }
8579412e9a14SMatthew G. Knepley       ierr = DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr);
85809bf0dad6SMatthew G. Knepley       ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
85819bf0dad6SMatthew G. Knepley     }
85823554e41dSMatthew G. Knepley   }
8583552f7358SJed Brown   PetscFunctionReturn(0);
8584552f7358SJed Brown }
85853913d7c8SMatthew G. Knepley 
8586bb6a34a8SMatthew G. Knepley /*@
8587bb6a34a8SMatthew G. Knepley   DMPlexCheckGeometry - Check the geometry of mesh cells
8588bb6a34a8SMatthew G. Knepley 
8589bb6a34a8SMatthew G. Knepley   Input Parameter:
8590bb6a34a8SMatthew G. Knepley . dm - The DMPlex object
8591bb6a34a8SMatthew G. Knepley 
859295eb5ee5SVaclav Hapla   Notes:
859395eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
859495eb5ee5SVaclav Hapla 
859595eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
8596bb6a34a8SMatthew G. Knepley 
8597bb6a34a8SMatthew G. Knepley   Level: developer
8598bb6a34a8SMatthew G. Knepley 
859995eb5ee5SVaclav Hapla .seealso: DMCreate(), DMSetFromOptions()
8600bb6a34a8SMatthew G. Knepley @*/
8601bb6a34a8SMatthew G. Knepley PetscErrorCode DMPlexCheckGeometry(DM dm)
8602bb6a34a8SMatthew G. Knepley {
8603a2a9e04cSMatthew G. Knepley   Vec            coordinates;
8604bb6a34a8SMatthew G. Knepley   PetscReal      detJ, J[9], refVol = 1.0;
8605bb6a34a8SMatthew G. Knepley   PetscReal      vol;
8606412e9a14SMatthew G. Knepley   PetscBool      periodic;
860751a74b61SMatthew G. Knepley   PetscInt       dim, depth, dE, d, cStart, cEnd, c;
8608bb6a34a8SMatthew G. Knepley   PetscErrorCode ierr;
8609bb6a34a8SMatthew G. Knepley 
8610bb6a34a8SMatthew G. Knepley   PetscFunctionBegin;
8611bb6a34a8SMatthew G. Knepley   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
861251a74b61SMatthew G. Knepley   ierr = DMGetCoordinateDim(dm, &dE);CHKERRQ(ierr);
861351a74b61SMatthew G. Knepley   if (dim != dE) PetscFunctionReturn(0);
8614bb6a34a8SMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
8615412e9a14SMatthew G. Knepley   ierr = DMGetPeriodicity(dm, &periodic, NULL, NULL, NULL);CHKERRQ(ierr);
8616bb6a34a8SMatthew G. Knepley   for (d = 0; d < dim; ++d) refVol *= 2.0;
8617bb6a34a8SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
8618a2a9e04cSMatthew G. Knepley   /* Make sure local coordinates are created, because that step is collective */
8619a2a9e04cSMatthew G. Knepley   ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
8620412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
8621412e9a14SMatthew G. Knepley     DMPolytopeType ct;
8622412e9a14SMatthew G. Knepley     PetscInt       unsplit;
8623412e9a14SMatthew G. Knepley     PetscBool      ignoreZeroVol = PETSC_FALSE;
8624412e9a14SMatthew G. Knepley 
8625412e9a14SMatthew G. Knepley     ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr);
8626412e9a14SMatthew G. Knepley     switch (ct) {
8627412e9a14SMatthew G. Knepley       case DM_POLYTOPE_SEG_PRISM_TENSOR:
8628412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM_TENSOR:
8629412e9a14SMatthew G. Knepley       case DM_POLYTOPE_QUAD_PRISM_TENSOR:
8630412e9a14SMatthew G. Knepley         ignoreZeroVol = PETSC_TRUE; break;
8631412e9a14SMatthew G. Knepley       default: break;
8632412e9a14SMatthew G. Knepley     }
8633412e9a14SMatthew G. Knepley     switch (ct) {
8634412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM:
8635412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM_TENSOR:
8636412e9a14SMatthew G. Knepley       case DM_POLYTOPE_QUAD_PRISM_TENSOR:
8637a2a9e04cSMatthew G. Knepley       case DM_POLYTOPE_PYRAMID:
8638412e9a14SMatthew G. Knepley         continue;
8639412e9a14SMatthew G. Knepley       default: break;
8640412e9a14SMatthew G. Knepley     }
8641412e9a14SMatthew G. Knepley     ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr);
8642412e9a14SMatthew G. Knepley     if (unsplit) continue;
8643bb6a34a8SMatthew G. Knepley     ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ);CHKERRQ(ierr);
86442c71b3e2SJacob Faibussowitsch     PetscCheckFalse(detJ < -PETSC_SMALL || (detJ <= 0.0 && !ignoreZeroVol),PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %D of type %s is inverted, |J| = %g", c, DMPolytopeTypes[ct], (double) detJ);
86457d3de750SJacob Faibussowitsch     ierr = PetscInfo(dm, "Cell %D FEM Volume %g\n", c, (double) detJ*refVol);CHKERRQ(ierr);
8646412e9a14SMatthew G. Knepley     if (depth > 1 && !periodic) {
8647bb6a34a8SMatthew G. Knepley       ierr = DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL);CHKERRQ(ierr);
86482c71b3e2SJacob Faibussowitsch       PetscCheckFalse(vol < -PETSC_SMALL || (vol <= 0.0 && !ignoreZeroVol),PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %D of type %s is inverted, vol = %g", c, DMPolytopeTypes[ct], (double) vol);
86497d3de750SJacob Faibussowitsch       ierr = PetscInfo(dm, "Cell %D FVM Volume %g\n", c, (double) vol);CHKERRQ(ierr);
8650bb6a34a8SMatthew G. Knepley     }
8651bb6a34a8SMatthew G. Knepley   }
8652bb6a34a8SMatthew G. Knepley   PetscFunctionReturn(0);
8653bb6a34a8SMatthew G. Knepley }
8654bb6a34a8SMatthew G. Knepley 
865503da9461SVaclav Hapla /*@
8656e83a0d2dSVaclav Hapla   DMPlexCheckPointSF - Check that several necessary conditions are met for the point SF of this plex.
865703da9461SVaclav Hapla 
865803da9461SVaclav Hapla   Input Parameters:
865903da9461SVaclav Hapla . dm - The DMPlex object
866003da9461SVaclav Hapla 
8661e83a0d2dSVaclav Hapla   Notes:
8662e83a0d2dSVaclav Hapla   This is mainly intended for debugging/testing purposes.
86638918e3e2SVaclav Hapla   It currently checks only meshes with no partition overlapping.
866403da9461SVaclav Hapla 
866595eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
866695eb5ee5SVaclav Hapla 
866703da9461SVaclav Hapla   Level: developer
866803da9461SVaclav Hapla 
866995eb5ee5SVaclav Hapla .seealso: DMGetPointSF(), DMSetFromOptions()
867003da9461SVaclav Hapla @*/
867103da9461SVaclav Hapla PetscErrorCode DMPlexCheckPointSF(DM dm)
867203da9461SVaclav Hapla {
8673f0cfc026SVaclav Hapla   PetscSF         pointSF;
8674f5869d18SMatthew G. Knepley   PetscInt        cellHeight, cStart, cEnd, l, nleaves, nroots, overlap;
8675f5869d18SMatthew G. Knepley   const PetscInt *locals, *rootdegree;
8676f0cfc026SVaclav Hapla   PetscBool       distributed;
867703da9461SVaclav Hapla   PetscErrorCode  ierr;
867803da9461SVaclav Hapla 
867903da9461SVaclav Hapla   PetscFunctionBegin;
868003da9461SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8681f0cfc026SVaclav Hapla   ierr = DMGetPointSF(dm, &pointSF);CHKERRQ(ierr);
8682f0cfc026SVaclav Hapla   ierr = DMPlexIsDistributed(dm, &distributed);CHKERRQ(ierr);
8683f0cfc026SVaclav Hapla   if (!distributed) PetscFunctionReturn(0);
8684f0cfc026SVaclav Hapla   ierr = DMPlexGetOverlap(dm, &overlap);CHKERRQ(ierr);
8685f0cfc026SVaclav Hapla   if (overlap) {
86861e1ea65dSPierre Jolivet     ierr = PetscPrintf(PetscObjectComm((PetscObject)dm), "Warning: DMPlexCheckPointSF() is currently not implemented for meshes with partition overlapping");CHKERRQ(ierr);
86878918e3e2SVaclav Hapla     PetscFunctionReturn(0);
86888918e3e2SVaclav Hapla   }
86892c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!pointSF,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but does not have PointSF attached");
8690f0cfc026SVaclav Hapla   ierr = PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, NULL);CHKERRQ(ierr);
86912c71b3e2SJacob Faibussowitsch   PetscCheckFalse(nroots < 0,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but its PointSF has no graph set");
8692f5869d18SMatthew G. Knepley   ierr = PetscSFComputeDegreeBegin(pointSF, &rootdegree);CHKERRQ(ierr);
8693f5869d18SMatthew G. Knepley   ierr = PetscSFComputeDegreeEnd(pointSF, &rootdegree);CHKERRQ(ierr);
869403da9461SVaclav Hapla 
8695ece87651SVaclav Hapla   /* 1) check there are no faces in 2D, cells in 3D, in interface */
8696f5869d18SMatthew G. Knepley   ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr);
8697f5869d18SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);
8698f5869d18SMatthew G. Knepley   for (l = 0; l < nleaves; ++l) {
8699f5869d18SMatthew G. Knepley     const PetscInt point = locals[l];
8700f5869d18SMatthew G. Knepley 
87012c71b3e2SJacob Faibussowitsch     PetscCheckFalse(point >= cStart && point < cEnd,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %D which is a cell", point);
870203da9461SVaclav Hapla   }
8703ece87651SVaclav Hapla 
8704f5869d18SMatthew G. Knepley   /* 2) if some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */
8705f5869d18SMatthew G. Knepley   for (l = 0; l < nleaves; ++l) {
8706f5869d18SMatthew G. Knepley     const PetscInt  point = locals[l];
8707f5869d18SMatthew G. Knepley     const PetscInt *cone;
8708f5869d18SMatthew G. Knepley     PetscInt        coneSize, c, idx;
8709f5869d18SMatthew G. Knepley 
8710f5869d18SMatthew G. Knepley     ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr);
8711f5869d18SMatthew G. Knepley     ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr);
8712f5869d18SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
8713f5869d18SMatthew G. Knepley       if (!rootdegree[cone[c]]) {
8714f5869d18SMatthew G. Knepley         ierr = PetscFindInt(cone[c], nleaves, locals, &idx);CHKERRQ(ierr);
87152c71b3e2SJacob Faibussowitsch         PetscCheckFalse(idx < 0,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %D but not %D from its cone", point, cone[c]);
8716f5869d18SMatthew G. Knepley       }
8717f5869d18SMatthew G. Knepley     }
8718ece87651SVaclav Hapla   }
871903da9461SVaclav Hapla   PetscFunctionReturn(0);
872003da9461SVaclav Hapla }
872103da9461SVaclav Hapla 
8722b5a892a1SMatthew G. Knepley PetscErrorCode DMPlexCheckAll_Internal(DM dm, PetscInt cellHeight)
8723b5a892a1SMatthew G. Knepley {
8724b5a892a1SMatthew G. Knepley   PetscErrorCode ierr;
8725b5a892a1SMatthew G. Knepley 
8726b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
8727b5a892a1SMatthew G. Knepley   ierr = DMPlexCheckSymmetry(dm);CHKERRQ(ierr);
8728b5a892a1SMatthew G. Knepley   ierr = DMPlexCheckSkeleton(dm, cellHeight);CHKERRQ(ierr);
8729b5a892a1SMatthew G. Knepley   ierr = DMPlexCheckFaces(dm, cellHeight);CHKERRQ(ierr);
8730b5a892a1SMatthew G. Knepley   ierr = DMPlexCheckGeometry(dm);CHKERRQ(ierr);
8731b5a892a1SMatthew G. Knepley   ierr = DMPlexCheckPointSF(dm);CHKERRQ(ierr);
8732b5a892a1SMatthew G. Knepley   ierr = DMPlexCheckInterfaceCones(dm);CHKERRQ(ierr);
8733b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
8734b5a892a1SMatthew G. Knepley }
8735b5a892a1SMatthew G. Knepley 
8736068a5610SStefano Zampini typedef struct cell_stats
8737068a5610SStefano Zampini {
8738068a5610SStefano Zampini   PetscReal min, max, sum, squaresum;
8739068a5610SStefano Zampini   PetscInt  count;
8740068a5610SStefano Zampini } cell_stats_t;
8741068a5610SStefano Zampini 
874225befc3bSSatish Balay static void MPIAPI cell_stats_reduce(void *a, void *b, int * len, MPI_Datatype *datatype)
8743068a5610SStefano Zampini {
8744068a5610SStefano Zampini   PetscInt i, N = *len;
8745068a5610SStefano Zampini 
8746068a5610SStefano Zampini   for (i = 0; i < N; i++) {
8747068a5610SStefano Zampini     cell_stats_t *A = (cell_stats_t *) a;
8748068a5610SStefano Zampini     cell_stats_t *B = (cell_stats_t *) b;
8749068a5610SStefano Zampini 
8750068a5610SStefano Zampini     B->min = PetscMin(A->min,B->min);
8751068a5610SStefano Zampini     B->max = PetscMax(A->max,B->max);
8752068a5610SStefano Zampini     B->sum += A->sum;
8753068a5610SStefano Zampini     B->squaresum += A->squaresum;
8754068a5610SStefano Zampini     B->count += A->count;
8755068a5610SStefano Zampini   }
8756068a5610SStefano Zampini }
8757068a5610SStefano Zampini 
8758068a5610SStefano Zampini /*@
875943fa8764SMatthew G. Knepley   DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics.
8760068a5610SStefano Zampini 
87618261a58bSMatthew G. Knepley   Collective on dm
87628261a58bSMatthew G. Knepley 
8763068a5610SStefano Zampini   Input Parameters:
8764068a5610SStefano Zampini + dm        - The DMPlex object
876543fa8764SMatthew G. Knepley . output    - If true, statistics will be displayed on stdout
876643fa8764SMatthew G. Knepley - condLimit - Display all cells above this condition number, or PETSC_DETERMINE for no cell output
8767068a5610SStefano Zampini 
876895eb5ee5SVaclav Hapla   Notes:
876995eb5ee5SVaclav Hapla   This is mainly intended for debugging/testing purposes.
877095eb5ee5SVaclav Hapla 
877195eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
8772068a5610SStefano Zampini 
8773068a5610SStefano Zampini   Level: developer
8774068a5610SStefano Zampini 
8775f108dbd7SJacob Faibussowitsch .seealso: DMSetFromOptions(), DMPlexComputeOrthogonalQuality()
8776068a5610SStefano Zampini @*/
877743fa8764SMatthew G. Knepley PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit)
8778068a5610SStefano Zampini {
8779068a5610SStefano Zampini   DM             dmCoarse;
878043fa8764SMatthew G. Knepley   cell_stats_t   stats, globalStats;
878143fa8764SMatthew G. Knepley   MPI_Comm       comm = PetscObjectComm((PetscObject)dm);
878243fa8764SMatthew G. Knepley   PetscReal      *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0;
878343fa8764SMatthew G. Knepley   PetscReal      limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL;
8784412e9a14SMatthew G. Knepley   PetscInt       cdim, cStart, cEnd, c, eStart, eEnd, count = 0;
878543fa8764SMatthew G. Knepley   PetscMPIInt    rank,size;
8786068a5610SStefano Zampini   PetscErrorCode ierr;
8787068a5610SStefano Zampini 
8788068a5610SStefano Zampini   PetscFunctionBegin;
8789068a5610SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8790068a5610SStefano Zampini   stats.min   = PETSC_MAX_REAL;
8791068a5610SStefano Zampini   stats.max   = PETSC_MIN_REAL;
8792068a5610SStefano Zampini   stats.sum   = stats.squaresum = 0.;
8793068a5610SStefano Zampini   stats.count = 0;
8794068a5610SStefano Zampini 
8795ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr);
8796ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
879743fa8764SMatthew G. Knepley   ierr = DMGetCoordinateDim(dm,&cdim);CHKERRQ(ierr);
879843fa8764SMatthew G. Knepley   ierr = PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ);CHKERRQ(ierr);
8799412e9a14SMatthew G. Knepley   ierr = DMPlexGetSimplexOrBoxCells(dm,0,&cStart,&cEnd);CHKERRQ(ierr);
880043fa8764SMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm,1,&eStart,&eEnd);CHKERRQ(ierr);
8801412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; c++) {
8802068a5610SStefano Zampini     PetscInt  i;
8803068a5610SStefano Zampini     PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ;
8804068a5610SStefano Zampini 
8805068a5610SStefano Zampini     ierr = DMPlexComputeCellGeometryAffineFEM(dm,c,NULL,J,invJ,&detJ);CHKERRQ(ierr);
88062c71b3e2SJacob Faibussowitsch     PetscCheckFalse(detJ < 0.0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %D is inverted", c);
880743fa8764SMatthew G. Knepley     for (i = 0; i < PetscSqr(cdim); ++i) {
8808068a5610SStefano Zampini       frobJ    += J[i] * J[i];
8809068a5610SStefano Zampini       frobInvJ += invJ[i] * invJ[i];
8810068a5610SStefano Zampini     }
8811068a5610SStefano Zampini     cond2 = frobJ * frobInvJ;
8812068a5610SStefano Zampini     cond  = PetscSqrtReal(cond2);
8813068a5610SStefano Zampini 
8814068a5610SStefano Zampini     stats.min        = PetscMin(stats.min,cond);
8815068a5610SStefano Zampini     stats.max        = PetscMax(stats.max,cond);
8816068a5610SStefano Zampini     stats.sum       += cond;
8817068a5610SStefano Zampini     stats.squaresum += cond2;
8818068a5610SStefano Zampini     stats.count++;
88198261a58bSMatthew G. Knepley     if (output && cond > limit) {
882043fa8764SMatthew G. Knepley       PetscSection coordSection;
882143fa8764SMatthew G. Knepley       Vec          coordsLocal;
882243fa8764SMatthew G. Knepley       PetscScalar *coords = NULL;
882343fa8764SMatthew G. Knepley       PetscInt     Nv, d, clSize, cl, *closure = NULL;
882443fa8764SMatthew G. Knepley 
882543fa8764SMatthew G. Knepley       ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr);
882643fa8764SMatthew G. Knepley       ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr);
882743fa8764SMatthew G. Knepley       ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords);CHKERRQ(ierr);
8828087ef6b2SMatthew G. Knepley       ierr = PetscSynchronizedPrintf(comm, "[%d] Cell %D cond %g\n", rank, c, (double) cond);CHKERRQ(ierr);
882943fa8764SMatthew G. Knepley       for (i = 0; i < Nv/cdim; ++i) {
883043fa8764SMatthew G. Knepley         ierr = PetscSynchronizedPrintf(comm, "  Vertex %D: (", i);CHKERRQ(ierr);
883143fa8764SMatthew G. Knepley         for (d = 0; d < cdim; ++d) {
883243fa8764SMatthew G. Knepley           if (d > 0) {ierr = PetscSynchronizedPrintf(comm, ", ");CHKERRQ(ierr);}
883348afe810SSatish Balay           ierr = PetscSynchronizedPrintf(comm, "%g", (double) PetscRealPart(coords[i*cdim+d]));CHKERRQ(ierr);
883443fa8764SMatthew G. Knepley         }
883543fa8764SMatthew G. Knepley         ierr = PetscSynchronizedPrintf(comm, ")\n");CHKERRQ(ierr);
883643fa8764SMatthew G. Knepley       }
883743fa8764SMatthew G. Knepley       ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr);
883843fa8764SMatthew G. Knepley       for (cl = 0; cl < clSize*2; cl += 2) {
883943fa8764SMatthew G. Knepley         const PetscInt edge = closure[cl];
884043fa8764SMatthew G. Knepley 
884143fa8764SMatthew G. Knepley         if ((edge >= eStart) && (edge < eEnd)) {
884243fa8764SMatthew G. Knepley           PetscReal len;
884343fa8764SMatthew G. Knepley 
884443fa8764SMatthew G. Knepley           ierr = DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL);CHKERRQ(ierr);
8845087ef6b2SMatthew G. Knepley           ierr = PetscSynchronizedPrintf(comm, "  Edge %D: length %g\n", edge, (double) len);CHKERRQ(ierr);
884643fa8764SMatthew G. Knepley         }
884743fa8764SMatthew G. Knepley       }
884843fa8764SMatthew G. Knepley       ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr);
884943fa8764SMatthew G. Knepley       ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords);CHKERRQ(ierr);
885043fa8764SMatthew G. Knepley     }
8851068a5610SStefano Zampini   }
88528261a58bSMatthew G. Knepley   if (output) {ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);}
8853068a5610SStefano Zampini 
8854068a5610SStefano Zampini   if (size > 1) {
8855068a5610SStefano Zampini     PetscMPIInt   blockLengths[2] = {4,1};
8856068a5610SStefano Zampini     MPI_Aint      blockOffsets[2] = {offsetof(cell_stats_t,min),offsetof(cell_stats_t,count)};
8857068a5610SStefano Zampini     MPI_Datatype  blockTypes[2]   = {MPIU_REAL,MPIU_INT}, statType;
8858068a5610SStefano Zampini     MPI_Op        statReduce;
8859068a5610SStefano Zampini 
8860ffc4695bSBarry Smith     ierr = MPI_Type_create_struct(2,blockLengths,blockOffsets,blockTypes,&statType);CHKERRMPI(ierr);
8861ffc4695bSBarry Smith     ierr = MPI_Type_commit(&statType);CHKERRMPI(ierr);
8862ffc4695bSBarry Smith     ierr = MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce);CHKERRMPI(ierr);
8863ffc4695bSBarry Smith     ierr = MPI_Reduce(&stats,&globalStats,1,statType,statReduce,0,comm);CHKERRMPI(ierr);
8864ffc4695bSBarry Smith     ierr = MPI_Op_free(&statReduce);CHKERRMPI(ierr);
8865ffc4695bSBarry Smith     ierr = MPI_Type_free(&statType);CHKERRMPI(ierr);
8866068a5610SStefano Zampini   } else {
8867580bdb30SBarry Smith     ierr = PetscArraycpy(&globalStats,&stats,1);CHKERRQ(ierr);
8868068a5610SStefano Zampini   }
8869dd400576SPatrick Sanan   if (rank == 0) {
8870068a5610SStefano Zampini     count = globalStats.count;
8871068a5610SStefano Zampini     min   = globalStats.min;
8872068a5610SStefano Zampini     max   = globalStats.max;
8873068a5610SStefano Zampini     mean  = globalStats.sum / globalStats.count;
8874068a5610SStefano Zampini     stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1),0)) : 0.0;
8875068a5610SStefano Zampini   }
8876068a5610SStefano Zampini 
8877068a5610SStefano Zampini   if (output) {
8878068a5610SStefano Zampini     ierr = PetscPrintf(comm,"Mesh with %D cells, shape condition numbers: min = %g, max = %g, mean = %g, stddev = %g\n", count, (double) min, (double) max, (double) mean, (double) stdev);CHKERRQ(ierr);
8879068a5610SStefano Zampini   }
8880068a5610SStefano Zampini   ierr = PetscFree2(J,invJ);CHKERRQ(ierr);
8881068a5610SStefano Zampini 
8882068a5610SStefano Zampini   ierr = DMGetCoarseDM(dm,&dmCoarse);CHKERRQ(ierr);
8883068a5610SStefano Zampini   if (dmCoarse) {
8884068a5610SStefano Zampini     PetscBool isplex;
8885068a5610SStefano Zampini 
8886068a5610SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)dmCoarse,DMPLEX,&isplex);CHKERRQ(ierr);
8887068a5610SStefano Zampini     if (isplex) {
888843fa8764SMatthew G. Knepley       ierr = DMPlexCheckCellShape(dmCoarse,output,condLimit);CHKERRQ(ierr);
8889068a5610SStefano Zampini     }
8890068a5610SStefano Zampini   }
8891068a5610SStefano Zampini   PetscFunctionReturn(0);
8892068a5610SStefano Zampini }
8893068a5610SStefano Zampini 
8894f108dbd7SJacob Faibussowitsch /*@
8895f108dbd7SJacob Faibussowitsch   DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with
8896f108dbd7SJacob Faibussowitsch   orthogonal quality below given tolerance.
8897f108dbd7SJacob Faibussowitsch 
88986ed19f2fSJacob Faibussowitsch   Collective on dm
8899f108dbd7SJacob Faibussowitsch 
8900f108dbd7SJacob Faibussowitsch   Input Parameters:
8901f108dbd7SJacob Faibussowitsch + dm   - The DMPlex object
8902f108dbd7SJacob Faibussowitsch . fv   - Optional PetscFV object for pre-computed cell/face centroid information
8903f108dbd7SJacob Faibussowitsch - atol - [0, 1] Absolute tolerance for tagging cells.
8904f108dbd7SJacob Faibussowitsch 
8905f108dbd7SJacob Faibussowitsch   Output Parameters:
8906f108dbd7SJacob Faibussowitsch + OrthQual      - Vec containing orthogonal quality per cell
8907f108dbd7SJacob Faibussowitsch - OrthQualLabel - DMLabel tagging cells below atol with DM_ADAPT_REFINE
8908f108dbd7SJacob Faibussowitsch 
8909f108dbd7SJacob Faibussowitsch   Options Database Keys:
8910f108dbd7SJacob Faibussowitsch + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only PETSCVIEWERASCII is
8911f108dbd7SJacob Faibussowitsch supported.
8912f108dbd7SJacob Faibussowitsch - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector.
8913f108dbd7SJacob Faibussowitsch 
8914f108dbd7SJacob Faibussowitsch   Notes:
8915f108dbd7SJacob Faibussowitsch   Orthogonal quality is given by the following formula:
8916f108dbd7SJacob Faibussowitsch 
8917f108dbd7SJacob Faibussowitsch   \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right]
8918f108dbd7SJacob Faibussowitsch 
8919f108dbd7SJacob Faibussowitsch   Where A_i is the i'th face-normal vector, f_i is the vector from the cell centroid to the i'th face centroid, and c_i
8920f108dbd7SJacob Faibussowitsch   is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the
8921f108dbd7SJacob Faibussowitsch   current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by
8922f108dbd7SJacob Faibussowitsch   calculating the cosine of the angle between these vectors.
8923f108dbd7SJacob Faibussowitsch 
8924f108dbd7SJacob Faibussowitsch   Orthogonal quality ranges from 1 (best) to 0 (worst).
8925f108dbd7SJacob Faibussowitsch 
8926f108dbd7SJacob Faibussowitsch   This routine is mainly useful for FVM, however is not restricted to only FVM. The PetscFV object is optionally used to check for
8927f108dbd7SJacob Faibussowitsch   pre-computed FVM cell data, but if it is not passed in then this data will be computed.
8928f108dbd7SJacob Faibussowitsch 
8929f108dbd7SJacob Faibussowitsch   Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance.
8930f108dbd7SJacob Faibussowitsch 
8931f108dbd7SJacob Faibussowitsch   Level: intermediate
8932f108dbd7SJacob Faibussowitsch 
8933f108dbd7SJacob Faibussowitsch .seealso: DMPlexCheckCellShape(), DMCreateLabel()
8934f108dbd7SJacob Faibussowitsch @*/
8935f108dbd7SJacob Faibussowitsch PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel)
8936f108dbd7SJacob Faibussowitsch {
89376ed19f2fSJacob Faibussowitsch   PetscInt                nc, cellHeight, cStart, cEnd, cell, cellIter = 0;
89386ed19f2fSJacob Faibussowitsch   PetscInt                *idx;
89396ed19f2fSJacob Faibussowitsch   PetscScalar             *oqVals;
8940f108dbd7SJacob Faibussowitsch   const PetscScalar       *cellGeomArr, *faceGeomArr;
89416ed19f2fSJacob Faibussowitsch   PetscReal               *ci, *fi, *Ai;
8942f108dbd7SJacob Faibussowitsch   MPI_Comm                comm;
8943f108dbd7SJacob Faibussowitsch   Vec                     cellgeom, facegeom;
8944f108dbd7SJacob Faibussowitsch   DM                      dmFace, dmCell;
8945f108dbd7SJacob Faibussowitsch   IS                      glob;
8946f108dbd7SJacob Faibussowitsch   ISLocalToGlobalMapping  ltog;
8947f108dbd7SJacob Faibussowitsch   PetscViewer             vwr;
8948f108dbd7SJacob Faibussowitsch   PetscErrorCode          ierr;
8949f108dbd7SJacob Faibussowitsch 
8950f108dbd7SJacob Faibussowitsch   PetscFunctionBegin;
8951f108dbd7SJacob Faibussowitsch   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
89526ed19f2fSJacob Faibussowitsch   if (fv) {PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2);}
8953f108dbd7SJacob Faibussowitsch   PetscValidPointer(OrthQual, 4);
89546bdcaf15SBarry Smith   PetscCheck(atol >= 0.0 && atol <= 1.0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Absolute tolerance %g not in [0,1]",(double)atol);
8955f108dbd7SJacob Faibussowitsch   ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr);
8956f108dbd7SJacob Faibussowitsch   ierr = DMGetDimension(dm, &nc);CHKERRQ(ierr);
89572c71b3e2SJacob Faibussowitsch   PetscCheckFalse(nc < 2,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %D)", nc);
89586ed19f2fSJacob Faibussowitsch   {
89596ed19f2fSJacob Faibussowitsch     DMPlexInterpolatedFlag interpFlag;
89606ed19f2fSJacob Faibussowitsch 
8961f108dbd7SJacob Faibussowitsch     ierr = DMPlexIsInterpolated(dm, &interpFlag);CHKERRQ(ierr);
8962f108dbd7SJacob Faibussowitsch     if (interpFlag != DMPLEX_INTERPOLATED_FULL) {
8963f108dbd7SJacob Faibussowitsch       PetscMPIInt rank;
8964f108dbd7SJacob Faibussowitsch 
8965ffc4695bSBarry Smith       ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
896698921bdaSJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank);
8967f108dbd7SJacob Faibussowitsch     }
89686ed19f2fSJacob Faibussowitsch   }
8969f108dbd7SJacob Faibussowitsch   if (OrthQualLabel) {
8970f108dbd7SJacob Faibussowitsch     PetscValidPointer(OrthQualLabel, 5);
8971f108dbd7SJacob Faibussowitsch     ierr = DMCreateLabel(dm, "Orthogonal_Quality");CHKERRQ(ierr);
8972f108dbd7SJacob Faibussowitsch     ierr = DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel);CHKERRQ(ierr);
89736ed19f2fSJacob Faibussowitsch   } else {*OrthQualLabel = NULL;}
8974f108dbd7SJacob Faibussowitsch   ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr);
8975f108dbd7SJacob Faibussowitsch   ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);
8976f108dbd7SJacob Faibussowitsch   ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob);CHKERRQ(ierr);
8977f108dbd7SJacob Faibussowitsch   ierr = ISLocalToGlobalMappingCreateIS(glob, &ltog);CHKERRQ(ierr);
8978f108dbd7SJacob Faibussowitsch   ierr = ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr);
8979f108dbd7SJacob Faibussowitsch   ierr = VecCreate(comm, OrthQual);CHKERRQ(ierr);
8980f108dbd7SJacob Faibussowitsch   ierr = VecSetType(*OrthQual, VECSTANDARD);CHKERRQ(ierr);
8981f108dbd7SJacob Faibussowitsch   ierr = VecSetSizes(*OrthQual, cEnd-cStart, PETSC_DETERMINE);CHKERRQ(ierr);
8982f108dbd7SJacob Faibussowitsch   ierr = VecSetLocalToGlobalMapping(*OrthQual, ltog);CHKERRQ(ierr);
8983f108dbd7SJacob Faibussowitsch   ierr = VecSetUp(*OrthQual);CHKERRQ(ierr);
8984f108dbd7SJacob Faibussowitsch   ierr = ISDestroy(&glob);CHKERRQ(ierr);
8985f108dbd7SJacob Faibussowitsch   ierr = ISLocalToGlobalMappingDestroy(&ltog);CHKERRQ(ierr);
8986f108dbd7SJacob Faibussowitsch   ierr = DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL);CHKERRQ(ierr);
8987f108dbd7SJacob Faibussowitsch   ierr = VecGetArrayRead(cellgeom, &cellGeomArr);CHKERRQ(ierr);
8988f108dbd7SJacob Faibussowitsch   ierr = VecGetArrayRead(facegeom, &faceGeomArr);CHKERRQ(ierr);
8989f108dbd7SJacob Faibussowitsch   ierr = VecGetDM(cellgeom, &dmCell);CHKERRQ(ierr);
8990f108dbd7SJacob Faibussowitsch   ierr = VecGetDM(facegeom, &dmFace);CHKERRQ(ierr);
89916ed19f2fSJacob Faibussowitsch   ierr = PetscMalloc5(cEnd-cStart, &idx, cEnd-cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai);CHKERRQ(ierr);
89926ed19f2fSJacob Faibussowitsch   for (cell = cStart; cell < cEnd; cellIter++,cell++) {
89936ed19f2fSJacob Faibussowitsch     PetscInt           cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE;
8994f108dbd7SJacob Faibussowitsch     PetscInt           cellarr[2], *adj = NULL;
8995f108dbd7SJacob Faibussowitsch     PetscScalar        *cArr, *fArr;
8996898cd552SSatish Balay     PetscReal          minvalc = 1.0, minvalf = 1.0;
8997f108dbd7SJacob Faibussowitsch     PetscFVCellGeom    *cg;
8998f108dbd7SJacob Faibussowitsch 
89996ed19f2fSJacob Faibussowitsch     idx[cellIter] = cell-cStart;
9000f108dbd7SJacob Faibussowitsch     cellarr[0] = cell;
9001f108dbd7SJacob Faibussowitsch     /* Make indexing into cellGeom easier */
9002f108dbd7SJacob Faibussowitsch     ierr = DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg);CHKERRQ(ierr);
9003f108dbd7SJacob Faibussowitsch     ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj);CHKERRQ(ierr);
9004f108dbd7SJacob Faibussowitsch     /* Technically 1 too big, but easier than fiddling with empty adjacency array */
9005f108dbd7SJacob Faibussowitsch     ierr = PetscCalloc2(adjSize, &cArr, adjSize, &fArr);CHKERRQ(ierr);
90066ed19f2fSJacob Faibussowitsch     for (cellneigh = 0; cellneigh < adjSize; cellneighiter++,cellneigh++) {
90076ed19f2fSJacob Faibussowitsch       PetscInt         i;
90086ed19f2fSJacob Faibussowitsch       const PetscInt   neigh = adj[cellneigh];
9009f108dbd7SJacob Faibussowitsch       PetscReal        normci = 0, normfi = 0, normai = 0;
9010f108dbd7SJacob Faibussowitsch       PetscFVCellGeom  *cgneigh;
9011f108dbd7SJacob Faibussowitsch       PetscFVFaceGeom  *fg;
9012f108dbd7SJacob Faibussowitsch 
9013f108dbd7SJacob Faibussowitsch       /* Don't count ourselves in the neighbor list */
9014f108dbd7SJacob Faibussowitsch       if (neigh == cell) continue;
9015f108dbd7SJacob Faibussowitsch       ierr = DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh);CHKERRQ(ierr);
9016f108dbd7SJacob Faibussowitsch       cellarr[1] = neigh;
90176ed19f2fSJacob Faibussowitsch       {
90186ed19f2fSJacob Faibussowitsch         PetscInt       numcovpts;
90196ed19f2fSJacob Faibussowitsch         const PetscInt *covpts;
90206ed19f2fSJacob Faibussowitsch 
9021f108dbd7SJacob Faibussowitsch         ierr = DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts);CHKERRQ(ierr);
9022f108dbd7SJacob Faibussowitsch         ierr = DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg);CHKERRQ(ierr);
9023f108dbd7SJacob Faibussowitsch         ierr = DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts);CHKERRQ(ierr);
90246ed19f2fSJacob Faibussowitsch       }
9025f108dbd7SJacob Faibussowitsch 
9026f108dbd7SJacob Faibussowitsch       /* Compute c_i, f_i and their norms */
9027f108dbd7SJacob Faibussowitsch       for (i = 0; i < nc; i++) {
9028f108dbd7SJacob Faibussowitsch         ci[i] = cgneigh->centroid[i] - cg->centroid[i];
9029f108dbd7SJacob Faibussowitsch         fi[i] = fg->centroid[i] - cg->centroid[i];
9030f108dbd7SJacob Faibussowitsch         Ai[i] = fg->normal[i];
9031addd1e01SJunchao Zhang         normci += PetscPowReal(ci[i], 2);
9032addd1e01SJunchao Zhang         normfi += PetscPowReal(fi[i], 2);
9033addd1e01SJunchao Zhang         normai += PetscPowReal(Ai[i], 2);
9034f108dbd7SJacob Faibussowitsch       }
9035addd1e01SJunchao Zhang       normci = PetscSqrtReal(normci);
9036addd1e01SJunchao Zhang       normfi = PetscSqrtReal(normfi);
9037addd1e01SJunchao Zhang       normai = PetscSqrtReal(normai);
9038f108dbd7SJacob Faibussowitsch 
9039f108dbd7SJacob Faibussowitsch       /* Normalize and compute for each face-cell-normal pair */
9040f108dbd7SJacob Faibussowitsch       for (i = 0; i < nc; i++) {
9041f108dbd7SJacob Faibussowitsch         ci[i] = ci[i]/normci;
9042f108dbd7SJacob Faibussowitsch         fi[i] = fi[i]/normfi;
9043f108dbd7SJacob Faibussowitsch         Ai[i] = Ai[i]/normai;
9044f108dbd7SJacob Faibussowitsch         /* PetscAbs because I don't know if normals are guaranteed to point out */
9045f108dbd7SJacob Faibussowitsch         cArr[cellneighiter] += PetscAbs(Ai[i]*ci[i]);
9046f108dbd7SJacob Faibussowitsch         fArr[cellneighiter] += PetscAbs(Ai[i]*fi[i]);
9047f108dbd7SJacob Faibussowitsch       }
9048f108dbd7SJacob Faibussowitsch       if (PetscRealPart(cArr[cellneighiter]) < minvalc) {
9049f108dbd7SJacob Faibussowitsch         minvalc = PetscRealPart(cArr[cellneighiter]);
9050f108dbd7SJacob Faibussowitsch       }
9051f108dbd7SJacob Faibussowitsch       if (PetscRealPart(fArr[cellneighiter]) < minvalf) {
9052f108dbd7SJacob Faibussowitsch         minvalf = PetscRealPart(fArr[cellneighiter]);
9053f108dbd7SJacob Faibussowitsch       }
9054f108dbd7SJacob Faibussowitsch     }
9055f108dbd7SJacob Faibussowitsch     ierr = PetscFree(adj);CHKERRQ(ierr);
9056f108dbd7SJacob Faibussowitsch     ierr = PetscFree2(cArr, fArr);CHKERRQ(ierr);
9057f108dbd7SJacob Faibussowitsch     /* Defer to cell if they're equal */
90586ed19f2fSJacob Faibussowitsch     oqVals[cellIter] = PetscMin(minvalf, minvalc);
9059f108dbd7SJacob Faibussowitsch     if (OrthQualLabel) {
90606ed19f2fSJacob Faibussowitsch       if (PetscRealPart(oqVals[cellIter]) <= atol) {ierr = DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE);CHKERRQ(ierr);}
9061f108dbd7SJacob Faibussowitsch     }
9062f108dbd7SJacob Faibussowitsch   }
90636ed19f2fSJacob Faibussowitsch   ierr = VecSetValuesLocal(*OrthQual, cEnd-cStart, idx, oqVals, INSERT_VALUES);CHKERRQ(ierr);
9064f108dbd7SJacob Faibussowitsch   ierr = VecAssemblyBegin(*OrthQual);CHKERRQ(ierr);
9065f108dbd7SJacob Faibussowitsch   ierr = VecAssemblyEnd(*OrthQual);CHKERRQ(ierr);
9066f108dbd7SJacob Faibussowitsch   ierr = VecRestoreArrayRead(cellgeom, &cellGeomArr);CHKERRQ(ierr);
9067f108dbd7SJacob Faibussowitsch   ierr = VecRestoreArrayRead(facegeom, &faceGeomArr);CHKERRQ(ierr);
9068f108dbd7SJacob Faibussowitsch   ierr = PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL);CHKERRQ(ierr);
9069f108dbd7SJacob Faibussowitsch   if (OrthQualLabel) {
90706ed19f2fSJacob Faibussowitsch     if (vwr) {ierr = DMLabelView(*OrthQualLabel, vwr);CHKERRQ(ierr);}
9071f108dbd7SJacob Faibussowitsch   }
90726ed19f2fSJacob Faibussowitsch   ierr = PetscFree5(idx, oqVals, ci, fi, Ai);CHKERRQ(ierr);
9073f108dbd7SJacob Faibussowitsch   ierr = PetscViewerDestroy(&vwr);CHKERRQ(ierr);
9074f108dbd7SJacob Faibussowitsch   ierr = VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view");CHKERRQ(ierr);
9075f108dbd7SJacob Faibussowitsch   PetscFunctionReturn(0);
9076f108dbd7SJacob Faibussowitsch }
9077f108dbd7SJacob Faibussowitsch 
90781eb70e55SToby Isaac /* this is here insead of DMGetOutputDM because output DM still has constraints in the local indices that affect
90791eb70e55SToby Isaac  * interpolator construction */
90801eb70e55SToby Isaac static PetscErrorCode DMGetFullDM(DM dm, DM *odm)
90811eb70e55SToby Isaac {
90821eb70e55SToby Isaac   PetscSection   section, newSection, gsection;
90831eb70e55SToby Isaac   PetscSF        sf;
90841eb70e55SToby Isaac   PetscBool      hasConstraints, ghasConstraints;
90851eb70e55SToby Isaac   PetscErrorCode ierr;
90861eb70e55SToby Isaac 
90871eb70e55SToby Isaac   PetscFunctionBegin;
90881eb70e55SToby Isaac   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
90891eb70e55SToby Isaac   PetscValidPointer(odm,2);
90901eb70e55SToby Isaac   ierr = DMGetLocalSection(dm, &section);CHKERRQ(ierr);
90911eb70e55SToby Isaac   ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr);
90921eb70e55SToby Isaac   ierr = MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr);
90931eb70e55SToby Isaac   if (!ghasConstraints) {
90941eb70e55SToby Isaac     ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr);
90951eb70e55SToby Isaac     *odm = dm;
90961eb70e55SToby Isaac     PetscFunctionReturn(0);
90971eb70e55SToby Isaac   }
90981eb70e55SToby Isaac   ierr = DMClone(dm, odm);CHKERRQ(ierr);
90991eb70e55SToby Isaac   ierr = DMCopyFields(dm, *odm);CHKERRQ(ierr);
91001eb70e55SToby Isaac   ierr = DMGetLocalSection(*odm, &newSection);CHKERRQ(ierr);
91011eb70e55SToby Isaac   ierr = DMGetPointSF(*odm, &sf);CHKERRQ(ierr);
91021eb70e55SToby Isaac   ierr = PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr);
91031eb70e55SToby Isaac   ierr = DMSetGlobalSection(*odm, gsection);CHKERRQ(ierr);
91041eb70e55SToby Isaac   ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr);
91051eb70e55SToby Isaac   PetscFunctionReturn(0);
91061eb70e55SToby Isaac }
91071eb70e55SToby Isaac 
91081eb70e55SToby Isaac static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift)
91091eb70e55SToby Isaac {
91101eb70e55SToby Isaac   DM             dmco, dmfo;
91111eb70e55SToby Isaac   Mat            interpo;
91121eb70e55SToby Isaac   Vec            rscale;
91131eb70e55SToby Isaac   Vec            cglobalo, clocal;
91141eb70e55SToby Isaac   Vec            fglobal, fglobalo, flocal;
91151eb70e55SToby Isaac   PetscBool      regular;
91161eb70e55SToby Isaac   PetscErrorCode ierr;
91171eb70e55SToby Isaac 
91181eb70e55SToby Isaac   PetscFunctionBegin;
91191eb70e55SToby Isaac   ierr = DMGetFullDM(dmc, &dmco);CHKERRQ(ierr);
91201eb70e55SToby Isaac   ierr = DMGetFullDM(dmf, &dmfo);CHKERRQ(ierr);
91211eb70e55SToby Isaac   ierr = DMSetCoarseDM(dmfo, dmco);CHKERRQ(ierr);
91221eb70e55SToby Isaac   ierr = DMPlexGetRegularRefinement(dmf, &regular);CHKERRQ(ierr);
91231eb70e55SToby Isaac   ierr = DMPlexSetRegularRefinement(dmfo, regular);CHKERRQ(ierr);
91241eb70e55SToby Isaac   ierr = DMCreateInterpolation(dmco, dmfo, &interpo, &rscale);CHKERRQ(ierr);
91251eb70e55SToby Isaac   ierr = DMCreateGlobalVector(dmco, &cglobalo);CHKERRQ(ierr);
91261eb70e55SToby Isaac   ierr = DMCreateLocalVector(dmc, &clocal);CHKERRQ(ierr);
91271eb70e55SToby Isaac   ierr = VecSet(cglobalo, 0.);CHKERRQ(ierr);
91281eb70e55SToby Isaac   ierr = VecSet(clocal, 0.);CHKERRQ(ierr);
91291eb70e55SToby Isaac   ierr = DMCreateGlobalVector(dmf, &fglobal);CHKERRQ(ierr);
91301eb70e55SToby Isaac   ierr = DMCreateGlobalVector(dmfo, &fglobalo);CHKERRQ(ierr);
91311eb70e55SToby Isaac   ierr = DMCreateLocalVector(dmf, &flocal);CHKERRQ(ierr);
91321eb70e55SToby Isaac   ierr = VecSet(fglobal, 0.);CHKERRQ(ierr);
91331eb70e55SToby Isaac   ierr = VecSet(fglobalo, 0.);CHKERRQ(ierr);
91341eb70e55SToby Isaac   ierr = VecSet(flocal, 0.);CHKERRQ(ierr);
91351eb70e55SToby Isaac   ierr = DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL);CHKERRQ(ierr);
91361eb70e55SToby Isaac   ierr = DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo);CHKERRQ(ierr);
91371eb70e55SToby Isaac   ierr = DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo);CHKERRQ(ierr);
91381eb70e55SToby Isaac   ierr = MatMult(interpo, cglobalo, fglobalo);CHKERRQ(ierr);
91391eb70e55SToby Isaac   ierr = DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal);CHKERRQ(ierr);
91401eb70e55SToby Isaac   ierr = DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal);CHKERRQ(ierr);
91411eb70e55SToby Isaac   ierr = DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal);CHKERRQ(ierr);
91421eb70e55SToby Isaac   ierr = DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal);CHKERRQ(ierr);
91431eb70e55SToby Isaac   *shift = fglobal;
91441eb70e55SToby Isaac   ierr = VecDestroy(&flocal);CHKERRQ(ierr);
91451eb70e55SToby Isaac   ierr = VecDestroy(&fglobalo);CHKERRQ(ierr);
91461eb70e55SToby Isaac   ierr = VecDestroy(&clocal);CHKERRQ(ierr);
91471eb70e55SToby Isaac   ierr = VecDestroy(&cglobalo);CHKERRQ(ierr);
91481eb70e55SToby Isaac   ierr = VecDestroy(&rscale);CHKERRQ(ierr);
91491eb70e55SToby Isaac   ierr = MatDestroy(&interpo);CHKERRQ(ierr);
91501eb70e55SToby Isaac   ierr = DMDestroy(&dmfo);CHKERRQ(ierr);
91511eb70e55SToby Isaac   ierr = DMDestroy(&dmco);CHKERRQ(ierr);
91521eb70e55SToby Isaac   PetscFunctionReturn(0);
91531eb70e55SToby Isaac }
91541eb70e55SToby Isaac 
91551eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol)
91561eb70e55SToby Isaac {
91571eb70e55SToby Isaac   PetscObject    shifto;
91581eb70e55SToby Isaac   Vec            shift;
91591eb70e55SToby Isaac 
91601eb70e55SToby Isaac   PetscErrorCode ierr;
91611eb70e55SToby Isaac 
91621eb70e55SToby Isaac   PetscFunctionBegin;
91631eb70e55SToby Isaac   if (!interp) {
91641eb70e55SToby Isaac     Vec rscale;
91651eb70e55SToby Isaac 
91661eb70e55SToby Isaac     ierr = DMCreateInterpolation(coarse, fine, &interp, &rscale);CHKERRQ(ierr);
91671eb70e55SToby Isaac     ierr = VecDestroy(&rscale);CHKERRQ(ierr);
91681eb70e55SToby Isaac   } else {
91691eb70e55SToby Isaac     ierr = PetscObjectReference((PetscObject)interp);CHKERRQ(ierr);
91701eb70e55SToby Isaac   }
91711eb70e55SToby Isaac   ierr = PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto);CHKERRQ(ierr);
91721eb70e55SToby Isaac   if (!shifto) {
91731eb70e55SToby Isaac     ierr = DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift);CHKERRQ(ierr);
91741eb70e55SToby Isaac     ierr = PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject) shift);CHKERRQ(ierr);
91751eb70e55SToby Isaac     shifto = (PetscObject) shift;
91761eb70e55SToby Isaac     ierr = VecDestroy(&shift);CHKERRQ(ierr);
91771eb70e55SToby Isaac   }
91781eb70e55SToby Isaac   shift = (Vec) shifto;
91791eb70e55SToby Isaac   ierr = MatInterpolate(interp, coarseSol, fineSol);CHKERRQ(ierr);
91801eb70e55SToby Isaac   ierr = VecAXPY(fineSol, 1.0, shift);CHKERRQ(ierr);
91811eb70e55SToby Isaac   ierr = MatDestroy(&interp);CHKERRQ(ierr);
91821eb70e55SToby Isaac   PetscFunctionReturn(0);
91831eb70e55SToby Isaac }
91841eb70e55SToby Isaac 
9185bceba477SMatthew G. Knepley /* Pointwise interpolation
9186bceba477SMatthew G. Knepley      Just code FEM for now
9187bceba477SMatthew G. Knepley      u^f = I u^c
91884ca5e9f5SMatthew G. Knepley      sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j
91894ca5e9f5SMatthew G. Knepley      u^f_i = sum_j psi^f_i I phi^c_j u^c_j
91904ca5e9f5SMatthew G. Knepley      I_{ij} = psi^f_i phi^c_j
9191bceba477SMatthew G. Knepley */
9192bceba477SMatthew G. Knepley PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling)
9193bceba477SMatthew G. Knepley {
9194bceba477SMatthew G. Knepley   PetscSection   gsc, gsf;
9195bceba477SMatthew G. Knepley   PetscInt       m, n;
9196a063dac3SMatthew G. Knepley   void          *ctx;
919768132eb9SMatthew G. Knepley   DM             cdm;
9198cf51de39SMatthew G. Knepley   PetscBool      regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE;
9199bceba477SMatthew G. Knepley   PetscErrorCode ierr;
9200bceba477SMatthew G. Knepley 
9201bceba477SMatthew G. Knepley   PetscFunctionBegin;
9202e87a4003SBarry Smith   ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr);
9203bceba477SMatthew G. Knepley   ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr);
9204e87a4003SBarry Smith   ierr = DMGetGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr);
9205bceba477SMatthew G. Knepley   ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr);
920668132eb9SMatthew G. Knepley 
9207fd194bc8SStefano Zampini   ierr = PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis);CHKERRQ(ierr);
9208bceba477SMatthew G. Knepley   ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation);CHKERRQ(ierr);
9209bceba477SMatthew G. Knepley   ierr = MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
9210fd194bc8SStefano Zampini   ierr = MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype);CHKERRQ(ierr);
9211a063dac3SMatthew G. Knepley   ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr);
921268132eb9SMatthew G. Knepley 
9213a8fb8f29SToby Isaac   ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr);
921468132eb9SMatthew G. Knepley   ierr = DMPlexGetRegularRefinement(dmFine, &regular);CHKERRQ(ierr);
9215cf51de39SMatthew G. Knepley   if (!isRefined || (regular && cdm == dmCoarse)) {ierr = DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx);CHKERRQ(ierr);}
921668132eb9SMatthew G. Knepley   else                                            {ierr = DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);}
921768132eb9SMatthew G. Knepley   ierr = MatViewFromOptions(*interpolation, NULL, "-interp_mat_view");CHKERRQ(ierr);
92184db47ee9SStefano Zampini   if (scaling) {
92195d1c2e58SMatthew G. Knepley     /* Use naive scaling */
92205d1c2e58SMatthew G. Knepley     ierr = DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling);CHKERRQ(ierr);
92214db47ee9SStefano Zampini   }
9222a063dac3SMatthew G. Knepley   PetscFunctionReturn(0);
9223a063dac3SMatthew G. Knepley }
9224bceba477SMatthew G. Knepley 
92256dbf9973SLawrence Mitchell PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat)
9226a063dac3SMatthew G. Knepley {
922790748bafSMatthew G. Knepley   PetscErrorCode ierr;
92286dbf9973SLawrence Mitchell   VecScatter     ctx;
922990748bafSMatthew G. Knepley 
9230a063dac3SMatthew G. Knepley   PetscFunctionBegin;
92316dbf9973SLawrence Mitchell   ierr = DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL);CHKERRQ(ierr);
92326dbf9973SLawrence Mitchell   ierr = MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat);CHKERRQ(ierr);
92336dbf9973SLawrence Mitchell   ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr);
9234bceba477SMatthew G. Knepley   PetscFunctionReturn(0);
9235bceba477SMatthew G. Knepley }
9236bceba477SMatthew G. Knepley 
92373e9753d6SMatthew G. Knepley static void g0_identity_private(PetscInt dim, PetscInt Nf, PetscInt NfAux,
92383e9753d6SMatthew G. Knepley                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
92393e9753d6SMatthew G. Knepley                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
92403e9753d6SMatthew G. Knepley                                 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[])
92413e9753d6SMatthew G. Knepley {
924200635df3SMatthew G. Knepley   const PetscInt Nc = uOff[1] - uOff[0];
924300635df3SMatthew G. Knepley   PetscInt       c;
924400635df3SMatthew G. Knepley   for (c = 0; c < Nc; ++c) g0[c*Nc+c] = 1.0;
92453e9753d6SMatthew G. Knepley }
92463e9753d6SMatthew G. Knepley 
9247b4937a87SMatthew G. Knepley PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *mass)
9248b4937a87SMatthew G. Knepley {
9249b4937a87SMatthew G. Knepley   DM             dmc;
9250b4937a87SMatthew G. Knepley   PetscDS        ds;
9251b4937a87SMatthew G. Knepley   Vec            ones, locmass;
9252b4937a87SMatthew G. Knepley   IS             cellIS;
9253b4937a87SMatthew G. Knepley   PetscFormKey   key;
9254b4937a87SMatthew G. Knepley   PetscInt       depth;
9255b4937a87SMatthew G. Knepley   PetscErrorCode ierr;
9256b4937a87SMatthew G. Knepley 
9257b4937a87SMatthew G. Knepley   PetscFunctionBegin;
9258b4937a87SMatthew G. Knepley   ierr = DMClone(dm, &dmc);CHKERRQ(ierr);
9259b4937a87SMatthew G. Knepley   ierr = DMCopyDisc(dm, dmc);CHKERRQ(ierr);
9260b4937a87SMatthew G. Knepley   ierr = DMGetDS(dmc, &ds);CHKERRQ(ierr);
9261b4937a87SMatthew G. Knepley   ierr = PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL);CHKERRQ(ierr);
9262b4937a87SMatthew G. Knepley   ierr = DMCreateGlobalVector(dmc, mass);CHKERRQ(ierr);
9263b4937a87SMatthew G. Knepley   ierr = DMGetLocalVector(dmc, &ones);CHKERRQ(ierr);
9264b4937a87SMatthew G. Knepley   ierr = DMGetLocalVector(dmc, &locmass);CHKERRQ(ierr);
9265b4937a87SMatthew G. Knepley   ierr = DMPlexGetDepth(dmc, &depth);CHKERRQ(ierr);
9266b4937a87SMatthew G. Knepley   ierr = DMGetStratumIS(dmc, "depth", depth, &cellIS);CHKERRQ(ierr);
9267b4937a87SMatthew G. Knepley   ierr = VecSet(locmass, 0.0);CHKERRQ(ierr);
9268b4937a87SMatthew G. Knepley   ierr = VecSet(ones, 1.0);CHKERRQ(ierr);
9269b4937a87SMatthew G. Knepley   key.label = NULL;
9270b4937a87SMatthew G. Knepley   key.value = 0;
9271b4937a87SMatthew G. Knepley   key.field = 0;
9272b4937a87SMatthew G. Knepley   key.part  = 0;
9273b4937a87SMatthew G. Knepley   ierr = DMPlexComputeJacobian_Action_Internal(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL);CHKERRQ(ierr);
9274b4937a87SMatthew G. Knepley   ierr = ISDestroy(&cellIS);CHKERRQ(ierr);
9275b4937a87SMatthew G. Knepley   ierr = VecSet(*mass, 0.0);CHKERRQ(ierr);
9276b4937a87SMatthew G. Knepley   ierr = DMLocalToGlobalBegin(dmc, locmass, ADD_VALUES, *mass);CHKERRQ(ierr);
9277b4937a87SMatthew G. Knepley   ierr = DMLocalToGlobalEnd(dmc, locmass, ADD_VALUES, *mass);CHKERRQ(ierr);
9278b4937a87SMatthew G. Knepley   ierr = DMRestoreLocalVector(dmc, &ones);CHKERRQ(ierr);
9279b4937a87SMatthew G. Knepley   ierr = DMRestoreLocalVector(dmc, &locmass);CHKERRQ(ierr);
9280b4937a87SMatthew G. Knepley   ierr = DMDestroy(&dmc);CHKERRQ(ierr);
9281b4937a87SMatthew G. Knepley   PetscFunctionReturn(0);
9282b4937a87SMatthew G. Knepley }
9283b4937a87SMatthew G. Knepley 
9284bd041c0cSMatthew G. Knepley PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass)
9285bd041c0cSMatthew G. Knepley {
9286bd041c0cSMatthew G. Knepley   PetscSection   gsc, gsf;
9287bd041c0cSMatthew G. Knepley   PetscInt       m, n;
9288bd041c0cSMatthew G. Knepley   void          *ctx;
9289bd041c0cSMatthew G. Knepley   DM             cdm;
9290bd041c0cSMatthew G. Knepley   PetscBool      regular;
9291bd041c0cSMatthew G. Knepley   PetscErrorCode ierr;
9292bd041c0cSMatthew G. Knepley 
9293bd041c0cSMatthew G. Knepley   PetscFunctionBegin;
92943e9753d6SMatthew G. Knepley   if (dmFine == dmCoarse) {
92953e9753d6SMatthew G. Knepley     DM            dmc;
92963e9753d6SMatthew G. Knepley     PetscDS       ds;
9297b4937a87SMatthew G. Knepley     PetscWeakForm wf;
92983e9753d6SMatthew G. Knepley     Vec           u;
92993e9753d6SMatthew G. Knepley     IS            cellIS;
930006ad1575SMatthew G. Knepley     PetscFormKey  key;
93013e9753d6SMatthew G. Knepley     PetscInt      depth;
93023e9753d6SMatthew G. Knepley 
93033e9753d6SMatthew G. Knepley     ierr = DMClone(dmFine, &dmc);CHKERRQ(ierr);
93043e9753d6SMatthew G. Knepley     ierr = DMCopyDisc(dmFine, dmc);CHKERRQ(ierr);
93053e9753d6SMatthew G. Knepley     ierr = DMGetDS(dmc, &ds);CHKERRQ(ierr);
9306b4937a87SMatthew G. Knepley     ierr = PetscDSGetWeakForm(ds, &wf);CHKERRQ(ierr);
9307b4937a87SMatthew G. Knepley     ierr = PetscWeakFormClear(wf);CHKERRQ(ierr);
93083e9753d6SMatthew G. Knepley     ierr = PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL);CHKERRQ(ierr);
93093e9753d6SMatthew G. Knepley     ierr = DMCreateMatrix(dmc, mass);CHKERRQ(ierr);
93103e9753d6SMatthew G. Knepley     ierr = DMGetGlobalVector(dmc, &u);CHKERRQ(ierr);
93113e9753d6SMatthew G. Knepley     ierr = DMPlexGetDepth(dmc, &depth);CHKERRQ(ierr);
93123e9753d6SMatthew G. Knepley     ierr = DMGetStratumIS(dmc, "depth", depth, &cellIS);CHKERRQ(ierr);
93133e9753d6SMatthew G. Knepley     ierr = MatZeroEntries(*mass);CHKERRQ(ierr);
93146528b96dSMatthew G. Knepley     key.label = NULL;
93156528b96dSMatthew G. Knepley     key.value = 0;
93166528b96dSMatthew G. Knepley     key.field = 0;
931706ad1575SMatthew G. Knepley     key.part  = 0;
93186528b96dSMatthew G. Knepley     ierr = DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL);CHKERRQ(ierr);
93193e9753d6SMatthew G. Knepley     ierr = ISDestroy(&cellIS);CHKERRQ(ierr);
93203e9753d6SMatthew G. Knepley     ierr = DMRestoreGlobalVector(dmc, &u);CHKERRQ(ierr);
93213e9753d6SMatthew G. Knepley     ierr = DMDestroy(&dmc);CHKERRQ(ierr);
93223e9753d6SMatthew G. Knepley   } else {
9323e87a4003SBarry Smith     ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr);
9324bd041c0cSMatthew G. Knepley     ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr);
9325e87a4003SBarry Smith     ierr = DMGetGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr);
9326bd041c0cSMatthew G. Knepley     ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr);
9327bd041c0cSMatthew G. Knepley 
9328bd041c0cSMatthew G. Knepley     ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass);CHKERRQ(ierr);
9329bd041c0cSMatthew G. Knepley     ierr = MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
9330bd041c0cSMatthew G. Knepley     ierr = MatSetType(*mass, dmCoarse->mattype);CHKERRQ(ierr);
9331bd041c0cSMatthew G. Knepley     ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr);
9332bd041c0cSMatthew G. Knepley 
9333bd041c0cSMatthew G. Knepley     ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr);
9334bd041c0cSMatthew G. Knepley     ierr = DMPlexGetRegularRefinement(dmFine, &regular);CHKERRQ(ierr);
9335bd041c0cSMatthew G. Knepley     if (regular && cdm == dmCoarse) {ierr = DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);}
9336bd041c0cSMatthew G. Knepley     else                            {ierr = DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);}
93373e9753d6SMatthew G. Knepley   }
9338bd041c0cSMatthew G. Knepley   ierr = MatViewFromOptions(*mass, NULL, "-mass_mat_view");CHKERRQ(ierr);
9339bd041c0cSMatthew G. Knepley   PetscFunctionReturn(0);
9340bd041c0cSMatthew G. Knepley }
9341bd041c0cSMatthew G. Knepley 
93420aef6b92SMatthew G. Knepley /*@
93430aef6b92SMatthew G. Knepley   DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh
93440aef6b92SMatthew G. Knepley 
93450aef6b92SMatthew G. Knepley   Input Parameter:
93460aef6b92SMatthew G. Knepley . dm - The DMPlex object
93470aef6b92SMatthew G. Knepley 
93480aef6b92SMatthew G. Knepley   Output Parameter:
93490aef6b92SMatthew G. Knepley . regular - The flag
93500aef6b92SMatthew G. Knepley 
93510aef6b92SMatthew G. Knepley   Level: intermediate
93520aef6b92SMatthew G. Knepley 
93530aef6b92SMatthew G. Knepley .seealso: DMPlexSetRegularRefinement()
93540aef6b92SMatthew G. Knepley @*/
93550aef6b92SMatthew G. Knepley PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular)
93560aef6b92SMatthew G. Knepley {
93570aef6b92SMatthew G. Knepley   PetscFunctionBegin;
93580aef6b92SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
93590aef6b92SMatthew G. Knepley   PetscValidPointer(regular, 2);
93600aef6b92SMatthew G. Knepley   *regular = ((DM_Plex *) dm->data)->regularRefinement;
93610aef6b92SMatthew G. Knepley   PetscFunctionReturn(0);
93620aef6b92SMatthew G. Knepley }
93630aef6b92SMatthew G. Knepley 
93640aef6b92SMatthew G. Knepley /*@
93650aef6b92SMatthew G. Knepley   DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh
93660aef6b92SMatthew G. Knepley 
93670aef6b92SMatthew G. Knepley   Input Parameters:
93680aef6b92SMatthew G. Knepley + dm - The DMPlex object
93690aef6b92SMatthew G. Knepley - regular - The flag
93700aef6b92SMatthew G. Knepley 
93710aef6b92SMatthew G. Knepley   Level: intermediate
93720aef6b92SMatthew G. Knepley 
93730aef6b92SMatthew G. Knepley .seealso: DMPlexGetRegularRefinement()
93740aef6b92SMatthew G. Knepley @*/
93750aef6b92SMatthew G. Knepley PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular)
93760aef6b92SMatthew G. Knepley {
93770aef6b92SMatthew G. Knepley   PetscFunctionBegin;
93780aef6b92SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
93790aef6b92SMatthew G. Knepley   ((DM_Plex *) dm->data)->regularRefinement = regular;
93800aef6b92SMatthew G. Knepley   PetscFunctionReturn(0);
93810aef6b92SMatthew G. Knepley }
93820aef6b92SMatthew G. Knepley 
9383f7c74593SToby Isaac /* anchors */
9384a68b90caSToby Isaac /*@
9385f7c74593SToby Isaac   DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints.  Typically, the user will not have to
9386ebdb1bfaSJed Brown   call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetDefaultConstraints().
9387a68b90caSToby Isaac 
9388e228b242SToby Isaac   not collective
9389a68b90caSToby Isaac 
9390f899ff85SJose E. Roman   Input Parameter:
9391a68b90caSToby Isaac . dm - The DMPlex object
9392a68b90caSToby Isaac 
9393a68b90caSToby Isaac   Output Parameters:
9394a68b90caSToby Isaac + anchorSection - If not NULL, set to the section describing which points anchor the constrained points.
9395a68b90caSToby Isaac - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection
9396a68b90caSToby Isaac 
9397a68b90caSToby Isaac   Level: intermediate
9398a68b90caSToby Isaac 
9399ebdb1bfaSJed Brown .seealso: DMPlexSetAnchors(), DMGetDefaultConstraints(), DMSetDefaultConstraints()
9400a68b90caSToby Isaac @*/
9401a17985deSToby Isaac PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS)
9402a68b90caSToby Isaac {
9403a68b90caSToby Isaac   DM_Plex *plex = (DM_Plex *)dm->data;
940441e6d900SToby Isaac   PetscErrorCode ierr;
9405a68b90caSToby Isaac 
9406a68b90caSToby Isaac   PetscFunctionBegin;
9407a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
940841e6d900SToby Isaac   if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) {ierr = (*plex->createanchors)(dm);CHKERRQ(ierr);}
9409a68b90caSToby Isaac   if (anchorSection) *anchorSection = plex->anchorSection;
9410a68b90caSToby Isaac   if (anchorIS) *anchorIS = plex->anchorIS;
9411a68b90caSToby Isaac   PetscFunctionReturn(0);
9412a68b90caSToby Isaac }
9413a68b90caSToby Isaac 
9414a68b90caSToby Isaac /*@
9415f7c74593SToby Isaac   DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints.  Unlike boundary conditions,
9416f7c74593SToby Isaac   when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a
9417a68b90caSToby Isaac   point's degrees of freedom to be a linear combination of other points' degrees of freedom.
9418a68b90caSToby Isaac 
9419a17985deSToby Isaac   After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling
9420ebdb1bfaSJed Brown   DMGetDefaultConstraints() and filling in the entries in the constraint matrix.
9421a68b90caSToby Isaac 
9422e228b242SToby Isaac   collective on dm
9423a68b90caSToby Isaac 
9424a68b90caSToby Isaac   Input Parameters:
9425a68b90caSToby Isaac + dm - The DMPlex object
9426e228b242SToby Isaac . anchorSection - The section that describes the mapping from constrained points to the anchor points listed in anchorIS.  Must have a local communicator (PETSC_COMM_SELF or derivative).
9427e228b242SToby Isaac - anchorIS - The list of all anchor points.  Must have a local communicator (PETSC_COMM_SELF or derivative).
9428a68b90caSToby Isaac 
9429a68b90caSToby Isaac   The reference counts of anchorSection and anchorIS are incremented.
9430a68b90caSToby Isaac 
9431a68b90caSToby Isaac   Level: intermediate
9432a68b90caSToby Isaac 
9433ebdb1bfaSJed Brown .seealso: DMPlexGetAnchors(), DMGetDefaultConstraints(), DMSetDefaultConstraints()
9434a68b90caSToby Isaac @*/
9435a17985deSToby Isaac PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS)
9436a68b90caSToby Isaac {
9437a68b90caSToby Isaac   DM_Plex        *plex = (DM_Plex *)dm->data;
9438e228b242SToby Isaac   PetscMPIInt    result;
9439a68b90caSToby Isaac   PetscErrorCode ierr;
9440a68b90caSToby Isaac 
9441a68b90caSToby Isaac   PetscFunctionBegin;
9442a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9443e228b242SToby Isaac   if (anchorSection) {
9444e228b242SToby Isaac     PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2);
9445ffc4695bSBarry Smith     ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result);CHKERRMPI(ierr);
94462c71b3e2SJacob Faibussowitsch     PetscCheckFalse(result != MPI_CONGRUENT && result != MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator");
9447e228b242SToby Isaac   }
9448e228b242SToby Isaac   if (anchorIS) {
9449e228b242SToby Isaac     PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3);
9450ffc4695bSBarry Smith     ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result);CHKERRMPI(ierr);
94512c71b3e2SJacob Faibussowitsch     PetscCheckFalse(result != MPI_CONGRUENT && result != MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator");
9452e228b242SToby Isaac   }
9453a68b90caSToby Isaac 
9454a68b90caSToby Isaac   ierr = PetscObjectReference((PetscObject)anchorSection);CHKERRQ(ierr);
9455a68b90caSToby Isaac   ierr = PetscSectionDestroy(&plex->anchorSection);CHKERRQ(ierr);
9456a68b90caSToby Isaac   plex->anchorSection = anchorSection;
9457a68b90caSToby Isaac 
9458a68b90caSToby Isaac   ierr = PetscObjectReference((PetscObject)anchorIS);CHKERRQ(ierr);
9459a68b90caSToby Isaac   ierr = ISDestroy(&plex->anchorIS);CHKERRQ(ierr);
9460a68b90caSToby Isaac   plex->anchorIS = anchorIS;
9461a68b90caSToby Isaac 
9462cf9c20a2SJed Brown   if (PetscUnlikelyDebug(anchorIS && anchorSection)) {
9463a68b90caSToby Isaac     PetscInt size, a, pStart, pEnd;
9464a68b90caSToby Isaac     const PetscInt *anchors;
9465a68b90caSToby Isaac 
9466a68b90caSToby Isaac     ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr);
9467a68b90caSToby Isaac     ierr = ISGetLocalSize(anchorIS,&size);CHKERRQ(ierr);
9468a68b90caSToby Isaac     ierr = ISGetIndices(anchorIS,&anchors);CHKERRQ(ierr);
9469a68b90caSToby Isaac     for (a = 0; a < size; a++) {
9470a68b90caSToby Isaac       PetscInt p;
9471a68b90caSToby Isaac 
9472a68b90caSToby Isaac       p = anchors[a];
9473a68b90caSToby Isaac       if (p >= pStart && p < pEnd) {
9474a68b90caSToby Isaac         PetscInt dof;
9475a68b90caSToby Isaac 
9476a68b90caSToby Isaac         ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr);
9477a68b90caSToby Isaac         if (dof) {
9478a68b90caSToby Isaac           PetscErrorCode ierr2;
9479a68b90caSToby Isaac 
9480a68b90caSToby Isaac           ierr2 = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr2);
948198921bdaSJacob Faibussowitsch           SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %D cannot be constrained and an anchor",p);
9482a68b90caSToby Isaac         }
9483a68b90caSToby Isaac       }
9484a68b90caSToby Isaac     }
9485a68b90caSToby Isaac     ierr = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr);
9486a68b90caSToby Isaac   }
9487f7c74593SToby Isaac   /* reset the generic constraints */
948879769bd5SJed Brown   ierr = DMSetDefaultConstraints(dm,NULL,NULL,NULL);CHKERRQ(ierr);
9489a68b90caSToby Isaac   PetscFunctionReturn(0);
9490a68b90caSToby Isaac }
9491a68b90caSToby Isaac 
9492f7c74593SToby Isaac static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec)
9493a68b90caSToby Isaac {
9494f7c74593SToby Isaac   PetscSection anchorSection;
94956995de1eSToby Isaac   PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f;
9496a68b90caSToby Isaac   PetscErrorCode ierr;
9497a68b90caSToby Isaac 
9498a68b90caSToby Isaac   PetscFunctionBegin;
9499a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9500a17985deSToby Isaac   ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr);
9501e228b242SToby Isaac   ierr = PetscSectionCreate(PETSC_COMM_SELF,cSec);CHKERRQ(ierr);
9502a68b90caSToby Isaac   ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr);
95036995de1eSToby Isaac   if (numFields) {
9504719ab38cSToby Isaac     PetscInt f;
9505a68b90caSToby Isaac     ierr = PetscSectionSetNumFields(*cSec,numFields);CHKERRQ(ierr);
9506719ab38cSToby Isaac 
9507719ab38cSToby Isaac     for (f = 0; f < numFields; f++) {
9508719ab38cSToby Isaac       PetscInt numComp;
9509719ab38cSToby Isaac 
9510719ab38cSToby Isaac       ierr = PetscSectionGetFieldComponents(section,f,&numComp);CHKERRQ(ierr);
9511719ab38cSToby Isaac       ierr = PetscSectionSetFieldComponents(*cSec,f,numComp);CHKERRQ(ierr);
9512719ab38cSToby Isaac     }
95136995de1eSToby Isaac   }
9514a68b90caSToby Isaac   ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr);
95156995de1eSToby Isaac   ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr);
95166995de1eSToby Isaac   pStart = PetscMax(pStart,sStart);
95176995de1eSToby Isaac   pEnd   = PetscMin(pEnd,sEnd);
95186995de1eSToby Isaac   pEnd   = PetscMax(pStart,pEnd);
9519a68b90caSToby Isaac   ierr = PetscSectionSetChart(*cSec,pStart,pEnd);CHKERRQ(ierr);
9520a68b90caSToby Isaac   for (p = pStart; p < pEnd; p++) {
9521a68b90caSToby Isaac     ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr);
9522a68b90caSToby Isaac     if (dof) {
9523a68b90caSToby Isaac       ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr);
9524a68b90caSToby Isaac       ierr = PetscSectionSetDof(*cSec,p,dof);CHKERRQ(ierr);
9525a68b90caSToby Isaac       for (f = 0; f < numFields; f++) {
9526a68b90caSToby Isaac         ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr);
9527a68b90caSToby Isaac         ierr = PetscSectionSetFieldDof(*cSec,p,f,dof);CHKERRQ(ierr);
9528a68b90caSToby Isaac       }
9529a68b90caSToby Isaac     }
9530a68b90caSToby Isaac   }
9531a68b90caSToby Isaac   ierr = PetscSectionSetUp(*cSec);CHKERRQ(ierr);
9532ae65431dSMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) *cSec, "Constraint Section");CHKERRQ(ierr);
9533a68b90caSToby Isaac   PetscFunctionReturn(0);
9534a68b90caSToby Isaac }
9535a68b90caSToby Isaac 
9536f7c74593SToby Isaac static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat)
9537a68b90caSToby Isaac {
9538f7c74593SToby Isaac   PetscSection   aSec;
9539ae65431dSMatthew G. Knepley   PetscInt       pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j;
95400ac89760SToby Isaac   const PetscInt *anchors;
95410ac89760SToby Isaac   PetscInt       numFields, f;
954266ad2231SToby Isaac   IS             aIS;
95430ac89760SToby Isaac   PetscErrorCode ierr;
9544e19f7ee6SMark Adams   MatType        mtype;
9545e19f7ee6SMark Adams   PetscBool      iscuda,iskokkos;
95460ac89760SToby Isaac 
95470ac89760SToby Isaac   PetscFunctionBegin;
95480ac89760SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
95490ac89760SToby Isaac   ierr = PetscSectionGetStorageSize(cSec, &m);CHKERRQ(ierr);
95500ac89760SToby Isaac   ierr = PetscSectionGetStorageSize(section, &n);CHKERRQ(ierr);
95510ac89760SToby Isaac   ierr = MatCreate(PETSC_COMM_SELF,cMat);CHKERRQ(ierr);
95520ac89760SToby Isaac   ierr = MatSetSizes(*cMat,m,n,m,n);CHKERRQ(ierr);
9553e19f7ee6SMark Adams   ierr = PetscStrcmp(dm->mattype,MATSEQAIJCUSPARSE,&iscuda);CHKERRQ(ierr);
9554e19f7ee6SMark Adams   if (!iscuda) { ierr = PetscStrcmp(dm->mattype,MATMPIAIJCUSPARSE,&iscuda);CHKERRQ(ierr); }
9555e19f7ee6SMark Adams   ierr = PetscStrcmp(dm->mattype,MATSEQAIJKOKKOS,&iskokkos);CHKERRQ(ierr);
9556e19f7ee6SMark Adams   if (!iskokkos) { ierr = PetscStrcmp(dm->mattype,MATMPIAIJKOKKOS,&iskokkos);CHKERRQ(ierr); }
9557e19f7ee6SMark Adams   if (iscuda) mtype = MATSEQAIJCUSPARSE;
9558e19f7ee6SMark Adams   else if (iskokkos) mtype = MATSEQAIJKOKKOS;
9559e19f7ee6SMark Adams   else mtype = MATSEQAIJ;
9560e19f7ee6SMark Adams   ierr = MatSetType(*cMat,mtype);CHKERRQ(ierr);
9561a17985deSToby Isaac   ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr);
956266ad2231SToby Isaac   ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr);
95636995de1eSToby Isaac   /* cSec will be a subset of aSec and section */
95646995de1eSToby Isaac   ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr);
9565ae65431dSMatthew G. Knepley   ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr);
95660ac89760SToby Isaac   ierr = PetscMalloc1(m+1,&i);CHKERRQ(ierr);
95670ac89760SToby Isaac   i[0] = 0;
95680ac89760SToby Isaac   ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr);
95690ac89760SToby Isaac   for (p = pStart; p < pEnd; p++) {
9570f19733c5SToby Isaac     PetscInt rDof, rOff, r;
9571f19733c5SToby Isaac 
9572f19733c5SToby Isaac     ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr);
9573f19733c5SToby Isaac     if (!rDof) continue;
9574f19733c5SToby Isaac     ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr);
95750ac89760SToby Isaac     if (numFields) {
95760ac89760SToby Isaac       for (f = 0; f < numFields; f++) {
95770ac89760SToby Isaac         annz = 0;
9578f19733c5SToby Isaac         for (r = 0; r < rDof; r++) {
9579f19733c5SToby Isaac           a = anchors[rOff + r];
9580ae65431dSMatthew G. Knepley           if (a < sStart || a >= sEnd) continue;
95810ac89760SToby Isaac           ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr);
95820ac89760SToby Isaac           annz += aDof;
95830ac89760SToby Isaac         }
95840ac89760SToby Isaac         ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr);
95850ac89760SToby Isaac         ierr = PetscSectionGetFieldOffset(cSec,p,f,&off);CHKERRQ(ierr);
95860ac89760SToby Isaac         for (q = 0; q < dof; q++) {
95870ac89760SToby Isaac           i[off + q + 1] = i[off + q] + annz;
95880ac89760SToby Isaac         }
95890ac89760SToby Isaac       }
95902f7452b8SBarry Smith     } else {
95910ac89760SToby Isaac       annz = 0;
9592326b8f31SMatthew G. Knepley       ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr);
95930ac89760SToby Isaac       for (q = 0; q < dof; q++) {
9594ae65431dSMatthew G. Knepley         a = anchors[rOff + q];
9595ae65431dSMatthew G. Knepley         if (a < sStart || a >= sEnd) continue;
95960ac89760SToby Isaac         ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr);
95970ac89760SToby Isaac         annz += aDof;
95980ac89760SToby Isaac       }
95990ac89760SToby Isaac       ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr);
96000ac89760SToby Isaac       ierr = PetscSectionGetOffset(cSec,p,&off);CHKERRQ(ierr);
96010ac89760SToby Isaac       for (q = 0; q < dof; q++) {
96020ac89760SToby Isaac         i[off + q + 1] = i[off + q] + annz;
96030ac89760SToby Isaac       }
96040ac89760SToby Isaac     }
96050ac89760SToby Isaac   }
96060ac89760SToby Isaac   nnz = i[m];
96070ac89760SToby Isaac   ierr = PetscMalloc1(nnz,&j);CHKERRQ(ierr);
96080ac89760SToby Isaac   offset = 0;
96090ac89760SToby Isaac   for (p = pStart; p < pEnd; p++) {
96100ac89760SToby Isaac     if (numFields) {
96110ac89760SToby Isaac       for (f = 0; f < numFields; f++) {
96120ac89760SToby Isaac         ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr);
96130ac89760SToby Isaac         for (q = 0; q < dof; q++) {
96140ac89760SToby Isaac           PetscInt rDof, rOff, r;
96150ac89760SToby Isaac           ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr);
96160ac89760SToby Isaac           ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr);
96170ac89760SToby Isaac           for (r = 0; r < rDof; r++) {
96180ac89760SToby Isaac             PetscInt s;
96190ac89760SToby Isaac 
96200ac89760SToby Isaac             a = anchors[rOff + r];
9621ae65431dSMatthew G. Knepley             if (a < sStart || a >= sEnd) continue;
96220ac89760SToby Isaac             ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr);
96230ac89760SToby Isaac             ierr = PetscSectionGetFieldOffset(section,a,f,&aOff);CHKERRQ(ierr);
96240ac89760SToby Isaac             for (s = 0; s < aDof; s++) {
96250ac89760SToby Isaac               j[offset++] = aOff + s;
96260ac89760SToby Isaac             }
96270ac89760SToby Isaac           }
96280ac89760SToby Isaac         }
96290ac89760SToby Isaac       }
96302f7452b8SBarry Smith     } else {
96310ac89760SToby Isaac       ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr);
96320ac89760SToby Isaac       for (q = 0; q < dof; q++) {
96330ac89760SToby Isaac         PetscInt rDof, rOff, r;
96340ac89760SToby Isaac         ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr);
96350ac89760SToby Isaac         ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr);
96360ac89760SToby Isaac         for (r = 0; r < rDof; r++) {
96370ac89760SToby Isaac           PetscInt s;
96380ac89760SToby Isaac 
96390ac89760SToby Isaac           a = anchors[rOff + r];
9640ae65431dSMatthew G. Knepley           if (a < sStart || a >= sEnd) continue;
96410ac89760SToby Isaac           ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr);
96420ac89760SToby Isaac           ierr = PetscSectionGetOffset(section,a,&aOff);CHKERRQ(ierr);
96430ac89760SToby Isaac           for (s = 0; s < aDof; s++) {
96440ac89760SToby Isaac             j[offset++] = aOff + s;
96450ac89760SToby Isaac           }
96460ac89760SToby Isaac         }
96470ac89760SToby Isaac       }
96480ac89760SToby Isaac     }
96490ac89760SToby Isaac   }
96500ac89760SToby Isaac   ierr = MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL);CHKERRQ(ierr);
965125570a81SToby Isaac   ierr = PetscFree(i);CHKERRQ(ierr);
965225570a81SToby Isaac   ierr = PetscFree(j);CHKERRQ(ierr);
965366ad2231SToby Isaac   ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);
96540ac89760SToby Isaac   PetscFunctionReturn(0);
96550ac89760SToby Isaac }
96560ac89760SToby Isaac 
965766ad2231SToby Isaac PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm)
965866ad2231SToby Isaac {
9659f7c74593SToby Isaac   DM_Plex        *plex = (DM_Plex *)dm->data;
9660f7c74593SToby Isaac   PetscSection   anchorSection, section, cSec;
966166ad2231SToby Isaac   Mat            cMat;
966266ad2231SToby Isaac   PetscErrorCode ierr;
966366ad2231SToby Isaac 
966466ad2231SToby Isaac   PetscFunctionBegin;
966566ad2231SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9666a17985deSToby Isaac   ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr);
966766ad2231SToby Isaac   if (anchorSection) {
966844a7f3ddSMatthew G. Knepley     PetscInt Nf;
9669e228b242SToby Isaac 
967092fd8e1eSJed Brown     ierr = DMGetLocalSection(dm,&section);CHKERRQ(ierr);
9671f7c74593SToby Isaac     ierr = DMPlexCreateConstraintSection_Anchors(dm,section,&cSec);CHKERRQ(ierr);
9672f7c74593SToby Isaac     ierr = DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat);CHKERRQ(ierr);
967344a7f3ddSMatthew G. Knepley     ierr = DMGetNumFields(dm,&Nf);CHKERRQ(ierr);
967444a7f3ddSMatthew G. Knepley     if (Nf && plex->computeanchormatrix) {ierr = (*plex->computeanchormatrix)(dm,section,cSec,cMat);CHKERRQ(ierr);}
967579769bd5SJed Brown     ierr = DMSetDefaultConstraints(dm,cSec,cMat,NULL);CHKERRQ(ierr);
967666ad2231SToby Isaac     ierr = PetscSectionDestroy(&cSec);CHKERRQ(ierr);
967766ad2231SToby Isaac     ierr = MatDestroy(&cMat);CHKERRQ(ierr);
967866ad2231SToby Isaac   }
967966ad2231SToby Isaac   PetscFunctionReturn(0);
968066ad2231SToby Isaac }
9681a93c429eSMatthew G. Knepley 
9682a93c429eSMatthew G. Knepley PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm)
9683a93c429eSMatthew G. Knepley {
9684a93c429eSMatthew G. Knepley   IS             subis;
9685a93c429eSMatthew G. Knepley   PetscSection   section, subsection;
9686a93c429eSMatthew G. Knepley   PetscErrorCode ierr;
9687a93c429eSMatthew G. Knepley 
9688a93c429eSMatthew G. Knepley   PetscFunctionBegin;
968992fd8e1eSJed Brown   ierr = DMGetLocalSection(dm, &section);CHKERRQ(ierr);
96902c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!section,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain");
96912c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!subdm,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain");
9692a93c429eSMatthew G. Knepley   /* Create subdomain */
9693a93c429eSMatthew G. Knepley   ierr = DMPlexFilter(dm, label, value, subdm);CHKERRQ(ierr);
9694a93c429eSMatthew G. Knepley   /* Create submodel */
969597d8846cSMatthew Knepley   ierr = DMPlexGetSubpointIS(*subdm, &subis);CHKERRQ(ierr);
9696a93c429eSMatthew G. Knepley   ierr = PetscSectionCreateSubmeshSection(section, subis, &subsection);CHKERRQ(ierr);
969792fd8e1eSJed Brown   ierr = DMSetLocalSection(*subdm, subsection);CHKERRQ(ierr);
9698a93c429eSMatthew G. Knepley   ierr = PetscSectionDestroy(&subsection);CHKERRQ(ierr);
9699e5e52638SMatthew G. Knepley   ierr = DMCopyDisc(dm, *subdm);CHKERRQ(ierr);
9700a93c429eSMatthew G. Knepley   /* Create map from submodel to global model */
9701a93c429eSMatthew G. Knepley   if (is) {
9702a93c429eSMatthew G. Knepley     PetscSection    sectionGlobal, subsectionGlobal;
9703a93c429eSMatthew G. Knepley     IS              spIS;
9704a93c429eSMatthew G. Knepley     const PetscInt *spmap;
9705a93c429eSMatthew G. Knepley     PetscInt       *subIndices;
9706a93c429eSMatthew G. Knepley     PetscInt        subSize = 0, subOff = 0, pStart, pEnd, p;
9707a93c429eSMatthew G. Knepley     PetscInt        Nf, f, bs = -1, bsLocal[2], bsMinMax[2];
9708a93c429eSMatthew G. Knepley 
970997d8846cSMatthew Knepley     ierr = DMPlexGetSubpointIS(*subdm, &spIS);CHKERRQ(ierr);
9710a93c429eSMatthew G. Knepley     ierr = ISGetIndices(spIS, &spmap);CHKERRQ(ierr);
9711a93c429eSMatthew G. Knepley     ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr);
97126f0eb057SJed Brown     ierr = DMGetGlobalSection(dm, &sectionGlobal);CHKERRQ(ierr);
97136f0eb057SJed Brown     ierr = DMGetGlobalSection(*subdm, &subsectionGlobal);CHKERRQ(ierr);
9714a93c429eSMatthew G. Knepley     ierr = PetscSectionGetChart(subsection, &pStart, &pEnd);CHKERRQ(ierr);
9715a93c429eSMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
9716a93c429eSMatthew G. Knepley       PetscInt gdof, pSubSize  = 0;
9717a93c429eSMatthew G. Knepley 
9718a93c429eSMatthew G. Knepley       ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr);
9719a93c429eSMatthew G. Knepley       if (gdof > 0) {
9720a93c429eSMatthew G. Knepley         for (f = 0; f < Nf; ++f) {
9721a93c429eSMatthew G. Knepley           PetscInt fdof, fcdof;
9722a93c429eSMatthew G. Knepley 
9723a93c429eSMatthew G. Knepley           ierr     = PetscSectionGetFieldDof(subsection, p, f, &fdof);CHKERRQ(ierr);
9724a93c429eSMatthew G. Knepley           ierr     = PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof);CHKERRQ(ierr);
9725a93c429eSMatthew G. Knepley           pSubSize += fdof-fcdof;
9726a93c429eSMatthew G. Knepley         }
9727a93c429eSMatthew G. Knepley         subSize += pSubSize;
9728a93c429eSMatthew G. Knepley         if (pSubSize) {
9729a93c429eSMatthew G. Knepley           if (bs < 0) {
9730a93c429eSMatthew G. Knepley             bs = pSubSize;
9731a93c429eSMatthew G. Knepley           } else if (bs != pSubSize) {
9732a93c429eSMatthew G. Knepley             /* Layout does not admit a pointwise block size */
9733a93c429eSMatthew G. Knepley             bs = 1;
9734a93c429eSMatthew G. Knepley           }
9735a93c429eSMatthew G. Knepley         }
9736a93c429eSMatthew G. Knepley       }
9737a93c429eSMatthew G. Knepley     }
9738a93c429eSMatthew G. Knepley     /* Must have same blocksize on all procs (some might have no points) */
9739a93c429eSMatthew G. Knepley     bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs;
9740a93c429eSMatthew G. Knepley     ierr = PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);CHKERRQ(ierr);
9741a93c429eSMatthew G. Knepley     if (bsMinMax[0] != bsMinMax[1]) {bs = 1;}
9742a93c429eSMatthew G. Knepley     else                            {bs = bsMinMax[0];}
9743a93c429eSMatthew G. Knepley     ierr = PetscMalloc1(subSize, &subIndices);CHKERRQ(ierr);
9744a93c429eSMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
9745a93c429eSMatthew G. Knepley       PetscInt gdof, goff;
9746a93c429eSMatthew G. Knepley 
9747a93c429eSMatthew G. Knepley       ierr = PetscSectionGetDof(subsectionGlobal, p, &gdof);CHKERRQ(ierr);
9748a93c429eSMatthew G. Knepley       if (gdof > 0) {
9749a93c429eSMatthew G. Knepley         const PetscInt point = spmap[p];
9750a93c429eSMatthew G. Knepley 
9751a93c429eSMatthew G. Knepley         ierr = PetscSectionGetOffset(sectionGlobal, point, &goff);CHKERRQ(ierr);
9752a93c429eSMatthew G. Knepley         for (f = 0; f < Nf; ++f) {
9753a93c429eSMatthew G. Knepley           PetscInt fdof, fcdof, fc, f2, poff = 0;
9754a93c429eSMatthew G. Knepley 
9755a93c429eSMatthew G. Knepley           /* Can get rid of this loop by storing field information in the global section */
9756a93c429eSMatthew G. Knepley           for (f2 = 0; f2 < f; ++f2) {
9757a93c429eSMatthew G. Knepley             ierr  = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr);
9758a93c429eSMatthew G. Knepley             ierr  = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr);
9759a93c429eSMatthew G. Knepley             poff += fdof-fcdof;
9760a93c429eSMatthew G. Knepley           }
9761a93c429eSMatthew G. Knepley           ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr);
9762a93c429eSMatthew G. Knepley           ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr);
9763a93c429eSMatthew G. Knepley           for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) {
9764a93c429eSMatthew G. Knepley             subIndices[subOff] = goff+poff+fc;
9765a93c429eSMatthew G. Knepley           }
9766a93c429eSMatthew G. Knepley         }
9767a93c429eSMatthew G. Knepley       }
9768a93c429eSMatthew G. Knepley     }
9769a93c429eSMatthew G. Knepley     ierr = ISRestoreIndices(spIS, &spmap);CHKERRQ(ierr);
9770a93c429eSMatthew G. Knepley     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr);
9771a93c429eSMatthew G. Knepley     if (bs > 1) {
9772a93c429eSMatthew G. Knepley       /* We need to check that the block size does not come from non-contiguous fields */
9773a93c429eSMatthew G. Knepley       PetscInt i, j, set = 1;
9774a93c429eSMatthew G. Knepley       for (i = 0; i < subSize; i += bs) {
9775a93c429eSMatthew G. Knepley         for (j = 0; j < bs; ++j) {
9776a93c429eSMatthew G. Knepley           if (subIndices[i+j] != subIndices[i]+j) {set = 0; break;}
9777a93c429eSMatthew G. Knepley         }
9778a93c429eSMatthew G. Knepley       }
9779a93c429eSMatthew G. Knepley       if (set) {ierr = ISSetBlockSize(*is, bs);CHKERRQ(ierr);}
9780a93c429eSMatthew G. Knepley     }
9781a93c429eSMatthew G. Knepley     /* Attach nullspace */
9782a93c429eSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
9783a93c429eSMatthew G. Knepley       (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f];
9784a93c429eSMatthew G. Knepley       if ((*subdm)->nullspaceConstructors[f]) break;
9785a93c429eSMatthew G. Knepley     }
9786a93c429eSMatthew G. Knepley     if (f < Nf) {
9787a93c429eSMatthew G. Knepley       MatNullSpace nullSpace;
97888cda7954SMatthew G. Knepley       ierr = (*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace);CHKERRQ(ierr);
97896823f3c5SBlaise Bourdin 
9790a93c429eSMatthew G. Knepley       ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr);
9791a93c429eSMatthew G. Knepley       ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr);
9792a93c429eSMatthew G. Knepley     }
9793a93c429eSMatthew G. Knepley   }
9794a93c429eSMatthew G. Knepley   PetscFunctionReturn(0);
9795a93c429eSMatthew G. Knepley }
9796c0f0dcc3SMatthew G. Knepley 
9797c0f0dcc3SMatthew G. Knepley /*@
9798c0f0dcc3SMatthew G. Knepley   DMPlexMonitorThroughput - Report the cell throughput of FE integration
9799c0f0dcc3SMatthew G. Knepley 
9800c0f0dcc3SMatthew G. Knepley   Input Parameter:
9801c0f0dcc3SMatthew G. Knepley - dm - The DM
9802c0f0dcc3SMatthew G. Knepley 
9803c0f0dcc3SMatthew G. Knepley   Level: developer
9804c0f0dcc3SMatthew G. Knepley 
9805c0f0dcc3SMatthew G. Knepley   Options Database Keys:
9806c0f0dcc3SMatthew G. Knepley . -dm_plex_monitor_throughput - Activate the monitor
9807c0f0dcc3SMatthew G. Knepley 
9808c0f0dcc3SMatthew G. Knepley .seealso: DMSetFromOptions(), DMPlexCreate()
9809c0f0dcc3SMatthew G. Knepley @*/
9810c0f0dcc3SMatthew G. Knepley PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy)
9811c0f0dcc3SMatthew G. Knepley {
9812e5ed2c37SJose E. Roman #if defined(PETSC_USE_LOG)
9813c0f0dcc3SMatthew G. Knepley   PetscStageLog      stageLog;
9814c0f0dcc3SMatthew G. Knepley   PetscLogEvent      event;
9815c0f0dcc3SMatthew G. Knepley   PetscLogStage      stage;
9816c0f0dcc3SMatthew G. Knepley   PetscEventPerfInfo eventInfo;
9817c0f0dcc3SMatthew G. Knepley   PetscReal          cellRate, flopRate;
9818c0f0dcc3SMatthew G. Knepley   PetscInt           cStart, cEnd, Nf, N;
9819c0f0dcc3SMatthew G. Knepley   const char        *name;
9820c0f0dcc3SMatthew G. Knepley   PetscErrorCode     ierr;
9821e5ed2c37SJose E. Roman #endif
9822c0f0dcc3SMatthew G. Knepley 
9823c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
9824c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9825c0f0dcc3SMatthew G. Knepley #if defined(PETSC_USE_LOG)
9826c0f0dcc3SMatthew G. Knepley   ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr);
9827c0f0dcc3SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
9828c0f0dcc3SMatthew G. Knepley   ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr);
9829c0f0dcc3SMatthew G. Knepley   ierr = PetscLogGetStageLog(&stageLog);CHKERRQ(ierr);
9830c0f0dcc3SMatthew G. Knepley   ierr = PetscStageLogGetCurrent(stageLog, &stage);CHKERRQ(ierr);
9831c0f0dcc3SMatthew G. Knepley   ierr = PetscLogEventGetId("DMPlexResidualFE", &event);CHKERRQ(ierr);
9832c0f0dcc3SMatthew G. Knepley   ierr = PetscLogEventGetPerfInfo(stage, event, &eventInfo);CHKERRQ(ierr);
9833c0f0dcc3SMatthew G. Knepley   N        = (cEnd - cStart)*Nf*eventInfo.count;
9834c0f0dcc3SMatthew G. Knepley   flopRate = eventInfo.flops/eventInfo.time;
9835c0f0dcc3SMatthew G. Knepley   cellRate = N/eventInfo.time;
9836fae64647SBarry Smith   ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), "DM (%s) FE Residual Integration: %D integrals %D reps\n  Cell rate: %.2g/s flop rate: %.2g MF/s\n", name ? name : "unknown", N, eventInfo.count, (double) cellRate, (double) (flopRate/1.e6));CHKERRQ(ierr);
9837c0f0dcc3SMatthew G. Knepley #else
9838c0f0dcc3SMatthew G. Knepley   SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Plex Throughput Monitor is not supported if logging is turned off. Reconfigure using --with-log.");
9839c0f0dcc3SMatthew G. Knepley #endif
9840c0f0dcc3SMatthew G. Knepley   PetscFunctionReturn(0);
9841c0f0dcc3SMatthew G. Knepley }
9842