xref: /petsc/src/dm/impls/plex/plex.c (revision 9edc354295df6154e58c218ddf771ab21428fc97)
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>
9552f7358SJed Brown 
10552f7358SJed Brown /* Logging support */
11cadf77a0SMark Adams 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;
12552f7358SJed Brown 
135a576424SJed Brown PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer);
14552f7358SJed Brown 
15e5337592SStefano Zampini /*@
169318fe57SMatthew G. Knepley   DMPlexIsSimplex - Is the first cell in this mesh a simplex?
179318fe57SMatthew G. Knepley 
189318fe57SMatthew G. Knepley   Input Parameter:
199318fe57SMatthew G. Knepley . dm      - The DMPlex object
209318fe57SMatthew G. Knepley 
219318fe57SMatthew G. Knepley   Output Parameter:
229318fe57SMatthew G. Knepley . simplex - Flag checking for a simplex
239318fe57SMatthew G. Knepley 
249318fe57SMatthew 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.
259318fe57SMatthew G. Knepley   If the mesh has no cells, this returns PETSC_FALSE.
269318fe57SMatthew G. Knepley 
279318fe57SMatthew G. Knepley   Level: intermediate
289318fe57SMatthew G. Knepley 
299318fe57SMatthew G. Knepley .seealso DMPlexGetSimplexOrBoxCells(), DMPlexGetCellType(), DMPlexGetHeightStratum(), DMPolytopeTypeGetNumVertices()
309318fe57SMatthew G. Knepley @*/
319318fe57SMatthew G. Knepley PetscErrorCode DMPlexIsSimplex(DM dm, PetscBool *simplex)
329318fe57SMatthew G. Knepley {
339318fe57SMatthew G. Knepley   DMPolytopeType ct;
349318fe57SMatthew G. Knepley   PetscInt       cStart, cEnd;
359318fe57SMatthew G. Knepley   PetscErrorCode ierr;
369318fe57SMatthew G. Knepley 
379318fe57SMatthew G. Knepley   PetscFunctionBegin;
389318fe57SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
399318fe57SMatthew G. Knepley   if (cEnd <= cStart) {*simplex = PETSC_FALSE; PetscFunctionReturn(0);}
409318fe57SMatthew G. Knepley   ierr = DMPlexGetCellType(dm, cStart, &ct);CHKERRQ(ierr);
419318fe57SMatthew G. Knepley   *simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE;
429318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
439318fe57SMatthew G. Knepley }
449318fe57SMatthew G. Knepley 
459318fe57SMatthew G. Knepley /*@
46412e9a14SMatthew G. Knepley   DMPlexGetSimplexOrBoxCells - Get the range of cells which are neither prisms nor ghost FV cells
47e5337592SStefano Zampini 
48412e9a14SMatthew G. Knepley   Input Parameter:
49412e9a14SMatthew G. Knepley + dm     - The DMPlex object
50412e9a14SMatthew G. Knepley - height - The cell height in the Plex, 0 is the default
51e5337592SStefano Zampini 
52e5337592SStefano Zampini   Output Parameters:
53412e9a14SMatthew G. Knepley + cStart - The first "normal" cell
54412e9a14SMatthew G. Knepley - cEnd   - The upper bound on "normal"" cells
55e5337592SStefano Zampini 
56412e9a14SMatthew 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.
57e5337592SStefano Zampini 
58412e9a14SMatthew G. Knepley   Level: developer
59e5337592SStefano Zampini 
608065b584SMatthew Knepley .seealso DMPlexConstructGhostCells(), DMPlexGetGhostCellStratum()
61e5337592SStefano Zampini @*/
62412e9a14SMatthew G. Knepley PetscErrorCode DMPlexGetSimplexOrBoxCells(DM dm, PetscInt height, PetscInt *cStart, PetscInt *cEnd)
63e5337592SStefano Zampini {
64412e9a14SMatthew G. Knepley   DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
65412e9a14SMatthew G. Knepley   PetscInt       cS, cE, c;
66e5337592SStefano Zampini   PetscErrorCode ierr;
67e5337592SStefano Zampini 
68e5337592SStefano Zampini   PetscFunctionBegin;
69412e9a14SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, PetscMax(height, 0), &cS, &cE);CHKERRQ(ierr);
70412e9a14SMatthew G. Knepley   for (c = cS; c < cE; ++c) {
71412e9a14SMatthew G. Knepley     DMPolytopeType cct;
72412e9a14SMatthew G. Knepley 
73412e9a14SMatthew G. Knepley     ierr = DMPlexGetCellType(dm, c, &cct);CHKERRQ(ierr);
74412e9a14SMatthew G. Knepley     if ((PetscInt) cct < 0) break;
75412e9a14SMatthew G. Knepley     switch (cct) {
76ba2698f1SMatthew G. Knepley       case DM_POLYTOPE_POINT:
77ba2698f1SMatthew G. Knepley       case DM_POLYTOPE_SEGMENT:
78ba2698f1SMatthew G. Knepley       case DM_POLYTOPE_TRIANGLE:
79ba2698f1SMatthew G. Knepley       case DM_POLYTOPE_QUADRILATERAL:
80ba2698f1SMatthew G. Knepley       case DM_POLYTOPE_TETRAHEDRON:
81ba2698f1SMatthew G. Knepley       case DM_POLYTOPE_HEXAHEDRON:
82412e9a14SMatthew G. Knepley         ct = cct;
83e5337592SStefano Zampini         break;
84412e9a14SMatthew G. Knepley       default: break;
85e5337592SStefano Zampini     }
86412e9a14SMatthew G. Knepley     if (ct != DM_POLYTOPE_UNKNOWN) break;
87e5337592SStefano Zampini   }
88412e9a14SMatthew G. Knepley   if (ct != DM_POLYTOPE_UNKNOWN) {
89412e9a14SMatthew G. Knepley     DMLabel ctLabel;
90412e9a14SMatthew G. Knepley 
91412e9a14SMatthew G. Knepley     ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr);
92412e9a14SMatthew G. Knepley     ierr = DMLabelGetStratumBounds(ctLabel, ct, &cS, &cE);CHKERRQ(ierr);
93e5337592SStefano Zampini   }
94412e9a14SMatthew G. Knepley   if (cStart) *cStart = cS;
95412e9a14SMatthew G. Knepley   if (cEnd)   *cEnd   = cE;
96e5337592SStefano Zampini   PetscFunctionReturn(0);
97e5337592SStefano Zampini }
98e5337592SStefano Zampini 
997afe7537SMatthew G. Knepley PetscErrorCode DMPlexGetFieldType_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *sStart, PetscInt *sEnd, PetscViewerVTKFieldType *ft)
1007e42fee7SMatthew G. Knepley {
101412e9a14SMatthew G. Knepley   PetscInt       cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd;
102a99a26bcSAdrian Croucher   PetscInt       vcdof[2] = {0,0}, globalvcdof[2];
1037e42fee7SMatthew G. Knepley   PetscErrorCode ierr;
1047e42fee7SMatthew G. Knepley 
1057e42fee7SMatthew G. Knepley   PetscFunctionBegin;
106e630c359SToby Isaac   *ft  = PETSC_VTK_INVALID;
107f094498dSMatthew G. Knepley   ierr = DMGetCoordinateDim(dm, &cdim);CHKERRQ(ierr);
1087e42fee7SMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
109412e9a14SMatthew G. Knepley   ierr = DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
1107e42fee7SMatthew G. Knepley   ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr);
1117e42fee7SMatthew G. Knepley   if (field >= 0) {
112a99a26bcSAdrian Croucher     if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetFieldDof(section, vStart, field, &vcdof[0]);CHKERRQ(ierr);}
113a99a26bcSAdrian Croucher     if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetFieldDof(section, cStart, field, &vcdof[1]);CHKERRQ(ierr);}
1147e42fee7SMatthew G. Knepley   } else {
115a99a26bcSAdrian Croucher     if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetDof(section, vStart, &vcdof[0]);CHKERRQ(ierr);}
116a99a26bcSAdrian Croucher     if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetDof(section, cStart, &vcdof[1]);CHKERRQ(ierr);}
1177e42fee7SMatthew G. Knepley   }
118ffc4695bSBarry Smith   ierr = MPI_Allreduce(vcdof, globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr);
119a99a26bcSAdrian Croucher   if (globalvcdof[0]) {
1207e42fee7SMatthew G. Knepley     *sStart = vStart;
1217e42fee7SMatthew G. Knepley     *sEnd   = vEnd;
122f094498dSMatthew G. Knepley     if (globalvcdof[0] == cdim) *ft = PETSC_VTK_POINT_VECTOR_FIELD;
1237e42fee7SMatthew G. Knepley     else                        *ft = PETSC_VTK_POINT_FIELD;
124a99a26bcSAdrian Croucher   } else if (globalvcdof[1]) {
1257e42fee7SMatthew G. Knepley     *sStart = cStart;
1267e42fee7SMatthew G. Knepley     *sEnd   = cEnd;
127f094498dSMatthew G. Knepley     if (globalvcdof[1] == cdim) *ft = PETSC_VTK_CELL_VECTOR_FIELD;
1287e42fee7SMatthew G. Knepley     else                        *ft = PETSC_VTK_CELL_FIELD;
129e630c359SToby Isaac   } else {
130e630c359SToby Isaac     if (field >= 0) {
131e630c359SToby Isaac       const char *fieldname;
132e630c359SToby Isaac 
133e630c359SToby Isaac       ierr = PetscSectionGetFieldName(section, field, &fieldname);CHKERRQ(ierr);
134e630c359SToby Isaac       ierr = PetscInfo2((PetscObject) dm, "Could not classify VTK output type of section field %D \"%s\"\n", field, fieldname);CHKERRQ(ierr);
135e630c359SToby Isaac     } else {
1366823f3c5SBlaise Bourdin       ierr = PetscInfo((PetscObject) dm, "Could not classify VTK output type of section\"%s\"\n");CHKERRQ(ierr);
137e630c359SToby Isaac     }
138e630c359SToby Isaac   }
1397e42fee7SMatthew G. Knepley   PetscFunctionReturn(0);
1407e42fee7SMatthew G. Knepley }
1417e42fee7SMatthew G. Knepley 
1427cd05799SMatthew G. Knepley static PetscErrorCode VecView_Plex_Local_Draw(Vec v, PetscViewer viewer)
143e412dcbdSMatthew G. Knepley {
144e412dcbdSMatthew G. Knepley   DM                 dm;
145d1df6f1dSMatthew G. Knepley   PetscSection       s;
146e412dcbdSMatthew G. Knepley   PetscDraw          draw, popup;
147e412dcbdSMatthew G. Knepley   DM                 cdm;
148e412dcbdSMatthew G. Knepley   PetscSection       coordSection;
149e412dcbdSMatthew G. Knepley   Vec                coordinates;
150e412dcbdSMatthew G. Knepley   const PetscScalar *coords, *array;
151e412dcbdSMatthew G. Knepley   PetscReal          bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL};
152339e3443SMatthew G. Knepley   PetscReal          vbound[2], time;
153339e3443SMatthew G. Knepley   PetscBool          isnull, flg;
154d1df6f1dSMatthew G. Knepley   PetscInt           dim, Nf, f, Nc, comp, vStart, vEnd, cStart, cEnd, c, N, level, step, w = 0;
155e412dcbdSMatthew G. Knepley   const char        *name;
156339e3443SMatthew G. Knepley   char               title[PETSC_MAX_PATH_LEN];
157e412dcbdSMatthew G. Knepley   PetscErrorCode     ierr;
158e412dcbdSMatthew G. Knepley 
159e412dcbdSMatthew G. Knepley   PetscFunctionBegin;
160d1df6f1dSMatthew G. Knepley   ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr);
161d1df6f1dSMatthew G. Knepley   ierr = PetscDrawIsNull(draw, &isnull);CHKERRQ(ierr);
162d1df6f1dSMatthew G. Knepley   if (isnull) PetscFunctionReturn(0);
163d1df6f1dSMatthew G. Knepley 
164e412dcbdSMatthew G. Knepley   ierr = VecGetDM(v, &dm);CHKERRQ(ierr);
165e412dcbdSMatthew G. Knepley   ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr);
1668135c375SStefano Zampini   if (dim != 2) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %D. Use PETSCVIEWERGLVIS", dim);
16792fd8e1eSJed Brown   ierr = DMGetLocalSection(dm, &s);CHKERRQ(ierr);
168d1df6f1dSMatthew G. Knepley   ierr = PetscSectionGetNumFields(s, &Nf);CHKERRQ(ierr);
169e412dcbdSMatthew G. Knepley   ierr = DMGetCoarsenLevel(dm, &level);CHKERRQ(ierr);
170e412dcbdSMatthew G. Knepley   ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
17192fd8e1eSJed Brown   ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr);
172e412dcbdSMatthew G. Knepley   ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
173e412dcbdSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
174e412dcbdSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
175e412dcbdSMatthew G. Knepley 
176e412dcbdSMatthew G. Knepley   ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr);
177339e3443SMatthew G. Knepley   ierr = DMGetOutputSequenceNumber(dm, &step, &time);CHKERRQ(ierr);
178e412dcbdSMatthew G. Knepley 
179e412dcbdSMatthew G. Knepley   ierr = VecGetLocalSize(coordinates, &N);CHKERRQ(ierr);
180e412dcbdSMatthew G. Knepley   ierr = VecGetArrayRead(coordinates, &coords);CHKERRQ(ierr);
181e412dcbdSMatthew G. Knepley   for (c = 0; c < N; c += dim) {
1820c81f2a8SMatthew G. Knepley     bound[0] = PetscMin(bound[0], PetscRealPart(coords[c]));   bound[2] = PetscMax(bound[2], PetscRealPart(coords[c]));
1830c81f2a8SMatthew G. Knepley     bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1]));
184e412dcbdSMatthew G. Knepley   }
185e412dcbdSMatthew G. Knepley   ierr = VecRestoreArrayRead(coordinates, &coords);CHKERRQ(ierr);
186e412dcbdSMatthew G. Knepley   ierr = PetscDrawClear(draw);CHKERRQ(ierr);
187e412dcbdSMatthew G. Knepley 
188d1df6f1dSMatthew G. Knepley   /* Could implement something like DMDASelectFields() */
189d1df6f1dSMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
190d1df6f1dSMatthew G. Knepley     DM   fdm = dm;
191d1df6f1dSMatthew G. Knepley     Vec  fv  = v;
192d1df6f1dSMatthew G. Knepley     IS   fis;
193d1df6f1dSMatthew G. Knepley     char prefix[PETSC_MAX_PATH_LEN];
194d1df6f1dSMatthew G. Knepley     const char *fname;
195d1df6f1dSMatthew G. Knepley 
196d1df6f1dSMatthew G. Knepley     ierr = PetscSectionGetFieldComponents(s, f, &Nc);CHKERRQ(ierr);
197d1df6f1dSMatthew G. Knepley     ierr = PetscSectionGetFieldName(s, f, &fname);CHKERRQ(ierr);
198d1df6f1dSMatthew G. Knepley 
199a126751eSBarry Smith     if (v->hdr.prefix) {ierr = PetscStrncpy(prefix, v->hdr.prefix,sizeof(prefix));CHKERRQ(ierr);}
200d1df6f1dSMatthew G. Knepley     else               {prefix[0] = '\0';}
201d1df6f1dSMatthew G. Knepley     if (Nf > 1) {
202d1df6f1dSMatthew G. Knepley       ierr = DMCreateSubDM(dm, 1, &f, &fis, &fdm);CHKERRQ(ierr);
203d1df6f1dSMatthew G. Knepley       ierr = VecGetSubVector(v, fis, &fv);CHKERRQ(ierr);
204a126751eSBarry Smith       ierr = PetscStrlcat(prefix, fname,sizeof(prefix));CHKERRQ(ierr);
205a126751eSBarry Smith       ierr = PetscStrlcat(prefix, "_",sizeof(prefix));CHKERRQ(ierr);
206d1df6f1dSMatthew G. Knepley     }
207d1df6f1dSMatthew G. Knepley     for (comp = 0; comp < Nc; ++comp, ++w) {
208d1df6f1dSMatthew G. Knepley       PetscInt nmax = 2;
209d1df6f1dSMatthew G. Knepley 
210d1df6f1dSMatthew G. Knepley       ierr = PetscViewerDrawGetDraw(viewer, w, &draw);CHKERRQ(ierr);
211d1df6f1dSMatthew G. Knepley       if (Nc > 1) {ierr = PetscSNPrintf(title, sizeof(title), "%s:%s_%D Step: %D Time: %.4g", name, fname, comp, step, time);CHKERRQ(ierr);}
212d1df6f1dSMatthew G. Knepley       else        {ierr = PetscSNPrintf(title, sizeof(title), "%s:%s Step: %D Time: %.4g", name, fname, step, time);CHKERRQ(ierr);}
213d1df6f1dSMatthew G. Knepley       ierr = PetscDrawSetTitle(draw, title);CHKERRQ(ierr);
214d1df6f1dSMatthew G. Knepley 
215d1df6f1dSMatthew G. Knepley       /* TODO Get max and min only for this component */
216d1df6f1dSMatthew G. Knepley       ierr = PetscOptionsGetRealArray(NULL, prefix, "-vec_view_bounds", vbound, &nmax, &flg);CHKERRQ(ierr);
217339e3443SMatthew G. Knepley       if (!flg) {
218d1df6f1dSMatthew G. Knepley         ierr = VecMin(fv, NULL, &vbound[0]);CHKERRQ(ierr);
219d1df6f1dSMatthew G. Knepley         ierr = VecMax(fv, NULL, &vbound[1]);CHKERRQ(ierr);
220d1df6f1dSMatthew G. Knepley         if (vbound[1] <= vbound[0]) vbound[1] = vbound[0] + 1.0;
221339e3443SMatthew G. Knepley       }
222e412dcbdSMatthew G. Knepley       ierr = PetscDrawGetPopup(draw, &popup);CHKERRQ(ierr);
223339e3443SMatthew G. Knepley       ierr = PetscDrawScalePopup(popup, vbound[0], vbound[1]);CHKERRQ(ierr);
224d1df6f1dSMatthew G. Knepley       ierr = PetscDrawSetCoordinates(draw, bound[0], bound[1], bound[2], bound[3]);CHKERRQ(ierr);
225e412dcbdSMatthew G. Knepley 
226d1df6f1dSMatthew G. Knepley       ierr = VecGetArrayRead(fv, &array);CHKERRQ(ierr);
227e412dcbdSMatthew G. Knepley       for (c = cStart; c < cEnd; ++c) {
22899a2f7bcSMatthew G. Knepley         PetscScalar *coords = NULL, *a = NULL;
229e56f9228SJed Brown         PetscInt     numCoords, color[4] = {-1,-1,-1,-1};
230e412dcbdSMatthew G. Knepley 
231d1df6f1dSMatthew G. Knepley         ierr = DMPlexPointLocalRead(fdm, c, array, &a);CHKERRQ(ierr);
232339e3443SMatthew G. Knepley         if (a) {
233d1df6f1dSMatthew G. Knepley           color[0] = PetscDrawRealToColor(PetscRealPart(a[comp]), vbound[0], vbound[1]);
234339e3443SMatthew G. Knepley           color[1] = color[2] = color[3] = color[0];
235339e3443SMatthew G. Knepley         } else {
236339e3443SMatthew G. Knepley           PetscScalar *vals = NULL;
237339e3443SMatthew G. Knepley           PetscInt     numVals, va;
238339e3443SMatthew G. Knepley 
239d1df6f1dSMatthew G. Knepley           ierr = DMPlexVecGetClosure(fdm, NULL, fv, c, &numVals, &vals);CHKERRQ(ierr);
240d1df6f1dSMatthew G. Knepley           if (numVals % Nc) SETERRQ2(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);
241d1df6f1dSMatthew G. Knepley           switch (numVals/Nc) {
242d1df6f1dSMatthew G. Knepley           case 3: /* P1 Triangle */
243d1df6f1dSMatthew G. Knepley           case 4: /* P1 Quadrangle */
244d1df6f1dSMatthew G. Knepley             for (va = 0; va < numVals/Nc; ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va*Nc+comp]), vbound[0], vbound[1]);
245339e3443SMatthew G. Knepley             break;
246d1df6f1dSMatthew G. Knepley           case 6: /* P2 Triangle */
247d1df6f1dSMatthew G. Knepley           case 8: /* P2 Quadrangle */
248d1df6f1dSMatthew 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]);
249d1df6f1dSMatthew G. Knepley             break;
250d1df6f1dSMatthew G. Knepley           default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of values for cell closure %D cannot be handled", numVals/Nc);
251339e3443SMatthew G. Knepley           }
252d1df6f1dSMatthew G. Knepley           ierr = DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals);CHKERRQ(ierr);
253339e3443SMatthew G. Knepley         }
254e412dcbdSMatthew G. Knepley         ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr);
255e412dcbdSMatthew G. Knepley         switch (numCoords) {
256e412dcbdSMatthew G. Knepley         case 6:
257*9edc3542SMatthew Knepley         case 12: /* Localized triangle */
258339e3443SMatthew 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);
259e412dcbdSMatthew G. Knepley           break;
260e412dcbdSMatthew G. Knepley         case 8:
261*9edc3542SMatthew Knepley         case 16: /* Localized quadrilateral */
262339e3443SMatthew 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);
263339e3443SMatthew 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);
264e412dcbdSMatthew G. Knepley           break;
265e412dcbdSMatthew G. Knepley         default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %D coordinates", numCoords);
266e412dcbdSMatthew G. Knepley         }
267e412dcbdSMatthew G. Knepley         ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr);
268e412dcbdSMatthew G. Knepley       }
269d1df6f1dSMatthew G. Knepley       ierr = VecRestoreArrayRead(fv, &array);CHKERRQ(ierr);
270e412dcbdSMatthew G. Knepley       ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
271e412dcbdSMatthew G. Knepley       ierr = PetscDrawPause(draw);CHKERRQ(ierr);
272e412dcbdSMatthew G. Knepley       ierr = PetscDrawSave(draw);CHKERRQ(ierr);
273d1df6f1dSMatthew G. Knepley     }
274d1df6f1dSMatthew G. Knepley     if (Nf > 1) {
275d1df6f1dSMatthew G. Knepley       ierr = VecRestoreSubVector(v, fis, &fv);CHKERRQ(ierr);
276d1df6f1dSMatthew G. Knepley       ierr = ISDestroy(&fis);CHKERRQ(ierr);
277d1df6f1dSMatthew G. Knepley       ierr = DMDestroy(&fdm);CHKERRQ(ierr);
278d1df6f1dSMatthew G. Knepley     }
279d1df6f1dSMatthew G. Knepley   }
280e412dcbdSMatthew G. Knepley   PetscFunctionReturn(0);
281e412dcbdSMatthew G. Knepley }
282e412dcbdSMatthew G. Knepley 
283684b87d9SLisandro Dalcin static PetscErrorCode VecView_Plex_Local_VTK(Vec v, PetscViewer viewer)
284684b87d9SLisandro Dalcin {
285684b87d9SLisandro Dalcin   DM                      dm;
286684b87d9SLisandro Dalcin   Vec                     locv;
287684b87d9SLisandro Dalcin   const char              *name;
288684b87d9SLisandro Dalcin   PetscSection            section;
289684b87d9SLisandro Dalcin   PetscInt                pStart, pEnd;
290e630c359SToby Isaac   PetscInt                numFields;
291684b87d9SLisandro Dalcin   PetscViewerVTKFieldType ft;
292684b87d9SLisandro Dalcin   PetscErrorCode          ierr;
293684b87d9SLisandro Dalcin 
294684b87d9SLisandro Dalcin   PetscFunctionBegin;
295684b87d9SLisandro Dalcin   ierr = VecGetDM(v, &dm);CHKERRQ(ierr);
296684b87d9SLisandro Dalcin   ierr = DMCreateLocalVector(dm, &locv);CHKERRQ(ierr); /* VTK viewer requires exclusive ownership of the vector */
297684b87d9SLisandro Dalcin   ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr);
298684b87d9SLisandro Dalcin   ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr);
299684b87d9SLisandro Dalcin   ierr = VecCopy(v, locv);CHKERRQ(ierr);
30092fd8e1eSJed Brown   ierr = DMGetLocalSection(dm, &section);CHKERRQ(ierr);
301e630c359SToby Isaac   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
302e630c359SToby Isaac   if (!numFields) {
303684b87d9SLisandro Dalcin     ierr = DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft);CHKERRQ(ierr);
304e630c359SToby Isaac     ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, PETSC_TRUE,(PetscObject) locv);CHKERRQ(ierr);
305e630c359SToby Isaac   } else {
306e630c359SToby Isaac     PetscInt f;
307e630c359SToby Isaac 
308e630c359SToby Isaac     for (f = 0; f < numFields; f++) {
309e630c359SToby Isaac       ierr = DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft);CHKERRQ(ierr);
310e630c359SToby Isaac       if (ft == PETSC_VTK_INVALID) continue;
311e630c359SToby Isaac       ierr = PetscObjectReference((PetscObject)locv);CHKERRQ(ierr);
312e630c359SToby Isaac       ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE,(PetscObject) locv);CHKERRQ(ierr);
313e630c359SToby Isaac     }
314e630c359SToby Isaac     ierr = VecDestroy(&locv);CHKERRQ(ierr);
315e630c359SToby Isaac   }
316684b87d9SLisandro Dalcin   PetscFunctionReturn(0);
317684b87d9SLisandro Dalcin }
318684b87d9SLisandro Dalcin 
319552f7358SJed Brown PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer)
320552f7358SJed Brown {
321552f7358SJed Brown   DM             dm;
322684b87d9SLisandro Dalcin   PetscBool      isvtk, ishdf5, isdraw, isglvis;
323552f7358SJed Brown   PetscErrorCode ierr;
324552f7358SJed Brown 
325552f7358SJed Brown   PetscFunctionBegin;
326552f7358SJed Brown   ierr = VecGetDM(v, &dm);CHKERRQ(ierr);
32782f516ccSBarry Smith   if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
328552f7358SJed Brown   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK,   &isvtk);CHKERRQ(ierr);
329b136c2c9SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
330f13a32a3SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW,  &isdraw);CHKERRQ(ierr);
3318135c375SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis);CHKERRQ(ierr);
332684b87d9SLisandro Dalcin   if (isvtk || ishdf5 || isdraw || isglvis) {
333684b87d9SLisandro Dalcin     PetscInt    i,numFields;
334684b87d9SLisandro Dalcin     PetscObject fe;
335ef31f671SMatthew G. Knepley     PetscBool   fem = PETSC_FALSE;
336684b87d9SLisandro Dalcin     Vec         locv = v;
337684b87d9SLisandro Dalcin     const char  *name;
338684b87d9SLisandro Dalcin     PetscInt    step;
339684b87d9SLisandro Dalcin     PetscReal   time;
340ef31f671SMatthew G. Knepley 
341ef31f671SMatthew G. Knepley     ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr);
342684b87d9SLisandro Dalcin     for (i=0; i<numFields; i++) {
34344a7f3ddSMatthew G. Knepley       ierr = DMGetField(dm, i, NULL, &fe);CHKERRQ(ierr);
344684b87d9SLisandro Dalcin       if (fe->classid == PETSCFE_CLASSID) { fem = PETSC_TRUE; break; }
345ef31f671SMatthew G. Knepley     }
346684b87d9SLisandro Dalcin     if (fem) {
347798534f6SMatthew G. Knepley       PetscObject isZero;
348798534f6SMatthew G. Knepley 
349684b87d9SLisandro Dalcin       ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr);
350684b87d9SLisandro Dalcin       ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr);
351684b87d9SLisandro Dalcin       ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr);
352798534f6SMatthew G. Knepley       ierr = PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero);CHKERRQ(ierr);
353798534f6SMatthew G. Knepley       ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero);CHKERRQ(ierr);
354684b87d9SLisandro Dalcin       ierr = VecCopy(v, locv);CHKERRQ(ierr);
355684b87d9SLisandro Dalcin       ierr = DMGetOutputSequenceNumber(dm, NULL, &time);CHKERRQ(ierr);
356684b87d9SLisandro Dalcin       ierr = DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL);CHKERRQ(ierr);
357ef31f671SMatthew G. Knepley     }
358552f7358SJed Brown     if (isvtk) {
359684b87d9SLisandro Dalcin       ierr = VecView_Plex_Local_VTK(locv, viewer);CHKERRQ(ierr);
360b136c2c9SMatthew G. Knepley     } else if (ishdf5) {
361b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
362684b87d9SLisandro Dalcin       ierr = VecView_Plex_Local_HDF5_Internal(locv, viewer);CHKERRQ(ierr);
363b136c2c9SMatthew G. Knepley #else
364b136c2c9SMatthew G. Knepley       SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
365b136c2c9SMatthew G. Knepley #endif
366f13a32a3SMatthew G. Knepley     } else if (isdraw) {
367684b87d9SLisandro Dalcin       ierr = VecView_Plex_Local_Draw(locv, viewer);CHKERRQ(ierr);
368684b87d9SLisandro Dalcin     } else if (isglvis) {
369684b87d9SLisandro Dalcin       ierr = DMGetOutputSequenceNumber(dm, &step, NULL);CHKERRQ(ierr);
370684b87d9SLisandro Dalcin       ierr = PetscViewerGLVisSetSnapId(viewer, step);CHKERRQ(ierr);
371684b87d9SLisandro Dalcin       ierr = VecView_GLVis(locv, viewer);CHKERRQ(ierr);
372684b87d9SLisandro Dalcin     }
373798534f6SMatthew G. Knepley     if (fem) {
374798534f6SMatthew G. Knepley       ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL);CHKERRQ(ierr);
375798534f6SMatthew G. Knepley       ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr);
376798534f6SMatthew G. Knepley     }
377552f7358SJed Brown   } else {
378684b87d9SLisandro Dalcin     PetscBool isseq;
379684b87d9SLisandro Dalcin 
380684b87d9SLisandro Dalcin     ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr);
38155f2e967SMatthew G. Knepley     if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);}
38255f2e967SMatthew G. Knepley     else       {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);}
383552f7358SJed Brown   }
384552f7358SJed Brown   PetscFunctionReturn(0);
385552f7358SJed Brown }
386552f7358SJed Brown 
387552f7358SJed Brown PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer)
388552f7358SJed Brown {
389552f7358SJed Brown   DM             dm;
3906823f3c5SBlaise Bourdin   PetscBool      isvtk, ishdf5, isdraw, isglvis, isexodusii;
391552f7358SJed Brown   PetscErrorCode ierr;
392552f7358SJed Brown 
393552f7358SJed Brown   PetscFunctionBegin;
394552f7358SJed Brown   ierr = VecGetDM(v, &dm);CHKERRQ(ierr);
39582f516ccSBarry Smith   if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
396552f7358SJed Brown   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK,      &isvtk);CHKERRQ(ierr);
39733c3e6b4SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,     &ishdf5);CHKERRQ(ierr);
398e412dcbdSMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW,     &isdraw);CHKERRQ(ierr);
3998135c375SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS,    &isglvis);CHKERRQ(ierr);
4006823f3c5SBlaise Bourdin   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii);CHKERRQ(ierr);
401684b87d9SLisandro Dalcin   if (isvtk || isdraw || isglvis) {
402552f7358SJed Brown     Vec         locv;
403798534f6SMatthew G. Knepley     PetscObject isZero;
404552f7358SJed Brown     const char *name;
405552f7358SJed Brown 
406c8dd51e9SBarry Smith     ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr);
407552f7358SJed Brown     ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr);
408552f7358SJed Brown     ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr);
409552f7358SJed Brown     ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr);
410552f7358SJed Brown     ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr);
411798534f6SMatthew G. Knepley     ierr = PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero);CHKERRQ(ierr);
412798534f6SMatthew G. Knepley     ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero);CHKERRQ(ierr);
413552f7358SJed Brown     ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr);
414798534f6SMatthew G. Knepley     ierr = PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL);CHKERRQ(ierr);
415c8dd51e9SBarry Smith     ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr);
416b136c2c9SMatthew G. Knepley   } else if (ishdf5) {
417b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
41839d25373SMatthew G. Knepley     ierr = VecView_Plex_HDF5_Internal(v, viewer);CHKERRQ(ierr);
419b136c2c9SMatthew G. Knepley #else
420b136c2c9SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
421b136c2c9SMatthew G. Knepley #endif
4226823f3c5SBlaise Bourdin   } else if (isexodusii) {
4236823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII)
4246823f3c5SBlaise Bourdin     ierr = VecView_PlexExodusII_Internal(v, viewer);CHKERRQ(ierr);
4256823f3c5SBlaise Bourdin #else
4266823f3c5SBlaise Bourdin     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii");
4276823f3c5SBlaise Bourdin #endif
428552f7358SJed Brown   } else {
429684b87d9SLisandro Dalcin     PetscBool isseq;
430684b87d9SLisandro Dalcin 
431684b87d9SLisandro Dalcin     ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr);
43255f2e967SMatthew G. Knepley     if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);}
43355f2e967SMatthew G. Knepley     else       {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);}
434552f7358SJed Brown   }
435552f7358SJed Brown   PetscFunctionReturn(0);
436552f7358SJed Brown }
437552f7358SJed Brown 
438d930f514SMatthew G. Knepley PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer)
439d930f514SMatthew G. Knepley {
440d930f514SMatthew G. Knepley   DM                dm;
441d930f514SMatthew G. Knepley   MPI_Comm          comm;
442d930f514SMatthew G. Knepley   PetscViewerFormat format;
443d930f514SMatthew G. Knepley   Vec               v;
444d930f514SMatthew G. Knepley   PetscBool         isvtk, ishdf5;
445d930f514SMatthew G. Knepley   PetscErrorCode    ierr;
446d930f514SMatthew G. Knepley 
447d930f514SMatthew G. Knepley   PetscFunctionBegin;
448d930f514SMatthew G. Knepley   ierr = VecGetDM(originalv, &dm);CHKERRQ(ierr);
449d930f514SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject) originalv, &comm);CHKERRQ(ierr);
4502c4c0c81SMatthew G. Knepley   if (!dm) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
451d930f514SMatthew G. Knepley   ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr);
452d930f514SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr);
453d930f514SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK,  &isvtk);CHKERRQ(ierr);
454d930f514SMatthew G. Knepley   if (format == PETSC_VIEWER_NATIVE) {
455a8ad634aSStefano Zampini     /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */
456a8ad634aSStefano Zampini     /* this need a better fix */
457a8ad634aSStefano Zampini     if (dm->useNatural) {
458a8ad634aSStefano Zampini       if (dm->sfNatural) {
459d930f514SMatthew G. Knepley         const char *vecname;
460d930f514SMatthew G. Knepley         PetscInt    n, nroots;
461d930f514SMatthew G. Knepley 
462ca43db0aSBarry Smith         ierr = VecGetLocalSize(originalv, &n);CHKERRQ(ierr);
463d930f514SMatthew G. Knepley         ierr = PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL);CHKERRQ(ierr);
464d930f514SMatthew G. Knepley         if (n == nroots) {
465d930f514SMatthew G. Knepley           ierr = DMGetGlobalVector(dm, &v);CHKERRQ(ierr);
466d930f514SMatthew G. Knepley           ierr = DMPlexGlobalToNaturalBegin(dm, originalv, v);CHKERRQ(ierr);
467d930f514SMatthew G. Knepley           ierr = DMPlexGlobalToNaturalEnd(dm, originalv, v);CHKERRQ(ierr);
468d930f514SMatthew G. Knepley           ierr = PetscObjectGetName((PetscObject) originalv, &vecname);CHKERRQ(ierr);
469d930f514SMatthew G. Knepley           ierr = PetscObjectSetName((PetscObject) v, vecname);CHKERRQ(ierr);
470d930f514SMatthew G. Knepley         } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors");
471d930f514SMatthew G. Knepley       } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created");
472a8ad634aSStefano Zampini     } else v = originalv;
473a8ad634aSStefano Zampini   } else v = originalv;
474a8ad634aSStefano Zampini 
475d930f514SMatthew G. Knepley   if (ishdf5) {
476d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
47739d25373SMatthew G. Knepley     ierr = VecView_Plex_HDF5_Native_Internal(v, viewer);CHKERRQ(ierr);
478d930f514SMatthew G. Knepley #else
479d930f514SMatthew G. Knepley     SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
480d930f514SMatthew G. Knepley #endif
481d930f514SMatthew G. Knepley   } else if (isvtk) {
482d930f514SMatthew G. Knepley     SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5.");
483d930f514SMatthew G. Knepley   } else {
484d930f514SMatthew G. Knepley     PetscBool isseq;
485d930f514SMatthew G. Knepley 
486d930f514SMatthew G. Knepley     ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr);
487d930f514SMatthew G. Knepley     if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);}
488d930f514SMatthew G. Knepley     else       {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);}
489d930f514SMatthew G. Knepley   }
490a8ad634aSStefano Zampini   if (v != originalv) {ierr = DMRestoreGlobalVector(dm, &v);CHKERRQ(ierr);}
491d930f514SMatthew G. Knepley   PetscFunctionReturn(0);
492d930f514SMatthew G. Knepley }
493d930f514SMatthew G. Knepley 
4942c40f234SMatthew G. Knepley PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer)
4952c40f234SMatthew G. Knepley {
4962c40f234SMatthew G. Knepley   DM             dm;
4972c40f234SMatthew G. Knepley   PetscBool      ishdf5;
4982c40f234SMatthew G. Knepley   PetscErrorCode ierr;
4992c40f234SMatthew G. Knepley 
5002c40f234SMatthew G. Knepley   PetscFunctionBegin;
5012c40f234SMatthew G. Knepley   ierr = VecGetDM(v, &dm);CHKERRQ(ierr);
5022c40f234SMatthew G. Knepley   if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
5032c40f234SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr);
5042c40f234SMatthew G. Knepley   if (ishdf5) {
5052c40f234SMatthew G. Knepley     DM          dmBC;
5062c40f234SMatthew G. Knepley     Vec         gv;
5072c40f234SMatthew G. Knepley     const char *name;
5082c40f234SMatthew G. Knepley 
5092c40f234SMatthew G. Knepley     ierr = DMGetOutputDM(dm, &dmBC);CHKERRQ(ierr);
5102c40f234SMatthew G. Knepley     ierr = DMGetGlobalVector(dmBC, &gv);CHKERRQ(ierr);
5112c40f234SMatthew G. Knepley     ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr);
5122c40f234SMatthew G. Knepley     ierr = PetscObjectSetName((PetscObject) gv, name);CHKERRQ(ierr);
5132c40f234SMatthew G. Knepley     ierr = VecLoad_Default(gv, viewer);CHKERRQ(ierr);
5142c40f234SMatthew G. Knepley     ierr = DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v);CHKERRQ(ierr);
5152c40f234SMatthew G. Knepley     ierr = DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v);CHKERRQ(ierr);
5162c40f234SMatthew G. Knepley     ierr = DMRestoreGlobalVector(dmBC, &gv);CHKERRQ(ierr);
5172c40f234SMatthew G. Knepley   } else {
5182c40f234SMatthew G. Knepley     ierr = VecLoad_Default(v, viewer);CHKERRQ(ierr);
5192c40f234SMatthew G. Knepley   }
5202c40f234SMatthew G. Knepley   PetscFunctionReturn(0);
5212c40f234SMatthew G. Knepley }
5222c40f234SMatthew G. Knepley 
5232c40f234SMatthew G. Knepley PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer)
5242c40f234SMatthew G. Knepley {
5252c40f234SMatthew G. Knepley   DM             dm;
5266823f3c5SBlaise Bourdin   PetscBool      ishdf5,isexodusii;
5272c40f234SMatthew G. Knepley   PetscErrorCode ierr;
5282c40f234SMatthew G. Knepley 
5292c40f234SMatthew G. Knepley   PetscFunctionBegin;
5302c40f234SMatthew G. Knepley   ierr = VecGetDM(v, &dm);CHKERRQ(ierr);
5312c40f234SMatthew G. Knepley   if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
5322c40f234SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,     &ishdf5);CHKERRQ(ierr);
5336823f3c5SBlaise Bourdin   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii);CHKERRQ(ierr);
5342c40f234SMatthew G. Knepley   if (ishdf5) {
535878b459fSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
53639d25373SMatthew G. Knepley     ierr = VecLoad_Plex_HDF5_Internal(v, viewer);CHKERRQ(ierr);
537b136c2c9SMatthew G. Knepley #else
538b136c2c9SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
539878b459fSMatthew G. Knepley #endif
5406823f3c5SBlaise Bourdin   } else if (isexodusii) {
5416823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII)
5426823f3c5SBlaise Bourdin     ierr = VecLoad_PlexExodusII_Internal(v, viewer);CHKERRQ(ierr);
5436823f3c5SBlaise Bourdin #else
5446823f3c5SBlaise Bourdin     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii");
5456823f3c5SBlaise Bourdin #endif
5462c40f234SMatthew G. Knepley   } else {
5472c40f234SMatthew G. Knepley     ierr = VecLoad_Default(v, viewer);CHKERRQ(ierr);
548552f7358SJed Brown   }
549552f7358SJed Brown   PetscFunctionReturn(0);
550552f7358SJed Brown }
551552f7358SJed Brown 
552d930f514SMatthew G. Knepley PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer)
553d930f514SMatthew G. Knepley {
554d930f514SMatthew G. Knepley   DM                dm;
555d930f514SMatthew G. Knepley   PetscViewerFormat format;
556d930f514SMatthew G. Knepley   PetscBool         ishdf5;
557d930f514SMatthew G. Knepley   PetscErrorCode    ierr;
558d930f514SMatthew G. Knepley 
559d930f514SMatthew G. Knepley   PetscFunctionBegin;
560d930f514SMatthew G. Knepley   ierr = VecGetDM(originalv, &dm);CHKERRQ(ierr);
561d930f514SMatthew G. Knepley   if (!dm) SETERRQ(PetscObjectComm((PetscObject) originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
562d930f514SMatthew G. Knepley   ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr);
563d930f514SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr);
564d930f514SMatthew G. Knepley   if (format == PETSC_VIEWER_NATIVE) {
565a8ad634aSStefano Zampini     if (dm->useNatural) {
566d930f514SMatthew G. Knepley       if (dm->sfNatural) {
567d930f514SMatthew G. Knepley         if (ishdf5) {
568d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
569d930f514SMatthew G. Knepley           Vec         v;
570d930f514SMatthew G. Knepley           const char *vecname;
571d930f514SMatthew G. Knepley 
572d930f514SMatthew G. Knepley           ierr = DMGetGlobalVector(dm, &v);CHKERRQ(ierr);
573d930f514SMatthew G. Knepley           ierr = PetscObjectGetName((PetscObject) originalv, &vecname);CHKERRQ(ierr);
574d930f514SMatthew G. Knepley           ierr = PetscObjectSetName((PetscObject) v, vecname);CHKERRQ(ierr);
57539d25373SMatthew G. Knepley           ierr = VecLoad_Plex_HDF5_Native_Internal(v, viewer);CHKERRQ(ierr);
576d930f514SMatthew G. Knepley           ierr = DMPlexNaturalToGlobalBegin(dm, v, originalv);CHKERRQ(ierr);
577d930f514SMatthew G. Knepley           ierr = DMPlexNaturalToGlobalEnd(dm, v, originalv);CHKERRQ(ierr);
578d930f514SMatthew G. Knepley           ierr = DMRestoreGlobalVector(dm, &v);CHKERRQ(ierr);
579d930f514SMatthew G. Knepley #else
580d930f514SMatthew G. Knepley           SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
581d930f514SMatthew G. Knepley #endif
582d930f514SMatthew G. Knepley         } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5.");
583d930f514SMatthew G. Knepley       }
584a8ad634aSStefano Zampini     } else {
585a8ad634aSStefano Zampini       ierr = VecLoad_Default(originalv, viewer);CHKERRQ(ierr);
586a8ad634aSStefano Zampini     }
587d930f514SMatthew G. Knepley   }
588d930f514SMatthew G. Knepley   PetscFunctionReturn(0);
589d930f514SMatthew G. Knepley }
590d930f514SMatthew G. Knepley 
5917cd05799SMatthew G. Knepley PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer)
592731e8ddeSMatthew G. Knepley {
593731e8ddeSMatthew G. Knepley   PetscSection       coordSection;
594731e8ddeSMatthew G. Knepley   Vec                coordinates;
595ba2698f1SMatthew G. Knepley   DMLabel            depthLabel, celltypeLabel;
596731e8ddeSMatthew G. Knepley   const char        *name[4];
597731e8ddeSMatthew G. Knepley   const PetscScalar *a;
598731e8ddeSMatthew G. Knepley   PetscInt           dim, pStart, pEnd, cStart, cEnd, c;
599731e8ddeSMatthew G. Knepley   PetscErrorCode     ierr;
600731e8ddeSMatthew G. Knepley 
601731e8ddeSMatthew G. Knepley   PetscFunctionBegin;
602731e8ddeSMatthew G. Knepley   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
603731e8ddeSMatthew G. Knepley   ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
604731e8ddeSMatthew G. Knepley   ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr);
605731e8ddeSMatthew G. Knepley   ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr);
606ba2698f1SMatthew G. Knepley   ierr = DMPlexGetCellTypeLabel(dm, &celltypeLabel);CHKERRQ(ierr);
607731e8ddeSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
608731e8ddeSMatthew G. Knepley   ierr = PetscSectionGetChart(coordSection, &pStart, &pEnd);CHKERRQ(ierr);
609731e8ddeSMatthew G. Knepley   ierr = VecGetArrayRead(coordinates, &a);CHKERRQ(ierr);
610731e8ddeSMatthew G. Knepley   name[0]     = "vertex";
611731e8ddeSMatthew G. Knepley   name[1]     = "edge";
612731e8ddeSMatthew G. Knepley   name[dim-1] = "face";
613731e8ddeSMatthew G. Knepley   name[dim]   = "cell";
614731e8ddeSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
615731e8ddeSMatthew G. Knepley     PetscInt *closure = NULL;
616ba2698f1SMatthew G. Knepley     PetscInt  closureSize, cl, ct;
617731e8ddeSMatthew G. Knepley 
618ba2698f1SMatthew G. Knepley     ierr = DMLabelGetValue(celltypeLabel, c, &ct);CHKERRQ(ierr);
619ba2698f1SMatthew G. Knepley     ierr = PetscViewerASCIIPrintf(viewer, "Geometry for cell %D polytope type %s:\n", c, DMPolytopeTypes[ct]);CHKERRQ(ierr);
620731e8ddeSMatthew G. Knepley     ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
621731e8ddeSMatthew G. Knepley     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
622731e8ddeSMatthew G. Knepley     for (cl = 0; cl < closureSize*2; cl += 2) {
623731e8ddeSMatthew G. Knepley       PetscInt point = closure[cl], depth, dof, off, d, p;
624731e8ddeSMatthew G. Knepley 
625731e8ddeSMatthew G. Knepley       if ((point < pStart) || (point >= pEnd)) continue;
626731e8ddeSMatthew G. Knepley       ierr = PetscSectionGetDof(coordSection, point, &dof);CHKERRQ(ierr);
627731e8ddeSMatthew G. Knepley       if (!dof) continue;
628731e8ddeSMatthew G. Knepley       ierr = DMLabelGetValue(depthLabel, point, &depth);CHKERRQ(ierr);
629731e8ddeSMatthew G. Knepley       ierr = PetscSectionGetOffset(coordSection, point, &off);CHKERRQ(ierr);
630f347f43bSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer, "%s %D coords:", name[depth], point);CHKERRQ(ierr);
631731e8ddeSMatthew G. Knepley       for (p = 0; p < dof/dim; ++p) {
632731e8ddeSMatthew G. Knepley         ierr = PetscViewerASCIIPrintf(viewer, " (");CHKERRQ(ierr);
633731e8ddeSMatthew G. Knepley         for (d = 0; d < dim; ++d) {
634731e8ddeSMatthew G. Knepley           if (d > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);}
635087ef6b2SMatthew G. Knepley           ierr = PetscViewerASCIIPrintf(viewer, "%g", (double) PetscRealPart(a[off+p*dim+d]));CHKERRQ(ierr);
636731e8ddeSMatthew G. Knepley         }
637731e8ddeSMatthew G. Knepley         ierr = PetscViewerASCIIPrintf(viewer, ")");CHKERRQ(ierr);
638731e8ddeSMatthew G. Knepley       }
639731e8ddeSMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr);
640731e8ddeSMatthew G. Knepley     }
641731e8ddeSMatthew G. Knepley     ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
642731e8ddeSMatthew G. Knepley     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
643731e8ddeSMatthew G. Knepley   }
644731e8ddeSMatthew G. Knepley   ierr = VecRestoreArrayRead(coordinates, &a);CHKERRQ(ierr);
645731e8ddeSMatthew G. Knepley   PetscFunctionReturn(0);
646731e8ddeSMatthew G. Knepley }
647731e8ddeSMatthew G. Knepley 
6487cd05799SMatthew G. Knepley static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer)
649552f7358SJed Brown {
650552f7358SJed Brown   DM_Plex          *mesh = (DM_Plex*) dm->data;
651552f7358SJed Brown   DM                cdm;
652552f7358SJed Brown   PetscSection      coordSection;
653552f7358SJed Brown   Vec               coordinates;
654552f7358SJed Brown   PetscViewerFormat format;
655552f7358SJed Brown   PetscErrorCode    ierr;
656552f7358SJed Brown 
657552f7358SJed Brown   PetscFunctionBegin;
658552f7358SJed Brown   ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
65992fd8e1eSJed Brown   ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr);
660552f7358SJed Brown   ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
661552f7358SJed Brown   ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr);
662552f7358SJed Brown   if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
663552f7358SJed Brown     const char *name;
664f73eea6eSMatthew G. Knepley     PetscInt    dim, cellHeight, maxConeSize, maxSupportSize;
6659318fe57SMatthew G. Knepley     PetscInt    pStart, pEnd, p, numLabels, l;
666552f7358SJed Brown     PetscMPIInt rank, size;
667552f7358SJed Brown 
668ffc4695bSBarry Smith     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRMPI(ierr);
669ffc4695bSBarry Smith     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRMPI(ierr);
670552f7358SJed Brown     ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr);
671552f7358SJed Brown     ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
672552f7358SJed Brown     ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr);
673f73eea6eSMatthew G. Knepley     ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
674f73eea6eSMatthew G. Knepley     ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr);
675f73eea6eSMatthew G. Knepley     if (name) {ierr = PetscViewerASCIIPrintf(viewer, "%s in %D dimension%s:\n", name, dim, dim == 1 ? "" : "s");CHKERRQ(ierr);}
676f73eea6eSMatthew G. Knepley     else      {ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimension%s:\n", dim, dim == 1 ? "" : "s");CHKERRQ(ierr);}
677f73eea6eSMatthew G. Knepley     if (cellHeight) {ierr = PetscViewerASCIIPrintf(viewer, "  Cells are at height %D\n", cellHeight);CHKERRQ(ierr);}
678e9cb465cSMatthew G. Knepley     ierr = PetscViewerASCIIPrintf(viewer, "Supports:\n", name);CHKERRQ(ierr);
6794d4c343aSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr);
680e9cb465cSMatthew G. Knepley     ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %D\n", rank, maxSupportSize);CHKERRQ(ierr);
681552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
682552f7358SJed Brown       PetscInt dof, off, s;
683552f7358SJed Brown 
684552f7358SJed Brown       ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr);
685552f7358SJed Brown       ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr);
686552f7358SJed Brown       for (s = off; s < off+dof; ++s) {
687e4b003c7SBarry Smith         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr);
688552f7358SJed Brown       }
689552f7358SJed Brown     }
690552f7358SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
691e9cb465cSMatthew G. Knepley     ierr = PetscViewerASCIIPrintf(viewer, "Cones:\n", name);CHKERRQ(ierr);
692e9cb465cSMatthew G. Knepley     ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %D\n", rank, maxConeSize);CHKERRQ(ierr);
693552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
694552f7358SJed Brown       PetscInt dof, off, c;
695552f7358SJed Brown 
696552f7358SJed Brown       ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr);
697552f7358SJed Brown       ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr);
698552f7358SJed Brown       for (c = off; c < off+dof; ++c) {
699e4b003c7SBarry Smith         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr);
700552f7358SJed Brown       }
701552f7358SJed Brown     }
702552f7358SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
7034d4c343aSBarry Smith     ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr);
7043d2e540fSStefano Zampini     if (coordSection && coordinates) {
70580180ce3SStefano Zampini       ierr = PetscSectionVecView(coordSection, coordinates, viewer);CHKERRQ(ierr);
7063d2e540fSStefano Zampini     }
7079318fe57SMatthew G. Knepley     ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr);
7089318fe57SMatthew G. Knepley     if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Labels:\n");CHKERRQ(ierr);}
7099318fe57SMatthew G. Knepley     for (l = 0; l < numLabels; ++l) {
7109318fe57SMatthew G. Knepley       DMLabel     label;
7119318fe57SMatthew G. Knepley       PetscBool   isdepth;
7129318fe57SMatthew G. Knepley       const char *name;
7139318fe57SMatthew G. Knepley 
7149318fe57SMatthew G. Knepley       ierr = DMGetLabelName(dm, l, &name);CHKERRQ(ierr);
7159318fe57SMatthew G. Knepley       ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr);
7169318fe57SMatthew G. Knepley       if (isdepth) continue;
7179318fe57SMatthew G. Knepley       ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr);
7189318fe57SMatthew G. Knepley       ierr = DMLabelView(label, viewer);CHKERRQ(ierr);
7199318fe57SMatthew G. Knepley     }
720552f7358SJed Brown     if (size > 1) {
721552f7358SJed Brown       PetscSF sf;
722552f7358SJed Brown 
723552f7358SJed Brown       ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr);
724552f7358SJed Brown       ierr = PetscSFView(sf, viewer);CHKERRQ(ierr);
725552f7358SJed Brown     }
726552f7358SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
727552f7358SJed Brown   } else if (format == PETSC_VIEWER_ASCII_LATEX) {
7280588280cSMatthew G. Knepley     const char  *name, *color;
7290588280cSMatthew G. Knepley     const char  *defcolors[3]  = {"gray", "orange", "green"};
7300588280cSMatthew G. Knepley     const char  *deflcolors[4] = {"blue", "cyan", "red", "magenta"};
731fe1cc32dSStefano Zampini     char         lname[PETSC_MAX_PATH_LEN];
732552f7358SJed Brown     PetscReal    scale         = 2.0;
73378081901SStefano Zampini     PetscReal    tikzscale     = 1.0;
7340588280cSMatthew G. Knepley     PetscBool    useNumbers    = PETSC_TRUE, useLabels, useColors;
7350588280cSMatthew G. Knepley     double       tcoords[3];
736552f7358SJed Brown     PetscScalar *coords;
7370588280cSMatthew G. Knepley     PetscInt     numLabels, l, numColors, numLColors, dim, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p;
738552f7358SJed Brown     PetscMPIInt  rank, size;
7390588280cSMatthew G. Knepley     char         **names, **colors, **lcolors;
740fe1cc32dSStefano Zampini     PetscBool    plotEdges, flg, lflg;
741fe1cc32dSStefano Zampini     PetscBT      wp = NULL;
742fe1cc32dSStefano Zampini     PetscInt     pEnd, pStart;
743552f7358SJed Brown 
7440588280cSMatthew G. Knepley     ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
745552f7358SJed Brown     ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
746c58f1c22SToby Isaac     ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr);
7470588280cSMatthew G. Knepley     numLabels  = PetscMax(numLabels, 10);
7480588280cSMatthew G. Knepley     numColors  = 10;
7490588280cSMatthew G. Knepley     numLColors = 10;
7500588280cSMatthew G. Knepley     ierr = PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors);CHKERRQ(ierr);
751c5929fdfSBarry Smith     ierr = PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_scale", &scale, NULL);CHKERRQ(ierr);
75278081901SStefano Zampini     ierr = PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL);CHKERRQ(ierr);
753c5929fdfSBarry Smith     ierr = PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL);CHKERRQ(ierr);
754c5929fdfSBarry Smith     ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels);CHKERRQ(ierr);
7550588280cSMatthew G. Knepley     if (!useLabels) numLabels = 0;
756c5929fdfSBarry Smith     ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors);CHKERRQ(ierr);
7570588280cSMatthew G. Knepley     if (!useColors) {
7580588280cSMatthew G. Knepley       numColors = 3;
7590588280cSMatthew G. Knepley       for (c = 0; c < numColors; ++c) {ierr = PetscStrallocpy(defcolors[c], &colors[c]);CHKERRQ(ierr);}
7600588280cSMatthew G. Knepley     }
761c5929fdfSBarry Smith     ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors);CHKERRQ(ierr);
7620588280cSMatthew G. Knepley     if (!useColors) {
7630588280cSMatthew G. Knepley       numLColors = 4;
7640588280cSMatthew G. Knepley       for (c = 0; c < numLColors; ++c) {ierr = PetscStrallocpy(deflcolors[c], &lcolors[c]);CHKERRQ(ierr);}
7650588280cSMatthew G. Knepley     }
766589a23caSBarry Smith     ierr = PetscOptionsGetString(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg);CHKERRQ(ierr);
767202fd40aSStefano Zampini     plotEdges = (PetscBool)(depth > 1 && useNumbers && dim < 3);
768202fd40aSStefano Zampini     ierr = PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg);CHKERRQ(ierr);
769202fd40aSStefano Zampini     if (flg && plotEdges && depth < dim) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Mesh must be interpolated");
770202fd40aSStefano Zampini     if (depth < dim) plotEdges = PETSC_FALSE;
771fe1cc32dSStefano Zampini 
772fe1cc32dSStefano Zampini     /* filter points with labelvalue != labeldefaultvalue */
773fe1cc32dSStefano Zampini     ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
774fe1cc32dSStefano Zampini     if (lflg) {
775fe1cc32dSStefano Zampini       DMLabel lbl;
776fe1cc32dSStefano Zampini 
777fe1cc32dSStefano Zampini       ierr = DMGetLabel(dm, lname, &lbl);CHKERRQ(ierr);
778fe1cc32dSStefano Zampini       if (lbl) {
779fe1cc32dSStefano Zampini         PetscInt val, defval;
780fe1cc32dSStefano Zampini 
781fe1cc32dSStefano Zampini         ierr = DMLabelGetDefaultValue(lbl, &defval);CHKERRQ(ierr);
782fe1cc32dSStefano Zampini         ierr = PetscBTCreate(pEnd-pStart, &wp);CHKERRQ(ierr);
783fe1cc32dSStefano Zampini         for (c = pStart;  c < pEnd; c++) {
784fe1cc32dSStefano Zampini           PetscInt *closure = NULL;
785fe1cc32dSStefano Zampini           PetscInt  closureSize;
786fe1cc32dSStefano Zampini 
787fe1cc32dSStefano Zampini           ierr = DMLabelGetValue(lbl, c, &val);CHKERRQ(ierr);
788fe1cc32dSStefano Zampini           if (val == defval) continue;
789fe1cc32dSStefano Zampini 
790fe1cc32dSStefano Zampini           ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
791fe1cc32dSStefano Zampini           for (p = 0; p < closureSize*2; p += 2) {
792fe1cc32dSStefano Zampini             ierr = PetscBTSet(wp, closure[p] - pStart);CHKERRQ(ierr);
793fe1cc32dSStefano Zampini           }
794fe1cc32dSStefano Zampini           ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
795fe1cc32dSStefano Zampini         }
796fe1cc32dSStefano Zampini       }
797fe1cc32dSStefano Zampini     }
798fe1cc32dSStefano Zampini 
799ffc4695bSBarry Smith     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRMPI(ierr);
800ffc4695bSBarry Smith     ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRMPI(ierr);
801552f7358SJed Brown     ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr);
802770b213bSMatthew G Knepley     ierr = PetscViewerASCIIPrintf(viewer, "\
8030588280cSMatthew G. Knepley \\documentclass[tikz]{standalone}\n\n\
804552f7358SJed Brown \\usepackage{pgflibraryshapes}\n\
805552f7358SJed Brown \\usetikzlibrary{backgrounds}\n\
806552f7358SJed Brown \\usetikzlibrary{arrows}\n\
8070588280cSMatthew G. Knepley \\begin{document}\n");CHKERRQ(ierr);
8080588280cSMatthew G. Knepley     if (size > 1) {
809f738dd31SMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "%s for process ", name);CHKERRQ(ierr);
810770b213bSMatthew G Knepley       for (p = 0; p < size; ++p) {
811770b213bSMatthew G Knepley         if (p > 0 && p == size-1) {
812770b213bSMatthew G Knepley           ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr);
813770b213bSMatthew G Knepley         } else if (p > 0) {
814770b213bSMatthew G Knepley           ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr);
815770b213bSMatthew G Knepley         }
816770b213bSMatthew G Knepley         ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr);
817770b213bSMatthew G Knepley       }
8180588280cSMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, ".\n\n\n");CHKERRQ(ierr);
8190588280cSMatthew G. Knepley     }
820087ef6b2SMatthew G. Knepley     ierr = PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double) tikzscale);CHKERRQ(ierr);
821fe1cc32dSStefano Zampini 
822552f7358SJed Brown     /* Plot vertices */
823552f7358SJed Brown     ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
824552f7358SJed Brown     ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr);
8254d4c343aSBarry Smith     ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr);
826552f7358SJed Brown     for (v = vStart; v < vEnd; ++v) {
827552f7358SJed Brown       PetscInt  off, dof, d;
8280588280cSMatthew G. Knepley       PetscBool isLabeled = PETSC_FALSE;
829552f7358SJed Brown 
830fe1cc32dSStefano Zampini       if (wp && !PetscBTLookup(wp,v - pStart)) continue;
831552f7358SJed Brown       ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr);
832552f7358SJed Brown       ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr);
8330588280cSMatthew G. Knepley       ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\path (");CHKERRQ(ierr);
834f6dae198SJed Brown       if (PetscUnlikely(dof > 3)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"coordSection vertex %D has dof %D > 3",v,dof);
8350588280cSMatthew G. Knepley       for (d = 0; d < dof; ++d) {
8360588280cSMatthew G. Knepley         tcoords[d] = (double) (scale*PetscRealPart(coords[off+d]));
837c068d9bbSLisandro Dalcin         tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
8380588280cSMatthew G. Knepley       }
8390588280cSMatthew G. Knepley       /* Rotate coordinates since PGF makes z point out of the page instead of up */
8400588280cSMatthew G. Knepley       if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;}
841552f7358SJed Brown       for (d = 0; d < dof; ++d) {
842552f7358SJed Brown         if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);}
843087ef6b2SMatthew G. Knepley         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) tcoords[d]);CHKERRQ(ierr);
844552f7358SJed Brown       }
8450588280cSMatthew G. Knepley       color = colors[rank%numColors];
8460588280cSMatthew G. Knepley       for (l = 0; l < numLabels; ++l) {
8470588280cSMatthew G. Knepley         PetscInt val;
848c58f1c22SToby Isaac         ierr = DMGetLabelValue(dm, names[l], v, &val);CHKERRQ(ierr);
8490588280cSMatthew G. Knepley         if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;}
8500588280cSMatthew G. Knepley       }
8510588280cSMatthew G. Knepley       if (useNumbers) {
852e4b003c7SBarry Smith         ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D};\n", v, rank, color, v);CHKERRQ(ierr);
8530588280cSMatthew G. Knepley       } else {
854e4b003c7SBarry Smith         ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color);CHKERRQ(ierr);
8550588280cSMatthew G. Knepley       }
856552f7358SJed Brown     }
857552f7358SJed Brown     ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr);
858552f7358SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
859846a3e8bSMatthew G. Knepley     /* Plot cells */
860846a3e8bSMatthew G. Knepley     ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
86178081901SStefano Zampini     ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
862846a3e8bSMatthew G. Knepley     if (dim == 3 || !useNumbers) {
863846a3e8bSMatthew G. Knepley       for (e = eStart; e < eEnd; ++e) {
864846a3e8bSMatthew G. Knepley         const PetscInt *cone;
865846a3e8bSMatthew G. Knepley 
866fe1cc32dSStefano Zampini         if (wp && !PetscBTLookup(wp,e - pStart)) continue;
867846a3e8bSMatthew G. Knepley         color = colors[rank%numColors];
868846a3e8bSMatthew G. Knepley         for (l = 0; l < numLabels; ++l) {
869846a3e8bSMatthew G. Knepley           PetscInt val;
870846a3e8bSMatthew G. Knepley           ierr = DMGetLabelValue(dm, names[l], e, &val);CHKERRQ(ierr);
871846a3e8bSMatthew G. Knepley           if (val >= 0) {color = lcolors[l%numLColors]; break;}
872846a3e8bSMatthew G. Knepley         }
873846a3e8bSMatthew G. Knepley         ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr);
874846a3e8bSMatthew G. Knepley         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%D_%d) -- (%D_%d);\n", color, cone[0], rank, cone[1], rank);CHKERRQ(ierr);
875846a3e8bSMatthew G. Knepley       }
876846a3e8bSMatthew G. Knepley     } else {
877846a3e8bSMatthew G. Knepley       for (c = cStart; c < cEnd; ++c) {
878846a3e8bSMatthew G. Knepley         PetscInt *closure = NULL;
879846a3e8bSMatthew G. Knepley         PetscInt  closureSize, firstPoint = -1;
880846a3e8bSMatthew G. Knepley 
881fe1cc32dSStefano Zampini         if (wp && !PetscBTLookup(wp,c - pStart)) continue;
882846a3e8bSMatthew G. Knepley         ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
883846a3e8bSMatthew G. Knepley         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]);CHKERRQ(ierr);
884846a3e8bSMatthew G. Knepley         for (p = 0; p < closureSize*2; p += 2) {
885846a3e8bSMatthew G. Knepley           const PetscInt point = closure[p];
886846a3e8bSMatthew G. Knepley 
887846a3e8bSMatthew G. Knepley           if ((point < vStart) || (point >= vEnd)) continue;
888846a3e8bSMatthew G. Knepley           if (firstPoint >= 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- ");CHKERRQ(ierr);}
889846a3e8bSMatthew G. Knepley           ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%d)", point, rank);CHKERRQ(ierr);
890846a3e8bSMatthew G. Knepley           if (firstPoint < 0) firstPoint = point;
891846a3e8bSMatthew G. Knepley         }
892846a3e8bSMatthew G. Knepley         /* Why doesn't this work? ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- cycle;\n");CHKERRQ(ierr); */
893846a3e8bSMatthew G. Knepley         ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%d);\n", firstPoint, rank);CHKERRQ(ierr);
894846a3e8bSMatthew G. Knepley         ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
895846a3e8bSMatthew G. Knepley       }
896846a3e8bSMatthew G. Knepley     }
897846a3e8bSMatthew G. Knepley     ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr);
898846a3e8bSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
899846a3e8bSMatthew G. Knepley       double    ccoords[3] = {0.0, 0.0, 0.0};
900846a3e8bSMatthew G. Knepley       PetscBool isLabeled  = PETSC_FALSE;
901846a3e8bSMatthew G. Knepley       PetscInt *closure    = NULL;
902846a3e8bSMatthew G. Knepley       PetscInt  closureSize, dof, d, n = 0;
903846a3e8bSMatthew G. Knepley 
904fe1cc32dSStefano Zampini       if (wp && !PetscBTLookup(wp,c - pStart)) continue;
905846a3e8bSMatthew G. Knepley       ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
906846a3e8bSMatthew G. Knepley       ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\path (");CHKERRQ(ierr);
907846a3e8bSMatthew G. Knepley       for (p = 0; p < closureSize*2; p += 2) {
908846a3e8bSMatthew G. Knepley         const PetscInt point = closure[p];
909846a3e8bSMatthew G. Knepley         PetscInt       off;
910846a3e8bSMatthew G. Knepley 
911846a3e8bSMatthew G. Knepley         if ((point < vStart) || (point >= vEnd)) continue;
912846a3e8bSMatthew G. Knepley         ierr = PetscSectionGetDof(coordSection, point, &dof);CHKERRQ(ierr);
913846a3e8bSMatthew G. Knepley         ierr = PetscSectionGetOffset(coordSection, point, &off);CHKERRQ(ierr);
914846a3e8bSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
915846a3e8bSMatthew G. Knepley           tcoords[d] = (double) (scale*PetscRealPart(coords[off+d]));
916846a3e8bSMatthew G. Knepley           tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
917846a3e8bSMatthew G. Knepley         }
918846a3e8bSMatthew G. Knepley         /* Rotate coordinates since PGF makes z point out of the page instead of up */
919846a3e8bSMatthew G. Knepley         if (dof == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;}
920846a3e8bSMatthew G. Knepley         for (d = 0; d < dof; ++d) {ccoords[d] += tcoords[d];}
921846a3e8bSMatthew G. Knepley         ++n;
922846a3e8bSMatthew G. Knepley       }
923846a3e8bSMatthew G. Knepley       for (d = 0; d < dof; ++d) {ccoords[d] /= n;}
924846a3e8bSMatthew G. Knepley       ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
925846a3e8bSMatthew G. Knepley       for (d = 0; d < dof; ++d) {
926846a3e8bSMatthew G. Knepley         if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);}
927087ef6b2SMatthew G. Knepley         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) ccoords[d]);CHKERRQ(ierr);
928846a3e8bSMatthew G. Knepley       }
929846a3e8bSMatthew G. Knepley       color = colors[rank%numColors];
930846a3e8bSMatthew G. Knepley       for (l = 0; l < numLabels; ++l) {
931846a3e8bSMatthew G. Knepley         PetscInt val;
932846a3e8bSMatthew G. Knepley         ierr = DMGetLabelValue(dm, names[l], c, &val);CHKERRQ(ierr);
933846a3e8bSMatthew G. Knepley         if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;}
934846a3e8bSMatthew G. Knepley       }
935846a3e8bSMatthew G. Knepley       if (useNumbers) {
936846a3e8bSMatthew G. Knepley         ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D};\n", c, rank, color, c);CHKERRQ(ierr);
937846a3e8bSMatthew G. Knepley       } else {
938846a3e8bSMatthew 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);
939846a3e8bSMatthew G. Knepley       }
940846a3e8bSMatthew G. Knepley     }
941846a3e8bSMatthew G. Knepley     ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr);
942552f7358SJed Brown     /* Plot edges */
943202fd40aSStefano Zampini     if (plotEdges) {
944552f7358SJed Brown       ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr);
945552f7358SJed Brown       ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr);
946552f7358SJed Brown       for (e = eStart; e < eEnd; ++e) {
947552f7358SJed Brown         const PetscInt *cone;
948552f7358SJed Brown         PetscInt        coneSize, offA, offB, dof, d;
949552f7358SJed Brown 
950fe1cc32dSStefano Zampini         if (wp && !PetscBTLookup(wp,e - pStart)) continue;
951552f7358SJed Brown         ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr);
952f347f43bSBarry Smith         if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %D cone should have two vertices, not %D", e, coneSize);
953552f7358SJed Brown         ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr);
954552f7358SJed Brown         ierr = PetscSectionGetDof(coordSection, cone[0], &dof);CHKERRQ(ierr);
955552f7358SJed Brown         ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr);
956552f7358SJed Brown         ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr);
957552f7358SJed Brown         ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr);
958552f7358SJed Brown         for (d = 0; d < dof; ++d) {
959202fd40aSStefano Zampini           tcoords[d] = (double) (0.5*scale*PetscRealPart(coords[offA+d]+coords[offB+d]));
960c068d9bbSLisandro Dalcin           tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
961552f7358SJed Brown         }
9620588280cSMatthew G. Knepley         /* Rotate coordinates since PGF makes z point out of the page instead of up */
9630588280cSMatthew G. Knepley         if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;}
9640588280cSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
9650588280cSMatthew G. Knepley           if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);}
966f347f43bSBarry Smith           ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d]);CHKERRQ(ierr);
9670588280cSMatthew G. Knepley         }
9680588280cSMatthew G. Knepley         color = colors[rank%numColors];
9690588280cSMatthew G. Knepley         for (l = 0; l < numLabels; ++l) {
9700588280cSMatthew G. Knepley           PetscInt val;
971c58f1c22SToby Isaac           ierr = DMGetLabelValue(dm, names[l], v, &val);CHKERRQ(ierr);
9720750fff4SMatthew G. Knepley           if (val >= 0) {color = lcolors[l%numLColors]; break;}
9730588280cSMatthew G. Knepley         }
974e4b003c7SBarry Smith         ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D} --\n", e, rank, color, e);CHKERRQ(ierr);
975552f7358SJed Brown       }
976552f7358SJed Brown       ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr);
977552f7358SJed Brown       ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
978552f7358SJed Brown       ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr);
9790588280cSMatthew G. Knepley     }
980552f7358SJed Brown     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
9814d4c343aSBarry Smith     ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr);
9820588280cSMatthew G. Knepley     ierr = PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n");CHKERRQ(ierr);
983770b213bSMatthew G Knepley     ierr = PetscViewerASCIIPrintf(viewer, "\\end{document}\n", name);CHKERRQ(ierr);
9840588280cSMatthew G. Knepley     for (l = 0; l < numLabels;  ++l) {ierr = PetscFree(names[l]);CHKERRQ(ierr);}
9850588280cSMatthew G. Knepley     for (c = 0; c < numColors;  ++c) {ierr = PetscFree(colors[c]);CHKERRQ(ierr);}
9860588280cSMatthew G. Knepley     for (c = 0; c < numLColors; ++c) {ierr = PetscFree(lcolors[c]);CHKERRQ(ierr);}
9870588280cSMatthew G. Knepley     ierr = PetscFree3(names, colors, lcolors);CHKERRQ(ierr);
988fe1cc32dSStefano Zampini     ierr = PetscBTDestroy(&wp);CHKERRQ(ierr);
9890f7d6e4aSStefano Zampini   } else if (format == PETSC_VIEWER_LOAD_BALANCE) {
9900f7d6e4aSStefano Zampini     Vec                    cown,acown;
9910f7d6e4aSStefano Zampini     VecScatter             sct;
9920f7d6e4aSStefano Zampini     ISLocalToGlobalMapping g2l;
9930f7d6e4aSStefano Zampini     IS                     gid,acis;
9940f7d6e4aSStefano Zampini     MPI_Comm               comm,ncomm = MPI_COMM_NULL;
9950f7d6e4aSStefano Zampini     MPI_Group              ggroup,ngroup;
9960f7d6e4aSStefano Zampini     PetscScalar            *array,nid;
9970f7d6e4aSStefano Zampini     const PetscInt         *idxs;
9980f7d6e4aSStefano Zampini     PetscInt               *idxs2,*start,*adjacency,*work;
9990f7d6e4aSStefano Zampini     PetscInt64             lm[3],gm[3];
10000f7d6e4aSStefano Zampini     PetscInt               i,c,cStart,cEnd,cum,numVertices,ect,ectn,cellHeight;
10010f7d6e4aSStefano Zampini     PetscMPIInt            d1,d2,rank;
10020f7d6e4aSStefano Zampini 
10030f7d6e4aSStefano Zampini     ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
1004ffc4695bSBarry Smith     ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
1005b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
1006ffc4695bSBarry Smith     ierr = MPI_Comm_split_type(comm,MPI_COMM_TYPE_SHARED,rank,MPI_INFO_NULL,&ncomm);CHKERRMPI(ierr);
10070f7d6e4aSStefano Zampini #endif
10080f7d6e4aSStefano Zampini     if (ncomm != MPI_COMM_NULL) {
1009ffc4695bSBarry Smith       ierr = MPI_Comm_group(comm,&ggroup);CHKERRMPI(ierr);
1010ffc4695bSBarry Smith       ierr = MPI_Comm_group(ncomm,&ngroup);CHKERRMPI(ierr);
10110f7d6e4aSStefano Zampini       d1   = 0;
1012ffc4695bSBarry Smith       ierr = MPI_Group_translate_ranks(ngroup,1,&d1,ggroup,&d2);CHKERRMPI(ierr);
10130f7d6e4aSStefano Zampini       nid  = d2;
1014ffc4695bSBarry Smith       ierr = MPI_Group_free(&ggroup);CHKERRMPI(ierr);
1015ffc4695bSBarry Smith       ierr = MPI_Group_free(&ngroup);CHKERRMPI(ierr);
1016ffc4695bSBarry Smith       ierr = MPI_Comm_free(&ncomm);CHKERRMPI(ierr);
10170f7d6e4aSStefano Zampini     } else nid = 0.0;
10180f7d6e4aSStefano Zampini 
10190f7d6e4aSStefano Zampini     /* Get connectivity */
10200f7d6e4aSStefano Zampini     ierr = DMPlexGetVTKCellHeight(dm,&cellHeight);CHKERRQ(ierr);
10210f7d6e4aSStefano Zampini     ierr = DMPlexCreatePartitionerGraph(dm,cellHeight,&numVertices,&start,&adjacency,&gid);CHKERRQ(ierr);
10220f7d6e4aSStefano Zampini 
10230f7d6e4aSStefano Zampini     /* filter overlapped local cells */
10240f7d6e4aSStefano Zampini     ierr = DMPlexGetHeightStratum(dm,cellHeight,&cStart,&cEnd);CHKERRQ(ierr);
10250f7d6e4aSStefano Zampini     ierr = ISGetIndices(gid,&idxs);CHKERRQ(ierr);
10260f7d6e4aSStefano Zampini     ierr = ISGetLocalSize(gid,&cum);CHKERRQ(ierr);
10270f7d6e4aSStefano Zampini     ierr = PetscMalloc1(cum,&idxs2);CHKERRQ(ierr);
10280f7d6e4aSStefano Zampini     for (c = cStart, cum = 0; c < cEnd; c++) {
10290f7d6e4aSStefano Zampini       if (idxs[c-cStart] < 0) continue;
10300f7d6e4aSStefano Zampini       idxs2[cum++] = idxs[c-cStart];
10310f7d6e4aSStefano Zampini     }
10320f7d6e4aSStefano Zampini     ierr = ISRestoreIndices(gid,&idxs);CHKERRQ(ierr);
10330f7d6e4aSStefano Zampini     if (numVertices != cum) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected %D != %D",numVertices,cum);
10340f7d6e4aSStefano Zampini     ierr = ISDestroy(&gid);CHKERRQ(ierr);
10350f7d6e4aSStefano Zampini     ierr = ISCreateGeneral(comm,numVertices,idxs2,PETSC_OWN_POINTER,&gid);CHKERRQ(ierr);
10360f7d6e4aSStefano Zampini 
10370f7d6e4aSStefano Zampini     /* support for node-aware cell locality */
10380f7d6e4aSStefano Zampini     ierr = ISCreateGeneral(comm,start[numVertices],adjacency,PETSC_USE_POINTER,&acis);CHKERRQ(ierr);
10390f7d6e4aSStefano Zampini     ierr = VecCreateSeq(PETSC_COMM_SELF,start[numVertices],&acown);CHKERRQ(ierr);
10400f7d6e4aSStefano Zampini     ierr = VecCreateMPI(comm,numVertices,PETSC_DECIDE,&cown);CHKERRQ(ierr);
10410f7d6e4aSStefano Zampini     ierr = VecGetArray(cown,&array);CHKERRQ(ierr);
10420f7d6e4aSStefano Zampini     for (c = 0; c < numVertices; c++) array[c] = nid;
10430f7d6e4aSStefano Zampini     ierr = VecRestoreArray(cown,&array);CHKERRQ(ierr);
10440f7d6e4aSStefano Zampini     ierr = VecScatterCreate(cown,acis,acown,NULL,&sct);CHKERRQ(ierr);
10450f7d6e4aSStefano Zampini     ierr = VecScatterBegin(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
10460f7d6e4aSStefano Zampini     ierr = VecScatterEnd(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
10470f7d6e4aSStefano Zampini     ierr = ISDestroy(&acis);CHKERRQ(ierr);
10480f7d6e4aSStefano Zampini     ierr = VecScatterDestroy(&sct);CHKERRQ(ierr);
10490f7d6e4aSStefano Zampini     ierr = VecDestroy(&cown);CHKERRQ(ierr);
10500f7d6e4aSStefano Zampini 
10510f7d6e4aSStefano Zampini     /* compute edgeCut */
10520f7d6e4aSStefano Zampini     for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum,start[c+1]-start[c]);
10530f7d6e4aSStefano Zampini     ierr = PetscMalloc1(cum,&work);CHKERRQ(ierr);
10540f7d6e4aSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(gid,&g2l);CHKERRQ(ierr);
10550f7d6e4aSStefano Zampini     ierr = ISLocalToGlobalMappingSetType(g2l,ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr);
10560f7d6e4aSStefano Zampini     ierr = ISDestroy(&gid);CHKERRQ(ierr);
10570f7d6e4aSStefano Zampini     ierr = VecGetArray(acown,&array);CHKERRQ(ierr);
10580f7d6e4aSStefano Zampini     for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) {
10590f7d6e4aSStefano Zampini       PetscInt totl;
10600f7d6e4aSStefano Zampini 
10610f7d6e4aSStefano Zampini       totl = start[c+1]-start[c];
10620f7d6e4aSStefano Zampini       ierr = ISGlobalToLocalMappingApply(g2l,IS_GTOLM_MASK,totl,adjacency+start[c],NULL,work);CHKERRQ(ierr);
10630f7d6e4aSStefano Zampini       for (i = 0; i < totl; i++) {
10640f7d6e4aSStefano Zampini         if (work[i] < 0) {
10650f7d6e4aSStefano Zampini           ect  += 1;
10660f7d6e4aSStefano Zampini           ectn += (array[i + start[c]] != nid) ? 0 : 1;
10670f7d6e4aSStefano Zampini         }
10680f7d6e4aSStefano Zampini       }
10690f7d6e4aSStefano Zampini     }
10700f7d6e4aSStefano Zampini     ierr  = PetscFree(work);CHKERRQ(ierr);
10710f7d6e4aSStefano Zampini     ierr  = VecRestoreArray(acown,&array);CHKERRQ(ierr);
10720f7d6e4aSStefano Zampini     lm[0] = numVertices > 0 ?  numVertices : PETSC_MAX_INT;
10730f7d6e4aSStefano Zampini     lm[1] = -numVertices;
1074820f2d46SBarry Smith     ierr  = MPIU_Allreduce(lm,gm,2,MPIU_INT64,MPI_MIN,comm);CHKERRMPI(ierr);
10750f7d6e4aSStefano 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);
10760f7d6e4aSStefano Zampini     lm[0] = ect; /* edgeCut */
10770f7d6e4aSStefano Zampini     lm[1] = ectn; /* node-aware edgeCut */
10780f7d6e4aSStefano Zampini     lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */
1079820f2d46SBarry Smith     ierr  = MPIU_Allreduce(lm,gm,3,MPIU_INT64,MPI_SUM,comm);CHKERRMPI(ierr);
10800f7d6e4aSStefano Zampini     ierr  = PetscViewerASCIIPrintf(viewer,", empty %D)\n",(PetscInt)gm[2]);CHKERRQ(ierr);
1081b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
10820f7d6e4aSStefano 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);
10830f7d6e4aSStefano Zampini #else
10840f7d6e4aSStefano Zampini     ierr  = PetscViewerASCIIPrintf(viewer,"  Edge Cut: %D (on node %.3f)\n",(PetscInt)(gm[0]/2),0.0);CHKERRQ(ierr);
10850f7d6e4aSStefano Zampini #endif
10860f7d6e4aSStefano Zampini     ierr  = ISLocalToGlobalMappingDestroy(&g2l);CHKERRQ(ierr);
10870f7d6e4aSStefano Zampini     ierr  = PetscFree(start);CHKERRQ(ierr);
10880f7d6e4aSStefano Zampini     ierr  = PetscFree(adjacency);CHKERRQ(ierr);
10890f7d6e4aSStefano Zampini     ierr  = VecDestroy(&acown);CHKERRQ(ierr);
1090552f7358SJed Brown   } else {
1091412e9a14SMatthew G. Knepley     const char    *name;
1092d80ece95SMatthew G. Knepley     PetscInt      *sizes, *hybsizes, *ghostsizes;
1093412e9a14SMatthew G. Knepley     PetscInt       locDepth, depth, cellHeight, dim, d;
1094d80ece95SMatthew G. Knepley     PetscInt       pStart, pEnd, p, gcStart, gcEnd, gcNum;
1095a57dd577SMatthew G Knepley     PetscInt       numLabels, l;
10969318fe57SMatthew G. Knepley     DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN;
1097412e9a14SMatthew G. Knepley     MPI_Comm       comm;
1098412e9a14SMatthew G. Knepley     PetscMPIInt    size, rank;
1099552f7358SJed Brown 
110082f516ccSBarry Smith     ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr);
1101ffc4695bSBarry Smith     ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr);
1102ffc4695bSBarry Smith     ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
1103c73cfb54SMatthew G. Knepley     ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
1104f73eea6eSMatthew G. Knepley     ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr);
11055f64d76eSMatthew G. Knepley     ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr);
1106f73eea6eSMatthew G. Knepley     if (name) {ierr = PetscViewerASCIIPrintf(viewer, "%s in %D dimension%s:\n", name, dim, dim == 1 ? "" : "s");CHKERRQ(ierr);}
1107f73eea6eSMatthew G. Knepley     else      {ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimension%s:\n", dim, dim == 1 ? "" : "s");CHKERRQ(ierr);}
1108f73eea6eSMatthew G. Knepley     if (cellHeight) {ierr = PetscViewerASCIIPrintf(viewer, "  Cells are at height %D\n", cellHeight);CHKERRQ(ierr);}
1109552f7358SJed Brown     ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr);
1110820f2d46SBarry Smith     ierr = MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRMPI(ierr);
1111d80ece95SMatthew G. Knepley     ierr = DMPlexGetGhostCellStratum(dm, &gcStart, &gcEnd);CHKERRQ(ierr);
1112d80ece95SMatthew G. Knepley     gcNum = gcEnd - gcStart;
1113d80ece95SMatthew G. Knepley     ierr = PetscCalloc3(size,&sizes,size,&hybsizes,size,&ghostsizes);CHKERRQ(ierr);
1114412e9a14SMatthew G. Knepley     for (d = 0; d <= depth; d++) {
1115412e9a14SMatthew G. Knepley       PetscInt Nc[2] = {0, 0}, ict;
1116412e9a14SMatthew G. Knepley 
1117552f7358SJed Brown       ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr);
11189318fe57SMatthew G. Knepley       if (pStart < pEnd) {ierr = DMPlexGetCellType(dm, pStart, &ct0);CHKERRQ(ierr);}
1119412e9a14SMatthew G. Knepley       ict  = ct0;
1120ffc4695bSBarry Smith       ierr = MPI_Bcast(&ict, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr);
1121412e9a14SMatthew G. Knepley       ct0  = (DMPolytopeType) ict;
1122412e9a14SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
1123412e9a14SMatthew G. Knepley         DMPolytopeType ct;
1124412e9a14SMatthew G. Knepley 
1125412e9a14SMatthew G. Knepley         ierr = DMPlexGetCellType(dm, p, &ct);CHKERRQ(ierr);
1126412e9a14SMatthew G. Knepley         if (ct == ct0) ++Nc[0];
1127412e9a14SMatthew G. Knepley         else           ++Nc[1];
1128412e9a14SMatthew G. Knepley       }
1129ffc4695bSBarry Smith       ierr = MPI_Gather(&Nc[0], 1, MPIU_INT, sizes,    1, MPIU_INT, 0, comm);CHKERRMPI(ierr);
1130ffc4695bSBarry Smith       ierr = MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr);
1131ffc4695bSBarry Smith       if (d == depth) {ierr = MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm);CHKERRMPI(ierr);}
1132412e9a14SMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "  %D-cells:", (depth == 1) && d ? dim : d);CHKERRQ(ierr);
1133834065abSMatthew G. Knepley       for (p = 0; p < size; ++p) {
1134cbb7f117SMark Adams         if (!rank) {
1135412e9a14SMatthew G. Knepley           ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]+hybsizes[p]);CHKERRQ(ierr);
1136412e9a14SMatthew G. Knepley           if (hybsizes[p]   > 0) {ierr = PetscViewerASCIIPrintf(viewer, " (%D)", hybsizes[p]);CHKERRQ(ierr);}
1137412e9a14SMatthew G. Knepley           if (ghostsizes[p] > 0) {ierr = PetscViewerASCIIPrintf(viewer, " [%D]", ghostsizes[p]);CHKERRQ(ierr);}
1138834065abSMatthew G. Knepley         }
1139cbb7f117SMark Adams       }
1140552f7358SJed Brown       ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr);
1141552f7358SJed Brown     }
1142d80ece95SMatthew G. Knepley     ierr = PetscFree3(sizes,hybsizes,ghostsizes);CHKERRQ(ierr);
11439318fe57SMatthew G. Knepley     {
11449318fe57SMatthew G. Knepley       const PetscReal      *maxCell;
11459318fe57SMatthew G. Knepley       const PetscReal      *L;
11469318fe57SMatthew G. Knepley       const DMBoundaryType *bd;
11479318fe57SMatthew G. Knepley       PetscBool             per, localized;
11489318fe57SMatthew G. Knepley 
11499318fe57SMatthew G. Knepley       ierr = DMGetPeriodicity(dm, &per, &maxCell, &L, &bd);CHKERRQ(ierr);
11509318fe57SMatthew G. Knepley       ierr = DMGetCoordinatesLocalized(dm, &localized);CHKERRQ(ierr);
11519318fe57SMatthew G. Knepley       if (per) {
11529318fe57SMatthew G. Knepley         ierr = PetscViewerASCIIPrintf(viewer, "Periodic mesh (");CHKERRQ(ierr);
11539318fe57SMatthew G. Knepley         ierr = PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);CHKERRQ(ierr);
11549318fe57SMatthew G. Knepley         for (d = 0; d < dim; ++d) {
11559318fe57SMatthew G. Knepley           if (bd && d > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);}
11569318fe57SMatthew G. Knepley           if (bd)    {ierr = PetscViewerASCIIPrintf(viewer, "%s", DMBoundaryTypes[bd[d]]);CHKERRQ(ierr);}
11579318fe57SMatthew G. Knepley         }
11589318fe57SMatthew G. Knepley         ierr = PetscViewerASCIIPrintf(viewer, ") coordinates %s\n", localized ? "localized" : "not localized");CHKERRQ(ierr);
11599318fe57SMatthew G. Knepley         ierr = PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);CHKERRQ(ierr);
11609318fe57SMatthew G. Knepley       }
11619318fe57SMatthew G. Knepley     }
1162c58f1c22SToby Isaac     ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr);
1163a57dd577SMatthew G Knepley     if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Labels:\n");CHKERRQ(ierr);}
1164a57dd577SMatthew G Knepley     for (l = 0; l < numLabels; ++l) {
1165a57dd577SMatthew G Knepley       DMLabel         label;
1166a57dd577SMatthew G Knepley       const char     *name;
1167a57dd577SMatthew G Knepley       IS              valueIS;
1168a57dd577SMatthew G Knepley       const PetscInt *values;
1169a57dd577SMatthew G Knepley       PetscInt        numValues, v;
1170a57dd577SMatthew G Knepley 
1171c58f1c22SToby Isaac       ierr = DMGetLabelName(dm, l, &name);CHKERRQ(ierr);
1172c58f1c22SToby Isaac       ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr);
1173a57dd577SMatthew G Knepley       ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr);
1174d72f73ffSMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, "  %s: %D strata with value/size (", name, numValues);CHKERRQ(ierr);
1175a57dd577SMatthew G Knepley       ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr);
1176a57dd577SMatthew G Knepley       ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr);
1177120dea56SMatthew G. Knepley       ierr = PetscViewerASCIIUseTabs(viewer, PETSC_FALSE);CHKERRQ(ierr);
1178a57dd577SMatthew G Knepley       for (v = 0; v < numValues; ++v) {
1179a57dd577SMatthew G Knepley         PetscInt size;
1180a57dd577SMatthew G Knepley 
1181a57dd577SMatthew G Knepley         ierr = DMLabelGetStratumSize(label, values[v], &size);CHKERRQ(ierr);
1182a57dd577SMatthew G Knepley         if (v > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);}
1183d72f73ffSMatthew G. Knepley         ierr = PetscViewerASCIIPrintf(viewer, "%D (%D)", values[v], size);CHKERRQ(ierr);
1184a57dd577SMatthew G Knepley       }
1185a57dd577SMatthew G Knepley       ierr = PetscViewerASCIIPrintf(viewer, ")\n");CHKERRQ(ierr);
1186120dea56SMatthew G. Knepley       ierr = PetscViewerASCIIUseTabs(viewer, PETSC_TRUE);CHKERRQ(ierr);
1187a57dd577SMatthew G Knepley       ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr);
11884d41221fSMatthew G Knepley       ierr = ISDestroy(&valueIS);CHKERRQ(ierr);
1189a57dd577SMatthew G Knepley     }
119034aa8a36SMatthew G. Knepley     /* If no fields are specified, people do not want to see adjacency */
119134aa8a36SMatthew G. Knepley     if (dm->Nf) {
119234aa8a36SMatthew G. Knepley       PetscInt f;
119334aa8a36SMatthew G. Knepley 
119434aa8a36SMatthew G. Knepley       for (f = 0; f < dm->Nf; ++f) {
119534aa8a36SMatthew G. Knepley         const char *name;
119634aa8a36SMatthew G. Knepley 
119734aa8a36SMatthew G. Knepley         ierr = PetscObjectGetName(dm->fields[f].disc, &name);CHKERRQ(ierr);
119834aa8a36SMatthew G. Knepley         if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Field %s:\n", name);CHKERRQ(ierr);}
119934aa8a36SMatthew G. Knepley         ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
120034aa8a36SMatthew G. Knepley         if (dm->fields[f].label) {ierr = DMLabelView(dm->fields[f].label, viewer);CHKERRQ(ierr);}
120134aa8a36SMatthew G. Knepley         if (dm->fields[f].adjacency[0]) {
120234aa8a36SMatthew G. Knepley           if (dm->fields[f].adjacency[1]) {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n");CHKERRQ(ierr);}
1203ed59e46eSMatthew G. Knepley           else                            {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FVM\n");CHKERRQ(ierr);}
120434aa8a36SMatthew G. Knepley         } else {
120534aa8a36SMatthew G. Knepley           if (dm->fields[f].adjacency[1]) {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FEM\n");CHKERRQ(ierr);}
120634aa8a36SMatthew G. Knepley           else                            {ierr = PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n");CHKERRQ(ierr);}
120734aa8a36SMatthew G. Knepley         }
120834aa8a36SMatthew G. Knepley         ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
120934aa8a36SMatthew G. Knepley       }
121034aa8a36SMatthew G. Knepley     }
1211a8fb8f29SToby Isaac     ierr = DMGetCoarseDM(dm, &cdm);CHKERRQ(ierr);
12128e7ff633SMatthew G. Knepley     if (cdm) {
12138e7ff633SMatthew G. Knepley       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
12148e7ff633SMatthew G. Knepley       ierr = DMPlexView_Ascii(cdm, viewer);CHKERRQ(ierr);
12158e7ff633SMatthew G. Knepley       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
12168e7ff633SMatthew G. Knepley     }
1217552f7358SJed Brown   }
1218552f7358SJed Brown   PetscFunctionReturn(0);
1219552f7358SJed Brown }
1220552f7358SJed Brown 
1221e5c487bfSMatthew G. Knepley static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[])
1222e5c487bfSMatthew G. Knepley {
1223e5c487bfSMatthew G. Knepley   DMPolytopeType ct;
1224e5c487bfSMatthew G. Knepley   PetscMPIInt    rank;
1225e5c487bfSMatthew G. Knepley   PetscErrorCode ierr;
1226e5c487bfSMatthew G. Knepley 
1227e5c487bfSMatthew G. Knepley   PetscFunctionBegin;
1228ffc4695bSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr);
1229e5c487bfSMatthew G. Knepley   ierr = DMPlexGetCellType(dm, cell, &ct);CHKERRQ(ierr);
1230e5c487bfSMatthew G. Knepley   switch (ct) {
1231e5c487bfSMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
1232e5c487bfSMatthew G. Knepley     ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]),
1233e5c487bfSMatthew G. Knepley                              PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2,
1234e5c487bfSMatthew G. Knepley                              PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2,
1235e5c487bfSMatthew G. Knepley                              PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr);
1236e5c487bfSMatthew G. Knepley     ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK);CHKERRQ(ierr);
1237e5c487bfSMatthew G. Knepley     ierr = PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK);CHKERRQ(ierr);
1238e5c487bfSMatthew G. Knepley     ierr = PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK);CHKERRQ(ierr);
1239e5c487bfSMatthew G. Knepley     break;
1240e5c487bfSMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
1241e5c487bfSMatthew G. Knepley     ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]),
1242e5c487bfSMatthew G. Knepley                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2,
1243e5c487bfSMatthew G. Knepley                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2,
1244e5c487bfSMatthew G. Knepley                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr);
1245e5c487bfSMatthew G. Knepley     ierr = PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]),
1246e5c487bfSMatthew G. Knepley                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2,
1247e5c487bfSMatthew G. Knepley                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2,
1248e5c487bfSMatthew G. Knepley                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2);CHKERRQ(ierr);
1249e5c487bfSMatthew G. Knepley     ierr = PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK);CHKERRQ(ierr);
1250e5c487bfSMatthew G. Knepley     ierr = PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK);CHKERRQ(ierr);
1251e5c487bfSMatthew G. Knepley     ierr = PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK);CHKERRQ(ierr);
1252e5c487bfSMatthew G. Knepley     ierr = PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK);CHKERRQ(ierr);
1253e5c487bfSMatthew G. Knepley     break;
1254e5c487bfSMatthew G. Knepley   default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]);
1255e5c487bfSMatthew G. Knepley   }
1256e5c487bfSMatthew G. Knepley   PetscFunctionReturn(0);
1257e5c487bfSMatthew G. Knepley }
1258e5c487bfSMatthew G. Knepley 
1259e5c487bfSMatthew G. Knepley static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[])
1260e5c487bfSMatthew G. Knepley {
1261e5c487bfSMatthew G. Knepley   DMPolytopeType ct;
1262e5c487bfSMatthew G. Knepley   PetscReal      centroid[2] = {0., 0.};
1263e5c487bfSMatthew G. Knepley   PetscMPIInt    rank;
1264e5c487bfSMatthew G. Knepley   PetscInt       fillColor, v, e, d;
1265e5c487bfSMatthew G. Knepley   PetscErrorCode ierr;
1266e5c487bfSMatthew G. Knepley 
1267e5c487bfSMatthew G. Knepley   PetscFunctionBegin;
1268ffc4695bSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr);
1269e5c487bfSMatthew G. Knepley   ierr = DMPlexGetCellType(dm, cell, &ct);CHKERRQ(ierr);
1270e5c487bfSMatthew G. Knepley   fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2;
1271e5c487bfSMatthew G. Knepley   switch (ct) {
1272e5c487bfSMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
1273e5c487bfSMatthew G. Knepley     {
1274e5c487bfSMatthew G. Knepley       PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.};
1275e5c487bfSMatthew G. Knepley 
1276e5c487bfSMatthew G. Knepley       for (v = 0; v < 3; ++v) {centroid[0] += PetscRealPart(coords[v*2+0])/3.;centroid[1] += PetscRealPart(coords[v*2+1])/3.;}
1277e5c487bfSMatthew G. Knepley       for (e = 0; e < 3; ++e) {
1278e5c487bfSMatthew G. Knepley         refCoords[0] = refVertices[e*2+0];
1279e5c487bfSMatthew G. Knepley         refCoords[1] = refVertices[e*2+1];
1280e5c487bfSMatthew G. Knepley         for (d = 1; d <= edgeDiv; ++d) {
1281e5c487bfSMatthew G. Knepley           refCoords[d*2+0] = refCoords[0] + (refVertices[(e+1)%3 * 2 + 0] - refCoords[0])*d/edgeDiv;
1282e5c487bfSMatthew G. Knepley           refCoords[d*2+1] = refCoords[1] + (refVertices[(e+1)%3 * 2 + 1] - refCoords[1])*d/edgeDiv;
1283e5c487bfSMatthew G. Knepley         }
1284e5c487bfSMatthew G. Knepley         ierr = DMPlexReferenceToCoordinates(dm, cell, edgeDiv+1, refCoords, edgeCoords);CHKERRQ(ierr);
1285e5c487bfSMatthew G. Knepley         for (d = 0; d < edgeDiv; ++d) {
1286e5c487bfSMatthew 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);
1287e5c487bfSMatthew 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);
1288e5c487bfSMatthew G. Knepley         }
1289e5c487bfSMatthew G. Knepley       }
1290e5c487bfSMatthew G. Knepley     }
1291e5c487bfSMatthew G. Knepley     break;
1292e5c487bfSMatthew G. Knepley   default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]);
1293e5c487bfSMatthew G. Knepley   }
1294e5c487bfSMatthew G. Knepley   PetscFunctionReturn(0);
1295e5c487bfSMatthew G. Knepley }
1296e5c487bfSMatthew G. Knepley 
12977cd05799SMatthew G. Knepley static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer)
1298e412dcbdSMatthew G. Knepley {
1299e412dcbdSMatthew G. Knepley   PetscDraw          draw;
1300e412dcbdSMatthew G. Knepley   DM                 cdm;
1301e412dcbdSMatthew G. Knepley   PetscSection       coordSection;
1302e412dcbdSMatthew G. Knepley   Vec                coordinates;
1303e412dcbdSMatthew G. Knepley   const PetscScalar *coords;
130429494db1SLisandro Dalcin   PetscReal          xyl[2],xyr[2],bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL};
1305e5c487bfSMatthew G. Knepley   PetscReal         *refCoords, *edgeCoords;
1306e5c487bfSMatthew G. Knepley   PetscBool          isnull, drawAffine = PETSC_TRUE;
1307e5c487bfSMatthew G. Knepley   PetscInt           dim, vStart, vEnd, cStart, cEnd, c, N, edgeDiv = 4;
1308e412dcbdSMatthew G. Knepley   PetscErrorCode     ierr;
1309e412dcbdSMatthew G. Knepley 
1310e412dcbdSMatthew G. Knepley   PetscFunctionBegin;
1311e412dcbdSMatthew G. Knepley   ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr);
1312e412dcbdSMatthew G. Knepley   if (dim != 2) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %D", dim);
1313e5c487bfSMatthew G. Knepley   ierr = PetscOptionsGetBool(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL);CHKERRQ(ierr);
1314e5c487bfSMatthew G. Knepley   if (!drawAffine) {ierr = PetscMalloc2((edgeDiv+1)*dim, &refCoords, (edgeDiv+1)*dim, &edgeCoords);CHKERRQ(ierr);}
1315e412dcbdSMatthew G. Knepley   ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
131692fd8e1eSJed Brown   ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr);
1317e412dcbdSMatthew G. Knepley   ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
1318e412dcbdSMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
1319e412dcbdSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
1320e412dcbdSMatthew G. Knepley 
1321e412dcbdSMatthew G. Knepley   ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr);
1322e412dcbdSMatthew G. Knepley   ierr = PetscDrawIsNull(draw, &isnull);CHKERRQ(ierr);
1323e412dcbdSMatthew G. Knepley   if (isnull) PetscFunctionReturn(0);
1324e412dcbdSMatthew G. Knepley   ierr = PetscDrawSetTitle(draw, "Mesh");CHKERRQ(ierr);
1325e412dcbdSMatthew G. Knepley 
1326e412dcbdSMatthew G. Knepley   ierr = VecGetLocalSize(coordinates, &N);CHKERRQ(ierr);
1327e412dcbdSMatthew G. Knepley   ierr = VecGetArrayRead(coordinates, &coords);CHKERRQ(ierr);
1328e412dcbdSMatthew G. Knepley   for (c = 0; c < N; c += dim) {
13290c81f2a8SMatthew G. Knepley     bound[0] = PetscMin(bound[0], PetscRealPart(coords[c]));   bound[2] = PetscMax(bound[2], PetscRealPart(coords[c]));
13300c81f2a8SMatthew G. Knepley     bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1]));
1331e412dcbdSMatthew G. Knepley   }
1332e412dcbdSMatthew G. Knepley   ierr = VecRestoreArrayRead(coordinates, &coords);CHKERRQ(ierr);
1333820f2d46SBarry Smith   ierr = MPIU_Allreduce(&bound[0],xyl,2,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr);
1334820f2d46SBarry Smith   ierr = MPIU_Allreduce(&bound[2],xyr,2,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr);
133529494db1SLisandro Dalcin   ierr = PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1]);CHKERRQ(ierr);
1336e412dcbdSMatthew G. Knepley   ierr = PetscDrawClear(draw);CHKERRQ(ierr);
1337e412dcbdSMatthew G. Knepley 
1338cf3064d3SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1339cf3064d3SMatthew G. Knepley     PetscScalar *coords = NULL;
1340ba2698f1SMatthew G. Knepley     PetscInt     numCoords;
1341cf3064d3SMatthew G. Knepley 
1342e5c487bfSMatthew G. Knepley     ierr = DMPlexVecGetClosureAtDepth_Internal(dm, coordSection, coordinates, c, 0, &numCoords, &coords);CHKERRQ(ierr);
1343e5c487bfSMatthew G. Knepley     if (drawAffine) {
1344e5c487bfSMatthew G. Knepley       ierr = DMPlexDrawCell(dm, draw, c, coords);CHKERRQ(ierr);
1345e5c487bfSMatthew G. Knepley     } else {
1346e5c487bfSMatthew G. Knepley       ierr = DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords);CHKERRQ(ierr);
1347cf3064d3SMatthew G. Knepley     }
1348cf3064d3SMatthew G. Knepley     ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords);CHKERRQ(ierr);
1349cf3064d3SMatthew G. Knepley   }
1350e5c487bfSMatthew G. Knepley   if (!drawAffine) {ierr = PetscFree2(refCoords, edgeCoords);CHKERRQ(ierr);}
1351e412dcbdSMatthew G. Knepley   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
1352e412dcbdSMatthew G. Knepley   ierr = PetscDrawPause(draw);CHKERRQ(ierr);
1353e412dcbdSMatthew G. Knepley   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
1354e412dcbdSMatthew G. Knepley   PetscFunctionReturn(0);
1355e412dcbdSMatthew G. Knepley }
1356e412dcbdSMatthew G. Knepley 
13571e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII)
13581e50132fSMatthew G. Knepley #include <exodusII.h>
13596823f3c5SBlaise Bourdin #include <petscviewerexodusii.h>
13601e50132fSMatthew G. Knepley #endif
13611e50132fSMatthew G. Knepley 
1362552f7358SJed Brown PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer)
1363552f7358SJed Brown {
13641e50132fSMatthew G. Knepley   PetscBool      iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus;
1365002a2709SMatthew G. Knepley   char           name[PETSC_MAX_PATH_LEN];
1366552f7358SJed Brown   PetscErrorCode ierr;
1367552f7358SJed Brown 
1368552f7358SJed Brown   PetscFunctionBegin;
1369552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1370552f7358SJed Brown   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1371552f7358SJed Brown   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII,    &iascii);CHKERRQ(ierr);
1372fcf6c8fdSToby Isaac   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK,      &isvtk);CHKERRQ(ierr);
1373c6ccd67eSMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,     &ishdf5);CHKERRQ(ierr);
1374e412dcbdSMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW,     &isdraw);CHKERRQ(ierr);
13758135c375SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS,    &isglvis);CHKERRQ(ierr);
13761e50132fSMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodus);CHKERRQ(ierr);
1377552f7358SJed Brown   if (iascii) {
13788135c375SStefano Zampini     PetscViewerFormat format;
13798135c375SStefano Zampini     ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr);
13808135c375SStefano Zampini     if (format == PETSC_VIEWER_ASCII_GLVIS) {
13818135c375SStefano Zampini       ierr = DMPlexView_GLVis(dm, viewer);CHKERRQ(ierr);
13828135c375SStefano Zampini     } else {
1383552f7358SJed Brown       ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr);
13848135c375SStefano Zampini     }
1385c6ccd67eSMatthew G. Knepley   } else if (ishdf5) {
1386c6ccd67eSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
138739d25373SMatthew G. Knepley     ierr = DMPlexView_HDF5_Internal(dm, viewer);CHKERRQ(ierr);
1388c6ccd67eSMatthew G. Knepley #else
1389c6ccd67eSMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1390552f7358SJed Brown #endif
1391e412dcbdSMatthew G. Knepley   } else if (isvtk) {
1392fcf6c8fdSToby Isaac     ierr = DMPlexVTKWriteAll((PetscObject) dm,viewer);CHKERRQ(ierr);
1393e412dcbdSMatthew G. Knepley   } else if (isdraw) {
1394e412dcbdSMatthew G. Knepley     ierr = DMPlexView_Draw(dm, viewer);CHKERRQ(ierr);
13958135c375SStefano Zampini   } else if (isglvis) {
13968135c375SStefano Zampini     ierr = DMPlexView_GLVis(dm, viewer);CHKERRQ(ierr);
13971e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII)
13981e50132fSMatthew G. Knepley   } else if (isexodus) {
13996823f3c5SBlaise Bourdin /*
14006823f3c5SBlaise Bourdin       exodusII requires that all sets be part of exactly one cell set.
14016823f3c5SBlaise Bourdin       If the dm does not have a "Cell Sets" label defined, we create one
14026823f3c5SBlaise Bourdin       with ID 1, containig all cells.
14036823f3c5SBlaise Bourdin       Note that if the Cell Sets label is defined but does not cover all cells,
14046823f3c5SBlaise Bourdin       we may still have a problem. This should probably be checked here or in the viewer;
14056823f3c5SBlaise Bourdin     */
14066823f3c5SBlaise Bourdin     PetscInt numCS;
14076823f3c5SBlaise Bourdin     ierr = DMGetLabelSize(dm,"Cell Sets",&numCS);CHKERRQ(ierr);
14086823f3c5SBlaise Bourdin     if (!numCS) {
14091e50132fSMatthew G. Knepley       PetscInt cStart, cEnd, c;
14101e50132fSMatthew G. Knepley       ierr = DMCreateLabel(dm, "Cell Sets");CHKERRQ(ierr);
14111e50132fSMatthew G. Knepley       ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
14121e50132fSMatthew G. Knepley       for (c = cStart; c < cEnd; ++c) {ierr = DMSetLabelValue(dm, "Cell Sets", c, 1);CHKERRQ(ierr);}
14136823f3c5SBlaise Bourdin     }
14146823f3c5SBlaise Bourdin     ierr = DMView_PlexExodusII(dm, viewer);CHKERRQ(ierr);
14151e50132fSMatthew G. Knepley #endif
141662201deeSVaclav Hapla   } else {
1417a94aea51SVaclav Hapla     SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name);
1418fcf6c8fdSToby Isaac   }
1419cb3ba0daSMatthew G. Knepley   /* Optionally view the partition */
1420cb3ba0daSMatthew G. Knepley   ierr = PetscOptionsHasName(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_partition_view", &flg);CHKERRQ(ierr);
1421cb3ba0daSMatthew G. Knepley   if (flg) {
1422cb3ba0daSMatthew G. Knepley     Vec ranks;
1423cb3ba0daSMatthew G. Knepley     ierr = DMPlexCreateRankField(dm, &ranks);CHKERRQ(ierr);
1424cb3ba0daSMatthew G. Knepley     ierr = VecView(ranks, viewer);CHKERRQ(ierr);
1425cb3ba0daSMatthew G. Knepley     ierr = VecDestroy(&ranks);CHKERRQ(ierr);
1426cb3ba0daSMatthew G. Knepley   }
1427002a2709SMatthew G. Knepley   /* Optionally view a label */
1428589a23caSBarry Smith   ierr = PetscOptionsGetString(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_label_view", name, sizeof(name), &flg);CHKERRQ(ierr);
1429002a2709SMatthew G. Knepley   if (flg) {
1430002a2709SMatthew G. Knepley     DMLabel label;
1431002a2709SMatthew G. Knepley     Vec     val;
1432002a2709SMatthew G. Knepley 
1433002a2709SMatthew G. Knepley     ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr);
1434002a2709SMatthew G. Knepley     if (!label) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name);
1435002a2709SMatthew G. Knepley     ierr = DMPlexCreateLabelField(dm, label, &val);CHKERRQ(ierr);
1436002a2709SMatthew G. Knepley     ierr = VecView(val, viewer);CHKERRQ(ierr);
1437002a2709SMatthew G. Knepley     ierr = VecDestroy(&val);CHKERRQ(ierr);
1438002a2709SMatthew G. Knepley   }
1439552f7358SJed Brown   PetscFunctionReturn(0);
1440552f7358SJed Brown }
1441552f7358SJed Brown 
14427f96f51bSksagiyam /*@
14437f96f51bSksagiyam   DMPlexTopologyView - Saves a DMPlex topology into a file
14447f96f51bSksagiyam 
14457f96f51bSksagiyam   Collective on DM
14467f96f51bSksagiyam 
14477f96f51bSksagiyam   Input Parameters:
14487f96f51bSksagiyam + dm     - The DM whose topology is to be saved
14497f96f51bSksagiyam - viewer - The PetscViewer for saving
14507f96f51bSksagiyam 
14517f96f51bSksagiyam   Level: advanced
14527f96f51bSksagiyam 
14537f96f51bSksagiyam .seealso: DMView(), DMPlexCoordinatesView(), DMPlexLabelsView(), DMPlexTopologyLoad()
14547f96f51bSksagiyam @*/
14557f96f51bSksagiyam PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer)
14567f96f51bSksagiyam {
14577f96f51bSksagiyam   PetscBool      ishdf5;
14587f96f51bSksagiyam   PetscErrorCode ierr;
14597f96f51bSksagiyam 
14607f96f51bSksagiyam   PetscFunctionBegin;
14617f96f51bSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
14627f96f51bSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
14637f96f51bSksagiyam   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr);
14647f96f51bSksagiyam   if (ishdf5) {
14657f96f51bSksagiyam #if defined(PETSC_HAVE_HDF5)
14667f96f51bSksagiyam     PetscViewerFormat format;
14677f96f51bSksagiyam     ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr);
14687f96f51bSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
14697f96f51bSksagiyam       IS globalPointNumbering;
14707f96f51bSksagiyam 
14717f96f51bSksagiyam       ierr = DMPlexCreatePointNumbering(dm, &globalPointNumbering);CHKERRQ(ierr);
14727f96f51bSksagiyam       ierr = DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer);CHKERRQ(ierr);
14737f96f51bSksagiyam       ierr = ISDestroy(&globalPointNumbering);CHKERRQ(ierr);
14747f96f51bSksagiyam     } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]);
14757f96f51bSksagiyam #else
14767f96f51bSksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
14777f96f51bSksagiyam #endif
14787f96f51bSksagiyam   }
14797f96f51bSksagiyam   PetscFunctionReturn(0);
14807f96f51bSksagiyam }
14817f96f51bSksagiyam 
148277b8e257Sksagiyam /*@
148377b8e257Sksagiyam   DMPlexCoordinatesView - Saves DMPlex coordinates into a file
148477b8e257Sksagiyam 
148577b8e257Sksagiyam   Collective on DM
148677b8e257Sksagiyam 
148777b8e257Sksagiyam   Input Parameters:
148877b8e257Sksagiyam + dm     - The DM whose coordinates are to be saved
148977b8e257Sksagiyam - viewer - The PetscViewer for saving
149077b8e257Sksagiyam 
149177b8e257Sksagiyam   Level: advanced
149277b8e257Sksagiyam 
149377b8e257Sksagiyam .seealso: DMView(), DMPlexTopologyView(), DMPlexLabelsView(), DMPlexCoordinatesLoad()
149477b8e257Sksagiyam @*/
149577b8e257Sksagiyam PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer)
149677b8e257Sksagiyam {
149777b8e257Sksagiyam   PetscBool      ishdf5;
149877b8e257Sksagiyam   PetscErrorCode ierr;
149977b8e257Sksagiyam 
150077b8e257Sksagiyam   PetscFunctionBegin;
150177b8e257Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
150277b8e257Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
150377b8e257Sksagiyam   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr);
150477b8e257Sksagiyam   if (ishdf5) {
150577b8e257Sksagiyam #if defined(PETSC_HAVE_HDF5)
150677b8e257Sksagiyam     PetscViewerFormat format;
150777b8e257Sksagiyam     ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr);
150877b8e257Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
150977b8e257Sksagiyam       ierr = DMPlexCoordinatesView_HDF5_Internal(dm, viewer);CHKERRQ(ierr);
151077b8e257Sksagiyam     } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
151177b8e257Sksagiyam #else
151277b8e257Sksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
151377b8e257Sksagiyam #endif
151477b8e257Sksagiyam   }
151577b8e257Sksagiyam   PetscFunctionReturn(0);
151677b8e257Sksagiyam }
151777b8e257Sksagiyam 
1518bd6565f1Sksagiyam /*@
1519bd6565f1Sksagiyam   DMPlexLabelsView - Saves DMPlex labels into a file
1520bd6565f1Sksagiyam 
1521bd6565f1Sksagiyam   Collective on DM
1522bd6565f1Sksagiyam 
1523bd6565f1Sksagiyam   Input Parameters:
1524bd6565f1Sksagiyam + dm     - The DM whose labels are to be saved
1525bd6565f1Sksagiyam - viewer - The PetscViewer for saving
1526bd6565f1Sksagiyam 
1527bd6565f1Sksagiyam   Level: advanced
1528bd6565f1Sksagiyam 
1529bd6565f1Sksagiyam .seealso: DMView(), DMPlexTopologyView(), DMPlexCoordinatesView(), DMPlexLabelsLoad()
1530bd6565f1Sksagiyam @*/
1531bd6565f1Sksagiyam PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer)
1532bd6565f1Sksagiyam {
1533bd6565f1Sksagiyam   PetscBool      ishdf5;
1534bd6565f1Sksagiyam   PetscErrorCode ierr;
1535bd6565f1Sksagiyam 
1536bd6565f1Sksagiyam   PetscFunctionBegin;
1537bd6565f1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1538bd6565f1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1539bd6565f1Sksagiyam   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr);
1540bd6565f1Sksagiyam   if (ishdf5) {
1541bd6565f1Sksagiyam #if defined(PETSC_HAVE_HDF5)
1542bd6565f1Sksagiyam     IS                globalPointNumbering;
1543bd6565f1Sksagiyam     PetscViewerFormat format;
1544bd6565f1Sksagiyam 
1545bd6565f1Sksagiyam     ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr);
1546bd6565f1Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
1547bd6565f1Sksagiyam       ierr = DMPlexCreatePointNumbering(dm, &globalPointNumbering);CHKERRQ(ierr);
1548bd6565f1Sksagiyam       ierr = DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer);CHKERRQ(ierr);
1549bd6565f1Sksagiyam       ierr = ISDestroy(&globalPointNumbering);CHKERRQ(ierr);
1550bd6565f1Sksagiyam     } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
1551bd6565f1Sksagiyam #else
1552bd6565f1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1553bd6565f1Sksagiyam #endif
1554bd6565f1Sksagiyam   }
1555bd6565f1Sksagiyam   PetscFunctionReturn(0);
1556bd6565f1Sksagiyam }
1557bd6565f1Sksagiyam 
1558021affd3Sksagiyam /*@
1559021affd3Sksagiyam   DMPlexSectionView - Saves a section associated with a DMPlex
1560021affd3Sksagiyam 
1561021affd3Sksagiyam   Collective on DM
1562021affd3Sksagiyam 
1563021affd3Sksagiyam   Input Parameters:
1564021affd3Sksagiyam + dm         - The DM that contains the topology on which the section to be saved is defined
1565021affd3Sksagiyam . viewer     - The PetscViewer for saving
1566021affd3Sksagiyam - sectiondm  - The DM that contains the section to be saved
1567021affd3Sksagiyam 
1568021affd3Sksagiyam   Level: advanced
1569021affd3Sksagiyam 
1570021affd3Sksagiyam   Notes:
1571021affd3Sksagiyam   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.
1572021affd3Sksagiyam 
1573021affd3Sksagiyam   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.
1574021affd3Sksagiyam 
1575021affd3Sksagiyam .seealso: DMView(), DMPlexTopologyView(), DMPlexCoordinatesView(), DMPlexLabelsView(), DMPlexGlobalVectorView(), DMPlexLocalVectorView(), PetscSectionView(), DMPlexSectionLoad()
1576021affd3Sksagiyam @*/
1577021affd3Sksagiyam PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm)
1578021affd3Sksagiyam {
1579021affd3Sksagiyam   PetscBool      ishdf5;
1580021affd3Sksagiyam   PetscErrorCode ierr;
1581021affd3Sksagiyam 
1582021affd3Sksagiyam   PetscFunctionBegin;
1583021affd3Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1584021affd3Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1585021affd3Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
1586021affd3Sksagiyam   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr);
1587021affd3Sksagiyam   if (ishdf5) {
1588021affd3Sksagiyam #if defined(PETSC_HAVE_HDF5)
1589021affd3Sksagiyam     ierr = DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm);CHKERRQ(ierr);
1590021affd3Sksagiyam #else
1591021affd3Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1592021affd3Sksagiyam #endif
1593021affd3Sksagiyam   }
1594021affd3Sksagiyam   PetscFunctionReturn(0);
1595021affd3Sksagiyam }
1596021affd3Sksagiyam 
15973e97647fSksagiyam /*@
15983e97647fSksagiyam   DMPlexGlobalVectorView - Saves a global vector
15993e97647fSksagiyam 
16003e97647fSksagiyam   Collective on DM
16013e97647fSksagiyam 
16023e97647fSksagiyam   Input Parameters:
16033e97647fSksagiyam + dm        - The DM that represents the topology
16043e97647fSksagiyam . viewer    - The PetscViewer to save data with
16053e97647fSksagiyam . sectiondm - The DM that contains the global section on which vec is defined
16063e97647fSksagiyam - vec       - The global vector to be saved
16073e97647fSksagiyam 
16083e97647fSksagiyam   Level: advanced
16093e97647fSksagiyam 
16103e97647fSksagiyam   Notes:
16113e97647fSksagiyam   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.
16123e97647fSksagiyam 
16133e97647fSksagiyam   Typical calling sequence
16143e97647fSksagiyam $       DMCreate(PETSC_COMM_WORLD, &dm);
16153e97647fSksagiyam $       DMSetType(dm, DMPLEX);
16163e97647fSksagiyam $       PetscObjectSetName((PetscObject)dm, "topologydm_name");
16173e97647fSksagiyam $       DMClone(dm, &sectiondm);
16183e97647fSksagiyam $       PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
16193e97647fSksagiyam $       PetscSectionCreate(PETSC_COMM_WORLD, &section);
16203e97647fSksagiyam $       DMPlexGetChart(sectiondm, &pStart, &pEnd);
16213e97647fSksagiyam $       PetscSectionSetChart(section, pStart, pEnd);
16223e97647fSksagiyam $       PetscSectionSetUp(section);
16233e97647fSksagiyam $       DMSetLocalSection(sectiondm, section);
16243e97647fSksagiyam $       PetscSectionDestroy(&section);
16253e97647fSksagiyam $       DMGetGlobalVector(sectiondm, &vec);
16263e97647fSksagiyam $       PetscObjectSetName((PetscObject)vec, "vec_name");
16273e97647fSksagiyam $       DMPlexTopologyView(dm, viewer);
16283e97647fSksagiyam $       DMPlexSectionView(dm, viewer, sectiondm);
16293e97647fSksagiyam $       DMPlexGlobalVectorView(dm, viewer, sectiondm, vec);
16303e97647fSksagiyam $       DMRestoreGlobalVector(sectiondm, &vec);
16313e97647fSksagiyam $       DMDestroy(&sectiondm);
16323e97647fSksagiyam $       DMDestroy(&dm);
16333e97647fSksagiyam 
16343e97647fSksagiyam .seealso: DMPlexTopologyView(), DMPlexSectionView(), DMPlexLocalVectorView(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad()
16353e97647fSksagiyam @*/
16363e97647fSksagiyam PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec)
16373e97647fSksagiyam {
16383e97647fSksagiyam   PetscBool       ishdf5;
16393e97647fSksagiyam   PetscErrorCode  ierr;
16403e97647fSksagiyam 
16413e97647fSksagiyam   PetscFunctionBegin;
16423e97647fSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
16433e97647fSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
16443e97647fSksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
16453e97647fSksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 4);
16463e97647fSksagiyam   /* Check consistency */
16473e97647fSksagiyam   {
16483e97647fSksagiyam     PetscSection  section;
16493e97647fSksagiyam     PetscBool     includesConstraints;
16503e97647fSksagiyam     PetscInt      m, m1;
16513e97647fSksagiyam 
16523e97647fSksagiyam     ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr);
16533e97647fSksagiyam     ierr = DMGetGlobalSection(sectiondm, &section);CHKERRQ(ierr);
16543e97647fSksagiyam     ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr);
16553e97647fSksagiyam     if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);}
16563e97647fSksagiyam     else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);}
16573e97647fSksagiyam     if (m1 != m) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%D) != global section storage size (%D)", m1, m);
16583e97647fSksagiyam   }
16593e97647fSksagiyam   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr);
16603e97647fSksagiyam   if (ishdf5) {
16613e97647fSksagiyam #if defined(PETSC_HAVE_HDF5)
16623e97647fSksagiyam     ierr = DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec);CHKERRQ(ierr);
16633e97647fSksagiyam #else
16643e97647fSksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
16653e97647fSksagiyam #endif
16663e97647fSksagiyam   }
16673e97647fSksagiyam   PetscFunctionReturn(0);
16683e97647fSksagiyam }
16693e97647fSksagiyam 
16703e97647fSksagiyam /*@
16713e97647fSksagiyam   DMPlexLocalVectorView - Saves a local vector
16723e97647fSksagiyam 
16733e97647fSksagiyam   Collective on DM
16743e97647fSksagiyam 
16753e97647fSksagiyam   Input Parameters:
16763e97647fSksagiyam + dm        - The DM that represents the topology
16773e97647fSksagiyam . viewer    - The PetscViewer to save data with
16783e97647fSksagiyam . sectiondm - The DM that contains the local section on which vec is defined; may be the same as dm
16793e97647fSksagiyam - vec       - The local vector to be saved
16803e97647fSksagiyam 
16813e97647fSksagiyam   Level: advanced
16823e97647fSksagiyam 
16833e97647fSksagiyam   Notes:
16843e97647fSksagiyam   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.
16853e97647fSksagiyam 
16863e97647fSksagiyam   Typical calling sequence
16873e97647fSksagiyam $       DMCreate(PETSC_COMM_WORLD, &dm);
16883e97647fSksagiyam $       DMSetType(dm, DMPLEX);
16893e97647fSksagiyam $       PetscObjectSetName((PetscObject)dm, "topologydm_name");
16903e97647fSksagiyam $       DMClone(dm, &sectiondm);
16913e97647fSksagiyam $       PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
16923e97647fSksagiyam $       PetscSectionCreate(PETSC_COMM_WORLD, &section);
16933e97647fSksagiyam $       DMPlexGetChart(sectiondm, &pStart, &pEnd);
16943e97647fSksagiyam $       PetscSectionSetChart(section, pStart, pEnd);
16953e97647fSksagiyam $       PetscSectionSetUp(section);
16963e97647fSksagiyam $       DMSetLocalSection(sectiondm, section);
16973e97647fSksagiyam $       DMGetLocalVector(sectiondm, &vec);
16983e97647fSksagiyam $       PetscObjectSetName((PetscObject)vec, "vec_name");
16993e97647fSksagiyam $       DMPlexTopologyView(dm, viewer);
17003e97647fSksagiyam $       DMPlexSectionView(dm, viewer, sectiondm);
17013e97647fSksagiyam $       DMPlexLocalVectorView(dm, viewer, sectiondm, vec);
17023e97647fSksagiyam $       DMRestoreLocalVector(sectiondm, &vec);
17033e97647fSksagiyam $       DMDestroy(&sectiondm);
17043e97647fSksagiyam $       DMDestroy(&dm);
17053e97647fSksagiyam 
17063e97647fSksagiyam .seealso: DMPlexTopologyView(), DMPlexSectionView(), DMPlexGlobalVectorView(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad()
17073e97647fSksagiyam @*/
17083e97647fSksagiyam PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec)
17093e97647fSksagiyam {
17103e97647fSksagiyam   PetscBool       ishdf5;
17113e97647fSksagiyam   PetscErrorCode  ierr;
17123e97647fSksagiyam 
17133e97647fSksagiyam   PetscFunctionBegin;
17143e97647fSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
17153e97647fSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
17163e97647fSksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
17173e97647fSksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 4);
17183e97647fSksagiyam   /* Check consistency */
17193e97647fSksagiyam   {
17203e97647fSksagiyam     PetscSection  section;
17213e97647fSksagiyam     PetscBool     includesConstraints;
17223e97647fSksagiyam     PetscInt      m, m1;
17233e97647fSksagiyam 
17243e97647fSksagiyam     ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr);
17253e97647fSksagiyam     ierr = DMGetLocalSection(sectiondm, &section);CHKERRQ(ierr);
17263e97647fSksagiyam     ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr);
17273e97647fSksagiyam     if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);}
17283e97647fSksagiyam     else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);}
17293e97647fSksagiyam     if (m1 != m) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%D) != local section storage size (%D)", m1, m);
17303e97647fSksagiyam   }
17313e97647fSksagiyam   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr);
17323e97647fSksagiyam   if (ishdf5) {
17333e97647fSksagiyam #if defined(PETSC_HAVE_HDF5)
17343e97647fSksagiyam     ierr = DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec);CHKERRQ(ierr);
17353e97647fSksagiyam #else
17363e97647fSksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
17373e97647fSksagiyam #endif
17383e97647fSksagiyam   }
17393e97647fSksagiyam   PetscFunctionReturn(0);
17403e97647fSksagiyam }
17413e97647fSksagiyam 
17422c40f234SMatthew G. Knepley PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer)
17432c40f234SMatthew G. Knepley {
1744d4f5a9a0SVaclav Hapla   PetscBool      ishdf5;
17452c40f234SMatthew G. Knepley   PetscErrorCode ierr;
17462c40f234SMatthew G. Knepley 
17472c40f234SMatthew G. Knepley   PetscFunctionBegin;
17482c40f234SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
17492c40f234SMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
17502c40f234SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,   &ishdf5);CHKERRQ(ierr);
1751d4f5a9a0SVaclav Hapla   if (ishdf5) {
17522c40f234SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
17539c48423bSVaclav Hapla     PetscViewerFormat format;
17549c48423bSVaclav Hapla     ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr);
17559c48423bSVaclav Hapla     if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) {
17569c48423bSVaclav Hapla       ierr = DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer);CHKERRQ(ierr);
1757509517efSVaclav Hapla     } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
175839d25373SMatthew G. Knepley       ierr = DMPlexLoad_HDF5_Internal(dm, viewer);CHKERRQ(ierr);
1759509517efSVaclav Hapla     } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
1760b458e8f1SJose E. Roman     PetscFunctionReturn(0);
17612c40f234SMatthew G. Knepley #else
17622c40f234SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1763552f7358SJed Brown #endif
1764b458e8f1SJose E. Roman   } else SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name);
1765552f7358SJed Brown }
1766552f7358SJed Brown 
1767ea8e1828Sksagiyam /*@
1768ea8e1828Sksagiyam   DMPlexTopologyLoad - Loads a topology into a DMPlex
1769ea8e1828Sksagiyam 
1770ea8e1828Sksagiyam   Collective on DM
1771ea8e1828Sksagiyam 
1772ea8e1828Sksagiyam   Input Parameters:
1773ea8e1828Sksagiyam + dm     - The DM into which the topology is loaded
1774ea8e1828Sksagiyam - viewer - The PetscViewer for the saved topology
1775ea8e1828Sksagiyam 
1776dec9e869Sksagiyam   Output Parameters:
1777f84dd6b4Sksagiyam . 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
1778dec9e869Sksagiyam 
1779ea8e1828Sksagiyam   Level: advanced
1780ea8e1828Sksagiyam 
1781b08ad5deSksagiyam .seealso: DMLoad(), DMPlexCoordinatesLoad(), DMPlexLabelsLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat()
1782ea8e1828Sksagiyam @*/
1783f84dd6b4Sksagiyam PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF)
1784ea8e1828Sksagiyam {
1785ea8e1828Sksagiyam   PetscBool      ishdf5;
1786ea8e1828Sksagiyam   PetscErrorCode ierr;
1787ea8e1828Sksagiyam 
1788ea8e1828Sksagiyam   PetscFunctionBegin;
1789ea8e1828Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1790ea8e1828Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1791f84dd6b4Sksagiyam   if (globalToLocalPointSF) PetscValidPointer(globalToLocalPointSF, 3);
1792ea8e1828Sksagiyam   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr);
1793ea8e1828Sksagiyam   if (ishdf5) {
1794ea8e1828Sksagiyam #if defined(PETSC_HAVE_HDF5)
1795ea8e1828Sksagiyam     PetscViewerFormat format;
1796ea8e1828Sksagiyam     ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr);
1797ea8e1828Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
1798f84dd6b4Sksagiyam       ierr = DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF);CHKERRQ(ierr);
1799ea8e1828Sksagiyam     } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
1800ea8e1828Sksagiyam #else
1801ea8e1828Sksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1802ea8e1828Sksagiyam #endif
1803ea8e1828Sksagiyam   }
1804ea8e1828Sksagiyam   PetscFunctionReturn(0);
1805ea8e1828Sksagiyam }
1806ea8e1828Sksagiyam 
18073e701f1cSksagiyam /*@
18083e701f1cSksagiyam   DMPlexCoordinatesLoad - Loads coordinates into a DMPlex
18093e701f1cSksagiyam 
18103e701f1cSksagiyam   Collective on DM
18113e701f1cSksagiyam 
18123e701f1cSksagiyam   Input Parameters:
18133e701f1cSksagiyam + dm     - The DM into which the coordinates are loaded
18143e701f1cSksagiyam - viewer - The PetscViewer for the saved coordinates
18153e701f1cSksagiyam 
18163e701f1cSksagiyam   Level: advanced
18173e701f1cSksagiyam 
1818b08ad5deSksagiyam .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexLabelsLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat()
18193e701f1cSksagiyam @*/
18203e701f1cSksagiyam PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer)
18213e701f1cSksagiyam {
18223e701f1cSksagiyam   PetscBool      ishdf5;
18233e701f1cSksagiyam   PetscErrorCode ierr;
18243e701f1cSksagiyam 
18253e701f1cSksagiyam   PetscFunctionBegin;
18263e701f1cSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
18273e701f1cSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
18283e701f1cSksagiyam   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr);
18293e701f1cSksagiyam   if (ishdf5) {
18303e701f1cSksagiyam #if defined(PETSC_HAVE_HDF5)
18313e701f1cSksagiyam     PetscViewerFormat format;
18323e701f1cSksagiyam     ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr);
18333e701f1cSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
18343e701f1cSksagiyam       ierr = DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer);CHKERRQ(ierr);
18353e701f1cSksagiyam     } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
18363e701f1cSksagiyam #else
18373e701f1cSksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
18383e701f1cSksagiyam #endif
18393e701f1cSksagiyam   }
18403e701f1cSksagiyam   PetscFunctionReturn(0);
18413e701f1cSksagiyam }
18423e701f1cSksagiyam 
1843b08ad5deSksagiyam /*@
1844b08ad5deSksagiyam   DMPlexLabelsLoad - Loads labels into a DMPlex
1845b08ad5deSksagiyam 
1846b08ad5deSksagiyam   Collective on DM
1847b08ad5deSksagiyam 
1848b08ad5deSksagiyam   Input Parameters:
1849b08ad5deSksagiyam + dm     - The DM into which the labels are loaded
1850b08ad5deSksagiyam - viewer - The PetscViewer for the saved labels
1851b08ad5deSksagiyam 
1852b08ad5deSksagiyam   Level: advanced
1853b08ad5deSksagiyam 
1854b08ad5deSksagiyam .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexCoordinatesLoad(), DMView(), PetscViewerHDF5Open(), PetscViewerPushFormat()
1855b08ad5deSksagiyam @*/
1856b08ad5deSksagiyam PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer)
1857b08ad5deSksagiyam {
1858b08ad5deSksagiyam   PetscBool      ishdf5;
1859b08ad5deSksagiyam   PetscErrorCode ierr;
1860b08ad5deSksagiyam 
1861b08ad5deSksagiyam   PetscFunctionBegin;
1862b08ad5deSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1863b08ad5deSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1864b08ad5deSksagiyam   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr);
1865b08ad5deSksagiyam   if (ishdf5) {
1866b08ad5deSksagiyam #if defined(PETSC_HAVE_HDF5)
1867b08ad5deSksagiyam     PetscViewerFormat format;
1868b08ad5deSksagiyam 
1869b08ad5deSksagiyam     ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr);
1870b08ad5deSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
1871b08ad5deSksagiyam       ierr = DMPlexLabelsLoad_HDF5_Internal(dm, viewer);CHKERRQ(ierr);
1872b08ad5deSksagiyam     } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
1873b08ad5deSksagiyam #else
1874b08ad5deSksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1875b08ad5deSksagiyam #endif
1876b08ad5deSksagiyam   }
1877b08ad5deSksagiyam   PetscFunctionReturn(0);
1878b08ad5deSksagiyam }
1879b08ad5deSksagiyam 
1880f84dd6b4Sksagiyam /*@
1881f84dd6b4Sksagiyam   DMPlexSectionLoad - Loads section into a DMPlex
1882f84dd6b4Sksagiyam 
1883f84dd6b4Sksagiyam   Collective on DM
1884f84dd6b4Sksagiyam 
1885f84dd6b4Sksagiyam   Input Parameters:
1886f84dd6b4Sksagiyam + dm          - The DM that represents the topology
1887f84dd6b4Sksagiyam . viewer      - The PetscViewer that represents the on-disk section (sectionA)
1888f84dd6b4Sksagiyam . sectiondm   - The DM into which the on-disk section (sectionA) is migrated
1889f84dd6b4Sksagiyam - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer
1890f84dd6b4Sksagiyam 
1891f84dd6b4Sksagiyam   Output Parameters
1892f84dd6b4Sksagiyam + 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)
1893f84dd6b4Sksagiyam - 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)
1894f84dd6b4Sksagiyam 
1895f84dd6b4Sksagiyam   Level: advanced
1896f84dd6b4Sksagiyam 
1897f84dd6b4Sksagiyam   Notes:
1898f84dd6b4Sksagiyam   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.
1899f84dd6b4Sksagiyam 
1900f84dd6b4Sksagiyam   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.
1901f84dd6b4Sksagiyam 
1902f84dd6b4Sksagiyam   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.
1903f84dd6b4Sksagiyam 
1904f84dd6b4Sksagiyam   Example using 2 processes:
1905f84dd6b4Sksagiyam $  NX (number of points on dm): 4
1906f84dd6b4Sksagiyam $  sectionA                   : the on-disk section
1907f84dd6b4Sksagiyam $  vecA                       : a vector associated with sectionA
1908f84dd6b4Sksagiyam $  sectionB                   : sectiondm's local section constructed in this function
1909f84dd6b4Sksagiyam $  vecB (local)               : a vector associated with sectiondm's local section
1910f84dd6b4Sksagiyam $  vecB (global)              : a vector associated with sectiondm's global section
1911f84dd6b4Sksagiyam $
1912f84dd6b4Sksagiyam $                                     rank 0    rank 1
1913f84dd6b4Sksagiyam $  vecA (global)                  : [.0 .4 .1 | .2 .3]        <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad()
1914f84dd6b4Sksagiyam $  sectionA->atlasOff             :       0 2 | 1             <- loaded in PetscSectionLoad()
1915f84dd6b4Sksagiyam $  sectionA->atlasDof             :       1 3 | 1             <- loaded in PetscSectionLoad()
1916f84dd6b4Sksagiyam $  sectionA's global point numbers:       0 2 | 3             <- loaded in DMPlexSectionLoad()
1917f84dd6b4Sksagiyam $  [0, NX)                        :       0 1 | 2 3           <- conceptual partition used in globalToLocalPointSF
1918f84dd6b4Sksagiyam $  sectionB's global point numbers:     0 1 3 | 3 2           <- associated with [0, NX) by globalToLocalPointSF
1919f84dd6b4Sksagiyam $  sectionB->atlasDof             :     1 0 1 | 1 3
1920f84dd6b4Sksagiyam $  sectionB->atlasOff (no perm)   :     0 1 1 | 0 1
1921f84dd6b4Sksagiyam $  vecB (local)                   :   [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF
1922f84dd6b4Sksagiyam $  vecB (global)                  :    [.0 .4 | .1 .2 .3]     <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF
1923f84dd6b4Sksagiyam $
1924f84dd6b4Sksagiyam $  where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0.
1925f84dd6b4Sksagiyam 
1926f84dd6b4Sksagiyam .seealso: DMLoad(), DMPlexTopologyLoad(), DMPlexCoordinatesLoad(), DMPlexLabelsLoad(), DMPlexGlobalVectorLoad(), DMPlexLocalVectorLoad(), PetscSectionLoad(), DMPlexSectionView()
1927f84dd6b4Sksagiyam @*/
1928f84dd6b4Sksagiyam PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF globalToLocalPointSF, PetscSF *globalDofSF, PetscSF *localDofSF)
1929f84dd6b4Sksagiyam {
1930f84dd6b4Sksagiyam   PetscBool      ishdf5;
1931f84dd6b4Sksagiyam   PetscErrorCode ierr;
1932f84dd6b4Sksagiyam 
1933f84dd6b4Sksagiyam   PetscFunctionBegin;
1934f84dd6b4Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1935f84dd6b4Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1936f84dd6b4Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
1937f84dd6b4Sksagiyam   PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4);
1938f84dd6b4Sksagiyam   if (globalDofSF) PetscValidPointer(globalDofSF, 5);
1939f84dd6b4Sksagiyam   if (localDofSF) PetscValidPointer(localDofSF, 6);
1940f84dd6b4Sksagiyam   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr);
1941f84dd6b4Sksagiyam   if (ishdf5) {
1942f84dd6b4Sksagiyam #if defined(PETSC_HAVE_HDF5)
1943f84dd6b4Sksagiyam     ierr = DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF);CHKERRQ(ierr);
1944f84dd6b4Sksagiyam #else
1945f84dd6b4Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1946f84dd6b4Sksagiyam #endif
1947f84dd6b4Sksagiyam   }
1948f84dd6b4Sksagiyam   PetscFunctionReturn(0);
1949f84dd6b4Sksagiyam }
1950f84dd6b4Sksagiyam 
19518be3dfe1Sksagiyam /*@
19528be3dfe1Sksagiyam   DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector
19538be3dfe1Sksagiyam 
19548be3dfe1Sksagiyam   Collective on DM
19558be3dfe1Sksagiyam 
19568be3dfe1Sksagiyam   Input Parameters:
19578be3dfe1Sksagiyam + dm        - The DM that represents the topology
19588be3dfe1Sksagiyam . viewer    - The PetscViewer that represents the on-disk vector data
19598be3dfe1Sksagiyam . sectiondm - The DM that contains the global section on which vec is defined
19608be3dfe1Sksagiyam . sf        - The SF that migrates the on-disk vector data into vec
19618be3dfe1Sksagiyam - vec       - The global vector to set values of
19628be3dfe1Sksagiyam 
19638be3dfe1Sksagiyam   Level: advanced
19648be3dfe1Sksagiyam 
19658be3dfe1Sksagiyam   Notes:
19668be3dfe1Sksagiyam   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.
19678be3dfe1Sksagiyam 
19688be3dfe1Sksagiyam   Typical calling sequence
19698be3dfe1Sksagiyam $       DMCreate(PETSC_COMM_WORLD, &dm);
19708be3dfe1Sksagiyam $       DMSetType(dm, DMPLEX);
19718be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)dm, "topologydm_name");
19728be3dfe1Sksagiyam $       DMPlexTopologyLoad(dm, viewer, &sfX);
19738be3dfe1Sksagiyam $       DMClone(dm, &sectiondm);
19748be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
19758be3dfe1Sksagiyam $       DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL);
19768be3dfe1Sksagiyam $       DMGetGlobalVector(sectiondm, &vec);
19778be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)vec, "vec_name");
19788be3dfe1Sksagiyam $       DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec);
19798be3dfe1Sksagiyam $       DMRestoreGlobalVector(sectiondm, &vec);
19808be3dfe1Sksagiyam $       PetscSFDestroy(&gsf);
19818be3dfe1Sksagiyam $       PetscSFDestroy(&sfX);
19828be3dfe1Sksagiyam $       DMDestroy(&sectiondm);
19838be3dfe1Sksagiyam $       DMDestroy(&dm);
19848be3dfe1Sksagiyam 
19858be3dfe1Sksagiyam .seealso: DMPlexTopologyLoad(), DMPlexSectionLoad(), DMPlexLocalVectorLoad(), DMPlexGlobalVectorView(), DMPlexLocalVectorView()
19868be3dfe1Sksagiyam @*/
19878be3dfe1Sksagiyam PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec)
19888be3dfe1Sksagiyam {
19898be3dfe1Sksagiyam   PetscBool       ishdf5;
19908be3dfe1Sksagiyam   PetscErrorCode  ierr;
19918be3dfe1Sksagiyam 
19928be3dfe1Sksagiyam   PetscFunctionBegin;
19938be3dfe1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
19948be3dfe1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
19958be3dfe1Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
19968be3dfe1Sksagiyam   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4);
19978be3dfe1Sksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 5);
19988be3dfe1Sksagiyam   /* Check consistency */
19998be3dfe1Sksagiyam   {
20008be3dfe1Sksagiyam     PetscSection  section;
20018be3dfe1Sksagiyam     PetscBool     includesConstraints;
20028be3dfe1Sksagiyam     PetscInt      m, m1;
20038be3dfe1Sksagiyam 
20048be3dfe1Sksagiyam     ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr);
20058be3dfe1Sksagiyam     ierr = DMGetGlobalSection(sectiondm, &section);CHKERRQ(ierr);
20068be3dfe1Sksagiyam     ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr);
20078be3dfe1Sksagiyam     if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);}
20088be3dfe1Sksagiyam     else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);}
20098be3dfe1Sksagiyam     if (m1 != m) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%D) != global section storage size (%D)", m1, m);
20108be3dfe1Sksagiyam   }
20118be3dfe1Sksagiyam   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr);
20128be3dfe1Sksagiyam   if (ishdf5) {
20138be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5)
20148be3dfe1Sksagiyam     ierr = DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec);CHKERRQ(ierr);
20158be3dfe1Sksagiyam #else
20168be3dfe1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
20178be3dfe1Sksagiyam #endif
20188be3dfe1Sksagiyam   }
20198be3dfe1Sksagiyam   PetscFunctionReturn(0);
20208be3dfe1Sksagiyam }
20218be3dfe1Sksagiyam 
20228be3dfe1Sksagiyam /*@
20238be3dfe1Sksagiyam   DMPlexLocalVectorLoad - Loads on-disk vector data into a local vector
20248be3dfe1Sksagiyam 
20258be3dfe1Sksagiyam   Collective on DM
20268be3dfe1Sksagiyam 
20278be3dfe1Sksagiyam   Input Parameters:
20288be3dfe1Sksagiyam + dm        - The DM that represents the topology
20298be3dfe1Sksagiyam . viewer    - The PetscViewer that represents the on-disk vector data
20308be3dfe1Sksagiyam . sectiondm - The DM that contains the local section on which vec is defined
20318be3dfe1Sksagiyam . sf        - The SF that migrates the on-disk vector data into vec
20328be3dfe1Sksagiyam - vec       - The local vector to set values of
20338be3dfe1Sksagiyam 
20348be3dfe1Sksagiyam   Level: advanced
20358be3dfe1Sksagiyam 
20368be3dfe1Sksagiyam   Notes:
20378be3dfe1Sksagiyam   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.
20388be3dfe1Sksagiyam 
20398be3dfe1Sksagiyam   Typical calling sequence
20408be3dfe1Sksagiyam $       DMCreate(PETSC_COMM_WORLD, &dm);
20418be3dfe1Sksagiyam $       DMSetType(dm, DMPLEX);
20428be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)dm, "topologydm_name");
20438be3dfe1Sksagiyam $       DMPlexTopologyLoad(dm, viewer, &sfX);
20448be3dfe1Sksagiyam $       DMClone(dm, &sectiondm);
20458be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
20468be3dfe1Sksagiyam $       DMPlexSectionLoad(dm, viewer, sectiondm, sfX, NULL, &lsf);
20478be3dfe1Sksagiyam $       DMGetLocalVector(sectiondm, &vec);
20488be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)vec, "vec_name");
20498be3dfe1Sksagiyam $       DMPlexLocalVectorLoad(dm, viewer, sectiondm, lsf, vec);
20508be3dfe1Sksagiyam $       DMRestoreLocalVector(sectiondm, &vec);
20518be3dfe1Sksagiyam $       PetscSFDestroy(&lsf);
20528be3dfe1Sksagiyam $       PetscSFDestroy(&sfX);
20538be3dfe1Sksagiyam $       DMDestroy(&sectiondm);
20548be3dfe1Sksagiyam $       DMDestroy(&dm);
20558be3dfe1Sksagiyam 
20568be3dfe1Sksagiyam .seealso: DMPlexTopologyLoad(), DMPlexSectionLoad(), DMPlexGlobalVectorLoad(), DMPlexGlobalVectorView(), DMPlexLocalVectorView()
20578be3dfe1Sksagiyam @*/
20588be3dfe1Sksagiyam PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec)
20598be3dfe1Sksagiyam {
20608be3dfe1Sksagiyam   PetscBool       ishdf5;
20618be3dfe1Sksagiyam   PetscErrorCode  ierr;
20628be3dfe1Sksagiyam 
20638be3dfe1Sksagiyam   PetscFunctionBegin;
20648be3dfe1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
20658be3dfe1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
20668be3dfe1Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
20678be3dfe1Sksagiyam   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4);
20688be3dfe1Sksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 5);
20698be3dfe1Sksagiyam   /* Check consistency */
20708be3dfe1Sksagiyam   {
20718be3dfe1Sksagiyam     PetscSection  section;
20728be3dfe1Sksagiyam     PetscBool     includesConstraints;
20738be3dfe1Sksagiyam     PetscInt      m, m1;
20748be3dfe1Sksagiyam 
20758be3dfe1Sksagiyam     ierr = VecGetLocalSize(vec, &m1);CHKERRQ(ierr);
20768be3dfe1Sksagiyam     ierr = DMGetLocalSection(sectiondm, &section);CHKERRQ(ierr);
20778be3dfe1Sksagiyam     ierr = PetscSectionGetIncludesConstraints(section, &includesConstraints);CHKERRQ(ierr);
20788be3dfe1Sksagiyam     if (includesConstraints) {ierr = PetscSectionGetStorageSize(section, &m);CHKERRQ(ierr);}
20798be3dfe1Sksagiyam     else {ierr = PetscSectionGetConstrainedStorageSize(section, &m);CHKERRQ(ierr);}
20808be3dfe1Sksagiyam     if (m1 != m) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%D) != local section storage size (%D)", m1, m);
20818be3dfe1Sksagiyam   }
20828be3dfe1Sksagiyam   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5);CHKERRQ(ierr);
20838be3dfe1Sksagiyam   if (ishdf5) {
20848be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5)
20858be3dfe1Sksagiyam     ierr = DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec);CHKERRQ(ierr);
20868be3dfe1Sksagiyam #else
20878be3dfe1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
20888be3dfe1Sksagiyam #endif
20898be3dfe1Sksagiyam   }
20908be3dfe1Sksagiyam   PetscFunctionReturn(0);
20918be3dfe1Sksagiyam }
20928be3dfe1Sksagiyam 
2093552f7358SJed Brown PetscErrorCode DMDestroy_Plex(DM dm)
2094552f7358SJed Brown {
2095552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2096552f7358SJed Brown   PetscErrorCode ierr;
2097552f7358SJed Brown 
2098552f7358SJed Brown   PetscFunctionBegin;
20998135c375SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)dm,"DMSetUpGLVisViewer_C",NULL);CHKERRQ(ierr);
21008135c375SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertBoundaryValues_C", NULL);CHKERRQ(ierr);
210128d58a37SPierre Jolivet   ierr = PetscObjectComposeFunction((PetscObject)dm,"DMCreateNeumannOverlap_C", NULL);CHKERRQ(ierr);
21021eb70e55SToby Isaac   ierr = PetscObjectComposeFunction((PetscObject)dm,"DMInterpolateSolution_C", NULL);CHKERRQ(ierr);
21030d644c17SKarl Rupp   if (--mesh->refct > 0) PetscFunctionReturn(0);
2104552f7358SJed Brown   ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr);
2105552f7358SJed Brown   ierr = PetscFree(mesh->cones);CHKERRQ(ierr);
2106552f7358SJed Brown   ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr);
2107552f7358SJed Brown   ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr);
2108be36d101SStefano Zampini   ierr = PetscSectionDestroy(&mesh->subdomainSection);CHKERRQ(ierr);
2109552f7358SJed Brown   ierr = PetscFree(mesh->supports);CHKERRQ(ierr);
2110552f7358SJed Brown   ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr);
2111d9deefdfSMatthew G. Knepley   ierr = PetscFree(mesh->tetgenOpts);CHKERRQ(ierr);
2112d9deefdfSMatthew G. Knepley   ierr = PetscFree(mesh->triangleOpts);CHKERRQ(ierr);
211377623264SMatthew G. Knepley   ierr = PetscPartitionerDestroy(&mesh->partitioner);CHKERRQ(ierr);
2114a89082eeSMatthew G Knepley   ierr = DMLabelDestroy(&mesh->subpointMap);CHKERRQ(ierr);
211597d8846cSMatthew Knepley   ierr = ISDestroy(&mesh->subpointIS);CHKERRQ(ierr);
2116552f7358SJed Brown   ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr);
2117552f7358SJed Brown   ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr);
2118a68b90caSToby Isaac   ierr = PetscSectionDestroy(&mesh->anchorSection);CHKERRQ(ierr);
2119a68b90caSToby Isaac   ierr = ISDestroy(&mesh->anchorIS);CHKERRQ(ierr);
2120d961a43aSToby Isaac   ierr = PetscSectionDestroy(&mesh->parentSection);CHKERRQ(ierr);
2121d961a43aSToby Isaac   ierr = PetscFree(mesh->parents);CHKERRQ(ierr);
2122d961a43aSToby Isaac   ierr = PetscFree(mesh->childIDs);CHKERRQ(ierr);
2123d961a43aSToby Isaac   ierr = PetscSectionDestroy(&mesh->childSection);CHKERRQ(ierr);
2124d961a43aSToby Isaac   ierr = PetscFree(mesh->children);CHKERRQ(ierr);
2125d6a7ad0dSToby Isaac   ierr = DMDestroy(&mesh->referenceTree);CHKERRQ(ierr);
2126fec49543SMatthew G. Knepley   ierr = PetscGridHashDestroy(&mesh->lbox);CHKERRQ(ierr);
21270a19bb7dSprj-   ierr = PetscFree(mesh->neighbors);CHKERRQ(ierr);
2128552f7358SJed Brown   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
2129552f7358SJed Brown   ierr = PetscFree(mesh);CHKERRQ(ierr);
2130552f7358SJed Brown   PetscFunctionReturn(0);
2131552f7358SJed Brown }
2132552f7358SJed Brown 
2133b412c318SBarry Smith PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J)
2134552f7358SJed Brown {
21358d1174e4SMatthew G. Knepley   PetscSection           sectionGlobal;
2136acd755d7SMatthew G. Knepley   PetscInt               bs = -1, mbs;
2137552f7358SJed Brown   PetscInt               localSize;
2138837628f4SStefano Zampini   PetscBool              isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS;
2139552f7358SJed Brown   PetscErrorCode         ierr;
2140b412c318SBarry Smith   MatType                mtype;
21411428887cSShri Abhyankar   ISLocalToGlobalMapping ltog;
2142552f7358SJed Brown 
2143552f7358SJed Brown   PetscFunctionBegin;
2144607a6623SBarry Smith   ierr = MatInitializePackage();CHKERRQ(ierr);
2145b412c318SBarry Smith   mtype = dm->mattype;
2146e87a4003SBarry Smith   ierr = DMGetGlobalSection(dm, &sectionGlobal);CHKERRQ(ierr);
2147552f7358SJed Brown   /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */
2148552f7358SJed Brown   ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr);
214982f516ccSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)dm), J);CHKERRQ(ierr);
2150552f7358SJed Brown   ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
2151552f7358SJed Brown   ierr = MatSetType(*J, mtype);CHKERRQ(ierr);
2152552f7358SJed Brown   ierr = MatSetFromOptions(*J);CHKERRQ(ierr);
2153acd755d7SMatthew G. Knepley   ierr = MatGetBlockSize(*J, &mbs);CHKERRQ(ierr);
2154acd755d7SMatthew G. Knepley   if (mbs > 1) bs = mbs;
2155552f7358SJed Brown   ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr);
2156552f7358SJed Brown   ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr);
2157552f7358SJed Brown   ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr);
2158552f7358SJed Brown   ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr);
2159552f7358SJed Brown   ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr);
2160552f7358SJed Brown   ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr);
2161552f7358SJed Brown   ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr);
2162837628f4SStefano Zampini   ierr = PetscStrcmp(mtype, MATIS, &isMatIS);CHKERRQ(ierr);
2163552f7358SJed Brown   if (!isShell) {
2164be36d101SStefano Zampini     PetscSection subSection;
2165837628f4SStefano Zampini     PetscBool    fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS);
21660be3e97aSMatthew G. Knepley     PetscInt    *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *ltogidx, lsize;
2167fad22124SMatthew G Knepley     PetscInt     pStart, pEnd, p, dof, cdof;
2168552f7358SJed Brown 
216900140cc3SStefano Zampini     /* Set localtoglobalmapping on the matrix for MatSetValuesLocal() to work (it also creates the local matrices in case of MATIS) */
2170be36d101SStefano Zampini     if (isMatIS) { /* need a different l2g map than the one computed by DMGetLocalToGlobalMapping */
2171be36d101SStefano Zampini       PetscSection section;
2172be36d101SStefano Zampini       PetscInt     size;
2173be36d101SStefano Zampini 
217492fd8e1eSJed Brown       ierr = DMGetLocalSection(dm, &section);CHKERRQ(ierr);
2175be36d101SStefano Zampini       ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr);
2176be36d101SStefano Zampini       ierr = PetscMalloc1(size,&ltogidx);CHKERRQ(ierr);
2177be36d101SStefano Zampini       ierr = DMPlexGetSubdomainSection(dm, &subSection);CHKERRQ(ierr);
2178be36d101SStefano Zampini     } else {
217900140cc3SStefano Zampini       ierr = DMGetLocalToGlobalMapping(dm,&ltog);CHKERRQ(ierr);
2180be36d101SStefano Zampini     }
2181552f7358SJed Brown     ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr);
2182be36d101SStefano Zampini     for (p = pStart, lsize = 0; p < pEnd; ++p) {
2183a9d99c84SMatthew G. Knepley       PetscInt bdof;
2184a9d99c84SMatthew G. Knepley 
2185552f7358SJed Brown       ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr);
2186fad22124SMatthew G Knepley       ierr = PetscSectionGetConstraintDof(sectionGlobal, p, &cdof);CHKERRQ(ierr);
21871d17a0a3SMatthew G. Knepley       dof  = dof < 0 ? -(dof+1) : dof;
21881d17a0a3SMatthew G. Knepley       bdof = cdof && (dof-cdof) ? 1 : dof;
21891d17a0a3SMatthew G. Knepley       if (dof) {
21901d17a0a3SMatthew G. Knepley         if (bs < 0)          {bs = bdof;}
2191be36d101SStefano Zampini         else if (bs != bdof) {bs = 1; if (!isMatIS) break;}
2192be36d101SStefano Zampini       }
2193be36d101SStefano Zampini       if (isMatIS) {
2194be36d101SStefano Zampini         PetscInt loff,c,off;
2195be36d101SStefano Zampini         ierr = PetscSectionGetOffset(subSection, p, &loff);CHKERRQ(ierr);
2196be36d101SStefano Zampini         ierr = PetscSectionGetOffset(sectionGlobal, p, &off);CHKERRQ(ierr);
2197be36d101SStefano Zampini         for (c = 0; c < dof-cdof; ++c, ++lsize) ltogidx[loff+c] = off > -1 ? off+c : -(off+1)+c;
2198552f7358SJed Brown       }
21992a28c762SMatthew G Knepley     }
22002a28c762SMatthew G Knepley     /* Must have same blocksize on all procs (some might have no points) */
22010be3e97aSMatthew G. Knepley     bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs;
22020be3e97aSMatthew G. Knepley     ierr = PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);CHKERRQ(ierr);
22030be3e97aSMatthew G. Knepley     if (bsMinMax[0] != bsMinMax[1]) {bs = 1;}
22040be3e97aSMatthew G. Knepley     else                            {bs = bsMinMax[0];}
22056fd5c86aSStefano Zampini     bs = PetscMax(1,bs);
22066fd5c86aSStefano Zampini     if (isMatIS) { /* Must reduce indices by blocksize */
22074fa26246SMatthew G. Knepley       PetscInt l;
22086fd5c86aSStefano Zampini 
22096fd5c86aSStefano Zampini       lsize = lsize/bs;
22106fd5c86aSStefano Zampini       if (bs > 1) for (l = 0; l < lsize; ++l) ltogidx[l] = ltogidx[l*bs]/bs;
22114fa26246SMatthew G. Knepley       ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)dm), bs, lsize, ltogidx, PETSC_OWN_POINTER, &ltog);CHKERRQ(ierr);
2212be36d101SStefano Zampini     }
2213be36d101SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*J,ltog,ltog);CHKERRQ(ierr);
2214be36d101SStefano Zampini     if (isMatIS) {
2215be36d101SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&ltog);CHKERRQ(ierr);
2216be36d101SStefano Zampini     }
22171795a4d1SJed Brown     ierr = PetscCalloc4(localSize/bs, &dnz, localSize/bs, &onz, localSize/bs, &dnzu, localSize/bs, &onzu);CHKERRQ(ierr);
22188d1174e4SMatthew G. Knepley     ierr = DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr);
2219552f7358SJed Brown     ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr);
2220552f7358SJed Brown   }
2221b1f74addSMatthew G. Knepley   ierr = MatSetDM(*J, dm);CHKERRQ(ierr);
2222552f7358SJed Brown   PetscFunctionReturn(0);
2223552f7358SJed Brown }
2224552f7358SJed Brown 
22257cd05799SMatthew G. Knepley /*@
2226a8f00d21SMatthew G. Knepley   DMPlexGetSubdomainSection - Returns the section associated with the subdomain
2227be36d101SStefano Zampini 
2228be36d101SStefano Zampini   Not collective
2229be36d101SStefano Zampini 
2230be36d101SStefano Zampini   Input Parameter:
2231be36d101SStefano Zampini . mesh - The DMPlex
2232be36d101SStefano Zampini 
2233be36d101SStefano Zampini   Output Parameters:
2234be36d101SStefano Zampini . subsection - The subdomain section
2235be36d101SStefano Zampini 
2236be36d101SStefano Zampini   Level: developer
2237be36d101SStefano Zampini 
2238be36d101SStefano Zampini .seealso:
22397cd05799SMatthew G. Knepley @*/
2240be36d101SStefano Zampini PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection)
2241be36d101SStefano Zampini {
2242be36d101SStefano Zampini   DM_Plex       *mesh = (DM_Plex*) dm->data;
2243be36d101SStefano Zampini   PetscErrorCode ierr;
2244be36d101SStefano Zampini 
2245be36d101SStefano Zampini   PetscFunctionBegin;
2246be36d101SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2247be36d101SStefano Zampini   if (!mesh->subdomainSection) {
2248be36d101SStefano Zampini     PetscSection section;
2249be36d101SStefano Zampini     PetscSF      sf;
2250be36d101SStefano Zampini 
2251be36d101SStefano Zampini     ierr = PetscSFCreate(PETSC_COMM_SELF,&sf);CHKERRQ(ierr);
225292fd8e1eSJed Brown     ierr = DMGetLocalSection(dm,&section);CHKERRQ(ierr);
2253be36d101SStefano Zampini     ierr = PetscSectionCreateGlobalSection(section,sf,PETSC_FALSE,PETSC_TRUE,&mesh->subdomainSection);CHKERRQ(ierr);
2254be36d101SStefano Zampini     ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
2255be36d101SStefano Zampini   }
2256be36d101SStefano Zampini   *subsection = mesh->subdomainSection;
2257be36d101SStefano Zampini   PetscFunctionReturn(0);
2258be36d101SStefano Zampini }
2259be36d101SStefano Zampini 
2260552f7358SJed Brown /*@
2261552f7358SJed Brown   DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd)
2262552f7358SJed Brown 
2263552f7358SJed Brown   Not collective
2264552f7358SJed Brown 
2265552f7358SJed Brown   Input Parameter:
2266552f7358SJed Brown . mesh - The DMPlex
2267552f7358SJed Brown 
2268552f7358SJed Brown   Output Parameters:
2269552f7358SJed Brown + pStart - The first mesh point
2270552f7358SJed Brown - pEnd   - The upper bound for mesh points
2271552f7358SJed Brown 
2272552f7358SJed Brown   Level: beginner
2273552f7358SJed Brown 
2274552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetChart()
2275552f7358SJed Brown @*/
2276552f7358SJed Brown PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd)
2277552f7358SJed Brown {
2278552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2279552f7358SJed Brown   PetscErrorCode ierr;
2280552f7358SJed Brown 
2281552f7358SJed Brown   PetscFunctionBegin;
2282552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2283552f7358SJed Brown   ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr);
2284552f7358SJed Brown   PetscFunctionReturn(0);
2285552f7358SJed Brown }
2286552f7358SJed Brown 
2287552f7358SJed Brown /*@
2288552f7358SJed Brown   DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd)
2289552f7358SJed Brown 
2290552f7358SJed Brown   Not collective
2291552f7358SJed Brown 
2292552f7358SJed Brown   Input Parameters:
2293552f7358SJed Brown + mesh - The DMPlex
2294552f7358SJed Brown . pStart - The first mesh point
2295552f7358SJed Brown - pEnd   - The upper bound for mesh points
2296552f7358SJed Brown 
2297552f7358SJed Brown   Output Parameters:
2298552f7358SJed Brown 
2299552f7358SJed Brown   Level: beginner
2300552f7358SJed Brown 
2301552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetChart()
2302552f7358SJed Brown @*/
2303552f7358SJed Brown PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd)
2304552f7358SJed Brown {
2305552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2306552f7358SJed Brown   PetscErrorCode ierr;
2307552f7358SJed Brown 
2308552f7358SJed Brown   PetscFunctionBegin;
2309552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2310552f7358SJed Brown   ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr);
2311552f7358SJed Brown   ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr);
2312552f7358SJed Brown   PetscFunctionReturn(0);
2313552f7358SJed Brown }
2314552f7358SJed Brown 
2315552f7358SJed Brown /*@
2316eaf898f9SPatrick Sanan   DMPlexGetConeSize - Return the number of in-edges for this point in the DAG
2317552f7358SJed Brown 
2318552f7358SJed Brown   Not collective
2319552f7358SJed Brown 
2320552f7358SJed Brown   Input Parameters:
2321552f7358SJed Brown + mesh - The DMPlex
2322eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
2323552f7358SJed Brown 
2324552f7358SJed Brown   Output Parameter:
2325552f7358SJed Brown . size - The cone size for point p
2326552f7358SJed Brown 
2327552f7358SJed Brown   Level: beginner
2328552f7358SJed Brown 
2329552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart()
2330552f7358SJed Brown @*/
2331552f7358SJed Brown PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size)
2332552f7358SJed Brown {
2333552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2334552f7358SJed Brown   PetscErrorCode ierr;
2335552f7358SJed Brown 
2336552f7358SJed Brown   PetscFunctionBegin;
2337552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2338552f7358SJed Brown   PetscValidPointer(size, 3);
2339552f7358SJed Brown   ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr);
2340552f7358SJed Brown   PetscFunctionReturn(0);
2341552f7358SJed Brown }
2342552f7358SJed Brown 
2343552f7358SJed Brown /*@
2344eaf898f9SPatrick Sanan   DMPlexSetConeSize - Set the number of in-edges for this point in the DAG
2345552f7358SJed Brown 
2346552f7358SJed Brown   Not collective
2347552f7358SJed Brown 
2348552f7358SJed Brown   Input Parameters:
2349552f7358SJed Brown + mesh - The DMPlex
2350eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
2351552f7358SJed Brown - size - The cone size for point p
2352552f7358SJed Brown 
2353552f7358SJed Brown   Output Parameter:
2354552f7358SJed Brown 
2355552f7358SJed Brown   Note:
2356552f7358SJed Brown   This should be called after DMPlexSetChart().
2357552f7358SJed Brown 
2358552f7358SJed Brown   Level: beginner
2359552f7358SJed Brown 
2360552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart()
2361552f7358SJed Brown @*/
2362552f7358SJed Brown PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size)
2363552f7358SJed Brown {
2364552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2365552f7358SJed Brown   PetscErrorCode ierr;
2366552f7358SJed Brown 
2367552f7358SJed Brown   PetscFunctionBegin;
2368552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2369552f7358SJed Brown   ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr);
23700d644c17SKarl Rupp 
2371552f7358SJed Brown   mesh->maxConeSize = PetscMax(mesh->maxConeSize, size);
2372552f7358SJed Brown   PetscFunctionReturn(0);
2373552f7358SJed Brown }
2374552f7358SJed Brown 
2375f5a469b9SMatthew G. Knepley /*@
2376eaf898f9SPatrick Sanan   DMPlexAddConeSize - Add the given number of in-edges to this point in the DAG
2377f5a469b9SMatthew G. Knepley 
2378f5a469b9SMatthew G. Knepley   Not collective
2379f5a469b9SMatthew G. Knepley 
2380f5a469b9SMatthew G. Knepley   Input Parameters:
2381f5a469b9SMatthew G. Knepley + mesh - The DMPlex
2382eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
2383f5a469b9SMatthew G. Knepley - size - The additional cone size for point p
2384f5a469b9SMatthew G. Knepley 
2385f5a469b9SMatthew G. Knepley   Output Parameter:
2386f5a469b9SMatthew G. Knepley 
2387f5a469b9SMatthew G. Knepley   Note:
2388f5a469b9SMatthew G. Knepley   This should be called after DMPlexSetChart().
2389f5a469b9SMatthew G. Knepley 
2390f5a469b9SMatthew G. Knepley   Level: beginner
2391f5a469b9SMatthew G. Knepley 
2392f5a469b9SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexGetConeSize(), DMPlexSetChart()
2393f5a469b9SMatthew G. Knepley @*/
2394f5a469b9SMatthew G. Knepley PetscErrorCode DMPlexAddConeSize(DM dm, PetscInt p, PetscInt size)
2395f5a469b9SMatthew G. Knepley {
2396f5a469b9SMatthew G. Knepley   DM_Plex       *mesh = (DM_Plex*) dm->data;
2397f5a469b9SMatthew G. Knepley   PetscInt       csize;
2398f5a469b9SMatthew G. Knepley   PetscErrorCode ierr;
2399f5a469b9SMatthew G. Knepley 
2400f5a469b9SMatthew G. Knepley   PetscFunctionBegin;
2401f5a469b9SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2402f5a469b9SMatthew G. Knepley   ierr = PetscSectionAddDof(mesh->coneSection, p, size);CHKERRQ(ierr);
2403f5a469b9SMatthew G. Knepley   ierr = PetscSectionGetDof(mesh->coneSection, p, &csize);CHKERRQ(ierr);
2404f5a469b9SMatthew G. Knepley 
2405f5a469b9SMatthew G. Knepley   mesh->maxConeSize = PetscMax(mesh->maxConeSize, csize);
2406f5a469b9SMatthew G. Knepley   PetscFunctionReturn(0);
2407f5a469b9SMatthew G. Knepley }
2408f5a469b9SMatthew G. Knepley 
2409552f7358SJed Brown /*@C
2410eaf898f9SPatrick Sanan   DMPlexGetCone - Return the points on the in-edges for this point in the DAG
2411552f7358SJed Brown 
2412552f7358SJed Brown   Not collective
2413552f7358SJed Brown 
2414552f7358SJed Brown   Input Parameters:
2415833c876bSVaclav Hapla + dm - The DMPlex
2416eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
2417552f7358SJed Brown 
2418552f7358SJed Brown   Output Parameter:
2419552f7358SJed Brown . cone - An array of points which are on the in-edges for point p
2420552f7358SJed Brown 
2421552f7358SJed Brown   Level: beginner
2422552f7358SJed Brown 
24233813dfbdSMatthew G Knepley   Fortran Notes:
24243813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
24253813dfbdSMatthew G Knepley   include petsc.h90 in your code.
2426922102d1SVaclav Hapla   You must also call DMPlexRestoreCone() after you finish using the returned array.
2427922102d1SVaclav Hapla   DMPlexRestoreCone() is not needed/available in C.
24283813dfbdSMatthew G Knepley 
2429e45f02b0SMatthew G. Knepley .seealso: DMPlexGetConeSize(), DMPlexSetCone(), DMPlexGetConeTuple(), DMPlexSetChart()
2430552f7358SJed Brown @*/
2431552f7358SJed Brown PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[])
2432552f7358SJed Brown {
2433552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2434552f7358SJed Brown   PetscInt       off;
2435552f7358SJed Brown   PetscErrorCode ierr;
2436552f7358SJed Brown 
2437552f7358SJed Brown   PetscFunctionBegin;
2438552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2439552f7358SJed Brown   PetscValidPointer(cone, 3);
2440552f7358SJed Brown   ierr  = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr);
2441552f7358SJed Brown   *cone = &mesh->cones[off];
2442552f7358SJed Brown   PetscFunctionReturn(0);
2443552f7358SJed Brown }
2444552f7358SJed Brown 
24450ce7577fSVaclav Hapla /*@C
24460ce7577fSVaclav Hapla   DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG
24470ce7577fSVaclav Hapla 
24480ce7577fSVaclav Hapla   Not collective
24490ce7577fSVaclav Hapla 
24500ce7577fSVaclav Hapla   Input Parameters:
24510ce7577fSVaclav Hapla + dm - The DMPlex
24520ce7577fSVaclav Hapla - p - The IS of points, which must lie in the chart set with DMPlexSetChart()
24530ce7577fSVaclav Hapla 
24540ce7577fSVaclav Hapla   Output Parameter:
24550ce7577fSVaclav Hapla + pConesSection - PetscSection describing the layout of pCones
24560ce7577fSVaclav Hapla - pCones - An array of points which are on the in-edges for the point set p
24570ce7577fSVaclav Hapla 
24580ce7577fSVaclav Hapla   Level: intermediate
24590ce7577fSVaclav Hapla 
2460d4636a37SVaclav Hapla .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeRecursive(), DMPlexSetChart()
24610ce7577fSVaclav Hapla @*/
24620ce7577fSVaclav Hapla PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones)
24630ce7577fSVaclav Hapla {
24640ce7577fSVaclav Hapla   PetscSection        cs, newcs;
24650ce7577fSVaclav Hapla   PetscInt            *cones;
24660ce7577fSVaclav Hapla   PetscInt            *newarr=NULL;
24670ce7577fSVaclav Hapla   PetscInt            n;
24680ce7577fSVaclav Hapla   PetscErrorCode      ierr;
24690ce7577fSVaclav Hapla 
24700ce7577fSVaclav Hapla   PetscFunctionBegin;
24710ce7577fSVaclav Hapla   ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr);
24720ce7577fSVaclav Hapla   ierr = DMPlexGetConeSection(dm, &cs);CHKERRQ(ierr);
24730ce7577fSVaclav Hapla   ierr = PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void**)&newarr) : NULL);CHKERRQ(ierr);
24740ce7577fSVaclav Hapla   if (pConesSection) *pConesSection = newcs;
24750ce7577fSVaclav Hapla   if (pCones) {
24760ce7577fSVaclav Hapla     ierr = PetscSectionGetStorageSize(newcs, &n);CHKERRQ(ierr);
24770ce7577fSVaclav Hapla     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones);CHKERRQ(ierr);
24780ce7577fSVaclav Hapla   }
24790ce7577fSVaclav Hapla   PetscFunctionReturn(0);
24800ce7577fSVaclav Hapla }
24810ce7577fSVaclav Hapla 
2482af9eab45SVaclav Hapla /*@
2483af9eab45SVaclav Hapla   DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices.
2484d4636a37SVaclav Hapla 
2485d4636a37SVaclav Hapla   Not collective
2486d4636a37SVaclav Hapla 
2487d4636a37SVaclav Hapla   Input Parameters:
2488d4636a37SVaclav Hapla + dm - The DMPlex
2489af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart()
2490d4636a37SVaclav Hapla 
2491d4636a37SVaclav Hapla   Output Parameter:
2492af9eab45SVaclav Hapla . expandedPoints - An array of vertices recursively expanded from input points
2493d4636a37SVaclav Hapla 
2494d4636a37SVaclav Hapla   Level: advanced
2495d4636a37SVaclav Hapla 
2496af9eab45SVaclav Hapla   Notes:
2497af9eab45SVaclav Hapla   Like DMPlexGetConeRecursive but returns only the 0-depth IS (i.e. vertices only) and no sections.
2498af9eab45SVaclav Hapla   There is no corresponding Restore function, just call ISDestroy() on the returned IS to deallocate.
2499af9eab45SVaclav Hapla 
2500af9eab45SVaclav Hapla .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexGetConeRecursive(), DMPlexRestoreConeRecursive(), DMPlexGetDepth()
2501d4636a37SVaclav Hapla @*/
2502af9eab45SVaclav Hapla PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints)
2503d4636a37SVaclav Hapla {
2504af9eab45SVaclav Hapla   IS                  *expandedPointsAll;
2505af9eab45SVaclav Hapla   PetscInt            depth;
2506d4636a37SVaclav Hapla   PetscErrorCode      ierr;
2507d4636a37SVaclav Hapla 
2508d4636a37SVaclav Hapla   PetscFunctionBegin;
2509af9eab45SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2510af9eab45SVaclav Hapla   PetscValidHeaderSpecific(points, IS_CLASSID, 2);
2511af9eab45SVaclav Hapla   PetscValidPointer(expandedPoints, 3);
2512af9eab45SVaclav Hapla   ierr = DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL);CHKERRQ(ierr);
2513af9eab45SVaclav Hapla   *expandedPoints = expandedPointsAll[0];
25141e1ea65dSPierre Jolivet   ierr = PetscObjectReference((PetscObject)expandedPointsAll[0]);CHKERRQ(ierr);
2515af9eab45SVaclav Hapla   ierr = DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL);CHKERRQ(ierr);
2516af9eab45SVaclav Hapla   PetscFunctionReturn(0);
2517af9eab45SVaclav Hapla }
2518af9eab45SVaclav Hapla 
2519af9eab45SVaclav Hapla /*@
2520af9eab45SVaclav 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).
2521af9eab45SVaclav Hapla 
2522af9eab45SVaclav Hapla   Not collective
2523af9eab45SVaclav Hapla 
2524af9eab45SVaclav Hapla   Input Parameters:
2525af9eab45SVaclav Hapla + dm - The DMPlex
2526af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart()
2527af9eab45SVaclav Hapla 
2528af9eab45SVaclav Hapla   Output Parameter:
2529af9eab45SVaclav Hapla + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth()
2530af9eab45SVaclav Hapla . expandedPoints - (optional) An array of index sets with recursively expanded cones
2531af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points
2532af9eab45SVaclav Hapla 
2533af9eab45SVaclav Hapla   Level: advanced
2534af9eab45SVaclav Hapla 
2535af9eab45SVaclav Hapla   Notes:
2536af9eab45SVaclav Hapla   Like DMPlexGetConeTuple() but recursive.
2537af9eab45SVaclav Hapla 
2538af9eab45SVaclav 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.
2539af9eab45SVaclav Hapla   For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc.
2540af9eab45SVaclav Hapla 
2541af9eab45SVaclav 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:
2542af9eab45SVaclav Hapla   (1) DAG points in expandedPoints[d+1] with depth d+1 to their cone points in expandedPoints[d];
2543af9eab45SVaclav Hapla   (2) DAG points in expandedPoints[d+1] with depth in [0,d] to the same points in expandedPoints[d].
2544af9eab45SVaclav Hapla 
2545af9eab45SVaclav Hapla .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexRestoreConeRecursive(), DMPlexGetConeRecursiveVertices(), DMPlexGetDepth()
2546af9eab45SVaclav Hapla @*/
2547af9eab45SVaclav Hapla PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[])
2548af9eab45SVaclav Hapla {
2549af9eab45SVaclav Hapla   const PetscInt      *arr0=NULL, *cone=NULL;
2550af9eab45SVaclav Hapla   PetscInt            *arr=NULL, *newarr=NULL;
2551af9eab45SVaclav Hapla   PetscInt            d, depth_, i, n, newn, cn, co, start, end;
2552af9eab45SVaclav Hapla   IS                  *expandedPoints_;
2553af9eab45SVaclav Hapla   PetscSection        *sections_;
2554af9eab45SVaclav Hapla   PetscErrorCode      ierr;
2555af9eab45SVaclav Hapla 
2556af9eab45SVaclav Hapla   PetscFunctionBegin;
2557af9eab45SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2558af9eab45SVaclav Hapla   PetscValidHeaderSpecific(points, IS_CLASSID, 2);
2559af9eab45SVaclav Hapla   if (depth) PetscValidIntPointer(depth, 3);
2560af9eab45SVaclav Hapla   if (expandedPoints) PetscValidPointer(expandedPoints, 4);
2561af9eab45SVaclav Hapla   if (sections) PetscValidPointer(sections, 5);
2562af9eab45SVaclav Hapla   ierr = ISGetLocalSize(points, &n);CHKERRQ(ierr);
2563af9eab45SVaclav Hapla   ierr = ISGetIndices(points, &arr0);CHKERRQ(ierr);
2564af9eab45SVaclav Hapla   ierr = DMPlexGetDepth(dm, &depth_);CHKERRQ(ierr);
2565af9eab45SVaclav Hapla   ierr = PetscCalloc1(depth_, &expandedPoints_);CHKERRQ(ierr);
2566af9eab45SVaclav Hapla   ierr = PetscCalloc1(depth_, &sections_);CHKERRQ(ierr);
2567af9eab45SVaclav Hapla   arr = (PetscInt*) arr0; /* this is ok because first generation of arr is not modified */
2568af9eab45SVaclav Hapla   for (d=depth_-1; d>=0; d--) {
2569af9eab45SVaclav Hapla     ierr = PetscSectionCreate(PETSC_COMM_SELF, &sections_[d]);CHKERRQ(ierr);
2570af9eab45SVaclav Hapla     ierr = PetscSectionSetChart(sections_[d], 0, n);CHKERRQ(ierr);
2571af9eab45SVaclav Hapla     for (i=0; i<n; i++) {
2572af9eab45SVaclav Hapla       ierr = DMPlexGetDepthStratum(dm, d+1, &start, &end);CHKERRQ(ierr);
2573af9eab45SVaclav Hapla       if (arr[i] >= start && arr[i] < end) {
2574af9eab45SVaclav Hapla         ierr = DMPlexGetConeSize(dm, arr[i], &cn);CHKERRQ(ierr);
2575af9eab45SVaclav Hapla         ierr = PetscSectionSetDof(sections_[d], i, cn);CHKERRQ(ierr);
2576af9eab45SVaclav Hapla       } else {
2577af9eab45SVaclav Hapla         ierr = PetscSectionSetDof(sections_[d], i, 1);CHKERRQ(ierr);
2578af9eab45SVaclav Hapla       }
2579af9eab45SVaclav Hapla     }
2580af9eab45SVaclav Hapla     ierr = PetscSectionSetUp(sections_[d]);CHKERRQ(ierr);
2581af9eab45SVaclav Hapla     ierr = PetscSectionGetStorageSize(sections_[d], &newn);CHKERRQ(ierr);
2582af9eab45SVaclav Hapla     ierr = PetscMalloc1(newn, &newarr);CHKERRQ(ierr);
2583af9eab45SVaclav Hapla     for (i=0; i<n; i++) {
2584af9eab45SVaclav Hapla       ierr = PetscSectionGetDof(sections_[d], i, &cn);CHKERRQ(ierr);
2585af9eab45SVaclav Hapla       ierr = PetscSectionGetOffset(sections_[d], i, &co);CHKERRQ(ierr);
2586af9eab45SVaclav Hapla       if (cn > 1) {
2587af9eab45SVaclav Hapla         ierr = DMPlexGetCone(dm, arr[i], &cone);CHKERRQ(ierr);
2588af9eab45SVaclav Hapla         ierr = PetscMemcpy(&newarr[co], cone, cn*sizeof(PetscInt));CHKERRQ(ierr);
2589af9eab45SVaclav Hapla       } else {
2590af9eab45SVaclav Hapla         newarr[co] = arr[i];
2591af9eab45SVaclav Hapla       }
2592af9eab45SVaclav Hapla     }
2593af9eab45SVaclav Hapla     ierr = ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d]);CHKERRQ(ierr);
2594af9eab45SVaclav Hapla     arr = newarr;
2595af9eab45SVaclav Hapla     n = newn;
2596af9eab45SVaclav Hapla   }
2597ba2698f1SMatthew G. Knepley   ierr = ISRestoreIndices(points, &arr0);CHKERRQ(ierr);
2598af9eab45SVaclav Hapla   *depth = depth_;
2599af9eab45SVaclav Hapla   if (expandedPoints) *expandedPoints = expandedPoints_;
2600af9eab45SVaclav Hapla   else {
2601af9eab45SVaclav Hapla     for (d=0; d<depth_; d++) {ierr = ISDestroy(&expandedPoints_[d]);CHKERRQ(ierr);}
2602af9eab45SVaclav Hapla     ierr = PetscFree(expandedPoints_);CHKERRQ(ierr);
2603af9eab45SVaclav Hapla   }
2604af9eab45SVaclav Hapla   if (sections) *sections = sections_;
2605af9eab45SVaclav Hapla   else {
2606af9eab45SVaclav Hapla     for (d=0; d<depth_; d++) {ierr = PetscSectionDestroy(&sections_[d]);CHKERRQ(ierr);}
2607af9eab45SVaclav Hapla     ierr = PetscFree(sections_);CHKERRQ(ierr);
2608af9eab45SVaclav Hapla   }
2609af9eab45SVaclav Hapla   PetscFunctionReturn(0);
2610af9eab45SVaclav Hapla }
2611af9eab45SVaclav Hapla 
2612af9eab45SVaclav Hapla /*@
2613af9eab45SVaclav Hapla   DMPlexRestoreConeRecursive - Deallocates arrays created by DMPlexGetConeRecursive
2614af9eab45SVaclav Hapla 
2615af9eab45SVaclav Hapla   Not collective
2616af9eab45SVaclav Hapla 
2617af9eab45SVaclav Hapla   Input Parameters:
2618af9eab45SVaclav Hapla + dm - The DMPlex
2619af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart()
2620af9eab45SVaclav Hapla 
2621af9eab45SVaclav Hapla   Output Parameter:
2622af9eab45SVaclav Hapla + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth()
2623af9eab45SVaclav Hapla . expandedPoints - (optional) An array of recursively expanded cones
2624af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points
2625af9eab45SVaclav Hapla 
2626af9eab45SVaclav Hapla   Level: advanced
2627af9eab45SVaclav Hapla 
2628af9eab45SVaclav Hapla   Notes:
2629af9eab45SVaclav Hapla   See DMPlexGetConeRecursive() for details.
2630af9eab45SVaclav Hapla 
2631af9eab45SVaclav Hapla .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexGetConeTuple(), DMPlexGetConeRecursive(), DMPlexGetConeRecursiveVertices(), DMPlexGetDepth()
2632af9eab45SVaclav Hapla @*/
2633af9eab45SVaclav Hapla PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[])
2634af9eab45SVaclav Hapla {
2635af9eab45SVaclav Hapla   PetscInt            d, depth_;
2636af9eab45SVaclav Hapla   PetscErrorCode      ierr;
2637af9eab45SVaclav Hapla 
2638af9eab45SVaclav Hapla   PetscFunctionBegin;
2639af9eab45SVaclav Hapla   ierr = DMPlexGetDepth(dm, &depth_);CHKERRQ(ierr);
2640af9eab45SVaclav Hapla   if (depth && *depth != depth_) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive");
2641af9eab45SVaclav Hapla   if (depth) *depth = 0;
2642af9eab45SVaclav Hapla   if (expandedPoints) {
2643af9eab45SVaclav Hapla     for (d=0; d<depth_; d++) {ierr = ISDestroy(&((*expandedPoints)[d]));CHKERRQ(ierr);}
2644af9eab45SVaclav Hapla     ierr = PetscFree(*expandedPoints);CHKERRQ(ierr);
2645af9eab45SVaclav Hapla   }
2646af9eab45SVaclav Hapla   if (sections)  {
2647af9eab45SVaclav Hapla     for (d=0; d<depth_; d++) {ierr = PetscSectionDestroy(&((*sections)[d]));CHKERRQ(ierr);}
2648af9eab45SVaclav Hapla     ierr = PetscFree(*sections);CHKERRQ(ierr);
2649af9eab45SVaclav Hapla   }
2650d4636a37SVaclav Hapla   PetscFunctionReturn(0);
2651d4636a37SVaclav Hapla }
2652d4636a37SVaclav Hapla 
2653552f7358SJed Brown /*@
265492371b87SBarry 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
2655552f7358SJed Brown 
2656552f7358SJed Brown   Not collective
2657552f7358SJed Brown 
2658552f7358SJed Brown   Input Parameters:
2659552f7358SJed Brown + mesh - The DMPlex
2660eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
2661552f7358SJed Brown - cone - An array of points which are on the in-edges for point p
2662552f7358SJed Brown 
2663552f7358SJed Brown   Output Parameter:
2664552f7358SJed Brown 
2665552f7358SJed Brown   Note:
2666552f7358SJed Brown   This should be called after all calls to DMPlexSetConeSize() and DMSetUp().
2667552f7358SJed Brown 
266892371b87SBarry Smith   Developer Note: Why not call this DMPlexSetCover()
266992371b87SBarry Smith 
2670552f7358SJed Brown   Level: beginner
2671552f7358SJed Brown 
267292371b87SBarry Smith .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp(), DMPlexSetSupport(), DMPlexSetSupportSize()
2673552f7358SJed Brown @*/
2674552f7358SJed Brown PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[])
2675552f7358SJed Brown {
2676552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2677552f7358SJed Brown   PetscInt       pStart, pEnd;
2678552f7358SJed Brown   PetscInt       dof, off, c;
2679552f7358SJed Brown   PetscErrorCode ierr;
2680552f7358SJed Brown 
2681552f7358SJed Brown   PetscFunctionBegin;
2682552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2683552f7358SJed Brown   ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr);
2684552f7358SJed Brown   ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr);
2685552f7358SJed Brown   if (dof) PetscValidPointer(cone, 3);
2686552f7358SJed Brown   ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr);
268782f516ccSBarry Smith   if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd);
2688552f7358SJed Brown   for (c = 0; c < dof; ++c) {
268982f516ccSBarry Smith     if ((cone[c] < pStart) || (cone[c] >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", cone[c], pStart, pEnd);
2690552f7358SJed Brown     mesh->cones[off+c] = cone[c];
2691552f7358SJed Brown   }
2692552f7358SJed Brown   PetscFunctionReturn(0);
2693552f7358SJed Brown }
2694552f7358SJed Brown 
2695552f7358SJed Brown /*@C
2696eaf898f9SPatrick Sanan   DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG
2697552f7358SJed Brown 
2698552f7358SJed Brown   Not collective
2699552f7358SJed Brown 
2700552f7358SJed Brown   Input Parameters:
2701552f7358SJed Brown + mesh - The DMPlex
2702eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
2703552f7358SJed Brown 
2704552f7358SJed Brown   Output Parameter:
2705552f7358SJed Brown . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an
2706552f7358SJed Brown                     integer giving the prescription for cone traversal. If it is negative, the cone is
2707552f7358SJed Brown                     traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives
2708552f7358SJed Brown                     the index of the cone point on which to start.
2709552f7358SJed Brown 
2710552f7358SJed Brown   Level: beginner
2711552f7358SJed Brown 
27123813dfbdSMatthew G Knepley   Fortran Notes:
27133813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
27143813dfbdSMatthew G Knepley   include petsc.h90 in your code.
27153b12b3d8SVaclav Hapla   You must also call DMPlexRestoreConeOrientation() after you finish using the returned array.
2716922102d1SVaclav Hapla   DMPlexRestoreConeOrientation() is not needed/available in C.
27173813dfbdSMatthew G Knepley 
2718552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart()
2719552f7358SJed Brown @*/
2720552f7358SJed Brown PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[])
2721552f7358SJed Brown {
2722552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2723552f7358SJed Brown   PetscInt       off;
2724552f7358SJed Brown   PetscErrorCode ierr;
2725552f7358SJed Brown 
2726552f7358SJed Brown   PetscFunctionBegin;
2727552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
272876bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
2729552f7358SJed Brown     PetscInt dof;
2730552f7358SJed Brown     ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr);
2731552f7358SJed Brown     if (dof) PetscValidPointer(coneOrientation, 3);
2732552f7358SJed Brown   }
2733552f7358SJed Brown   ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr);
27340d644c17SKarl Rupp 
2735552f7358SJed Brown   *coneOrientation = &mesh->coneOrientations[off];
2736552f7358SJed Brown   PetscFunctionReturn(0);
2737552f7358SJed Brown }
2738552f7358SJed Brown 
2739552f7358SJed Brown /*@
2740eaf898f9SPatrick Sanan   DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG
2741552f7358SJed Brown 
2742552f7358SJed Brown   Not collective
2743552f7358SJed Brown 
2744552f7358SJed Brown   Input Parameters:
2745552f7358SJed Brown + mesh - The DMPlex
2746eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
2747552f7358SJed Brown - coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an
2748552f7358SJed Brown                     integer giving the prescription for cone traversal. If it is negative, the cone is
2749552f7358SJed Brown                     traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives
2750552f7358SJed Brown                     the index of the cone point on which to start.
2751552f7358SJed Brown 
2752552f7358SJed Brown   Output Parameter:
2753552f7358SJed Brown 
2754552f7358SJed Brown   Note:
2755552f7358SJed Brown   This should be called after all calls to DMPlexSetConeSize() and DMSetUp().
2756552f7358SJed Brown 
2757552f7358SJed Brown   Level: beginner
2758552f7358SJed Brown 
2759552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp()
2760552f7358SJed Brown @*/
2761552f7358SJed Brown PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[])
2762552f7358SJed Brown {
2763552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2764552f7358SJed Brown   PetscInt       pStart, pEnd;
2765552f7358SJed Brown   PetscInt       dof, off, c;
2766552f7358SJed Brown   PetscErrorCode ierr;
2767552f7358SJed Brown 
2768552f7358SJed Brown   PetscFunctionBegin;
2769552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2770552f7358SJed Brown   ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr);
2771552f7358SJed Brown   ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr);
2772552f7358SJed Brown   if (dof) PetscValidPointer(coneOrientation, 3);
2773552f7358SJed Brown   ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr);
277482f516ccSBarry Smith   if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd);
2775552f7358SJed Brown   for (c = 0; c < dof; ++c) {
2776552f7358SJed Brown     PetscInt cdof, o = coneOrientation[c];
2777552f7358SJed Brown 
2778552f7358SJed Brown     ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr);
277982f516ccSBarry Smith     if (o && ((o < -(cdof+1)) || (o >= cdof))) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone orientation %D is not in the valid range [%D. %D)", o, -(cdof+1), cdof);
2780552f7358SJed Brown     mesh->coneOrientations[off+c] = o;
2781552f7358SJed Brown   }
2782552f7358SJed Brown   PetscFunctionReturn(0);
2783552f7358SJed Brown }
2784552f7358SJed Brown 
27857cd05799SMatthew G. Knepley /*@
2786eaf898f9SPatrick Sanan   DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG
27877cd05799SMatthew G. Knepley 
27887cd05799SMatthew G. Knepley   Not collective
27897cd05799SMatthew G. Knepley 
27907cd05799SMatthew G. Knepley   Input Parameters:
27917cd05799SMatthew G. Knepley + mesh - The DMPlex
2792eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
27937cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put
27947cd05799SMatthew G. Knepley - conePoint - The mesh point to insert
27957cd05799SMatthew G. Knepley 
27967cd05799SMatthew G. Knepley   Level: beginner
27977cd05799SMatthew G. Knepley 
27987cd05799SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp()
27997cd05799SMatthew G. Knepley @*/
2800552f7358SJed Brown PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint)
2801552f7358SJed Brown {
2802552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2803552f7358SJed Brown   PetscInt       pStart, pEnd;
2804552f7358SJed Brown   PetscInt       dof, off;
2805552f7358SJed Brown   PetscErrorCode ierr;
2806552f7358SJed Brown 
2807552f7358SJed Brown   PetscFunctionBegin;
2808552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2809552f7358SJed Brown   ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr);
281082f516ccSBarry Smith   if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd);
281182f516ccSBarry Smith   if ((conePoint < pStart) || (conePoint >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", conePoint, pStart, pEnd);
281277c88f5bSMatthew G Knepley   ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr);
281377c88f5bSMatthew G Knepley   ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr);
281477c88f5bSMatthew G Knepley   if ((conePos < 0) || (conePos >= dof)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %D of point %D is not in the valid range [0, %D)", conePos, p, dof);
2815552f7358SJed Brown   mesh->cones[off+conePos] = conePoint;
2816552f7358SJed Brown   PetscFunctionReturn(0);
2817552f7358SJed Brown }
2818552f7358SJed Brown 
28197cd05799SMatthew G. Knepley /*@
2820eaf898f9SPatrick Sanan   DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG
28217cd05799SMatthew G. Knepley 
28227cd05799SMatthew G. Knepley   Not collective
28237cd05799SMatthew G. Knepley 
28247cd05799SMatthew G. Knepley   Input Parameters:
28257cd05799SMatthew G. Knepley + mesh - The DMPlex
2826eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
28277cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put
28287cd05799SMatthew G. Knepley - coneOrientation - The point orientation to insert
28297cd05799SMatthew G. Knepley 
28307cd05799SMatthew G. Knepley   Level: beginner
28317cd05799SMatthew G. Knepley 
28327cd05799SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp()
28337cd05799SMatthew G. Knepley @*/
283477c88f5bSMatthew G Knepley PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation)
283577c88f5bSMatthew G Knepley {
283677c88f5bSMatthew G Knepley   DM_Plex       *mesh = (DM_Plex*) dm->data;
283777c88f5bSMatthew G Knepley   PetscInt       pStart, pEnd;
283877c88f5bSMatthew G Knepley   PetscInt       dof, off;
283977c88f5bSMatthew G Knepley   PetscErrorCode ierr;
284077c88f5bSMatthew G Knepley 
284177c88f5bSMatthew G Knepley   PetscFunctionBegin;
284277c88f5bSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
284377c88f5bSMatthew G Knepley   ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr);
284477c88f5bSMatthew G Knepley   if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd);
284577c88f5bSMatthew G Knepley   ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr);
284677c88f5bSMatthew G Knepley   ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr);
284777c88f5bSMatthew G Knepley   if ((conePos < 0) || (conePos >= dof)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %D of point %D is not in the valid range [0, %D)", conePos, p, dof);
284877c88f5bSMatthew G Knepley   mesh->coneOrientations[off+conePos] = coneOrientation;
284977c88f5bSMatthew G Knepley   PetscFunctionReturn(0);
285077c88f5bSMatthew G Knepley }
285177c88f5bSMatthew G Knepley 
2852552f7358SJed Brown /*@
2853eaf898f9SPatrick Sanan   DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG
2854552f7358SJed Brown 
2855552f7358SJed Brown   Not collective
2856552f7358SJed Brown 
2857552f7358SJed Brown   Input Parameters:
2858552f7358SJed Brown + mesh - The DMPlex
2859eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
2860552f7358SJed Brown 
2861552f7358SJed Brown   Output Parameter:
2862552f7358SJed Brown . size - The support size for point p
2863552f7358SJed Brown 
2864552f7358SJed Brown   Level: beginner
2865552f7358SJed Brown 
2866552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize()
2867552f7358SJed Brown @*/
2868552f7358SJed Brown PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size)
2869552f7358SJed Brown {
2870552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2871552f7358SJed Brown   PetscErrorCode ierr;
2872552f7358SJed Brown 
2873552f7358SJed Brown   PetscFunctionBegin;
2874552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2875552f7358SJed Brown   PetscValidPointer(size, 3);
2876552f7358SJed Brown   ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr);
2877552f7358SJed Brown   PetscFunctionReturn(0);
2878552f7358SJed Brown }
2879552f7358SJed Brown 
2880552f7358SJed Brown /*@
2881eaf898f9SPatrick Sanan   DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG
2882552f7358SJed Brown 
2883552f7358SJed Brown   Not collective
2884552f7358SJed Brown 
2885552f7358SJed Brown   Input Parameters:
2886552f7358SJed Brown + mesh - The DMPlex
2887eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
2888552f7358SJed Brown - size - The support size for point p
2889552f7358SJed Brown 
2890552f7358SJed Brown   Output Parameter:
2891552f7358SJed Brown 
2892552f7358SJed Brown   Note:
2893552f7358SJed Brown   This should be called after DMPlexSetChart().
2894552f7358SJed Brown 
2895552f7358SJed Brown   Level: beginner
2896552f7358SJed Brown 
2897552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart()
2898552f7358SJed Brown @*/
2899552f7358SJed Brown PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size)
2900552f7358SJed Brown {
2901552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2902552f7358SJed Brown   PetscErrorCode ierr;
2903552f7358SJed Brown 
2904552f7358SJed Brown   PetscFunctionBegin;
2905552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2906552f7358SJed Brown   ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr);
29070d644c17SKarl Rupp 
2908552f7358SJed Brown   mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size);
2909552f7358SJed Brown   PetscFunctionReturn(0);
2910552f7358SJed Brown }
2911552f7358SJed Brown 
2912552f7358SJed Brown /*@C
2913eaf898f9SPatrick Sanan   DMPlexGetSupport - Return the points on the out-edges for this point in the DAG
2914552f7358SJed Brown 
2915552f7358SJed Brown   Not collective
2916552f7358SJed Brown 
2917552f7358SJed Brown   Input Parameters:
2918552f7358SJed Brown + mesh - The DMPlex
2919eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
2920552f7358SJed Brown 
2921552f7358SJed Brown   Output Parameter:
2922552f7358SJed Brown . support - An array of points which are on the out-edges for point p
2923552f7358SJed Brown 
2924552f7358SJed Brown   Level: beginner
2925552f7358SJed Brown 
29263813dfbdSMatthew G Knepley   Fortran Notes:
29273813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
29283813dfbdSMatthew G Knepley   include petsc.h90 in your code.
29293b12b3d8SVaclav Hapla   You must also call DMPlexRestoreSupport() after you finish using the returned array.
2930922102d1SVaclav Hapla   DMPlexRestoreSupport() is not needed/available in C.
29313813dfbdSMatthew G Knepley 
2932e45f02b0SMatthew G. Knepley .seealso: DMPlexGetSupportSize(), DMPlexSetSupport(), DMPlexGetCone(), DMPlexSetChart()
2933552f7358SJed Brown @*/
2934552f7358SJed Brown PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[])
2935552f7358SJed Brown {
2936552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2937552f7358SJed Brown   PetscInt       off;
2938552f7358SJed Brown   PetscErrorCode ierr;
2939552f7358SJed Brown 
2940552f7358SJed Brown   PetscFunctionBegin;
2941552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2942552f7358SJed Brown   PetscValidPointer(support, 3);
2943552f7358SJed Brown   ierr     = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr);
2944552f7358SJed Brown   *support = &mesh->supports[off];
2945552f7358SJed Brown   PetscFunctionReturn(0);
2946552f7358SJed Brown }
2947552f7358SJed Brown 
2948552f7358SJed Brown /*@
294992371b87SBarry 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
2950552f7358SJed Brown 
2951552f7358SJed Brown   Not collective
2952552f7358SJed Brown 
2953552f7358SJed Brown   Input Parameters:
2954552f7358SJed Brown + mesh - The DMPlex
2955eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
295692371b87SBarry Smith - support - An array of points which are on the out-edges for point p
2957552f7358SJed Brown 
2958552f7358SJed Brown   Output Parameter:
2959552f7358SJed Brown 
2960552f7358SJed Brown   Note:
2961552f7358SJed Brown   This should be called after all calls to DMPlexSetSupportSize() and DMSetUp().
2962552f7358SJed Brown 
2963552f7358SJed Brown   Level: beginner
2964552f7358SJed Brown 
296592371b87SBarry Smith .seealso: DMPlexSetCone(), DMPlexSetConeSize(), DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp()
2966552f7358SJed Brown @*/
2967552f7358SJed Brown PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[])
2968552f7358SJed Brown {
2969552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2970552f7358SJed Brown   PetscInt       pStart, pEnd;
2971552f7358SJed Brown   PetscInt       dof, off, c;
2972552f7358SJed Brown   PetscErrorCode ierr;
2973552f7358SJed Brown 
2974552f7358SJed Brown   PetscFunctionBegin;
2975552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2976552f7358SJed Brown   ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr);
2977552f7358SJed Brown   ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr);
2978552f7358SJed Brown   if (dof) PetscValidPointer(support, 3);
2979552f7358SJed Brown   ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr);
298082f516ccSBarry Smith   if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd);
2981552f7358SJed Brown   for (c = 0; c < dof; ++c) {
298282f516ccSBarry Smith     if ((support[c] < pStart) || (support[c] >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", support[c], pStart, pEnd);
2983552f7358SJed Brown     mesh->supports[off+c] = support[c];
2984552f7358SJed Brown   }
2985552f7358SJed Brown   PetscFunctionReturn(0);
2986552f7358SJed Brown }
2987552f7358SJed Brown 
29887cd05799SMatthew G. Knepley /*@
2989eaf898f9SPatrick Sanan   DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG
29907cd05799SMatthew G. Knepley 
29917cd05799SMatthew G. Knepley   Not collective
29927cd05799SMatthew G. Knepley 
29937cd05799SMatthew G. Knepley   Input Parameters:
29947cd05799SMatthew G. Knepley + mesh - The DMPlex
2995eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
29967cd05799SMatthew G. Knepley . supportPos - The local index in the cone where the point should be put
29977cd05799SMatthew G. Knepley - supportPoint - The mesh point to insert
29987cd05799SMatthew G. Knepley 
29997cd05799SMatthew G. Knepley   Level: beginner
30007cd05799SMatthew G. Knepley 
30017cd05799SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp()
30027cd05799SMatthew G. Knepley @*/
3003552f7358SJed Brown PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint)
3004552f7358SJed Brown {
3005552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3006552f7358SJed Brown   PetscInt       pStart, pEnd;
3007552f7358SJed Brown   PetscInt       dof, off;
3008552f7358SJed Brown   PetscErrorCode ierr;
3009552f7358SJed Brown 
3010552f7358SJed Brown   PetscFunctionBegin;
3011552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3012552f7358SJed Brown   ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr);
3013552f7358SJed Brown   ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr);
3014552f7358SJed Brown   ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr);
301582f516ccSBarry Smith   if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd);
301682f516ccSBarry Smith   if ((supportPoint < pStart) || (supportPoint >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", supportPoint, pStart, pEnd);
301782f516ccSBarry Smith   if (supportPos >= dof) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support position %D of point %D is not in the valid range [0, %D)", supportPos, p, dof);
3018552f7358SJed Brown   mesh->supports[off+supportPos] = supportPoint;
3019552f7358SJed Brown   PetscFunctionReturn(0);
3020552f7358SJed Brown }
3021552f7358SJed Brown 
3022552f7358SJed Brown /*@C
3023eaf898f9SPatrick Sanan   DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG
3024552f7358SJed Brown 
3025552f7358SJed Brown   Not collective
3026552f7358SJed Brown 
3027552f7358SJed Brown   Input Parameters:
3028552f7358SJed Brown + mesh - The DMPlex
3029eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
3030552f7358SJed Brown . useCone - PETSC_TRUE for in-edges,  otherwise use out-edges
30310298fd71SBarry Smith - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used
3032552f7358SJed Brown 
3033552f7358SJed Brown   Output Parameters:
3034552f7358SJed Brown + numPoints - The number of points in the closure, so points[] is of size 2*numPoints
3035552f7358SJed Brown - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]
3036552f7358SJed Brown 
3037552f7358SJed Brown   Note:
30380298fd71SBarry Smith   If using internal storage (points is NULL on input), each call overwrites the last output.
3039552f7358SJed Brown 
30403813dfbdSMatthew G Knepley   Fortran Notes:
30413813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
30423813dfbdSMatthew G Knepley   include petsc.h90 in your code.
30433813dfbdSMatthew G Knepley 
30443813dfbdSMatthew G Knepley   The numPoints argument is not present in the Fortran 90 binding since it is internal to the array.
30453813dfbdSMatthew G Knepley 
3046552f7358SJed Brown   Level: beginner
3047552f7358SJed Brown 
3048552f7358SJed Brown .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone()
3049552f7358SJed Brown @*/
3050552f7358SJed Brown PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3051552f7358SJed Brown {
3052552f7358SJed Brown   DM_Plex        *mesh = (DM_Plex*) dm->data;
3053552f7358SJed Brown   PetscInt       *closure, *fifo;
30540298fd71SBarry Smith   const PetscInt *tmp = NULL, *tmpO = NULL;
3055552f7358SJed Brown   PetscInt        tmpSize, t;
3056552f7358SJed Brown   PetscInt        depth       = 0, maxSize;
3057552f7358SJed Brown   PetscInt        closureSize = 2, fifoSize = 0, fifoStart = 0;
3058552f7358SJed Brown   PetscErrorCode  ierr;
3059552f7358SJed Brown 
3060552f7358SJed Brown   PetscFunctionBegin;
3061552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3062552f7358SJed Brown   ierr    = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
3063552f7358SJed Brown   /* This is only 1-level */
3064552f7358SJed Brown   if (useCone) {
3065552f7358SJed Brown     ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr);
3066552f7358SJed Brown     ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr);
3067552f7358SJed Brown     ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr);
3068552f7358SJed Brown   } else {
3069552f7358SJed Brown     ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr);
3070552f7358SJed Brown     ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr);
3071552f7358SJed Brown   }
3072bfbcdd7aSMatthew G. Knepley   if (depth == 1) {
3073bfbcdd7aSMatthew G. Knepley     if (*points) {
3074bfbcdd7aSMatthew G. Knepley       closure = *points;
3075bfbcdd7aSMatthew G. Knepley     } else {
3076bfbcdd7aSMatthew G. Knepley       maxSize = 2*(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)+1);
307769291d52SBarry Smith       ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &closure);CHKERRQ(ierr);
3078bfbcdd7aSMatthew G. Knepley     }
3079bfbcdd7aSMatthew G. Knepley     closure[0] = p; closure[1] = 0;
3080bfbcdd7aSMatthew G. Knepley     for (t = 0; t < tmpSize; ++t, closureSize += 2) {
3081bfbcdd7aSMatthew G. Knepley       closure[closureSize]   = tmp[t];
3082bfbcdd7aSMatthew G. Knepley       closure[closureSize+1] = tmpO ? tmpO[t] : 0;
3083bfbcdd7aSMatthew G. Knepley     }
3084bfbcdd7aSMatthew G. Knepley     if (numPoints) *numPoints = closureSize/2;
3085bfbcdd7aSMatthew G. Knepley     if (points)    *points    = closure;
3086bfbcdd7aSMatthew G. Knepley     PetscFunctionReturn(0);
3087bfbcdd7aSMatthew G. Knepley   }
308824c766afSToby Isaac   {
308924c766afSToby Isaac     PetscInt c, coneSeries, s,supportSeries;
309024c766afSToby Isaac 
309124c766afSToby Isaac     c = mesh->maxConeSize;
309224c766afSToby Isaac     coneSeries = (c > 1) ? ((PetscPowInt(c,depth+1)-1)/(c-1)) : depth+1;
309324c766afSToby Isaac     s = mesh->maxSupportSize;
309424c766afSToby Isaac     supportSeries = (s > 1) ? ((PetscPowInt(s,depth+1)-1)/(s-1)) : depth+1;
309524c766afSToby Isaac     maxSize = 2*PetscMax(coneSeries,supportSeries);
309624c766afSToby Isaac   }
309769291d52SBarry Smith   ierr    = DMGetWorkArray(dm, maxSize, MPIU_INT, &fifo);CHKERRQ(ierr);
3098bfbcdd7aSMatthew G. Knepley   if (*points) {
3099bfbcdd7aSMatthew G. Knepley     closure = *points;
3100bfbcdd7aSMatthew G. Knepley   } else {
310169291d52SBarry Smith     ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &closure);CHKERRQ(ierr);
3102bfbcdd7aSMatthew G. Knepley   }
3103bfbcdd7aSMatthew G. Knepley   closure[0] = p; closure[1] = 0;
3104552f7358SJed Brown   for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) {
3105552f7358SJed Brown     const PetscInt cp = tmp[t];
3106552f7358SJed Brown     const PetscInt co = tmpO ? tmpO[t] : 0;
3107552f7358SJed Brown 
3108552f7358SJed Brown     closure[closureSize]   = cp;
3109552f7358SJed Brown     closure[closureSize+1] = co;
3110552f7358SJed Brown     fifo[fifoSize]         = cp;
3111552f7358SJed Brown     fifo[fifoSize+1]       = co;
3112552f7358SJed Brown   }
3113bfbcdd7aSMatthew G. Knepley   /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */
3114552f7358SJed Brown   while (fifoSize - fifoStart) {
3115552f7358SJed Brown     const PetscInt q   = fifo[fifoStart];
3116552f7358SJed Brown     const PetscInt o   = fifo[fifoStart+1];
3117552f7358SJed Brown     const PetscInt rev = o >= 0 ? 0 : 1;
3118552f7358SJed Brown     const PetscInt off = rev ? -(o+1) : o;
3119552f7358SJed Brown 
3120552f7358SJed Brown     if (useCone) {
3121552f7358SJed Brown       ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr);
3122552f7358SJed Brown       ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr);
3123552f7358SJed Brown       ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr);
3124552f7358SJed Brown     } else {
3125552f7358SJed Brown       ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr);
3126552f7358SJed Brown       ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr);
31270298fd71SBarry Smith       tmpO = NULL;
3128552f7358SJed Brown     }
3129552f7358SJed Brown     for (t = 0; t < tmpSize; ++t) {
3130552f7358SJed Brown       const PetscInt i  = ((rev ? tmpSize-t : t) + off)%tmpSize;
3131552f7358SJed Brown       const PetscInt cp = tmp[i];
31322e1b13c2SMatthew G. Knepley       /* Must propogate orientation: When we reverse orientation, we both reverse the direction of iteration and start at the other end of the chain. */
31332e1b13c2SMatthew G. Knepley       /* HACK: It is worse to get the size here, than to change the interpretation of -(*+1)
31342e1b13c2SMatthew G. Knepley        const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; */
31352e1b13c2SMatthew G. Knepley       PetscInt       co = tmpO ? tmpO[i] : 0;
3136552f7358SJed Brown       PetscInt       c;
3137552f7358SJed Brown 
31382e1b13c2SMatthew G. Knepley       if (rev) {
31392e1b13c2SMatthew G. Knepley         PetscInt childSize, coff;
31402e1b13c2SMatthew G. Knepley         ierr = DMPlexGetConeSize(dm, cp, &childSize);CHKERRQ(ierr);
31412e1b13c2SMatthew G. Knepley         coff = tmpO[i] < 0 ? -(tmpO[i]+1) : tmpO[i];
31422e1b13c2SMatthew G. Knepley         co   = childSize ? -(((coff+childSize-1)%childSize)+1) : 0;
31432e1b13c2SMatthew G. Knepley       }
3144552f7358SJed Brown       /* Check for duplicate */
3145552f7358SJed Brown       for (c = 0; c < closureSize; c += 2) {
3146552f7358SJed Brown         if (closure[c] == cp) break;
3147552f7358SJed Brown       }
3148552f7358SJed Brown       if (c == closureSize) {
3149552f7358SJed Brown         closure[closureSize]   = cp;
3150552f7358SJed Brown         closure[closureSize+1] = co;
3151552f7358SJed Brown         fifo[fifoSize]         = cp;
3152552f7358SJed Brown         fifo[fifoSize+1]       = co;
3153552f7358SJed Brown         closureSize           += 2;
3154552f7358SJed Brown         fifoSize              += 2;
3155552f7358SJed Brown       }
3156552f7358SJed Brown     }
3157552f7358SJed Brown     fifoStart += 2;
3158552f7358SJed Brown   }
3159552f7358SJed Brown   if (numPoints) *numPoints = closureSize/2;
3160552f7358SJed Brown   if (points)    *points    = closure;
316169291d52SBarry Smith   ierr = DMRestoreWorkArray(dm, maxSize, MPIU_INT, &fifo);CHKERRQ(ierr);
3162552f7358SJed Brown   PetscFunctionReturn(0);
3163552f7358SJed Brown }
3164552f7358SJed Brown 
31659bf0dad6SMatthew G. Knepley /*@C
3166eaf898f9SPatrick Sanan   DMPlexGetTransitiveClosure_Internal - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG with a specified initial orientation
31679bf0dad6SMatthew G. Knepley 
31689bf0dad6SMatthew G. Knepley   Not collective
31699bf0dad6SMatthew G. Knepley 
31709bf0dad6SMatthew G. Knepley   Input Parameters:
31719bf0dad6SMatthew G. Knepley + mesh - The DMPlex
3172eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
31739bf0dad6SMatthew G. Knepley . orientation - The orientation of the point
31749bf0dad6SMatthew G. Knepley . useCone - PETSC_TRUE for in-edges,  otherwise use out-edges
31759bf0dad6SMatthew G. Knepley - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used
31769bf0dad6SMatthew G. Knepley 
31779bf0dad6SMatthew G. Knepley   Output Parameters:
31789bf0dad6SMatthew G. Knepley + numPoints - The number of points in the closure, so points[] is of size 2*numPoints
31799bf0dad6SMatthew G. Knepley - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]
31809bf0dad6SMatthew G. Knepley 
31819bf0dad6SMatthew G. Knepley   Note:
31829bf0dad6SMatthew G. Knepley   If using internal storage (points is NULL on input), each call overwrites the last output.
31839bf0dad6SMatthew G. Knepley 
31849bf0dad6SMatthew G. Knepley   Fortran Notes:
31859bf0dad6SMatthew G. Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
31869bf0dad6SMatthew G. Knepley   include petsc.h90 in your code.
31879bf0dad6SMatthew G. Knepley 
31889bf0dad6SMatthew G. Knepley   The numPoints argument is not present in the Fortran 90 binding since it is internal to the array.
31899bf0dad6SMatthew G. Knepley 
31909bf0dad6SMatthew G. Knepley   Level: beginner
31919bf0dad6SMatthew G. Knepley 
31929bf0dad6SMatthew G. Knepley .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone()
31939bf0dad6SMatthew G. Knepley @*/
31949bf0dad6SMatthew G. Knepley PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
31959bf0dad6SMatthew G. Knepley {
31969bf0dad6SMatthew G. Knepley   DM_Plex        *mesh = (DM_Plex*) dm->data;
31979bf0dad6SMatthew G. Knepley   PetscInt       *closure, *fifo;
31989bf0dad6SMatthew G. Knepley   const PetscInt *tmp = NULL, *tmpO = NULL;
31999bf0dad6SMatthew G. Knepley   PetscInt        tmpSize, t;
32009bf0dad6SMatthew G. Knepley   PetscInt        depth       = 0, maxSize;
32019bf0dad6SMatthew G. Knepley   PetscInt        closureSize = 2, fifoSize = 0, fifoStart = 0;
32029bf0dad6SMatthew G. Knepley   PetscErrorCode  ierr;
32039bf0dad6SMatthew G. Knepley 
32049bf0dad6SMatthew G. Knepley   PetscFunctionBegin;
32059bf0dad6SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
32069bf0dad6SMatthew G. Knepley   ierr    = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
32079bf0dad6SMatthew G. Knepley   /* This is only 1-level */
32089bf0dad6SMatthew G. Knepley   if (useCone) {
32099bf0dad6SMatthew G. Knepley     ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr);
32109bf0dad6SMatthew G. Knepley     ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr);
32119bf0dad6SMatthew G. Knepley     ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr);
32129bf0dad6SMatthew G. Knepley   } else {
32139bf0dad6SMatthew G. Knepley     ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr);
32149bf0dad6SMatthew G. Knepley     ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr);
32159bf0dad6SMatthew G. Knepley   }
32169bf0dad6SMatthew G. Knepley   if (depth == 1) {
32179bf0dad6SMatthew G. Knepley     if (*points) {
32189bf0dad6SMatthew G. Knepley       closure = *points;
32199bf0dad6SMatthew G. Knepley     } else {
32209bf0dad6SMatthew G. Knepley       maxSize = 2*(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)+1);
322169291d52SBarry Smith       ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &closure);CHKERRQ(ierr);
32229bf0dad6SMatthew G. Knepley     }
32239bf0dad6SMatthew G. Knepley     closure[0] = p; closure[1] = ornt;
32249bf0dad6SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t, closureSize += 2) {
32259bf0dad6SMatthew G. Knepley       const PetscInt i = ornt >= 0 ? (t+ornt)%tmpSize : (-(ornt+1) + tmpSize-t)%tmpSize;
32269bf0dad6SMatthew G. Knepley       closure[closureSize]   = tmp[i];
32279bf0dad6SMatthew G. Knepley       closure[closureSize+1] = tmpO ? tmpO[i] : 0;
32289bf0dad6SMatthew G. Knepley     }
32299bf0dad6SMatthew G. Knepley     if (numPoints) *numPoints = closureSize/2;
32309bf0dad6SMatthew G. Knepley     if (points)    *points    = closure;
32319bf0dad6SMatthew G. Knepley     PetscFunctionReturn(0);
32329bf0dad6SMatthew G. Knepley   }
323324c766afSToby Isaac   {
323424c766afSToby Isaac     PetscInt c, coneSeries, s,supportSeries;
323524c766afSToby Isaac 
323624c766afSToby Isaac     c = mesh->maxConeSize;
323724c766afSToby Isaac     coneSeries = (c > 1) ? ((PetscPowInt(c,depth+1)-1)/(c-1)) : depth+1;
323824c766afSToby Isaac     s = mesh->maxSupportSize;
323924c766afSToby Isaac     supportSeries = (s > 1) ? ((PetscPowInt(s,depth+1)-1)/(s-1)) : depth+1;
324024c766afSToby Isaac     maxSize = 2*PetscMax(coneSeries,supportSeries);
324124c766afSToby Isaac   }
324269291d52SBarry Smith   ierr    = DMGetWorkArray(dm, maxSize, MPIU_INT, &fifo);CHKERRQ(ierr);
32439bf0dad6SMatthew G. Knepley   if (*points) {
32449bf0dad6SMatthew G. Knepley     closure = *points;
32459bf0dad6SMatthew G. Knepley   } else {
324669291d52SBarry Smith     ierr = DMGetWorkArray(dm, maxSize, MPIU_INT, &closure);CHKERRQ(ierr);
32479bf0dad6SMatthew G. Knepley   }
32489bf0dad6SMatthew G. Knepley   closure[0] = p; closure[1] = ornt;
32499bf0dad6SMatthew G. Knepley   for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) {
32509bf0dad6SMatthew G. Knepley     const PetscInt i  = ornt >= 0 ? (t+ornt)%tmpSize : (-(ornt+1) + tmpSize-t)%tmpSize;
32519bf0dad6SMatthew G. Knepley     const PetscInt cp = tmp[i];
32529bf0dad6SMatthew G. Knepley     PetscInt       co = tmpO ? tmpO[i] : 0;
32539bf0dad6SMatthew G. Knepley 
32549bf0dad6SMatthew G. Knepley     if (ornt < 0) {
32559bf0dad6SMatthew G. Knepley       PetscInt childSize, coff;
32569bf0dad6SMatthew G. Knepley       ierr = DMPlexGetConeSize(dm, cp, &childSize);CHKERRQ(ierr);
325786b63641SMatthew G. Knepley       coff = co < 0 ? -(tmpO[i]+1) : tmpO[i];
32589bf0dad6SMatthew G. Knepley       co   = childSize ? -(((coff+childSize-1)%childSize)+1) : 0;
32599bf0dad6SMatthew G. Knepley     }
32609bf0dad6SMatthew G. Knepley     closure[closureSize]   = cp;
32619bf0dad6SMatthew G. Knepley     closure[closureSize+1] = co;
32629bf0dad6SMatthew G. Knepley     fifo[fifoSize]         = cp;
32639bf0dad6SMatthew G. Knepley     fifo[fifoSize+1]       = co;
32649bf0dad6SMatthew G. Knepley   }
32659bf0dad6SMatthew G. Knepley   /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */
32669bf0dad6SMatthew G. Knepley   while (fifoSize - fifoStart) {
32679bf0dad6SMatthew G. Knepley     const PetscInt q   = fifo[fifoStart];
32689bf0dad6SMatthew G. Knepley     const PetscInt o   = fifo[fifoStart+1];
32699bf0dad6SMatthew G. Knepley     const PetscInt rev = o >= 0 ? 0 : 1;
32709bf0dad6SMatthew G. Knepley     const PetscInt off = rev ? -(o+1) : o;
32719bf0dad6SMatthew G. Knepley 
32729bf0dad6SMatthew G. Knepley     if (useCone) {
32739bf0dad6SMatthew G. Knepley       ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr);
32749bf0dad6SMatthew G. Knepley       ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr);
32759bf0dad6SMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr);
32769bf0dad6SMatthew G. Knepley     } else {
32779bf0dad6SMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr);
32789bf0dad6SMatthew G. Knepley       ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr);
32799bf0dad6SMatthew G. Knepley       tmpO = NULL;
32809bf0dad6SMatthew G. Knepley     }
32819bf0dad6SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
32829bf0dad6SMatthew G. Knepley       const PetscInt i  = ((rev ? tmpSize-t : t) + off)%tmpSize;
32839bf0dad6SMatthew G. Knepley       const PetscInt cp = tmp[i];
32849bf0dad6SMatthew G. Knepley       /* Must propogate orientation: When we reverse orientation, we both reverse the direction of iteration and start at the other end of the chain. */
32859bf0dad6SMatthew G. Knepley       /* HACK: It is worse to get the size here, than to change the interpretation of -(*+1)
32869bf0dad6SMatthew G. Knepley        const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; */
32879bf0dad6SMatthew G. Knepley       PetscInt       co = tmpO ? tmpO[i] : 0;
32889bf0dad6SMatthew G. Knepley       PetscInt       c;
32899bf0dad6SMatthew G. Knepley 
32909bf0dad6SMatthew G. Knepley       if (rev) {
32919bf0dad6SMatthew G. Knepley         PetscInt childSize, coff;
32929bf0dad6SMatthew G. Knepley         ierr = DMPlexGetConeSize(dm, cp, &childSize);CHKERRQ(ierr);
32939bf0dad6SMatthew G. Knepley         coff = tmpO[i] < 0 ? -(tmpO[i]+1) : tmpO[i];
32949bf0dad6SMatthew G. Knepley         co   = childSize ? -(((coff+childSize-1)%childSize)+1) : 0;
32959bf0dad6SMatthew G. Knepley       }
32969bf0dad6SMatthew G. Knepley       /* Check for duplicate */
32979bf0dad6SMatthew G. Knepley       for (c = 0; c < closureSize; c += 2) {
32989bf0dad6SMatthew G. Knepley         if (closure[c] == cp) break;
32999bf0dad6SMatthew G. Knepley       }
33009bf0dad6SMatthew G. Knepley       if (c == closureSize) {
33019bf0dad6SMatthew G. Knepley         closure[closureSize]   = cp;
33029bf0dad6SMatthew G. Knepley         closure[closureSize+1] = co;
33039bf0dad6SMatthew G. Knepley         fifo[fifoSize]         = cp;
33049bf0dad6SMatthew G. Knepley         fifo[fifoSize+1]       = co;
33059bf0dad6SMatthew G. Knepley         closureSize           += 2;
33069bf0dad6SMatthew G. Knepley         fifoSize              += 2;
33079bf0dad6SMatthew G. Knepley       }
33089bf0dad6SMatthew G. Knepley     }
33099bf0dad6SMatthew G. Knepley     fifoStart += 2;
33109bf0dad6SMatthew G. Knepley   }
33119bf0dad6SMatthew G. Knepley   if (numPoints) *numPoints = closureSize/2;
33129bf0dad6SMatthew G. Knepley   if (points)    *points    = closure;
331369291d52SBarry Smith   ierr = DMRestoreWorkArray(dm, maxSize, MPIU_INT, &fifo);CHKERRQ(ierr);
33149bf0dad6SMatthew G. Knepley   PetscFunctionReturn(0);
33159bf0dad6SMatthew G. Knepley }
33169bf0dad6SMatthew G. Knepley 
3317552f7358SJed Brown /*@C
3318eaf898f9SPatrick Sanan   DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG
3319552f7358SJed Brown 
3320552f7358SJed Brown   Not collective
3321552f7358SJed Brown 
3322552f7358SJed Brown   Input Parameters:
3323552f7358SJed Brown + mesh - The DMPlex
3324eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
3325552f7358SJed Brown . useCone - PETSC_TRUE for in-edges,  otherwise use out-edges
3326e5c84f05SJed Brown . numPoints - The number of points in the closure, so points[] is of size 2*numPoints, zeroed on exit
3327e5c84f05SJed Brown - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...], zeroed on exit
3328552f7358SJed Brown 
3329552f7358SJed Brown   Note:
33300298fd71SBarry Smith   If not using internal storage (points is not NULL on input), this call is unnecessary
3331552f7358SJed Brown 
33323813dfbdSMatthew G Knepley   Fortran Notes:
33333813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
33343813dfbdSMatthew G Knepley   include petsc.h90 in your code.
33353813dfbdSMatthew G Knepley 
33363813dfbdSMatthew G Knepley   The numPoints argument is not present in the Fortran 90 binding since it is internal to the array.
33373813dfbdSMatthew G Knepley 
3338552f7358SJed Brown   Level: beginner
3339552f7358SJed Brown 
3340552f7358SJed Brown .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone()
3341552f7358SJed Brown @*/
3342552f7358SJed Brown PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3343552f7358SJed Brown {
3344552f7358SJed Brown   PetscErrorCode ierr;
3345552f7358SJed Brown 
3346552f7358SJed Brown   PetscFunctionBegin;
3347552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3348e5c84f05SJed Brown   if (numPoints) PetscValidIntPointer(numPoints,4);
3349e5c84f05SJed Brown   if (points) PetscValidPointer(points,5);
335069291d52SBarry Smith   ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, points);CHKERRQ(ierr);
33514ff43b2cSJed Brown   if (numPoints) *numPoints = 0;
3352552f7358SJed Brown   PetscFunctionReturn(0);
3353552f7358SJed Brown }
3354552f7358SJed Brown 
3355552f7358SJed Brown /*@
3356eaf898f9SPatrick Sanan   DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG
3357552f7358SJed Brown 
3358552f7358SJed Brown   Not collective
3359552f7358SJed Brown 
3360552f7358SJed Brown   Input Parameter:
3361552f7358SJed Brown . mesh - The DMPlex
3362552f7358SJed Brown 
3363552f7358SJed Brown   Output Parameters:
3364552f7358SJed Brown + maxConeSize - The maximum number of in-edges
3365552f7358SJed Brown - maxSupportSize - The maximum number of out-edges
3366552f7358SJed Brown 
3367552f7358SJed Brown   Level: beginner
3368552f7358SJed Brown 
3369552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart()
3370552f7358SJed Brown @*/
3371552f7358SJed Brown PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize)
3372552f7358SJed Brown {
3373552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
3374552f7358SJed Brown 
3375552f7358SJed Brown   PetscFunctionBegin;
3376552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3377552f7358SJed Brown   if (maxConeSize)    *maxConeSize    = mesh->maxConeSize;
3378552f7358SJed Brown   if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize;
3379552f7358SJed Brown   PetscFunctionReturn(0);
3380552f7358SJed Brown }
3381552f7358SJed Brown 
3382552f7358SJed Brown PetscErrorCode DMSetUp_Plex(DM dm)
3383552f7358SJed Brown {
3384552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3385552f7358SJed Brown   PetscInt       size;
3386552f7358SJed Brown   PetscErrorCode ierr;
3387552f7358SJed Brown 
3388552f7358SJed Brown   PetscFunctionBegin;
3389552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3390552f7358SJed Brown   ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr);
3391552f7358SJed Brown   ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr);
33921795a4d1SJed Brown   ierr = PetscMalloc1(size, &mesh->cones);CHKERRQ(ierr);
33931795a4d1SJed Brown   ierr = PetscCalloc1(size, &mesh->coneOrientations);CHKERRQ(ierr);
3394ef1259faSMatthew G. Knepley   ierr = PetscLogObjectMemory((PetscObject) dm, size*2*sizeof(PetscInt));CHKERRQ(ierr);
3395552f7358SJed Brown   if (mesh->maxSupportSize) {
3396552f7358SJed Brown     ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr);
3397552f7358SJed Brown     ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr);
33981795a4d1SJed Brown     ierr = PetscMalloc1(size, &mesh->supports);CHKERRQ(ierr);
3399ef1259faSMatthew G. Knepley     ierr = PetscLogObjectMemory((PetscObject) dm, size*sizeof(PetscInt));CHKERRQ(ierr);
3400552f7358SJed Brown   }
3401552f7358SJed Brown   PetscFunctionReturn(0);
3402552f7358SJed Brown }
3403552f7358SJed Brown 
3404276c5506SMatthew G. Knepley PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm)
3405552f7358SJed Brown {
3406552f7358SJed Brown   PetscErrorCode ierr;
3407552f7358SJed Brown 
3408552f7358SJed Brown   PetscFunctionBegin;
34094d9407bcSMatthew G. Knepley   if (subdm) {ierr = DMClone(dm, subdm);CHKERRQ(ierr);}
3410792b654fSMatthew G. Knepley   ierr = DMCreateSectionSubDM(dm, numFields, fields, is, subdm);CHKERRQ(ierr);
3411c2939958SSatish Balay   if (subdm) {(*subdm)->useNatural = dm->useNatural;}
3412736995cdSBlaise Bourdin   if (dm->useNatural && dm->sfMigration) {
3413f94b4a02SBlaise Bourdin     PetscSF        sfMigrationInv,sfNatural;
3414f94b4a02SBlaise Bourdin     PetscSection   section, sectionSeq;
3415f94b4a02SBlaise Bourdin 
34163dcd263cSBlaise Bourdin     (*subdm)->sfMigration = dm->sfMigration;
34173dcd263cSBlaise Bourdin     ierr = PetscObjectReference((PetscObject) dm->sfMigration);CHKERRQ(ierr);
3418c3b366b1Sprj-     ierr = DMGetLocalSection((*subdm), &section);CHKERRQ(ierr);
3419f94b4a02SBlaise Bourdin     ierr = PetscSFCreateInverseSF((*subdm)->sfMigration, &sfMigrationInv);CHKERRQ(ierr);
3420f94b4a02SBlaise Bourdin     ierr = PetscSectionCreate(PetscObjectComm((PetscObject) (*subdm)), &sectionSeq);CHKERRQ(ierr);
3421f94b4a02SBlaise Bourdin     ierr = PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq);CHKERRQ(ierr);
3422f94b4a02SBlaise Bourdin 
3423f94b4a02SBlaise Bourdin     ierr = DMPlexCreateGlobalToNaturalSF(*subdm, sectionSeq, (*subdm)->sfMigration, &sfNatural);CHKERRQ(ierr);
3424c40e9495SBlaise Bourdin     (*subdm)->sfNatural = sfNatural;
3425f94b4a02SBlaise Bourdin     ierr = PetscSectionDestroy(&sectionSeq);CHKERRQ(ierr);
3426f94b4a02SBlaise Bourdin     ierr = PetscSFDestroy(&sfMigrationInv);CHKERRQ(ierr);
3427f94b4a02SBlaise Bourdin   }
3428552f7358SJed Brown   PetscFunctionReturn(0);
3429552f7358SJed Brown }
3430552f7358SJed Brown 
34312adcc780SMatthew G. Knepley PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm)
34322adcc780SMatthew G. Knepley {
34332adcc780SMatthew G. Knepley   PetscErrorCode ierr;
34343dcd263cSBlaise Bourdin   PetscInt       i = 0;
34352adcc780SMatthew G. Knepley 
34362adcc780SMatthew G. Knepley   PetscFunctionBegin;
3437435bcee1SStefano Zampini   ierr = DMClone(dms[0], superdm);CHKERRQ(ierr);
3438792b654fSMatthew G. Knepley   ierr = DMCreateSectionSuperDM(dms, len, is, superdm);CHKERRQ(ierr);
3439c40e9495SBlaise Bourdin   (*superdm)->useNatural = PETSC_FALSE;
34403dcd263cSBlaise Bourdin   for (i = 0; i < len; i++) {
34413dcd263cSBlaise Bourdin     if (dms[i]->useNatural && dms[i]->sfMigration) {
34423dcd263cSBlaise Bourdin       PetscSF        sfMigrationInv,sfNatural;
34433dcd263cSBlaise Bourdin       PetscSection   section, sectionSeq;
34443dcd263cSBlaise Bourdin 
34453dcd263cSBlaise Bourdin       (*superdm)->sfMigration = dms[i]->sfMigration;
34463dcd263cSBlaise Bourdin       ierr = PetscObjectReference((PetscObject) dms[i]->sfMigration);CHKERRQ(ierr);
3447c40e9495SBlaise Bourdin       (*superdm)->useNatural = PETSC_TRUE;
344892fd8e1eSJed Brown       ierr = DMGetLocalSection((*superdm), &section);CHKERRQ(ierr);
34493dcd263cSBlaise Bourdin       ierr = PetscSFCreateInverseSF((*superdm)->sfMigration, &sfMigrationInv);CHKERRQ(ierr);
34503dcd263cSBlaise Bourdin       ierr = PetscSectionCreate(PetscObjectComm((PetscObject) (*superdm)), &sectionSeq);CHKERRQ(ierr);
34513dcd263cSBlaise Bourdin       ierr = PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq);CHKERRQ(ierr);
34523dcd263cSBlaise Bourdin 
34533dcd263cSBlaise Bourdin       ierr = DMPlexCreateGlobalToNaturalSF(*superdm, sectionSeq, (*superdm)->sfMigration, &sfNatural);CHKERRQ(ierr);
3454c40e9495SBlaise Bourdin       (*superdm)->sfNatural = sfNatural;
34553dcd263cSBlaise Bourdin       ierr = PetscSectionDestroy(&sectionSeq);CHKERRQ(ierr);
34563dcd263cSBlaise Bourdin       ierr = PetscSFDestroy(&sfMigrationInv);CHKERRQ(ierr);
34573dcd263cSBlaise Bourdin       break;
34583dcd263cSBlaise Bourdin     }
34593dcd263cSBlaise Bourdin   }
34602adcc780SMatthew G. Knepley   PetscFunctionReturn(0);
34612adcc780SMatthew G. Knepley }
34622adcc780SMatthew G. Knepley 
3463552f7358SJed Brown /*@
3464eaf898f9SPatrick Sanan   DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information
3465552f7358SJed Brown 
3466552f7358SJed Brown   Not collective
3467552f7358SJed Brown 
3468552f7358SJed Brown   Input Parameter:
3469552f7358SJed Brown . mesh - The DMPlex
3470552f7358SJed Brown 
3471552f7358SJed Brown   Output Parameter:
3472552f7358SJed Brown 
3473552f7358SJed Brown   Note:
3474552f7358SJed Brown   This should be called after all calls to DMPlexSetCone()
3475552f7358SJed Brown 
3476552f7358SJed Brown   Level: beginner
3477552f7358SJed Brown 
3478552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone()
3479552f7358SJed Brown @*/
3480552f7358SJed Brown PetscErrorCode DMPlexSymmetrize(DM dm)
3481552f7358SJed Brown {
3482552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3483552f7358SJed Brown   PetscInt      *offsets;
3484552f7358SJed Brown   PetscInt       supportSize;
3485552f7358SJed Brown   PetscInt       pStart, pEnd, p;
3486552f7358SJed Brown   PetscErrorCode ierr;
3487552f7358SJed Brown 
3488552f7358SJed Brown   PetscFunctionBegin;
3489552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
349082f516ccSBarry Smith   if (mesh->supports) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex");
349130b0ce1bSStefano Zampini   ierr = PetscLogEventBegin(DMPLEX_Symmetrize,dm,0,0,0);CHKERRQ(ierr);
3492552f7358SJed Brown   /* Calculate support sizes */
3493552f7358SJed Brown   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
3494552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
3495552f7358SJed Brown     PetscInt dof, off, c;
3496552f7358SJed Brown 
3497552f7358SJed Brown     ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr);
3498552f7358SJed Brown     ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr);
3499552f7358SJed Brown     for (c = off; c < off+dof; ++c) {
3500552f7358SJed Brown       ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr);
3501552f7358SJed Brown     }
3502552f7358SJed Brown   }
3503552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
3504552f7358SJed Brown     PetscInt dof;
3505552f7358SJed Brown 
3506552f7358SJed Brown     ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr);
35070d644c17SKarl Rupp 
3508552f7358SJed Brown     mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof);
3509552f7358SJed Brown   }
3510552f7358SJed Brown   ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr);
3511552f7358SJed Brown   /* Calculate supports */
3512552f7358SJed Brown   ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr);
35131795a4d1SJed Brown   ierr = PetscMalloc1(supportSize, &mesh->supports);CHKERRQ(ierr);
35141795a4d1SJed Brown   ierr = PetscCalloc1(pEnd - pStart, &offsets);CHKERRQ(ierr);
3515552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
3516552f7358SJed Brown     PetscInt dof, off, c;
3517552f7358SJed Brown 
3518552f7358SJed Brown     ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr);
3519552f7358SJed Brown     ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr);
3520552f7358SJed Brown     for (c = off; c < off+dof; ++c) {
3521552f7358SJed Brown       const PetscInt q = mesh->cones[c];
3522552f7358SJed Brown       PetscInt       offS;
3523552f7358SJed Brown 
3524552f7358SJed Brown       ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr);
35250d644c17SKarl Rupp 
3526552f7358SJed Brown       mesh->supports[offS+offsets[q]] = p;
3527552f7358SJed Brown       ++offsets[q];
3528552f7358SJed Brown     }
3529552f7358SJed Brown   }
3530552f7358SJed Brown   ierr = PetscFree(offsets);CHKERRQ(ierr);
353130b0ce1bSStefano Zampini   ierr = PetscLogEventEnd(DMPLEX_Symmetrize,dm,0,0,0);CHKERRQ(ierr);
3532552f7358SJed Brown   PetscFunctionReturn(0);
3533552f7358SJed Brown }
3534552f7358SJed Brown 
3535277ea44aSLisandro Dalcin static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd)
3536277ea44aSLisandro Dalcin {
3537277ea44aSLisandro Dalcin   IS             stratumIS;
3538277ea44aSLisandro Dalcin   PetscErrorCode ierr;
3539277ea44aSLisandro Dalcin 
3540277ea44aSLisandro Dalcin   PetscFunctionBegin;
3541277ea44aSLisandro Dalcin   if (pStart >= pEnd) PetscFunctionReturn(0);
354276bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
3543277ea44aSLisandro Dalcin     PetscInt  qStart, qEnd, numLevels, level;
3544277ea44aSLisandro Dalcin     PetscBool overlap = PETSC_FALSE;
3545277ea44aSLisandro Dalcin     ierr = DMLabelGetNumValues(label, &numLevels);CHKERRQ(ierr);
3546277ea44aSLisandro Dalcin     for (level = 0; level < numLevels; level++) {
3547277ea44aSLisandro Dalcin       ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr);
3548277ea44aSLisandro Dalcin       if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) {overlap = PETSC_TRUE; break;}
3549277ea44aSLisandro Dalcin     }
3550277ea44aSLisandro Dalcin     if (overlap) SETERRQ6(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);
3551277ea44aSLisandro Dalcin   }
3552277ea44aSLisandro Dalcin   ierr = ISCreateStride(PETSC_COMM_SELF, pEnd-pStart, pStart, 1, &stratumIS);CHKERRQ(ierr);
3553277ea44aSLisandro Dalcin   ierr = DMLabelSetStratumIS(label, depth, stratumIS);CHKERRQ(ierr);
3554277ea44aSLisandro Dalcin   ierr = ISDestroy(&stratumIS);CHKERRQ(ierr);
3555277ea44aSLisandro Dalcin   PetscFunctionReturn(0);
3556277ea44aSLisandro Dalcin }
3557277ea44aSLisandro Dalcin 
3558552f7358SJed Brown /*@
3559a8d69d7bSBarry Smith   DMPlexStratify - The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and
35606dd80730SBarry Smith   can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the
3561552f7358SJed Brown   same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in
3562552f7358SJed Brown   the DAG.
3563552f7358SJed Brown 
3564bf4602e4SToby Isaac   Collective on dm
3565552f7358SJed Brown 
3566552f7358SJed Brown   Input Parameter:
3567552f7358SJed Brown . mesh - The DMPlex
3568552f7358SJed Brown 
3569552f7358SJed Brown   Output Parameter:
3570552f7358SJed Brown 
3571552f7358SJed Brown   Notes:
3572b1bb481bSMatthew Knepley   Concretely, DMPlexStratify() creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex
3573b1bb481bSMatthew 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
3574b1bb481bSMatthew Knepley   until cells have depth equal to the dimension of the mesh. The depth label can be accessed through DMPlexGetDepthLabel() or DMPlexGetDepthStratum(), or
3575c58f1c22SToby Isaac   manually via DMGetLabel().  The height is defined implicitly by height = maxDimension - depth, and can be accessed
3576150b719bSJed Brown   via DMPlexGetHeightStratum().  For example, cells have height 0 and faces have height 1.
3577552f7358SJed Brown 
3578b1bb481bSMatthew Knepley   The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results
3579b1bb481bSMatthew Knepley   if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that
3580b1bb481bSMatthew 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
3581b1bb481bSMatthew Knepley   to interpolate only that one (e0), so that
3582b1bb481bSMatthew Knepley $  cone(c0) = {e0, v2}
3583b1bb481bSMatthew Knepley $  cone(e0) = {v0, v1}
3584b1bb481bSMatthew Knepley   If DMPlexStratify() is run on this mesh, it will give depths
3585b1bb481bSMatthew Knepley $  depth 0 = {v0, v1, v2}
3586b1bb481bSMatthew Knepley $  depth 1 = {e0, c0}
3587b1bb481bSMatthew Knepley   where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2.
3588b1bb481bSMatthew Knepley 
3589150b719bSJed Brown   DMPlexStratify() should be called after all calls to DMPlexSymmetrize()
3590552f7358SJed Brown 
3591552f7358SJed Brown   Level: beginner
3592552f7358SJed Brown 
3593ba2698f1SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexSymmetrize(), DMPlexComputeCellTypes()
3594552f7358SJed Brown @*/
3595552f7358SJed Brown PetscErrorCode DMPlexStratify(DM dm)
3596552f7358SJed Brown {
3597df0420ecSMatthew G. Knepley   DM_Plex       *mesh = (DM_Plex*) dm->data;
3598aa50250dSMatthew G. Knepley   DMLabel        label;
3599552f7358SJed Brown   PetscInt       pStart, pEnd, p;
3600552f7358SJed Brown   PetscInt       numRoots = 0, numLeaves = 0;
3601552f7358SJed Brown   PetscErrorCode ierr;
3602552f7358SJed Brown 
3603552f7358SJed Brown   PetscFunctionBegin;
3604552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3605552f7358SJed Brown   ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr);
3606277ea44aSLisandro Dalcin 
3607277ea44aSLisandro Dalcin   /* Create depth label */
3608aa50250dSMatthew G. Knepley   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
3609c58f1c22SToby Isaac   ierr = DMCreateLabel(dm, "depth");CHKERRQ(ierr);
3610aa50250dSMatthew G. Knepley   ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr);
3611277ea44aSLisandro Dalcin 
3612277ea44aSLisandro Dalcin   {
3613552f7358SJed Brown     /* Initialize roots and count leaves */
3614277ea44aSLisandro Dalcin     PetscInt sMin = PETSC_MAX_INT;
3615277ea44aSLisandro Dalcin     PetscInt sMax = PETSC_MIN_INT;
3616552f7358SJed Brown     PetscInt coneSize, supportSize;
3617552f7358SJed Brown 
3618277ea44aSLisandro Dalcin     for (p = pStart; p < pEnd; ++p) {
3619552f7358SJed Brown       ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
3620552f7358SJed Brown       ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr);
3621552f7358SJed Brown       if (!coneSize && supportSize) {
3622277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
3623277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
3624552f7358SJed Brown         ++numRoots;
3625552f7358SJed Brown       } else if (!supportSize && coneSize) {
3626552f7358SJed Brown         ++numLeaves;
3627552f7358SJed Brown       } else if (!supportSize && !coneSize) {
3628552f7358SJed Brown         /* Isolated points */
3629277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
3630277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
3631552f7358SJed Brown       }
3632552f7358SJed Brown     }
3633277ea44aSLisandro Dalcin     ierr = DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax+1);CHKERRQ(ierr);
3634277ea44aSLisandro Dalcin   }
3635277ea44aSLisandro Dalcin 
3636552f7358SJed Brown   if (numRoots + numLeaves == (pEnd - pStart)) {
3637277ea44aSLisandro Dalcin     PetscInt sMin = PETSC_MAX_INT;
3638277ea44aSLisandro Dalcin     PetscInt sMax = PETSC_MIN_INT;
3639552f7358SJed Brown     PetscInt coneSize, supportSize;
3640552f7358SJed Brown 
3641277ea44aSLisandro Dalcin     for (p = pStart; p < pEnd; ++p) {
3642552f7358SJed Brown       ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
3643552f7358SJed Brown       ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr);
3644552f7358SJed Brown       if (!supportSize && coneSize) {
3645277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
3646277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
3647552f7358SJed Brown       }
3648552f7358SJed Brown     }
3649277ea44aSLisandro Dalcin     ierr = DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax+1);CHKERRQ(ierr);
3650552f7358SJed Brown   } else {
3651277ea44aSLisandro Dalcin     PetscInt level = 0;
3652277ea44aSLisandro Dalcin     PetscInt qStart, qEnd, q;
3653552f7358SJed Brown 
3654277ea44aSLisandro Dalcin     ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr);
3655277ea44aSLisandro Dalcin     while (qEnd > qStart) {
3656277ea44aSLisandro Dalcin       PetscInt sMin = PETSC_MAX_INT;
3657277ea44aSLisandro Dalcin       PetscInt sMax = PETSC_MIN_INT;
365874ef644bSMatthew G. Knepley 
3659277ea44aSLisandro Dalcin       for (q = qStart; q < qEnd; ++q) {
366074ef644bSMatthew G. Knepley         const PetscInt *support;
366174ef644bSMatthew G. Knepley         PetscInt        supportSize, s;
366274ef644bSMatthew G. Knepley 
3663277ea44aSLisandro Dalcin         ierr = DMPlexGetSupportSize(dm, q, &supportSize);CHKERRQ(ierr);
3664277ea44aSLisandro Dalcin         ierr = DMPlexGetSupport(dm, q, &support);CHKERRQ(ierr);
366574ef644bSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
3666277ea44aSLisandro Dalcin           sMin = PetscMin(support[s], sMin);
3667277ea44aSLisandro Dalcin           sMax = PetscMax(support[s], sMax);
3668552f7358SJed Brown         }
3669552f7358SJed Brown       }
3670277ea44aSLisandro Dalcin       ierr = DMLabelGetNumValues(label, &level);CHKERRQ(ierr);
3671277ea44aSLisandro Dalcin       ierr = DMPlexCreateDepthStratum(dm, label, level, sMin, sMax+1);CHKERRQ(ierr);
3672277ea44aSLisandro Dalcin       ierr = DMLabelGetStratumBounds(label, level, &qStart, &qEnd);CHKERRQ(ierr);
367374ef644bSMatthew G. Knepley     }
367474ef644bSMatthew G. Knepley   }
3675bf4602e4SToby Isaac   { /* just in case there is an empty process */
3676bf4602e4SToby Isaac     PetscInt numValues, maxValues = 0, v;
3677bf4602e4SToby Isaac 
3678bf4602e4SToby Isaac     ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr);
3679ffc4695bSBarry Smith     ierr = MPI_Allreduce(&numValues,&maxValues,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr);
3680bf4602e4SToby Isaac     for (v = numValues; v < maxValues; v++) {
3681367003a6SStefano Zampini       ierr = DMLabelAddStratum(label, v);CHKERRQ(ierr);
3682bf4602e4SToby Isaac     }
3683bf4602e4SToby Isaac   }
3684d67d17b1SMatthew G. Knepley   ierr = PetscObjectStateGet((PetscObject) label, &mesh->depthState);CHKERRQ(ierr);
3685552f7358SJed Brown   ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr);
3686552f7358SJed Brown   PetscFunctionReturn(0);
3687552f7358SJed Brown }
3688552f7358SJed Brown 
3689412e9a14SMatthew G. Knepley PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt)
3690ba2698f1SMatthew G. Knepley {
3691412e9a14SMatthew G. Knepley   DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
3692412e9a14SMatthew G. Knepley   PetscInt       dim, depth, pheight, coneSize;
3693ba2698f1SMatthew G. Knepley   PetscErrorCode ierr;
3694ba2698f1SMatthew G. Knepley 
3695412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
3696ba2698f1SMatthew G. Knepley   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
3697ba2698f1SMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
3698ba2698f1SMatthew G. Knepley   ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
3699ba2698f1SMatthew G. Knepley   pheight = depth - pdepth;
3700ba2698f1SMatthew G. Knepley   if (depth <= 1) {
3701ba2698f1SMatthew G. Knepley     switch (pdepth) {
3702ba2698f1SMatthew G. Knepley       case 0: ct = DM_POLYTOPE_POINT;break;
3703ba2698f1SMatthew G. Knepley       case 1:
3704ba2698f1SMatthew G. Knepley         switch (coneSize) {
3705ba2698f1SMatthew G. Knepley           case 2: ct = DM_POLYTOPE_SEGMENT;break;
3706ba2698f1SMatthew G. Knepley           case 3: ct = DM_POLYTOPE_TRIANGLE;break;
3707ba2698f1SMatthew G. Knepley           case 4:
3708ba2698f1SMatthew G. Knepley           switch (dim) {
3709ba2698f1SMatthew G. Knepley             case 2: ct = DM_POLYTOPE_QUADRILATERAL;break;
3710ba2698f1SMatthew G. Knepley             case 3: ct = DM_POLYTOPE_TETRAHEDRON;break;
3711ba2698f1SMatthew G. Knepley             default: break;
3712ba2698f1SMatthew G. Knepley           }
3713ba2698f1SMatthew G. Knepley           break;
3714da9060c4SMatthew G. Knepley         case 5: ct = DM_POLYTOPE_PYRAMID;break;
3715ba2698f1SMatthew G. Knepley         case 6: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break;
3716ba2698f1SMatthew G. Knepley         case 8: ct = DM_POLYTOPE_HEXAHEDRON;break;
3717ba2698f1SMatthew G. Knepley         default: break;
3718ba2698f1SMatthew G. Knepley       }
3719ba2698f1SMatthew G. Knepley     }
3720ba2698f1SMatthew G. Knepley   } else {
3721ba2698f1SMatthew G. Knepley     if (pdepth == 0) {
3722ba2698f1SMatthew G. Knepley       ct = DM_POLYTOPE_POINT;
3723ba2698f1SMatthew G. Knepley     } else if (pheight == 0) {
3724ba2698f1SMatthew G. Knepley       switch (dim) {
3725ba2698f1SMatthew G. Knepley         case 1:
3726ba2698f1SMatthew G. Knepley           switch (coneSize) {
3727ba2698f1SMatthew G. Knepley             case 2: ct = DM_POLYTOPE_SEGMENT;break;
3728ba2698f1SMatthew G. Knepley             default: break;
3729ba2698f1SMatthew G. Knepley           }
3730ba2698f1SMatthew G. Knepley           break;
3731ba2698f1SMatthew G. Knepley         case 2:
3732ba2698f1SMatthew G. Knepley           switch (coneSize) {
3733ba2698f1SMatthew G. Knepley             case 3: ct = DM_POLYTOPE_TRIANGLE;break;
3734ba2698f1SMatthew G. Knepley             case 4: ct = DM_POLYTOPE_QUADRILATERAL;break;
3735ba2698f1SMatthew G. Knepley             default: break;
3736ba2698f1SMatthew G. Knepley           }
3737ba2698f1SMatthew G. Knepley           break;
3738ba2698f1SMatthew G. Knepley         case 3:
3739ba2698f1SMatthew G. Knepley           switch (coneSize) {
3740ba2698f1SMatthew G. Knepley             case 4: ct = DM_POLYTOPE_TETRAHEDRON;break;
3741da9060c4SMatthew G. Knepley             case 5:
3742da9060c4SMatthew G. Knepley             {
3743da9060c4SMatthew G. Knepley               const PetscInt *cone;
3744da9060c4SMatthew G. Knepley               PetscInt        faceConeSize;
3745da9060c4SMatthew G. Knepley 
3746da9060c4SMatthew G. Knepley               ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr);
3747da9060c4SMatthew G. Knepley               ierr = DMPlexGetConeSize(dm, cone[0], &faceConeSize);CHKERRQ(ierr);
3748da9060c4SMatthew G. Knepley               switch (faceConeSize) {
3749da9060c4SMatthew G. Knepley                 case 3: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break;
3750da9060c4SMatthew G. Knepley                 case 4: ct = DM_POLYTOPE_PYRAMID;break;
3751da9060c4SMatthew G. Knepley               }
3752da9060c4SMatthew G. Knepley             }
3753da9060c4SMatthew G. Knepley             break;
3754ba2698f1SMatthew G. Knepley             case 6: ct = DM_POLYTOPE_HEXAHEDRON;break;
3755ba2698f1SMatthew G. Knepley             default: break;
3756ba2698f1SMatthew G. Knepley           }
3757ba2698f1SMatthew G. Knepley           break;
3758ba2698f1SMatthew G. Knepley         default: break;
3759ba2698f1SMatthew G. Knepley       }
3760ba2698f1SMatthew G. Knepley     } else if (pheight > 0) {
3761ba2698f1SMatthew G. Knepley       switch (coneSize) {
3762ba2698f1SMatthew G. Knepley         case 2: ct = DM_POLYTOPE_SEGMENT;break;
3763ba2698f1SMatthew G. Knepley         case 3: ct = DM_POLYTOPE_TRIANGLE;break;
3764ba2698f1SMatthew G. Knepley         case 4: ct = DM_POLYTOPE_QUADRILATERAL;break;
3765ba2698f1SMatthew G. Knepley         default: break;
3766ba2698f1SMatthew G. Knepley       }
3767ba2698f1SMatthew G. Knepley     }
3768ba2698f1SMatthew G. Knepley   }
3769412e9a14SMatthew G. Knepley   *pt = ct;
3770412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
3771ba2698f1SMatthew G. Knepley }
3772412e9a14SMatthew G. Knepley 
3773412e9a14SMatthew G. Knepley /*@
3774412e9a14SMatthew G. Knepley   DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size.
3775412e9a14SMatthew G. Knepley 
3776412e9a14SMatthew G. Knepley   Collective on dm
3777412e9a14SMatthew G. Knepley 
3778412e9a14SMatthew G. Knepley   Input Parameter:
3779412e9a14SMatthew G. Knepley . mesh - The DMPlex
3780412e9a14SMatthew G. Knepley 
3781412e9a14SMatthew G. Knepley   DMPlexComputeCellTypes() should be called after all calls to DMPlexSymmetrize() and DMPlexStratify()
3782412e9a14SMatthew G. Knepley 
3783412e9a14SMatthew G. Knepley   Level: developer
3784412e9a14SMatthew G. Knepley 
3785412e9a14SMatthew G. Knepley   Note: This function is normally called automatically by Plex when a cell type is requested. It creates an
3786412e9a14SMatthew G. Knepley   internal DMLabel named "celltype" which can be directly accessed using DMGetLabel(). A user may disable
3787412e9a14SMatthew G. Knepley   automatic creation by creating the label manually, using DMCreateLabel(dm, "celltype").
3788412e9a14SMatthew G. Knepley 
3789412e9a14SMatthew G. Knepley .seealso: DMPlexCreate(), DMPlexSymmetrize(), DMPlexStratify(), DMGetLabel(), DMCreateLabel()
3790412e9a14SMatthew G. Knepley @*/
3791412e9a14SMatthew G. Knepley PetscErrorCode DMPlexComputeCellTypes(DM dm)
3792412e9a14SMatthew G. Knepley {
3793412e9a14SMatthew G. Knepley   DM_Plex       *mesh;
3794412e9a14SMatthew G. Knepley   DMLabel        ctLabel;
3795412e9a14SMatthew G. Knepley   PetscInt       pStart, pEnd, p;
3796412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
3797412e9a14SMatthew G. Knepley 
3798412e9a14SMatthew G. Knepley   PetscFunctionBegin;
3799412e9a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3800412e9a14SMatthew G. Knepley   mesh = (DM_Plex *) dm->data;
3801412e9a14SMatthew G. Knepley   ierr = DMCreateLabel(dm, "celltype");CHKERRQ(ierr);
3802412e9a14SMatthew G. Knepley   ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr);
3803412e9a14SMatthew G. Knepley   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
3804412e9a14SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
3805327c2912SStefano Zampini     DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
3806412e9a14SMatthew G. Knepley     PetscInt       pdepth;
3807412e9a14SMatthew G. Knepley 
3808412e9a14SMatthew G. Knepley     ierr = DMPlexGetPointDepth(dm, p, &pdepth);CHKERRQ(ierr);
3809412e9a14SMatthew G. Knepley     ierr = DMPlexComputeCellType_Internal(dm, p, pdepth, &ct);CHKERRQ(ierr);
3810412e9a14SMatthew G. Knepley     if (ct == DM_POLYTOPE_UNKNOWN) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Point %D is screwed up", p);
3811412e9a14SMatthew G. Knepley     ierr = DMLabelSetValue(ctLabel, p, ct);CHKERRQ(ierr);
3812412e9a14SMatthew G. Knepley   }
3813412e9a14SMatthew G. Knepley   ierr = PetscObjectStateGet((PetscObject) ctLabel, &mesh->celltypeState);CHKERRQ(ierr);
3814412e9a14SMatthew G. Knepley   ierr = PetscObjectViewFromOptions((PetscObject) ctLabel, NULL, "-dm_plex_celltypes_view");CHKERRQ(ierr);
3815ba2698f1SMatthew G. Knepley   PetscFunctionReturn(0);
3816ba2698f1SMatthew G. Knepley }
3817ba2698f1SMatthew G. Knepley 
3818552f7358SJed Brown /*@C
3819552f7358SJed Brown   DMPlexGetJoin - Get an array for the join of the set of points
3820552f7358SJed Brown 
3821552f7358SJed Brown   Not Collective
3822552f7358SJed Brown 
3823552f7358SJed Brown   Input Parameters:
3824552f7358SJed Brown + dm - The DMPlex object
3825552f7358SJed Brown . numPoints - The number of input points for the join
3826552f7358SJed Brown - points - The input points
3827552f7358SJed Brown 
3828552f7358SJed Brown   Output Parameters:
3829552f7358SJed Brown + numCoveredPoints - The number of points in the join
3830552f7358SJed Brown - coveredPoints - The points in the join
3831552f7358SJed Brown 
3832552f7358SJed Brown   Level: intermediate
3833552f7358SJed Brown 
3834552f7358SJed Brown   Note: Currently, this is restricted to a single level join
3835552f7358SJed Brown 
38363813dfbdSMatthew G Knepley   Fortran Notes:
38373813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
38383813dfbdSMatthew G Knepley   include petsc.h90 in your code.
38393813dfbdSMatthew G Knepley 
38403813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
38413813dfbdSMatthew G Knepley 
3842552f7358SJed Brown .seealso: DMPlexRestoreJoin(), DMPlexGetMeet()
3843552f7358SJed Brown @*/
3844552f7358SJed Brown PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
3845552f7358SJed Brown {
3846552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3847552f7358SJed Brown   PetscInt      *join[2];
3848552f7358SJed Brown   PetscInt       joinSize, i = 0;
3849552f7358SJed Brown   PetscInt       dof, off, p, c, m;
3850552f7358SJed Brown   PetscErrorCode ierr;
3851552f7358SJed Brown 
3852552f7358SJed Brown   PetscFunctionBegin;
3853552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
385448bb261cSVaclav Hapla   PetscValidIntPointer(points, 3);
385548bb261cSVaclav Hapla   PetscValidIntPointer(numCoveredPoints, 4);
385648bb261cSVaclav Hapla   PetscValidPointer(coveredPoints, 5);
385769291d52SBarry Smith   ierr = DMGetWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[0]);CHKERRQ(ierr);
385869291d52SBarry Smith   ierr = DMGetWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1]);CHKERRQ(ierr);
3859552f7358SJed Brown   /* Copy in support of first point */
3860552f7358SJed Brown   ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr);
3861552f7358SJed Brown   ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr);
3862552f7358SJed Brown   for (joinSize = 0; joinSize < dof; ++joinSize) {
3863552f7358SJed Brown     join[i][joinSize] = mesh->supports[off+joinSize];
3864552f7358SJed Brown   }
3865552f7358SJed Brown   /* Check each successive support */
3866552f7358SJed Brown   for (p = 1; p < numPoints; ++p) {
3867552f7358SJed Brown     PetscInt newJoinSize = 0;
3868552f7358SJed Brown 
3869552f7358SJed Brown     ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr);
3870552f7358SJed Brown     ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr);
3871552f7358SJed Brown     for (c = 0; c < dof; ++c) {
3872552f7358SJed Brown       const PetscInt point = mesh->supports[off+c];
3873552f7358SJed Brown 
3874552f7358SJed Brown       for (m = 0; m < joinSize; ++m) {
3875552f7358SJed Brown         if (point == join[i][m]) {
3876552f7358SJed Brown           join[1-i][newJoinSize++] = point;
3877552f7358SJed Brown           break;
3878552f7358SJed Brown         }
3879552f7358SJed Brown       }
3880552f7358SJed Brown     }
3881552f7358SJed Brown     joinSize = newJoinSize;
3882552f7358SJed Brown     i        = 1-i;
3883552f7358SJed Brown   }
3884552f7358SJed Brown   *numCoveredPoints = joinSize;
3885552f7358SJed Brown   *coveredPoints    = join[i];
388669291d52SBarry Smith   ierr              = DMRestoreWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1-i]);CHKERRQ(ierr);
3887552f7358SJed Brown   PetscFunctionReturn(0);
3888552f7358SJed Brown }
3889552f7358SJed Brown 
3890552f7358SJed Brown /*@C
3891552f7358SJed Brown   DMPlexRestoreJoin - Restore an array for the join of the set of points
3892552f7358SJed Brown 
3893552f7358SJed Brown   Not Collective
3894552f7358SJed Brown 
3895552f7358SJed Brown   Input Parameters:
3896552f7358SJed Brown + dm - The DMPlex object
3897552f7358SJed Brown . numPoints - The number of input points for the join
3898552f7358SJed Brown - points - The input points
3899552f7358SJed Brown 
3900552f7358SJed Brown   Output Parameters:
3901552f7358SJed Brown + numCoveredPoints - The number of points in the join
3902552f7358SJed Brown - coveredPoints - The points in the join
3903552f7358SJed Brown 
39043813dfbdSMatthew G Knepley   Fortran Notes:
39053813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
39063813dfbdSMatthew G Knepley   include petsc.h90 in your code.
39073813dfbdSMatthew G Knepley 
39083813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
39093813dfbdSMatthew G Knepley 
3910552f7358SJed Brown   Level: intermediate
3911552f7358SJed Brown 
3912552f7358SJed Brown .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet()
3913552f7358SJed Brown @*/
3914552f7358SJed Brown PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
3915552f7358SJed Brown {
3916552f7358SJed Brown   PetscErrorCode ierr;
3917552f7358SJed Brown 
3918552f7358SJed Brown   PetscFunctionBegin;
3919552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3920d7902bd2SMatthew G. Knepley   if (points) PetscValidIntPointer(points,3);
3921d7902bd2SMatthew G. Knepley   if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4);
3922d7902bd2SMatthew G. Knepley   PetscValidPointer(coveredPoints, 5);
392369291d52SBarry Smith   ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints);CHKERRQ(ierr);
3924d7902bd2SMatthew G. Knepley   if (numCoveredPoints) *numCoveredPoints = 0;
3925552f7358SJed Brown   PetscFunctionReturn(0);
3926552f7358SJed Brown }
3927552f7358SJed Brown 
3928552f7358SJed Brown /*@C
3929552f7358SJed Brown   DMPlexGetFullJoin - Get an array for the join of the set of points
3930552f7358SJed Brown 
3931552f7358SJed Brown   Not Collective
3932552f7358SJed Brown 
3933552f7358SJed Brown   Input Parameters:
3934552f7358SJed Brown + dm - The DMPlex object
3935552f7358SJed Brown . numPoints - The number of input points for the join
3936552f7358SJed Brown - points - The input points
3937552f7358SJed Brown 
3938552f7358SJed Brown   Output Parameters:
3939552f7358SJed Brown + numCoveredPoints - The number of points in the join
3940552f7358SJed Brown - coveredPoints - The points in the join
3941552f7358SJed Brown 
39423813dfbdSMatthew G Knepley   Fortran Notes:
39433813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
39443813dfbdSMatthew G Knepley   include petsc.h90 in your code.
39453813dfbdSMatthew G Knepley 
39463813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
39473813dfbdSMatthew G Knepley 
3948552f7358SJed Brown   Level: intermediate
3949552f7358SJed Brown 
3950552f7358SJed Brown .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet()
3951552f7358SJed Brown @*/
3952552f7358SJed Brown PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
3953552f7358SJed Brown {
3954552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3955552f7358SJed Brown   PetscInt      *offsets, **closures;
3956552f7358SJed Brown   PetscInt      *join[2];
3957552f7358SJed Brown   PetscInt       depth = 0, maxSize, joinSize = 0, i = 0;
395824c766afSToby Isaac   PetscInt       p, d, c, m, ms;
3959552f7358SJed Brown   PetscErrorCode ierr;
3960552f7358SJed Brown 
3961552f7358SJed Brown   PetscFunctionBegin;
3962552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
396348bb261cSVaclav Hapla   PetscValidIntPointer(points, 3);
396448bb261cSVaclav Hapla   PetscValidIntPointer(numCoveredPoints, 4);
396548bb261cSVaclav Hapla   PetscValidPointer(coveredPoints, 5);
3966552f7358SJed Brown 
3967552f7358SJed Brown   ierr    = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
39681795a4d1SJed Brown   ierr    = PetscCalloc1(numPoints, &closures);CHKERRQ(ierr);
396969291d52SBarry Smith   ierr    = DMGetWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets);CHKERRQ(ierr);
397024c766afSToby Isaac   ms      = mesh->maxSupportSize;
397124c766afSToby Isaac   maxSize = (ms > 1) ? ((PetscPowInt(ms,depth+1)-1)/(ms-1)) : depth + 1;
397269291d52SBarry Smith   ierr    = DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0]);CHKERRQ(ierr);
397369291d52SBarry Smith   ierr    = DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1]);CHKERRQ(ierr);
3974552f7358SJed Brown 
3975552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
3976552f7358SJed Brown     PetscInt closureSize;
3977552f7358SJed Brown 
3978552f7358SJed Brown     ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr);
39790d644c17SKarl Rupp 
3980552f7358SJed Brown     offsets[p*(depth+2)+0] = 0;
3981552f7358SJed Brown     for (d = 0; d < depth+1; ++d) {
3982552f7358SJed Brown       PetscInt pStart, pEnd, i;
3983552f7358SJed Brown 
3984552f7358SJed Brown       ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr);
3985552f7358SJed Brown       for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) {
3986552f7358SJed Brown         if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) {
3987552f7358SJed Brown           offsets[p*(depth+2)+d+1] = i;
3988552f7358SJed Brown           break;
3989552f7358SJed Brown         }
3990552f7358SJed Brown       }
3991552f7358SJed Brown       if (i == closureSize) offsets[p*(depth+2)+d+1] = i;
3992552f7358SJed Brown     }
399382f516ccSBarry Smith     if (offsets[p*(depth+2)+depth+1] != closureSize) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(depth+2)+depth+1], closureSize);
3994552f7358SJed Brown   }
3995552f7358SJed Brown   for (d = 0; d < depth+1; ++d) {
3996552f7358SJed Brown     PetscInt dof;
3997552f7358SJed Brown 
3998552f7358SJed Brown     /* Copy in support of first point */
3999552f7358SJed Brown     dof = offsets[d+1] - offsets[d];
4000552f7358SJed Brown     for (joinSize = 0; joinSize < dof; ++joinSize) {
4001552f7358SJed Brown       join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2];
4002552f7358SJed Brown     }
4003552f7358SJed Brown     /* Check each successive cone */
4004552f7358SJed Brown     for (p = 1; p < numPoints && joinSize; ++p) {
4005552f7358SJed Brown       PetscInt newJoinSize = 0;
4006552f7358SJed Brown 
4007552f7358SJed Brown       dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d];
4008552f7358SJed Brown       for (c = 0; c < dof; ++c) {
4009552f7358SJed Brown         const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2];
4010552f7358SJed Brown 
4011552f7358SJed Brown         for (m = 0; m < joinSize; ++m) {
4012552f7358SJed Brown           if (point == join[i][m]) {
4013552f7358SJed Brown             join[1-i][newJoinSize++] = point;
4014552f7358SJed Brown             break;
4015552f7358SJed Brown           }
4016552f7358SJed Brown         }
4017552f7358SJed Brown       }
4018552f7358SJed Brown       joinSize = newJoinSize;
4019552f7358SJed Brown       i        = 1-i;
4020552f7358SJed Brown     }
4021552f7358SJed Brown     if (joinSize) break;
4022552f7358SJed Brown   }
4023552f7358SJed Brown   *numCoveredPoints = joinSize;
4024552f7358SJed Brown   *coveredPoints    = join[i];
4025552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
40260298fd71SBarry Smith     ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]);CHKERRQ(ierr);
4027552f7358SJed Brown   }
4028552f7358SJed Brown   ierr = PetscFree(closures);CHKERRQ(ierr);
402969291d52SBarry Smith   ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets);CHKERRQ(ierr);
403069291d52SBarry Smith   ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, MPIU_INT, &join[1-i]);CHKERRQ(ierr);
4031552f7358SJed Brown   PetscFunctionReturn(0);
4032552f7358SJed Brown }
4033552f7358SJed Brown 
4034552f7358SJed Brown /*@C
4035552f7358SJed Brown   DMPlexGetMeet - Get an array for the meet of the set of points
4036552f7358SJed Brown 
4037552f7358SJed Brown   Not Collective
4038552f7358SJed Brown 
4039552f7358SJed Brown   Input Parameters:
4040552f7358SJed Brown + dm - The DMPlex object
4041552f7358SJed Brown . numPoints - The number of input points for the meet
4042552f7358SJed Brown - points - The input points
4043552f7358SJed Brown 
4044552f7358SJed Brown   Output Parameters:
4045552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4046552f7358SJed Brown - coveredPoints - The points in the meet
4047552f7358SJed Brown 
4048552f7358SJed Brown   Level: intermediate
4049552f7358SJed Brown 
4050552f7358SJed Brown   Note: Currently, this is restricted to a single level meet
4051552f7358SJed Brown 
40523813dfbdSMatthew G Knepley   Fortran Notes:
40533813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
40543813dfbdSMatthew G Knepley   include petsc.h90 in your code.
40553813dfbdSMatthew G Knepley 
40563813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
40573813dfbdSMatthew G Knepley 
4058552f7358SJed Brown .seealso: DMPlexRestoreMeet(), DMPlexGetJoin()
4059552f7358SJed Brown @*/
4060552f7358SJed Brown PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints)
4061552f7358SJed Brown {
4062552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
4063552f7358SJed Brown   PetscInt      *meet[2];
4064552f7358SJed Brown   PetscInt       meetSize, i = 0;
4065552f7358SJed Brown   PetscInt       dof, off, p, c, m;
4066552f7358SJed Brown   PetscErrorCode ierr;
4067552f7358SJed Brown 
4068552f7358SJed Brown   PetscFunctionBegin;
4069552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4070064a246eSJacob Faibussowitsch   PetscValidPointer(points, 3);
4071064a246eSJacob Faibussowitsch   PetscValidPointer(numCoveringPoints, 4);
4072064a246eSJacob Faibussowitsch   PetscValidPointer(coveringPoints, 5);
407369291d52SBarry Smith   ierr = DMGetWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[0]);CHKERRQ(ierr);
407469291d52SBarry Smith   ierr = DMGetWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1]);CHKERRQ(ierr);
4075552f7358SJed Brown   /* Copy in cone of first point */
4076552f7358SJed Brown   ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr);
4077552f7358SJed Brown   ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr);
4078552f7358SJed Brown   for (meetSize = 0; meetSize < dof; ++meetSize) {
4079552f7358SJed Brown     meet[i][meetSize] = mesh->cones[off+meetSize];
4080552f7358SJed Brown   }
4081552f7358SJed Brown   /* Check each successive cone */
4082552f7358SJed Brown   for (p = 1; p < numPoints; ++p) {
4083552f7358SJed Brown     PetscInt newMeetSize = 0;
4084552f7358SJed Brown 
4085552f7358SJed Brown     ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr);
4086552f7358SJed Brown     ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr);
4087552f7358SJed Brown     for (c = 0; c < dof; ++c) {
4088552f7358SJed Brown       const PetscInt point = mesh->cones[off+c];
4089552f7358SJed Brown 
4090552f7358SJed Brown       for (m = 0; m < meetSize; ++m) {
4091552f7358SJed Brown         if (point == meet[i][m]) {
4092552f7358SJed Brown           meet[1-i][newMeetSize++] = point;
4093552f7358SJed Brown           break;
4094552f7358SJed Brown         }
4095552f7358SJed Brown       }
4096552f7358SJed Brown     }
4097552f7358SJed Brown     meetSize = newMeetSize;
4098552f7358SJed Brown     i        = 1-i;
4099552f7358SJed Brown   }
4100552f7358SJed Brown   *numCoveringPoints = meetSize;
4101552f7358SJed Brown   *coveringPoints    = meet[i];
410269291d52SBarry Smith   ierr               = DMRestoreWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1-i]);CHKERRQ(ierr);
4103552f7358SJed Brown   PetscFunctionReturn(0);
4104552f7358SJed Brown }
4105552f7358SJed Brown 
4106552f7358SJed Brown /*@C
4107552f7358SJed Brown   DMPlexRestoreMeet - Restore an array for the meet of the set of points
4108552f7358SJed Brown 
4109552f7358SJed Brown   Not Collective
4110552f7358SJed Brown 
4111552f7358SJed Brown   Input Parameters:
4112552f7358SJed Brown + dm - The DMPlex object
4113552f7358SJed Brown . numPoints - The number of input points for the meet
4114552f7358SJed Brown - points - The input points
4115552f7358SJed Brown 
4116552f7358SJed Brown   Output Parameters:
4117552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4118552f7358SJed Brown - coveredPoints - The points in the meet
4119552f7358SJed Brown 
4120552f7358SJed Brown   Level: intermediate
4121552f7358SJed Brown 
41223813dfbdSMatthew G Knepley   Fortran Notes:
41233813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
41243813dfbdSMatthew G Knepley   include petsc.h90 in your code.
41253813dfbdSMatthew G Knepley 
41263813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
41273813dfbdSMatthew G Knepley 
4128552f7358SJed Brown .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin()
4129552f7358SJed Brown @*/
4130552f7358SJed Brown PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4131552f7358SJed Brown {
4132552f7358SJed Brown   PetscErrorCode ierr;
4133552f7358SJed Brown 
4134552f7358SJed Brown   PetscFunctionBegin;
4135552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4136d7902bd2SMatthew G. Knepley   if (points) PetscValidIntPointer(points,3);
4137d7902bd2SMatthew G. Knepley   if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4);
4138d7902bd2SMatthew G. Knepley   PetscValidPointer(coveredPoints,5);
413969291d52SBarry Smith   ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints);CHKERRQ(ierr);
4140d7902bd2SMatthew G. Knepley   if (numCoveredPoints) *numCoveredPoints = 0;
4141552f7358SJed Brown   PetscFunctionReturn(0);
4142552f7358SJed Brown }
4143552f7358SJed Brown 
4144552f7358SJed Brown /*@C
4145552f7358SJed Brown   DMPlexGetFullMeet - Get an array for the meet of the set of points
4146552f7358SJed Brown 
4147552f7358SJed Brown   Not Collective
4148552f7358SJed Brown 
4149552f7358SJed Brown   Input Parameters:
4150552f7358SJed Brown + dm - The DMPlex object
4151552f7358SJed Brown . numPoints - The number of input points for the meet
4152552f7358SJed Brown - points - The input points
4153552f7358SJed Brown 
4154552f7358SJed Brown   Output Parameters:
4155552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4156552f7358SJed Brown - coveredPoints - The points in the meet
4157552f7358SJed Brown 
4158552f7358SJed Brown   Level: intermediate
4159552f7358SJed Brown 
41603813dfbdSMatthew G Knepley   Fortran Notes:
41613813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
41623813dfbdSMatthew G Knepley   include petsc.h90 in your code.
41633813dfbdSMatthew G Knepley 
41643813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
41653813dfbdSMatthew G Knepley 
4166552f7358SJed Brown .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin()
4167552f7358SJed Brown @*/
4168552f7358SJed Brown PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4169552f7358SJed Brown {
4170552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
4171552f7358SJed Brown   PetscInt      *offsets, **closures;
4172552f7358SJed Brown   PetscInt      *meet[2];
4173552f7358SJed Brown   PetscInt       height = 0, maxSize, meetSize = 0, i = 0;
417424c766afSToby Isaac   PetscInt       p, h, c, m, mc;
4175552f7358SJed Brown   PetscErrorCode ierr;
4176552f7358SJed Brown 
4177552f7358SJed Brown   PetscFunctionBegin;
4178552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4179064a246eSJacob Faibussowitsch   PetscValidPointer(points, 3);
4180064a246eSJacob Faibussowitsch   PetscValidPointer(numCoveredPoints, 4);
4181064a246eSJacob Faibussowitsch   PetscValidPointer(coveredPoints, 5);
4182552f7358SJed Brown 
4183552f7358SJed Brown   ierr    = DMPlexGetDepth(dm, &height);CHKERRQ(ierr);
4184785e854fSJed Brown   ierr    = PetscMalloc1(numPoints, &closures);CHKERRQ(ierr);
418569291d52SBarry Smith   ierr    = DMGetWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets);CHKERRQ(ierr);
418624c766afSToby Isaac   mc      = mesh->maxConeSize;
418724c766afSToby Isaac   maxSize = (mc > 1) ? ((PetscPowInt(mc,height+1)-1)/(mc-1)) : height + 1;
418869291d52SBarry Smith   ierr    = DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0]);CHKERRQ(ierr);
418969291d52SBarry Smith   ierr    = DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1]);CHKERRQ(ierr);
4190552f7358SJed Brown 
4191552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
4192552f7358SJed Brown     PetscInt closureSize;
4193552f7358SJed Brown 
4194552f7358SJed Brown     ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr);
41950d644c17SKarl Rupp 
4196552f7358SJed Brown     offsets[p*(height+2)+0] = 0;
4197552f7358SJed Brown     for (h = 0; h < height+1; ++h) {
4198552f7358SJed Brown       PetscInt pStart, pEnd, i;
4199552f7358SJed Brown 
4200552f7358SJed Brown       ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr);
4201552f7358SJed Brown       for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) {
4202552f7358SJed Brown         if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) {
4203552f7358SJed Brown           offsets[p*(height+2)+h+1] = i;
4204552f7358SJed Brown           break;
4205552f7358SJed Brown         }
4206552f7358SJed Brown       }
4207552f7358SJed Brown       if (i == closureSize) offsets[p*(height+2)+h+1] = i;
4208552f7358SJed Brown     }
420982f516ccSBarry Smith     if (offsets[p*(height+2)+height+1] != closureSize) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(height+2)+height+1], closureSize);
4210552f7358SJed Brown   }
4211552f7358SJed Brown   for (h = 0; h < height+1; ++h) {
4212552f7358SJed Brown     PetscInt dof;
4213552f7358SJed Brown 
4214552f7358SJed Brown     /* Copy in cone of first point */
4215552f7358SJed Brown     dof = offsets[h+1] - offsets[h];
4216552f7358SJed Brown     for (meetSize = 0; meetSize < dof; ++meetSize) {
4217552f7358SJed Brown       meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2];
4218552f7358SJed Brown     }
4219552f7358SJed Brown     /* Check each successive cone */
4220552f7358SJed Brown     for (p = 1; p < numPoints && meetSize; ++p) {
4221552f7358SJed Brown       PetscInt newMeetSize = 0;
4222552f7358SJed Brown 
4223552f7358SJed Brown       dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h];
4224552f7358SJed Brown       for (c = 0; c < dof; ++c) {
4225552f7358SJed Brown         const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2];
4226552f7358SJed Brown 
4227552f7358SJed Brown         for (m = 0; m < meetSize; ++m) {
4228552f7358SJed Brown           if (point == meet[i][m]) {
4229552f7358SJed Brown             meet[1-i][newMeetSize++] = point;
4230552f7358SJed Brown             break;
4231552f7358SJed Brown           }
4232552f7358SJed Brown         }
4233552f7358SJed Brown       }
4234552f7358SJed Brown       meetSize = newMeetSize;
4235552f7358SJed Brown       i        = 1-i;
4236552f7358SJed Brown     }
4237552f7358SJed Brown     if (meetSize) break;
4238552f7358SJed Brown   }
4239552f7358SJed Brown   *numCoveredPoints = meetSize;
4240552f7358SJed Brown   *coveredPoints    = meet[i];
4241552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
42420298fd71SBarry Smith     ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]);CHKERRQ(ierr);
4243552f7358SJed Brown   }
4244552f7358SJed Brown   ierr = PetscFree(closures);CHKERRQ(ierr);
424569291d52SBarry Smith   ierr = DMRestoreWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets);CHKERRQ(ierr);
424669291d52SBarry Smith   ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, MPIU_INT, &meet[1-i]);CHKERRQ(ierr);
4247552f7358SJed Brown   PetscFunctionReturn(0);
4248552f7358SJed Brown }
4249552f7358SJed Brown 
42504e3744c5SMatthew G. Knepley /*@C
42514e3744c5SMatthew G. Knepley   DMPlexEqual - Determine if two DMs have the same topology
42524e3744c5SMatthew G. Knepley 
42534e3744c5SMatthew G. Knepley   Not Collective
42544e3744c5SMatthew G. Knepley 
42554e3744c5SMatthew G. Knepley   Input Parameters:
42564e3744c5SMatthew G. Knepley + dmA - A DMPlex object
42574e3744c5SMatthew G. Knepley - dmB - A DMPlex object
42584e3744c5SMatthew G. Knepley 
42594e3744c5SMatthew G. Knepley   Output Parameters:
42604e3744c5SMatthew G. Knepley . equal - PETSC_TRUE if the topologies are identical
42614e3744c5SMatthew G. Knepley 
42624e3744c5SMatthew G. Knepley   Level: intermediate
42634e3744c5SMatthew G. Knepley 
42644e3744c5SMatthew G. Knepley   Notes:
42654e3744c5SMatthew G. Knepley   We are not solving graph isomorphism, so we do not permutation.
42664e3744c5SMatthew G. Knepley 
42674e3744c5SMatthew G. Knepley .seealso: DMPlexGetCone()
42684e3744c5SMatthew G. Knepley @*/
42694e3744c5SMatthew G. Knepley PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal)
42704e3744c5SMatthew G. Knepley {
42714e3744c5SMatthew G. Knepley   PetscInt       depth, depthB, pStart, pEnd, pStartB, pEndB, p;
42724e3744c5SMatthew G. Knepley   PetscErrorCode ierr;
42734e3744c5SMatthew G. Knepley 
42744e3744c5SMatthew G. Knepley   PetscFunctionBegin;
42754e3744c5SMatthew G. Knepley   PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
42764e3744c5SMatthew G. Knepley   PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
42774e3744c5SMatthew G. Knepley   PetscValidPointer(equal, 3);
42784e3744c5SMatthew G. Knepley 
42794e3744c5SMatthew G. Knepley   *equal = PETSC_FALSE;
42804e3744c5SMatthew G. Knepley   ierr = DMPlexGetDepth(dmA, &depth);CHKERRQ(ierr);
42814e3744c5SMatthew G. Knepley   ierr = DMPlexGetDepth(dmB, &depthB);CHKERRQ(ierr);
42824e3744c5SMatthew G. Knepley   if (depth != depthB) PetscFunctionReturn(0);
42834e3744c5SMatthew G. Knepley   ierr = DMPlexGetChart(dmA, &pStart,  &pEnd);CHKERRQ(ierr);
42844e3744c5SMatthew G. Knepley   ierr = DMPlexGetChart(dmB, &pStartB, &pEndB);CHKERRQ(ierr);
42854e3744c5SMatthew G. Knepley   if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(0);
42864e3744c5SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
42874e3744c5SMatthew G. Knepley     const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB;
42884e3744c5SMatthew G. Knepley     PetscInt        coneSize, coneSizeB, c, supportSize, supportSizeB, s;
42894e3744c5SMatthew G. Knepley 
42904e3744c5SMatthew G. Knepley     ierr = DMPlexGetConeSize(dmA, p, &coneSize);CHKERRQ(ierr);
42914e3744c5SMatthew G. Knepley     ierr = DMPlexGetCone(dmA, p, &cone);CHKERRQ(ierr);
42924e3744c5SMatthew G. Knepley     ierr = DMPlexGetConeOrientation(dmA, p, &ornt);CHKERRQ(ierr);
42934e3744c5SMatthew G. Knepley     ierr = DMPlexGetConeSize(dmB, p, &coneSizeB);CHKERRQ(ierr);
42944e3744c5SMatthew G. Knepley     ierr = DMPlexGetCone(dmB, p, &coneB);CHKERRQ(ierr);
42954e3744c5SMatthew G. Knepley     ierr = DMPlexGetConeOrientation(dmB, p, &orntB);CHKERRQ(ierr);
42964e3744c5SMatthew G. Knepley     if (coneSize != coneSizeB) PetscFunctionReturn(0);
42974e3744c5SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
42984e3744c5SMatthew G. Knepley       if (cone[c] != coneB[c]) PetscFunctionReturn(0);
42994e3744c5SMatthew G. Knepley       if (ornt[c] != orntB[c]) PetscFunctionReturn(0);
43004e3744c5SMatthew G. Knepley     }
43014e3744c5SMatthew G. Knepley     ierr = DMPlexGetSupportSize(dmA, p, &supportSize);CHKERRQ(ierr);
43024e3744c5SMatthew G. Knepley     ierr = DMPlexGetSupport(dmA, p, &support);CHKERRQ(ierr);
43034e3744c5SMatthew G. Knepley     ierr = DMPlexGetSupportSize(dmB, p, &supportSizeB);CHKERRQ(ierr);
43044e3744c5SMatthew G. Knepley     ierr = DMPlexGetSupport(dmB, p, &supportB);CHKERRQ(ierr);
43054e3744c5SMatthew G. Knepley     if (supportSize != supportSizeB) PetscFunctionReturn(0);
43064e3744c5SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
43074e3744c5SMatthew G. Knepley       if (support[s] != supportB[s]) PetscFunctionReturn(0);
43084e3744c5SMatthew G. Knepley     }
43094e3744c5SMatthew G. Knepley   }
43104e3744c5SMatthew G. Knepley   *equal = PETSC_TRUE;
43114e3744c5SMatthew G. Knepley   PetscFunctionReturn(0);
43124e3744c5SMatthew G. Knepley }
43134e3744c5SMatthew G. Knepley 
43147cd05799SMatthew G. Knepley /*@C
43157cd05799SMatthew G. Knepley   DMPlexGetNumFaceVertices - Returns the number of vertices on a face
43167cd05799SMatthew G. Knepley 
43177cd05799SMatthew G. Knepley   Not Collective
43187cd05799SMatthew G. Knepley 
43197cd05799SMatthew G. Knepley   Input Parameters:
43207cd05799SMatthew G. Knepley + dm         - The DMPlex
43217cd05799SMatthew G. Knepley . cellDim    - The cell dimension
43227cd05799SMatthew G. Knepley - numCorners - The number of vertices on a cell
43237cd05799SMatthew G. Knepley 
43247cd05799SMatthew G. Knepley   Output Parameters:
43257cd05799SMatthew G. Knepley . numFaceVertices - The number of vertices on a face
43267cd05799SMatthew G. Knepley 
43277cd05799SMatthew G. Knepley   Level: developer
43287cd05799SMatthew G. Knepley 
43297cd05799SMatthew G. Knepley   Notes:
43307cd05799SMatthew G. Knepley   Of course this can only work for a restricted set of symmetric shapes
43317cd05799SMatthew G. Knepley 
43327cd05799SMatthew G. Knepley .seealso: DMPlexGetCone()
43337cd05799SMatthew G. Knepley @*/
433418ad9376SMatthew G. Knepley PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices)
4335a6dfd86eSKarl Rupp {
433682f516ccSBarry Smith   MPI_Comm       comm;
4337552f7358SJed Brown   PetscErrorCode ierr;
4338552f7358SJed Brown 
4339552f7358SJed Brown   PetscFunctionBegin;
434082f516ccSBarry Smith   ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr);
4341064a246eSJacob Faibussowitsch   PetscValidPointer(numFaceVertices,4);
4342552f7358SJed Brown   switch (cellDim) {
4343552f7358SJed Brown   case 0:
4344552f7358SJed Brown     *numFaceVertices = 0;
4345552f7358SJed Brown     break;
4346552f7358SJed Brown   case 1:
4347552f7358SJed Brown     *numFaceVertices = 1;
4348552f7358SJed Brown     break;
4349552f7358SJed Brown   case 2:
4350552f7358SJed Brown     switch (numCorners) {
435119436ca2SJed Brown     case 3: /* triangle */
435219436ca2SJed Brown       *numFaceVertices = 2; /* Edge has 2 vertices */
4353552f7358SJed Brown       break;
435419436ca2SJed Brown     case 4: /* quadrilateral */
435519436ca2SJed Brown       *numFaceVertices = 2; /* Edge has 2 vertices */
4356552f7358SJed Brown       break;
435719436ca2SJed Brown     case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */
435819436ca2SJed Brown       *numFaceVertices = 3; /* Edge has 3 vertices */
4359552f7358SJed Brown       break;
436019436ca2SJed Brown     case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */
436119436ca2SJed Brown       *numFaceVertices = 3; /* Edge has 3 vertices */
4362552f7358SJed Brown       break;
4363552f7358SJed Brown     default:
4364f347f43bSBarry Smith       SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim);
4365552f7358SJed Brown     }
4366552f7358SJed Brown     break;
4367552f7358SJed Brown   case 3:
4368552f7358SJed Brown     switch (numCorners) {
436919436ca2SJed Brown     case 4: /* tetradehdron */
437019436ca2SJed Brown       *numFaceVertices = 3; /* Face has 3 vertices */
4371552f7358SJed Brown       break;
437219436ca2SJed Brown     case 6: /* tet cohesive cells */
437319436ca2SJed Brown       *numFaceVertices = 4; /* Face has 4 vertices */
4374552f7358SJed Brown       break;
437519436ca2SJed Brown     case 8: /* hexahedron */
437619436ca2SJed Brown       *numFaceVertices = 4; /* Face has 4 vertices */
4377552f7358SJed Brown       break;
437819436ca2SJed Brown     case 9: /* tet cohesive Lagrange cells */
437919436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4380552f7358SJed Brown       break;
438119436ca2SJed Brown     case 10: /* quadratic tetrahedron */
438219436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4383552f7358SJed Brown       break;
438419436ca2SJed Brown     case 12: /* hex cohesive Lagrange cells */
438519436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4386552f7358SJed Brown       break;
438719436ca2SJed Brown     case 18: /* quadratic tet cohesive Lagrange cells */
438819436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4389552f7358SJed Brown       break;
439019436ca2SJed Brown     case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */
439119436ca2SJed Brown       *numFaceVertices = 9; /* Face has 9 vertices */
4392552f7358SJed Brown       break;
4393552f7358SJed Brown     default:
4394f347f43bSBarry Smith       SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim);
4395552f7358SJed Brown     }
4396552f7358SJed Brown     break;
4397552f7358SJed Brown   default:
4398f347f43bSBarry Smith     SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %D", cellDim);
4399552f7358SJed Brown   }
4400552f7358SJed Brown   PetscFunctionReturn(0);
4401552f7358SJed Brown }
4402552f7358SJed Brown 
4403552f7358SJed Brown /*@
4404aa50250dSMatthew G. Knepley   DMPlexGetDepthLabel - Get the DMLabel recording the depth of each point
4405552f7358SJed Brown 
4406552f7358SJed Brown   Not Collective
4407552f7358SJed Brown 
4408aa50250dSMatthew G. Knepley   Input Parameter:
4409552f7358SJed Brown . dm    - The DMPlex object
4410552f7358SJed Brown 
4411aa50250dSMatthew G. Knepley   Output Parameter:
4412aa50250dSMatthew G. Knepley . depthLabel - The DMLabel recording point depth
4413552f7358SJed Brown 
4414552f7358SJed Brown   Level: developer
4415552f7358SJed Brown 
4416dc287ab2SVaclav Hapla .seealso: DMPlexGetDepth(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum(), DMPlexGetPointDepth(),
4417aa50250dSMatthew G. Knepley @*/
4418aa50250dSMatthew G. Knepley PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel)
4419aa50250dSMatthew G. Knepley {
4420aa50250dSMatthew G. Knepley   PetscFunctionBegin;
4421aa50250dSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4422aa50250dSMatthew G. Knepley   PetscValidPointer(depthLabel, 2);
4423c58f1c22SToby Isaac   *depthLabel = dm->depthLabel;
4424aa50250dSMatthew G. Knepley   PetscFunctionReturn(0);
4425aa50250dSMatthew G. Knepley }
4426aa50250dSMatthew G. Knepley 
4427aa50250dSMatthew G. Knepley /*@
4428aa50250dSMatthew G. Knepley   DMPlexGetDepth - Get the depth of the DAG representing this mesh
4429aa50250dSMatthew G. Knepley 
4430aa50250dSMatthew G. Knepley   Not Collective
4431aa50250dSMatthew G. Knepley 
4432aa50250dSMatthew G. Knepley   Input Parameter:
4433aa50250dSMatthew G. Knepley . dm    - The DMPlex object
4434aa50250dSMatthew G. Knepley 
4435aa50250dSMatthew G. Knepley   Output Parameter:
4436aa50250dSMatthew G. Knepley . depth - The number of strata (breadth first levels) in the DAG
4437aa50250dSMatthew G. Knepley 
4438aa50250dSMatthew G. Knepley   Level: developer
4439552f7358SJed Brown 
4440b1bb481bSMatthew Knepley   Notes:
4441b1bb481bSMatthew Knepley   This returns maximum of point depths over all points, i.e. maximum value of the label returned by DMPlexGetDepthLabel().
4442dc287ab2SVaclav Hapla   The point depth is described more in detail in DMPlexGetDepthStratum().
4443dc287ab2SVaclav Hapla   An empty mesh gives -1.
4444b1bb481bSMatthew Knepley 
4445dc287ab2SVaclav Hapla .seealso: DMPlexGetDepthLabel(), DMPlexGetDepthStratum(), DMPlexGetPointDepth(), DMPlexSymmetrize()
4446552f7358SJed Brown @*/
4447552f7358SJed Brown PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth)
4448552f7358SJed Brown {
4449aa50250dSMatthew G. Knepley   DMLabel        label;
4450aa50250dSMatthew G. Knepley   PetscInt       d = 0;
4451552f7358SJed Brown   PetscErrorCode ierr;
4452552f7358SJed Brown 
4453552f7358SJed Brown   PetscFunctionBegin;
4454552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4455552f7358SJed Brown   PetscValidPointer(depth, 2);
4456aa50250dSMatthew G. Knepley   ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr);
4457aa50250dSMatthew G. Knepley   if (label) {ierr = DMLabelGetNumValues(label, &d);CHKERRQ(ierr);}
4458552f7358SJed Brown   *depth = d-1;
4459552f7358SJed Brown   PetscFunctionReturn(0);
4460552f7358SJed Brown }
4461552f7358SJed Brown 
4462552f7358SJed Brown /*@
4463552f7358SJed Brown   DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth.
4464552f7358SJed Brown 
4465552f7358SJed Brown   Not Collective
4466552f7358SJed Brown 
4467552f7358SJed Brown   Input Parameters:
4468552f7358SJed Brown + dm           - The DMPlex object
4469552f7358SJed Brown - stratumValue - The requested depth
4470552f7358SJed Brown 
4471552f7358SJed Brown   Output Parameters:
4472552f7358SJed Brown + start - The first point at this depth
4473552f7358SJed Brown - end   - One beyond the last point at this depth
4474552f7358SJed Brown 
4475647867b2SJed Brown   Notes:
4476647867b2SJed Brown   Depth indexing is related to topological dimension.  Depth stratum 0 contains the lowest topological dimension points,
4477647867b2SJed Brown   often "vertices".  If the mesh is "interpolated" (see DMPlexInterpolate()), then depth stratum 1 contains the next
4478647867b2SJed Brown   higher dimension, e.g., "edges".
4479647867b2SJed Brown 
4480552f7358SJed Brown   Level: developer
4481552f7358SJed Brown 
4482dc287ab2SVaclav Hapla .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth(), DMPlexGetDepthLabel(), DMPlexGetPointDepth(), DMPlexSymmetrize(), DMPlexInterpolate()
4483552f7358SJed Brown @*/
44840adebc6cSBarry Smith PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end)
44850adebc6cSBarry Smith {
4486aa50250dSMatthew G. Knepley   DMLabel        label;
448763d1a920SMatthew G. Knepley   PetscInt       pStart, pEnd;
4488552f7358SJed Brown   PetscErrorCode ierr;
4489552f7358SJed Brown 
4490552f7358SJed Brown   PetscFunctionBegin;
4491552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
449263d1a920SMatthew G. Knepley   if (start) {PetscValidPointer(start, 3); *start = 0;}
449363d1a920SMatthew G. Knepley   if (end)   {PetscValidPointer(end,   4); *end   = 0;}
4494552f7358SJed Brown   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
44950d644c17SKarl Rupp   if (pStart == pEnd) PetscFunctionReturn(0);
449663d1a920SMatthew G. Knepley   if (stratumValue < 0) {
449763d1a920SMatthew G. Knepley     if (start) *start = pStart;
449863d1a920SMatthew G. Knepley     if (end)   *end   = pEnd;
449963d1a920SMatthew G. Knepley     PetscFunctionReturn(0);
4500552f7358SJed Brown   }
4501aa50250dSMatthew G. Knepley   ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr);
450263d1a920SMatthew G. Knepley   if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");
450363d1a920SMatthew G. Knepley   ierr = DMLabelGetStratumBounds(label, stratumValue, start, end);CHKERRQ(ierr);
4504552f7358SJed Brown   PetscFunctionReturn(0);
4505552f7358SJed Brown }
4506552f7358SJed Brown 
4507552f7358SJed Brown /*@
4508552f7358SJed Brown   DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height.
4509552f7358SJed Brown 
4510552f7358SJed Brown   Not Collective
4511552f7358SJed Brown 
4512552f7358SJed Brown   Input Parameters:
4513552f7358SJed Brown + dm           - The DMPlex object
4514552f7358SJed Brown - stratumValue - The requested height
4515552f7358SJed Brown 
4516552f7358SJed Brown   Output Parameters:
4517552f7358SJed Brown + start - The first point at this height
4518552f7358SJed Brown - end   - One beyond the last point at this height
4519552f7358SJed Brown 
4520647867b2SJed Brown   Notes:
4521647867b2SJed Brown   Height indexing is related to topological codimension.  Height stratum 0 contains the highest topological dimension
4522647867b2SJed Brown   points, often called "cells" or "elements".  If the mesh is "interpolated" (see DMPlexInterpolate()), then height
4523647867b2SJed Brown   stratum 1 contains the boundary of these "cells", often called "faces" or "facets".
4524647867b2SJed Brown 
4525552f7358SJed Brown   Level: developer
4526552f7358SJed Brown 
45273dc9a465SVaclav Hapla .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth(), DMPlexGetPointHeight()
4528552f7358SJed Brown @*/
45290adebc6cSBarry Smith PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end)
45300adebc6cSBarry Smith {
4531aa50250dSMatthew G. Knepley   DMLabel        label;
453263d1a920SMatthew G. Knepley   PetscInt       depth, pStart, pEnd;
4533552f7358SJed Brown   PetscErrorCode ierr;
4534552f7358SJed Brown 
4535552f7358SJed Brown   PetscFunctionBegin;
4536552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
453763d1a920SMatthew G. Knepley   if (start) {PetscValidPointer(start, 3); *start = 0;}
453863d1a920SMatthew G. Knepley   if (end)   {PetscValidPointer(end,   4); *end   = 0;}
4539552f7358SJed Brown   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
45400d644c17SKarl Rupp   if (pStart == pEnd) PetscFunctionReturn(0);
454163d1a920SMatthew G. Knepley   if (stratumValue < 0) {
454263d1a920SMatthew G. Knepley     if (start) *start = pStart;
454363d1a920SMatthew G. Knepley     if (end)   *end   = pEnd;
454463d1a920SMatthew G. Knepley     PetscFunctionReturn(0);
4545552f7358SJed Brown   }
4546aa50250dSMatthew G. Knepley   ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr);
454713903a91SSatish Balay   if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");
454863d1a920SMatthew G. Knepley   ierr = DMLabelGetNumValues(label, &depth);CHKERRQ(ierr);
454963d1a920SMatthew G. Knepley   ierr = DMLabelGetStratumBounds(label, depth-1-stratumValue, start, end);CHKERRQ(ierr);
4550552f7358SJed Brown   PetscFunctionReturn(0);
4551552f7358SJed Brown }
4552552f7358SJed Brown 
4553ba2698f1SMatthew G. Knepley /*@
4554ba2698f1SMatthew G. Knepley   DMPlexGetPointDepth - Get the depth of a given point
4555ba2698f1SMatthew G. Knepley 
4556ba2698f1SMatthew G. Knepley   Not Collective
4557ba2698f1SMatthew G. Knepley 
4558ba2698f1SMatthew G. Knepley   Input Parameter:
4559ba2698f1SMatthew G. Knepley + dm    - The DMPlex object
4560ba2698f1SMatthew G. Knepley - point - The point
4561ba2698f1SMatthew G. Knepley 
4562ba2698f1SMatthew G. Knepley   Output Parameter:
4563ba2698f1SMatthew G. Knepley . depth - The depth of the point
4564ba2698f1SMatthew G. Knepley 
4565ba2698f1SMatthew G. Knepley   Level: intermediate
4566ba2698f1SMatthew G. Knepley 
45673dc9a465SVaclav Hapla .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexGetPointHeight()
4568ba2698f1SMatthew G. Knepley @*/
4569ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth)
4570ba2698f1SMatthew G. Knepley {
4571ba2698f1SMatthew G. Knepley   PetscErrorCode ierr;
4572ba2698f1SMatthew G. Knepley 
4573ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
4574ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
457540a2aa30SMatthew G. Knepley   PetscValidIntPointer(depth, 3);
4576ba2698f1SMatthew G. Knepley   ierr = DMLabelGetValue(dm->depthLabel, point, depth);CHKERRQ(ierr);
4577ba2698f1SMatthew G. Knepley   PetscFunctionReturn(0);
4578ba2698f1SMatthew G. Knepley }
4579ba2698f1SMatthew G. Knepley 
4580ba2698f1SMatthew G. Knepley /*@
45810c0a32dcSVaclav Hapla   DMPlexGetPointHeight - Get the height of a given point
45820c0a32dcSVaclav Hapla 
45830c0a32dcSVaclav Hapla   Not Collective
45840c0a32dcSVaclav Hapla 
45850c0a32dcSVaclav Hapla   Input Parameter:
45860c0a32dcSVaclav Hapla + dm    - The DMPlex object
45870c0a32dcSVaclav Hapla - point - The point
45880c0a32dcSVaclav Hapla 
45890c0a32dcSVaclav Hapla   Output Parameter:
45900c0a32dcSVaclav Hapla . height - The height of the point
45910c0a32dcSVaclav Hapla 
45920c0a32dcSVaclav Hapla   Level: intermediate
45930c0a32dcSVaclav Hapla 
45943dc9a465SVaclav Hapla .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexGetPointDepth()
45950c0a32dcSVaclav Hapla @*/
45960c0a32dcSVaclav Hapla PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height)
45970c0a32dcSVaclav Hapla {
45980c0a32dcSVaclav Hapla   PetscInt       n, pDepth;
45990c0a32dcSVaclav Hapla   PetscErrorCode ierr;
46000c0a32dcSVaclav Hapla 
46010c0a32dcSVaclav Hapla   PetscFunctionBegin;
46020c0a32dcSVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
46030c0a32dcSVaclav Hapla   PetscValidIntPointer(height, 3);
46040c0a32dcSVaclav Hapla   ierr = DMLabelGetNumValues(dm->depthLabel, &n);CHKERRQ(ierr);
46050c0a32dcSVaclav Hapla   ierr = DMLabelGetValue(dm->depthLabel, point, &pDepth);CHKERRQ(ierr);
46060c0a32dcSVaclav Hapla   *height = n - 1 - pDepth;  /* DAG depth is n-1 */
46070c0a32dcSVaclav Hapla   PetscFunctionReturn(0);
46080c0a32dcSVaclav Hapla }
46090c0a32dcSVaclav Hapla 
46100c0a32dcSVaclav Hapla /*@
4611ba2698f1SMatthew G. Knepley   DMPlexGetCellTypeLabel - Get the DMLabel recording the polytope type of each cell
4612ba2698f1SMatthew G. Knepley 
4613ba2698f1SMatthew G. Knepley   Not Collective
4614ba2698f1SMatthew G. Knepley 
4615ba2698f1SMatthew G. Knepley   Input Parameter:
4616ba2698f1SMatthew G. Knepley . dm - The DMPlex object
4617ba2698f1SMatthew G. Knepley 
4618ba2698f1SMatthew G. Knepley   Output Parameter:
4619ba2698f1SMatthew G. Knepley . celltypeLabel - The DMLabel recording cell polytope type
4620ba2698f1SMatthew G. Knepley 
4621412e9a14SMatthew G. Knepley   Note: This function will trigger automatica computation of cell types. This can be disabled by calling
4622412e9a14SMatthew G. Knepley   DMCreateLabel(dm, "celltype") beforehand.
4623412e9a14SMatthew G. Knepley 
4624ba2698f1SMatthew G. Knepley   Level: developer
4625ba2698f1SMatthew G. Knepley 
4626dc287ab2SVaclav Hapla .seealso: DMPlexGetCellType(), DMPlexGetDepthLabel(), DMCreateLabel()
4627ba2698f1SMatthew G. Knepley @*/
4628ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel)
4629ba2698f1SMatthew G. Knepley {
4630ba2698f1SMatthew G. Knepley   PetscErrorCode ierr;
4631ba2698f1SMatthew G. Knepley 
4632ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
4633ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4634ba2698f1SMatthew G. Knepley   PetscValidPointer(celltypeLabel, 2);
4635ba2698f1SMatthew G. Knepley   if (!dm->celltypeLabel) {ierr = DMPlexComputeCellTypes(dm);CHKERRQ(ierr);}
4636ba2698f1SMatthew G. Knepley   *celltypeLabel = dm->celltypeLabel;
4637ba2698f1SMatthew G. Knepley   PetscFunctionReturn(0);
4638ba2698f1SMatthew G. Knepley }
4639ba2698f1SMatthew G. Knepley 
4640ba2698f1SMatthew G. Knepley /*@
4641ba2698f1SMatthew G. Knepley   DMPlexGetCellType - Get the polytope type of a given cell
4642ba2698f1SMatthew G. Knepley 
4643ba2698f1SMatthew G. Knepley   Not Collective
4644ba2698f1SMatthew G. Knepley 
4645ba2698f1SMatthew G. Knepley   Input Parameter:
4646ba2698f1SMatthew G. Knepley + dm   - The DMPlex object
4647ba2698f1SMatthew G. Knepley - cell - The cell
4648ba2698f1SMatthew G. Knepley 
4649ba2698f1SMatthew G. Knepley   Output Parameter:
4650ba2698f1SMatthew G. Knepley . celltype - The polytope type of the cell
4651ba2698f1SMatthew G. Knepley 
4652ba2698f1SMatthew G. Knepley   Level: intermediate
4653ba2698f1SMatthew G. Knepley 
4654ba2698f1SMatthew G. Knepley .seealso: DMPlexGetCellTypeLabel(), DMPlexGetDepthLabel(), DMPlexGetDepth()
4655ba2698f1SMatthew G. Knepley @*/
4656ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype)
4657ba2698f1SMatthew G. Knepley {
4658ba2698f1SMatthew G. Knepley   DMLabel        label;
4659ba2698f1SMatthew G. Knepley   PetscInt       ct;
4660ba2698f1SMatthew G. Knepley   PetscErrorCode ierr;
4661ba2698f1SMatthew G. Knepley 
4662ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
4663ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4664ba2698f1SMatthew G. Knepley   PetscValidPointer(celltype, 3);
4665ba2698f1SMatthew G. Knepley   ierr = DMPlexGetCellTypeLabel(dm, &label);CHKERRQ(ierr);
4666ba2698f1SMatthew G. Knepley   ierr = DMLabelGetValue(label, cell, &ct);CHKERRQ(ierr);
46674a7ee7d0SMatthew G. Knepley   if (ct < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %D has not been assigned a cell type", cell);
4668ba2698f1SMatthew G. Knepley   *celltype = (DMPolytopeType) ct;
4669ba2698f1SMatthew G. Knepley   PetscFunctionReturn(0);
4670ba2698f1SMatthew G. Knepley }
4671ba2698f1SMatthew G. Knepley 
4672412e9a14SMatthew G. Knepley /*@
4673412e9a14SMatthew G. Knepley   DMPlexSetCellType - Set the polytope type of a given cell
4674412e9a14SMatthew G. Knepley 
4675412e9a14SMatthew G. Knepley   Not Collective
4676412e9a14SMatthew G. Knepley 
4677412e9a14SMatthew G. Knepley   Input Parameters:
4678412e9a14SMatthew G. Knepley + dm   - The DMPlex object
4679412e9a14SMatthew G. Knepley . cell - The cell
4680412e9a14SMatthew G. Knepley - celltype - The polytope type of the cell
4681412e9a14SMatthew G. Knepley 
4682412e9a14SMatthew G. Knepley   Note: By default, cell types will be automatically computed using DMPlexComputeCellTypes() before this function
4683412e9a14SMatthew G. Knepley   is executed. This function will override the computed type. However, if automatic classification will not succeed
4684412e9a14SMatthew G. Knepley   and a user wants to manually specify all types, the classification must be disabled by calling
4685412e9a14SMatthew G. Knepley   DMCreaateLabel(dm, "celltype") before getting or setting any cell types.
4686412e9a14SMatthew G. Knepley 
4687412e9a14SMatthew G. Knepley   Level: advanced
4688412e9a14SMatthew G. Knepley 
4689412e9a14SMatthew G. Knepley .seealso: DMPlexGetCellTypeLabel(), DMPlexGetDepthLabel(), DMPlexGetDepth(), DMPlexComputeCellTypes(), DMCreateLabel()
4690412e9a14SMatthew G. Knepley @*/
4691412e9a14SMatthew G. Knepley PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype)
4692412e9a14SMatthew G. Knepley {
4693412e9a14SMatthew G. Knepley   DMLabel        label;
4694412e9a14SMatthew G. Knepley   PetscErrorCode ierr;
4695412e9a14SMatthew G. Knepley 
4696412e9a14SMatthew G. Knepley   PetscFunctionBegin;
4697412e9a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4698412e9a14SMatthew G. Knepley   ierr = DMPlexGetCellTypeLabel(dm, &label);CHKERRQ(ierr);
4699412e9a14SMatthew G. Knepley   ierr = DMLabelSetValue(label, cell, celltype);CHKERRQ(ierr);
4700412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
4701412e9a14SMatthew G. Knepley }
4702412e9a14SMatthew G. Knepley 
47030adebc6cSBarry Smith PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm)
47040adebc6cSBarry Smith {
4705efe440bfSMatthew G. Knepley   PetscSection   section, s;
4706efe440bfSMatthew G. Knepley   Mat            m;
47073e922f36SToby Isaac   PetscInt       maxHeight;
4708552f7358SJed Brown   PetscErrorCode ierr;
4709552f7358SJed Brown 
4710552f7358SJed Brown   PetscFunctionBegin;
471138221697SMatthew G. Knepley   ierr = DMClone(dm, cdm);CHKERRQ(ierr);
47123e922f36SToby Isaac   ierr = DMPlexGetMaxProjectionHeight(dm, &maxHeight);CHKERRQ(ierr);
47133e922f36SToby Isaac   ierr = DMPlexSetMaxProjectionHeight(*cdm, maxHeight);CHKERRQ(ierr);
471482f516ccSBarry Smith   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section);CHKERRQ(ierr);
471592fd8e1eSJed Brown   ierr = DMSetLocalSection(*cdm, section);CHKERRQ(ierr);
47161d799100SJed Brown   ierr = PetscSectionDestroy(&section);CHKERRQ(ierr);
4717efe440bfSMatthew G. Knepley   ierr = PetscSectionCreate(PETSC_COMM_SELF, &s);CHKERRQ(ierr);
4718efe440bfSMatthew G. Knepley   ierr = MatCreate(PETSC_COMM_SELF, &m);CHKERRQ(ierr);
4719efe440bfSMatthew G. Knepley   ierr = DMSetDefaultConstraints(*cdm, s, m);CHKERRQ(ierr);
4720efe440bfSMatthew G. Knepley   ierr = PetscSectionDestroy(&s);CHKERRQ(ierr);
4721efe440bfSMatthew G. Knepley   ierr = MatDestroy(&m);CHKERRQ(ierr);
47228f4c458bSMatthew G. Knepley 
47238f4c458bSMatthew G. Knepley   ierr = DMSetNumFields(*cdm, 1);CHKERRQ(ierr);
47248f4c458bSMatthew G. Knepley   ierr = DMCreateDS(*cdm);CHKERRQ(ierr);
4725552f7358SJed Brown   PetscFunctionReturn(0);
4726552f7358SJed Brown }
4727552f7358SJed Brown 
4728f19dbd58SToby Isaac PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field)
4729f19dbd58SToby Isaac {
4730f19dbd58SToby Isaac   Vec            coordsLocal;
4731f19dbd58SToby Isaac   DM             coordsDM;
4732f19dbd58SToby Isaac   PetscErrorCode ierr;
4733f19dbd58SToby Isaac 
4734f19dbd58SToby Isaac   PetscFunctionBegin;
4735f19dbd58SToby Isaac   *field = NULL;
4736f19dbd58SToby Isaac   ierr = DMGetCoordinatesLocal(dm,&coordsLocal);CHKERRQ(ierr);
4737f19dbd58SToby Isaac   ierr = DMGetCoordinateDM(dm,&coordsDM);CHKERRQ(ierr);
4738f19dbd58SToby Isaac   if (coordsLocal && coordsDM) {
4739f19dbd58SToby Isaac     ierr = DMFieldCreateDS(coordsDM, 0, coordsLocal, field);CHKERRQ(ierr);
4740f19dbd58SToby Isaac   }
4741f19dbd58SToby Isaac   PetscFunctionReturn(0);
4742f19dbd58SToby Isaac }
4743f19dbd58SToby Isaac 
47447cd05799SMatthew G. Knepley /*@C
47457cd05799SMatthew G. Knepley   DMPlexGetConeSection - Return a section which describes the layout of cone data
47467cd05799SMatthew G. Knepley 
47477cd05799SMatthew G. Knepley   Not Collective
47487cd05799SMatthew G. Knepley 
47497cd05799SMatthew G. Knepley   Input Parameters:
47507cd05799SMatthew G. Knepley . dm        - The DMPlex object
47517cd05799SMatthew G. Knepley 
47527cd05799SMatthew G. Knepley   Output Parameter:
47537cd05799SMatthew G. Knepley . section - The PetscSection object
47547cd05799SMatthew G. Knepley 
47557cd05799SMatthew G. Knepley   Level: developer
47567cd05799SMatthew G. Knepley 
47577cd05799SMatthew G. Knepley .seealso: DMPlexGetSupportSection(), DMPlexGetCones(), DMPlexGetConeOrientations()
47587cd05799SMatthew G. Knepley @*/
47590adebc6cSBarry Smith PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section)
47600adebc6cSBarry Smith {
4761552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
4762552f7358SJed Brown 
4763552f7358SJed Brown   PetscFunctionBegin;
4764552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4765552f7358SJed Brown   if (section) *section = mesh->coneSection;
4766552f7358SJed Brown   PetscFunctionReturn(0);
4767552f7358SJed Brown }
4768552f7358SJed Brown 
47697cd05799SMatthew G. Knepley /*@C
47707cd05799SMatthew G. Knepley   DMPlexGetSupportSection - Return a section which describes the layout of support data
47717cd05799SMatthew G. Knepley 
47727cd05799SMatthew G. Knepley   Not Collective
47737cd05799SMatthew G. Knepley 
47747cd05799SMatthew G. Knepley   Input Parameters:
47757cd05799SMatthew G. Knepley . dm        - The DMPlex object
47767cd05799SMatthew G. Knepley 
47777cd05799SMatthew G. Knepley   Output Parameter:
47787cd05799SMatthew G. Knepley . section - The PetscSection object
47797cd05799SMatthew G. Knepley 
47807cd05799SMatthew G. Knepley   Level: developer
47817cd05799SMatthew G. Knepley 
47827cd05799SMatthew G. Knepley .seealso: DMPlexGetConeSection()
47837cd05799SMatthew G. Knepley @*/
47848cb4d582SMatthew G. Knepley PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section)
47858cb4d582SMatthew G. Knepley {
47868cb4d582SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
47878cb4d582SMatthew G. Knepley 
47888cb4d582SMatthew G. Knepley   PetscFunctionBegin;
47898cb4d582SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
47908cb4d582SMatthew G. Knepley   if (section) *section = mesh->supportSection;
47918cb4d582SMatthew G. Knepley   PetscFunctionReturn(0);
47928cb4d582SMatthew G. Knepley }
47938cb4d582SMatthew G. Knepley 
47947cd05799SMatthew G. Knepley /*@C
47957cd05799SMatthew G. Knepley   DMPlexGetCones - Return cone data
47967cd05799SMatthew G. Knepley 
47977cd05799SMatthew G. Knepley   Not Collective
47987cd05799SMatthew G. Knepley 
47997cd05799SMatthew G. Knepley   Input Parameters:
48007cd05799SMatthew G. Knepley . dm        - The DMPlex object
48017cd05799SMatthew G. Knepley 
48027cd05799SMatthew G. Knepley   Output Parameter:
48037cd05799SMatthew G. Knepley . cones - The cone for each point
48047cd05799SMatthew G. Knepley 
48057cd05799SMatthew G. Knepley   Level: developer
48067cd05799SMatthew G. Knepley 
48077cd05799SMatthew G. Knepley .seealso: DMPlexGetConeSection()
48087cd05799SMatthew G. Knepley @*/
4809a6dfd86eSKarl Rupp PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[])
4810a6dfd86eSKarl Rupp {
4811552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
4812552f7358SJed Brown 
4813552f7358SJed Brown   PetscFunctionBegin;
4814552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4815552f7358SJed Brown   if (cones) *cones = mesh->cones;
4816552f7358SJed Brown   PetscFunctionReturn(0);
4817552f7358SJed Brown }
4818552f7358SJed Brown 
48197cd05799SMatthew G. Knepley /*@C
48207cd05799SMatthew G. Knepley   DMPlexGetConeOrientations - Return cone orientation data
48217cd05799SMatthew G. Knepley 
48227cd05799SMatthew G. Knepley   Not Collective
48237cd05799SMatthew G. Knepley 
48247cd05799SMatthew G. Knepley   Input Parameters:
48257cd05799SMatthew G. Knepley . dm        - The DMPlex object
48267cd05799SMatthew G. Knepley 
48277cd05799SMatthew G. Knepley   Output Parameter:
48287cd05799SMatthew G. Knepley . coneOrientations - The cone orientation for each point
48297cd05799SMatthew G. Knepley 
48307cd05799SMatthew G. Knepley   Level: developer
48317cd05799SMatthew G. Knepley 
48327cd05799SMatthew G. Knepley .seealso: DMPlexGetConeSection()
48337cd05799SMatthew G. Knepley @*/
4834a6dfd86eSKarl Rupp PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[])
4835a6dfd86eSKarl Rupp {
4836552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
4837552f7358SJed Brown 
4838552f7358SJed Brown   PetscFunctionBegin;
4839552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4840552f7358SJed Brown   if (coneOrientations) *coneOrientations = mesh->coneOrientations;
4841552f7358SJed Brown   PetscFunctionReturn(0);
4842552f7358SJed Brown }
4843552f7358SJed Brown 
4844552f7358SJed Brown /******************************** FEM Support **********************************/
4845552f7358SJed Brown 
48469e8305c2SJed Brown /*
48479e8305c2SJed Brown  Returns number of components and tensor degree for the field.  For interpolated meshes, line should be a point
48489e8305c2SJed Brown  representing a line in the section.
48499e8305c2SJed Brown */
48509e8305c2SJed Brown static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(PetscSection section,PetscInt field,PetscInt line,PetscBool vertexchart,PetscInt *Nc,PetscInt *k)
48519e8305c2SJed Brown {
48529e8305c2SJed Brown   PetscErrorCode ierr;
48539e8305c2SJed Brown 
48549e8305c2SJed Brown   PetscFunctionBeginHot;
48559e8305c2SJed Brown   ierr = PetscSectionGetFieldComponents(section, field, Nc);CHKERRQ(ierr);
4856a433471fSStefano Zampini   if (line < 0) {
4857a433471fSStefano Zampini     *k = 0;
4858a433471fSStefano Zampini     *Nc = 0;
4859a433471fSStefano Zampini   } else if (vertexchart) {            /* If we only have a vertex chart, we must have degree k=1 */
48609e8305c2SJed Brown     *k = 1;
48619e8305c2SJed Brown   } else {                      /* Assume the full interpolated mesh is in the chart; lines in particular */
48629e8305c2SJed Brown     /* An order k SEM disc has k-1 dofs on an edge */
48639e8305c2SJed Brown     ierr = PetscSectionGetFieldDof(section, line, field, k);CHKERRQ(ierr);
48649e8305c2SJed Brown     *k = *k / *Nc + 1;
48659e8305c2SJed Brown   }
48669e8305c2SJed Brown   PetscFunctionReturn(0);
48679e8305c2SJed Brown }
48689e8305c2SJed Brown 
4869a4355906SMatthew Knepley /*@
4870bc1eb3faSJed Brown 
4871bc1eb3faSJed Brown   DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a
4872bc1eb3faSJed Brown   lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the
48731bb6d2a8SBarry Smith   section provided (or the section of the DM).
4874a4355906SMatthew Knepley 
4875a4355906SMatthew Knepley   Input Parameters:
4876a4355906SMatthew Knepley + dm      - The DM
4877a4355906SMatthew Knepley . point   - Either a cell (highest dim point) or an edge (dim 1 point), or PETSC_DETERMINE
4878a4355906SMatthew Knepley - section - The PetscSection to reorder, or NULL for the default section
4879a4355906SMatthew Knepley 
4880a4355906SMatthew Knepley   Note: The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial
4881a4355906SMatthew Knepley   degree of the basis.
4882a4355906SMatthew Knepley 
4883bc1eb3faSJed Brown   Example:
4884bc1eb3faSJed Brown   A typical interpolated single-quad mesh might order points as
4885bc1eb3faSJed Brown .vb
4886bc1eb3faSJed Brown   [c0, v1, v2, v3, v4, e5, e6, e7, e8]
4887bc1eb3faSJed Brown 
4888bc1eb3faSJed Brown   v4 -- e6 -- v3
4889bc1eb3faSJed Brown   |           |
4890bc1eb3faSJed Brown   e7    c0    e8
4891bc1eb3faSJed Brown   |           |
4892bc1eb3faSJed Brown   v1 -- e5 -- v2
4893bc1eb3faSJed Brown .ve
4894bc1eb3faSJed Brown 
4895bc1eb3faSJed Brown   (There is no significance to the ordering described here.)  The default section for a Q3 quad might typically assign
4896bc1eb3faSJed Brown   dofs in the order of points, e.g.,
4897bc1eb3faSJed Brown .vb
4898bc1eb3faSJed Brown     c0 -> [0,1,2,3]
4899bc1eb3faSJed Brown     v1 -> [4]
4900bc1eb3faSJed Brown     ...
4901bc1eb3faSJed Brown     e5 -> [8, 9]
4902bc1eb3faSJed Brown .ve
4903bc1eb3faSJed Brown 
4904bc1eb3faSJed Brown   which corresponds to the dofs
4905bc1eb3faSJed Brown .vb
4906bc1eb3faSJed Brown     6   10  11  7
4907bc1eb3faSJed Brown     13  2   3   15
4908bc1eb3faSJed Brown     12  0   1   14
4909bc1eb3faSJed Brown     4   8   9   5
4910bc1eb3faSJed Brown .ve
4911bc1eb3faSJed Brown 
4912bc1eb3faSJed Brown   The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering
4913bc1eb3faSJed Brown .vb
4914bc1eb3faSJed Brown   0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6
4915bc1eb3faSJed Brown .ve
4916bc1eb3faSJed Brown 
4917bc1eb3faSJed Brown   After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically,
4918bc1eb3faSJed Brown .vb
4919bc1eb3faSJed Brown    4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7
4920bc1eb3faSJed Brown .ve
4921bc1eb3faSJed Brown 
4922a4355906SMatthew Knepley   Level: developer
4923a4355906SMatthew Knepley 
49249df75925SJed Brown .seealso: DMGetLocalSection(), PetscSectionSetClosurePermutation(), DMSetGlobalSection()
4925a4355906SMatthew Knepley @*/
4926bc1eb3faSJed Brown PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section)
49273194fc30SMatthew G. Knepley {
49287391a63aSMatthew G. Knepley   DMLabel        label;
4929bb197d40SJed Brown   PetscInt       dim, depth = -1, eStart = -1, Nf;
49309e8305c2SJed Brown   PetscBool      vertexchart;
49313194fc30SMatthew G. Knepley   PetscErrorCode ierr;
49323194fc30SMatthew G. Knepley 
49333194fc30SMatthew G. Knepley   PetscFunctionBegin;
49343194fc30SMatthew G. Knepley   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
4935a433471fSStefano Zampini   if (dim < 1) PetscFunctionReturn(0);
4936a433471fSStefano Zampini   if (point < 0) {
4937a433471fSStefano Zampini     PetscInt sStart,sEnd;
4938a433471fSStefano Zampini 
4939a433471fSStefano Zampini     ierr = DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd);CHKERRQ(ierr);
4940a433471fSStefano Zampini     point = sEnd-sStart ? sStart : point;
4941a433471fSStefano Zampini   }
49427391a63aSMatthew G. Knepley   ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr);
4943a433471fSStefano Zampini   if (point >= 0) { ierr = DMLabelGetValue(label, point, &depth);CHKERRQ(ierr); }
4944a433471fSStefano Zampini   if (!section) {ierr = DMGetLocalSection(dm, &section);CHKERRQ(ierr);}
49457391a63aSMatthew G. Knepley   if (depth == 1) {eStart = point;}
49467391a63aSMatthew G. Knepley   else if  (depth == dim) {
49477391a63aSMatthew G. Knepley     const PetscInt *cone;
49487391a63aSMatthew G. Knepley 
49497391a63aSMatthew G. Knepley     ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr);
4950d4e6627bSStefano Zampini     if (dim == 2) eStart = cone[0];
4951d4e6627bSStefano Zampini     else if (dim == 3) {
4952d4e6627bSStefano Zampini       const PetscInt *cone2;
4953d4e6627bSStefano Zampini       ierr = DMPlexGetCone(dm, cone[0], &cone2);CHKERRQ(ierr);
4954d4e6627bSStefano Zampini       eStart = cone2[0];
4955d4e6627bSStefano Zampini     } else SETERRQ3(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);
4956a433471fSStefano Zampini   } else if (depth >= 0) SETERRQ3(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);
49579e8305c2SJed Brown   {                             /* Determine whether the chart covers all points or just vertices. */
49589e8305c2SJed Brown     PetscInt pStart,pEnd,cStart,cEnd;
49599e8305c2SJed Brown     ierr = DMPlexGetDepthStratum(dm,0,&pStart,&pEnd);CHKERRQ(ierr);
49609e8305c2SJed Brown     ierr = PetscSectionGetChart(section,&cStart,&cEnd);CHKERRQ(ierr);
49619e8305c2SJed Brown     if (pStart == cStart && pEnd == cEnd) vertexchart = PETSC_TRUE; /* Just vertices */
49629e8305c2SJed Brown     else vertexchart = PETSC_FALSE;                                 /* Assume all interpolated points are in chart */
49639e8305c2SJed Brown   }
49643194fc30SMatthew G. Knepley   ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr);
4965bb197d40SJed Brown   for (PetscInt d=1; d<=dim; d++) {
4966bb197d40SJed Brown     PetscInt k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0;
4967bb197d40SJed Brown     PetscInt *perm;
4968bb197d40SJed Brown 
49693194fc30SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
49709e8305c2SJed Brown       ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr);
4971bb197d40SJed Brown       size += PetscPowInt(k+1, d)*Nc;
49723194fc30SMatthew G. Knepley     }
49733194fc30SMatthew G. Knepley     ierr = PetscMalloc1(size, &perm);CHKERRQ(ierr);
49743194fc30SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
4975bb197d40SJed Brown       switch (d) {
4976babf31e0SJed Brown       case 1:
49779e8305c2SJed Brown         ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr);
4978babf31e0SJed Brown         /*
4979babf31e0SJed Brown          Original ordering is [ edge of length k-1; vtx0; vtx1 ]
4980babf31e0SJed Brown          We want              [ vtx0; edge of length k-1; vtx1 ]
4981babf31e0SJed Brown          */
4982babf31e0SJed Brown         for (c=0; c<Nc; c++,offset++) perm[offset] = (k-1)*Nc + c + foffset;
4983babf31e0SJed Brown         for (i=0; i<k-1; i++) for (c=0; c<Nc; c++,offset++) perm[offset] = i*Nc + c + foffset;
4984babf31e0SJed Brown         for (c=0; c<Nc; c++,offset++) perm[offset] = k*Nc + c + foffset;
4985babf31e0SJed Brown         foffset = offset;
4986babf31e0SJed Brown         break;
498789eabcffSMatthew G. Knepley       case 2:
49883194fc30SMatthew 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} */
49899e8305c2SJed Brown         ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr);
49903194fc30SMatthew G. Knepley         /* The SEM order is
49913194fc30SMatthew G. Knepley 
49923194fc30SMatthew G. Knepley          v_lb, {e_b}, v_rb,
499389eabcffSMatthew G. Knepley          e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r,
49943194fc30SMatthew G. Knepley          v_lt, reverse {e_t}, v_rt
49953194fc30SMatthew G. Knepley          */
49963194fc30SMatthew G. Knepley         {
49973194fc30SMatthew G. Knepley           const PetscInt of   = 0;
49983194fc30SMatthew G. Knepley           const PetscInt oeb  = of   + PetscSqr(k-1);
49993194fc30SMatthew G. Knepley           const PetscInt oer  = oeb  + (k-1);
50003194fc30SMatthew G. Knepley           const PetscInt oet  = oer  + (k-1);
50013194fc30SMatthew G. Knepley           const PetscInt oel  = oet  + (k-1);
50023194fc30SMatthew G. Knepley           const PetscInt ovlb = oel  + (k-1);
50033194fc30SMatthew G. Knepley           const PetscInt ovrb = ovlb + 1;
50043194fc30SMatthew G. Knepley           const PetscInt ovrt = ovrb + 1;
50053194fc30SMatthew G. Knepley           const PetscInt ovlt = ovrt + 1;
50063194fc30SMatthew G. Knepley           PetscInt       o;
50073194fc30SMatthew G. Knepley 
50083194fc30SMatthew G. Knepley           /* bottom */
50093194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb*Nc + c + foffset;
50103194fc30SMatthew G. Knepley           for (o = oeb; o < oer; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
50113194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb*Nc + c + foffset;
50123194fc30SMatthew G. Knepley           /* middle */
50133194fc30SMatthew G. Knepley           for (i = 0; i < k-1; ++i) {
50143194fc30SMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel+(k-2)-i)*Nc + c + foffset;
50153194fc30SMatthew 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;
50163194fc30SMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer+i)*Nc + c + foffset;
50173194fc30SMatthew G. Knepley           }
50183194fc30SMatthew G. Knepley           /* top */
50193194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt*Nc + c + foffset;
50203194fc30SMatthew G. Knepley           for (o = oel-1; o >= oet; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
50213194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt*Nc + c + foffset;
50223194fc30SMatthew G. Knepley           foffset = offset;
50233194fc30SMatthew G. Knepley         }
502489eabcffSMatthew G. Knepley         break;
502589eabcffSMatthew G. Knepley       case 3:
502689eabcffSMatthew G. Knepley         /* The original hex closure is
502789eabcffSMatthew G. Knepley 
502889eabcffSMatthew G. Knepley          {c,
502989eabcffSMatthew G. Knepley          f_b, f_t, f_f, f_b, f_r, f_l,
503089eabcffSMatthew 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,
503189eabcffSMatthew G. Knepley          v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb}
503289eabcffSMatthew G. Knepley          */
50339e8305c2SJed Brown         ierr = PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k);CHKERRQ(ierr);
503489eabcffSMatthew G. Knepley         /* The SEM order is
503589eabcffSMatthew G. Knepley          Bottom Slice
503689eabcffSMatthew G. Knepley          v_blf, {e^{(k-1)-n}_bf}, v_brf,
503789eabcffSMatthew G. Knepley          e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br,
503889eabcffSMatthew G. Knepley          v_blb, {e_bb}, v_brb,
503989eabcffSMatthew G. Knepley 
504089eabcffSMatthew G. Knepley          Middle Slice (j)
504189eabcffSMatthew G. Knepley          {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf,
504289eabcffSMatthew G. Knepley          f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r,
504389eabcffSMatthew G. Knepley          e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb,
504489eabcffSMatthew G. Knepley 
504589eabcffSMatthew G. Knepley          Top Slice
504689eabcffSMatthew G. Knepley          v_tlf, {e_tf}, v_trf,
504789eabcffSMatthew G. Knepley          e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr,
504889eabcffSMatthew G. Knepley          v_tlb, {e^{(k-1)-n}_tb}, v_trb,
504989eabcffSMatthew G. Knepley          */
505089eabcffSMatthew G. Knepley         {
505189eabcffSMatthew G. Knepley           const PetscInt oc    = 0;
505289eabcffSMatthew G. Knepley           const PetscInt ofb   = oc    + PetscSqr(k-1)*(k-1);
505389eabcffSMatthew G. Knepley           const PetscInt oft   = ofb   + PetscSqr(k-1);
505489eabcffSMatthew G. Knepley           const PetscInt off   = oft   + PetscSqr(k-1);
505589eabcffSMatthew G. Knepley           const PetscInt ofk   = off   + PetscSqr(k-1);
505689eabcffSMatthew G. Knepley           const PetscInt ofr   = ofk   + PetscSqr(k-1);
505789eabcffSMatthew G. Knepley           const PetscInt ofl   = ofr   + PetscSqr(k-1);
505889eabcffSMatthew G. Knepley           const PetscInt oebl  = ofl   + PetscSqr(k-1);
505989eabcffSMatthew G. Knepley           const PetscInt oebb  = oebl  + (k-1);
506089eabcffSMatthew G. Knepley           const PetscInt oebr  = oebb  + (k-1);
506189eabcffSMatthew G. Knepley           const PetscInt oebf  = oebr  + (k-1);
506289eabcffSMatthew G. Knepley           const PetscInt oetf  = oebf  + (k-1);
506389eabcffSMatthew G. Knepley           const PetscInt oetr  = oetf  + (k-1);
506489eabcffSMatthew G. Knepley           const PetscInt oetb  = oetr  + (k-1);
506589eabcffSMatthew G. Knepley           const PetscInt oetl  = oetb  + (k-1);
506689eabcffSMatthew G. Knepley           const PetscInt oerf  = oetl  + (k-1);
506789eabcffSMatthew G. Knepley           const PetscInt oelf  = oerf  + (k-1);
506889eabcffSMatthew G. Knepley           const PetscInt oelb  = oelf  + (k-1);
506989eabcffSMatthew G. Knepley           const PetscInt oerb  = oelb  + (k-1);
507089eabcffSMatthew G. Knepley           const PetscInt ovblf = oerb  + (k-1);
507189eabcffSMatthew G. Knepley           const PetscInt ovblb = ovblf + 1;
507289eabcffSMatthew G. Knepley           const PetscInt ovbrb = ovblb + 1;
507389eabcffSMatthew G. Knepley           const PetscInt ovbrf = ovbrb + 1;
507489eabcffSMatthew G. Knepley           const PetscInt ovtlf = ovbrf + 1;
507589eabcffSMatthew G. Knepley           const PetscInt ovtrf = ovtlf + 1;
507689eabcffSMatthew G. Knepley           const PetscInt ovtrb = ovtrf + 1;
507789eabcffSMatthew G. Knepley           const PetscInt ovtlb = ovtrb + 1;
507889eabcffSMatthew G. Knepley           PetscInt       o, n;
507989eabcffSMatthew G. Knepley 
508089eabcffSMatthew G. Knepley           /* Bottom Slice */
508189eabcffSMatthew G. Knepley           /*   bottom */
508289eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf*Nc + c + foffset;
508389eabcffSMatthew G. Knepley           for (o = oetf-1; o >= oebf; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
508489eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf*Nc + c + foffset;
508589eabcffSMatthew G. Knepley           /*   middle */
508689eabcffSMatthew G. Knepley           for (i = 0; i < k-1; ++i) {
508789eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl+i)*Nc + c + foffset;
5088316b7f87SMax 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;}
508989eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr+(k-2)-i)*Nc + c + foffset;
50903194fc30SMatthew G. Knepley           }
509189eabcffSMatthew G. Knepley           /*   top */
509289eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb*Nc + c + foffset;
509389eabcffSMatthew G. Knepley           for (o = oebb; o < oebr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
509489eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb*Nc + c + foffset;
509589eabcffSMatthew G. Knepley 
509689eabcffSMatthew G. Knepley           /* Middle Slice */
509789eabcffSMatthew G. Knepley           for (j = 0; j < k-1; ++j) {
509889eabcffSMatthew G. Knepley             /*   bottom */
509989eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf+(k-2)-j)*Nc + c + foffset;
510089eabcffSMatthew 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;
510189eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf+j)*Nc + c + foffset;
510289eabcffSMatthew G. Knepley             /*   middle */
510389eabcffSMatthew G. Knepley             for (i = 0; i < k-1; ++i) {
510489eabcffSMatthew G. Knepley               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl+i*(k-1)+j)*Nc + c + foffset;
510589eabcffSMatthew 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;
510689eabcffSMatthew G. Knepley               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr+j*(k-1)+i)*Nc + c + foffset;
510789eabcffSMatthew G. Knepley             }
510889eabcffSMatthew G. Knepley             /*   top */
510989eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb+j)*Nc + c + foffset;
511089eabcffSMatthew 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;
511189eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb+(k-2)-j)*Nc + c + foffset;
511289eabcffSMatthew G. Knepley           }
511389eabcffSMatthew G. Knepley 
511489eabcffSMatthew G. Knepley           /* Top Slice */
511589eabcffSMatthew G. Knepley           /*   bottom */
511689eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf*Nc + c + foffset;
511789eabcffSMatthew G. Knepley           for (o = oetf; o < oetr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
511889eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf*Nc + c + foffset;
511989eabcffSMatthew G. Knepley           /*   middle */
512089eabcffSMatthew G. Knepley           for (i = 0; i < k-1; ++i) {
512189eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl+(k-2)-i)*Nc + c + foffset;
512289eabcffSMatthew 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;
512389eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr+i)*Nc + c + foffset;
512489eabcffSMatthew G. Knepley           }
512589eabcffSMatthew G. Knepley           /*   top */
512689eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb*Nc + c + foffset;
512789eabcffSMatthew G. Knepley           for (o = oetl-1; o >= oetb; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
512889eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb*Nc + c + foffset;
512989eabcffSMatthew G. Knepley 
513089eabcffSMatthew G. Knepley           foffset = offset;
513189eabcffSMatthew G. Knepley         }
513289eabcffSMatthew G. Knepley         break;
5133bb197d40SJed Brown       default: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %D", d);
513489eabcffSMatthew G. Knepley       }
513589eabcffSMatthew G. Knepley     }
513689eabcffSMatthew G. Knepley     if (offset != size) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Number of permutation entries %D != %D", offset, size);
51373194fc30SMatthew G. Knepley     /* Check permutation */
51383194fc30SMatthew G. Knepley     {
51393194fc30SMatthew G. Knepley       PetscInt *check;
51403194fc30SMatthew G. Knepley 
51413194fc30SMatthew G. Knepley       ierr = PetscMalloc1(size, &check);CHKERRQ(ierr);
51423194fc30SMatthew G. Knepley       for (i = 0; i < size; ++i) {check[i] = -1; if (perm[i] < 0 || perm[i] >= size) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid permutation index p[%D] = %D", i, perm[i]);}
51433194fc30SMatthew G. Knepley       for (i = 0; i < size; ++i) check[perm[i]] = i;
51443194fc30SMatthew G. Knepley       for (i = 0; i < size; ++i) {if (check[i] < 0) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Missing permutation index %D", i);}
51453194fc30SMatthew G. Knepley       ierr = PetscFree(check);CHKERRQ(ierr);
51463194fc30SMatthew G. Knepley     }
5147bb197d40SJed Brown     ierr = PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size, PETSC_OWN_POINTER, perm);CHKERRQ(ierr);
5148bb197d40SJed Brown   }
51493194fc30SMatthew G. Knepley   PetscFunctionReturn(0);
51503194fc30SMatthew G. Knepley }
51513194fc30SMatthew G. Knepley 
5152e071409bSToby Isaac PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace)
5153e071409bSToby Isaac {
5154e071409bSToby Isaac   PetscDS        prob;
5155e071409bSToby Isaac   PetscInt       depth, Nf, h;
5156e071409bSToby Isaac   DMLabel        label;
5157e071409bSToby Isaac   PetscErrorCode ierr;
5158e071409bSToby Isaac 
5159e071409bSToby Isaac   PetscFunctionBeginHot;
5160e5e52638SMatthew G. Knepley   ierr = DMGetDS(dm, &prob);CHKERRQ(ierr);
5161e071409bSToby Isaac   Nf      = prob->Nf;
5162e071409bSToby Isaac   label   = dm->depthLabel;
5163e071409bSToby Isaac   *dspace = NULL;
5164e071409bSToby Isaac   if (field < Nf) {
5165e071409bSToby Isaac     PetscObject disc = prob->disc[field];
5166e071409bSToby Isaac 
5167e071409bSToby Isaac     if (disc->classid == PETSCFE_CLASSID) {
5168e071409bSToby Isaac       PetscDualSpace dsp;
5169e071409bSToby Isaac 
5170e071409bSToby Isaac       ierr = PetscFEGetDualSpace((PetscFE)disc,&dsp);CHKERRQ(ierr);
5171e071409bSToby Isaac       ierr = DMLabelGetNumValues(label,&depth);CHKERRQ(ierr);
5172e071409bSToby Isaac       ierr = DMLabelGetValue(label,point,&h);CHKERRQ(ierr);
5173e071409bSToby Isaac       h    = depth - 1 - h;
5174e071409bSToby Isaac       if (h) {
5175e071409bSToby Isaac         ierr = PetscDualSpaceGetHeightSubspace(dsp,h,dspace);CHKERRQ(ierr);
5176e071409bSToby Isaac       } else {
5177e071409bSToby Isaac         *dspace = dsp;
5178e071409bSToby Isaac       }
5179e071409bSToby Isaac     }
5180e071409bSToby Isaac   }
5181e071409bSToby Isaac   PetscFunctionReturn(0);
5182e071409bSToby Isaac }
5183e071409bSToby Isaac 
51841a271a75SMatthew G. Knepley PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
5185a6dfd86eSKarl Rupp {
5186552f7358SJed Brown   PetscScalar    *array, *vArray;
5187d9917b9dSMatthew G. Knepley   const PetscInt *cone, *coneO;
51881a271a75SMatthew G. Knepley   PetscInt        pStart, pEnd, p, numPoints, size = 0, offset = 0;
5189552f7358SJed Brown   PetscErrorCode  ierr;
5190552f7358SJed Brown 
51911b406b76SMatthew G. Knepley   PetscFunctionBeginHot;
51922a3aaacfSMatthew G. Knepley   ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr);
51935a1bb5cfSMatthew G. Knepley   ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr);
51945a1bb5cfSMatthew G. Knepley   ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr);
51955a1bb5cfSMatthew G. Knepley   ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr);
51963f7cbbe7SMatthew G. Knepley   if (!values || !*values) {
51979df71ca4SMatthew G. Knepley     if ((point >= pStart) && (point < pEnd)) {
51989df71ca4SMatthew G. Knepley       PetscInt dof;
5199d9917b9dSMatthew G. Knepley 
52009df71ca4SMatthew G. Knepley       ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr);
52019df71ca4SMatthew G. Knepley       size += dof;
52029df71ca4SMatthew G. Knepley     }
52039df71ca4SMatthew G. Knepley     for (p = 0; p < numPoints; ++p) {
52049df71ca4SMatthew G. Knepley       const PetscInt cp = cone[p];
52052a3aaacfSMatthew G. Knepley       PetscInt       dof;
52065a1bb5cfSMatthew G. Knepley 
52075a1bb5cfSMatthew G. Knepley       if ((cp < pStart) || (cp >= pEnd)) continue;
52082a3aaacfSMatthew G. Knepley       ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr);
52095a1bb5cfSMatthew G. Knepley       size += dof;
52105a1bb5cfSMatthew G. Knepley     }
52113f7cbbe7SMatthew G. Knepley     if (!values) {
52123f7cbbe7SMatthew G. Knepley       if (csize) *csize = size;
52133f7cbbe7SMatthew G. Knepley       PetscFunctionReturn(0);
52143f7cbbe7SMatthew G. Knepley     }
521569291d52SBarry Smith     ierr = DMGetWorkArray(dm, size, MPIU_SCALAR, &array);CHKERRQ(ierr);
5216982e9ed1SMatthew G. Knepley   } else {
5217982e9ed1SMatthew G. Knepley     array = *values;
5218982e9ed1SMatthew G. Knepley   }
52199df71ca4SMatthew G. Knepley   size = 0;
52205a1bb5cfSMatthew G. Knepley   ierr = VecGetArray(v, &vArray);CHKERRQ(ierr);
52219df71ca4SMatthew G. Knepley   if ((point >= pStart) && (point < pEnd)) {
52229df71ca4SMatthew G. Knepley     PetscInt     dof, off, d;
52239df71ca4SMatthew G. Knepley     PetscScalar *varr;
5224d9917b9dSMatthew G. Knepley 
52259df71ca4SMatthew G. Knepley     ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr);
52269df71ca4SMatthew G. Knepley     ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr);
52279df71ca4SMatthew G. Knepley     varr = &vArray[off];
52281a271a75SMatthew G. Knepley     for (d = 0; d < dof; ++d, ++offset) {
52291a271a75SMatthew G. Knepley       array[offset] = varr[d];
52309df71ca4SMatthew G. Knepley     }
52319df71ca4SMatthew G. Knepley     size += dof;
52329df71ca4SMatthew G. Knepley   }
52339df71ca4SMatthew G. Knepley   for (p = 0; p < numPoints; ++p) {
52349df71ca4SMatthew G. Knepley     const PetscInt cp = cone[p];
52359df71ca4SMatthew G. Knepley     PetscInt       o  = coneO[p];
52365a1bb5cfSMatthew G. Knepley     PetscInt       dof, off, d;
52375a1bb5cfSMatthew G. Knepley     PetscScalar   *varr;
52385a1bb5cfSMatthew G. Knepley 
523952ed52e8SMatthew G. Knepley     if ((cp < pStart) || (cp >= pEnd)) continue;
52405a1bb5cfSMatthew G. Knepley     ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr);
52415a1bb5cfSMatthew G. Knepley     ierr = PetscSectionGetOffset(section, cp, &off);CHKERRQ(ierr);
52425a1bb5cfSMatthew G. Knepley     varr = &vArray[off];
52435a1bb5cfSMatthew G. Knepley     if (o >= 0) {
52441a271a75SMatthew G. Knepley       for (d = 0; d < dof; ++d, ++offset) {
52451a271a75SMatthew G. Knepley         array[offset] = varr[d];
52465a1bb5cfSMatthew G. Knepley       }
52475a1bb5cfSMatthew G. Knepley     } else {
52481a271a75SMatthew G. Knepley       for (d = dof-1; d >= 0; --d, ++offset) {
52491a271a75SMatthew G. Knepley         array[offset] = varr[d];
52505a1bb5cfSMatthew G. Knepley       }
52515a1bb5cfSMatthew G. Knepley     }
52529df71ca4SMatthew G. Knepley     size += dof;
52535a1bb5cfSMatthew G. Knepley   }
52545a1bb5cfSMatthew G. Knepley   ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr);
52559df71ca4SMatthew G. Knepley   if (!*values) {
52565a1bb5cfSMatthew G. Knepley     if (csize) *csize = size;
52575a1bb5cfSMatthew G. Knepley     *values = array;
52589df71ca4SMatthew G. Knepley   } else {
52598ccfff9cSToby Isaac     if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size);
52608c312ff3SMatthew G. Knepley     *csize = size;
52619df71ca4SMatthew G. Knepley   }
52625a1bb5cfSMatthew G. Knepley   PetscFunctionReturn(0);
52635a1bb5cfSMatthew G. Knepley }
5264d9917b9dSMatthew G. Knepley 
526527f02ce8SMatthew G. Knepley /* Compress out points not in the section */
526627f02ce8SMatthew G. Knepley PETSC_STATIC_INLINE PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[])
526727f02ce8SMatthew G. Knepley {
526827f02ce8SMatthew G. Knepley   const PetscInt np = *numPoints;
526927f02ce8SMatthew G. Knepley   PetscInt       pStart, pEnd, p, q;
527027f02ce8SMatthew G. Knepley   PetscErrorCode ierr;
527127f02ce8SMatthew G. Knepley 
527227f02ce8SMatthew G. Knepley   ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr);
527327f02ce8SMatthew G. Knepley   for (p = 0, q = 0; p < np; ++p) {
527427f02ce8SMatthew G. Knepley     const PetscInt r = points[p*2];
527527f02ce8SMatthew G. Knepley     if ((r >= pStart) && (r < pEnd)) {
527627f02ce8SMatthew G. Knepley       points[q*2]   = r;
527727f02ce8SMatthew G. Knepley       points[q*2+1] = points[p*2+1];
527827f02ce8SMatthew G. Knepley       ++q;
527927f02ce8SMatthew G. Knepley     }
528027f02ce8SMatthew G. Knepley   }
528127f02ce8SMatthew G. Knepley   *numPoints = q;
528227f02ce8SMatthew G. Knepley   return 0;
528327f02ce8SMatthew G. Knepley }
528427f02ce8SMatthew G. Knepley 
528527f02ce8SMatthew G. Knepley static PetscErrorCode DMPlexTransitiveClosure_Hybrid_Internal(DM dm, PetscInt point, PetscInt np, PetscInt *numPoints, PetscInt **points)
528627f02ce8SMatthew G. Knepley {
528727f02ce8SMatthew G. Knepley   const PetscInt *cone, *ornt;
528827f02ce8SMatthew G. Knepley   PetscInt       *pts,  *closure = NULL;
528927f02ce8SMatthew G. Knepley   PetscInt        dim, coneSize, c, d, clSize, cl;
529027f02ce8SMatthew G. Knepley   PetscErrorCode  ierr;
529127f02ce8SMatthew G. Knepley 
529227f02ce8SMatthew G. Knepley   PetscFunctionBeginHot;
529327f02ce8SMatthew G. Knepley   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
529427f02ce8SMatthew G. Knepley   ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr);
529527f02ce8SMatthew G. Knepley   ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr);
529627f02ce8SMatthew G. Knepley   ierr = DMPlexGetConeOrientation(dm, point, &ornt);CHKERRQ(ierr);
529727f02ce8SMatthew G. Knepley   ierr = DMPlexGetTransitiveClosure(dm, cone[0], PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr);
529827f02ce8SMatthew G. Knepley   ierr = DMGetWorkArray(dm, np*2, MPIU_INT, &pts);CHKERRQ(ierr);
529927f02ce8SMatthew G. Knepley   c    = 0;
530027f02ce8SMatthew G. Knepley   pts[c*2+0] = point;
530127f02ce8SMatthew G. Knepley   pts[c*2+1] = 0;
530227f02ce8SMatthew G. Knepley   ++c;
530327f02ce8SMatthew G. Knepley   for (cl = 0; cl < clSize*2; cl += 2, ++c) {pts[c*2+0] = closure[cl]; pts[c*2+1] = closure[cl+1];}
530427f02ce8SMatthew G. Knepley   ierr = DMPlexGetTransitiveClosure(dm, cone[1], PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr);
530527f02ce8SMatthew G. Knepley   for (cl = 0; cl < clSize*2; cl += 2, ++c) {pts[c*2+0] = closure[cl]; pts[c*2+1] = closure[cl+1];}
530627f02ce8SMatthew G. Knepley   ierr = DMPlexRestoreTransitiveClosure(dm, cone[0], PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr);
530727f02ce8SMatthew G. Knepley   if (dim >= 2) {
530827f02ce8SMatthew G. Knepley     for (d = 2; d < coneSize; ++d, ++c) {pts[c*2+0] = cone[d]; pts[c*2+1] = ornt[d];}
530927f02ce8SMatthew G. Knepley   }
531027f02ce8SMatthew G. Knepley   if (dim >= 3) {
531127f02ce8SMatthew G. Knepley     for (d = 2; d < coneSize; ++d) {
531227f02ce8SMatthew G. Knepley       const PetscInt  fpoint = cone[d];
531327f02ce8SMatthew G. Knepley       const PetscInt *fcone;
531427f02ce8SMatthew G. Knepley       PetscInt        fconeSize, fc, i;
531527f02ce8SMatthew G. Knepley 
531627f02ce8SMatthew G. Knepley       ierr = DMPlexGetConeSize(dm, fpoint, &fconeSize);CHKERRQ(ierr);
531727f02ce8SMatthew G. Knepley       ierr = DMPlexGetCone(dm, fpoint, &fcone);CHKERRQ(ierr);
531827f02ce8SMatthew G. Knepley       for (fc = 0; fc < fconeSize; ++fc) {
531927f02ce8SMatthew G. Knepley         for (i = 0; i < c; ++i) if (pts[i*2] == fcone[fc]) break;
532027f02ce8SMatthew G. Knepley         if (i == c) {pts[c*2+0] = fcone[fc]; pts[c*2+1] = 0; ++c;}
532127f02ce8SMatthew G. Knepley       }
532227f02ce8SMatthew G. Knepley     }
532327f02ce8SMatthew G. Knepley   }
532427f02ce8SMatthew G. Knepley   if (c != np) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid closure for hybrid point %D, size %D != %D", point, c, np);
532527f02ce8SMatthew G. Knepley   *numPoints = np;
532627f02ce8SMatthew G. Knepley   *points    = pts;
532727f02ce8SMatthew G. Knepley   PetscFunctionReturn(0);
532827f02ce8SMatthew G. Knepley }
532927f02ce8SMatthew G. Knepley 
533097529cf3SJed Brown /* Compressed closure does not apply closure permutation */
53311dc59d61SMatthew G. Knepley PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp)
5332923c78e0SToby Isaac {
533327f02ce8SMatthew G. Knepley   const PetscInt *cla = NULL;
5334923c78e0SToby Isaac   PetscInt       np, *pts = NULL;
5335923c78e0SToby Isaac   PetscErrorCode ierr;
5336923c78e0SToby Isaac 
5337923c78e0SToby Isaac   PetscFunctionBeginHot;
5338923c78e0SToby Isaac   ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, clSec, clPoints);CHKERRQ(ierr);
533927f02ce8SMatthew G. Knepley   if (*clPoints) {
5340923c78e0SToby Isaac     PetscInt dof, off;
5341923c78e0SToby Isaac 
5342923c78e0SToby Isaac     ierr = PetscSectionGetDof(*clSec, point, &dof);CHKERRQ(ierr);
5343923c78e0SToby Isaac     ierr = PetscSectionGetOffset(*clSec, point, &off);CHKERRQ(ierr);
5344923c78e0SToby Isaac     ierr = ISGetIndices(*clPoints, &cla);CHKERRQ(ierr);
5345923c78e0SToby Isaac     np   = dof/2;
5346923c78e0SToby Isaac     pts  = (PetscInt *) &cla[off];
534727f02ce8SMatthew G. Knepley   } else {
5348665f567fSMatthew G. Knepley     DMPolytopeType ct;
5349665f567fSMatthew G. Knepley 
535027f02ce8SMatthew G. Knepley     /* Do not make the label if it does not exist */
535127f02ce8SMatthew G. Knepley     if (!dm->celltypeLabel) {ct = DM_POLYTOPE_POINT;}
535227f02ce8SMatthew G. Knepley     else                    {ierr = DMPlexGetCellType(dm, point, &ct);CHKERRQ(ierr);}
535327f02ce8SMatthew G. Knepley     switch (ct) {
535427f02ce8SMatthew G. Knepley       case DM_POLYTOPE_SEG_PRISM_TENSOR:
535527f02ce8SMatthew G. Knepley         ierr = DMPlexTransitiveClosure_Hybrid_Internal(dm, point, 9, &np, &pts);CHKERRQ(ierr);
535627f02ce8SMatthew G. Knepley         break;
535727f02ce8SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM_TENSOR:
535827f02ce8SMatthew G. Knepley         ierr = DMPlexTransitiveClosure_Hybrid_Internal(dm, point, 21, &np, &pts);CHKERRQ(ierr);
535927f02ce8SMatthew G. Knepley         break;
536027f02ce8SMatthew G. Knepley       case DM_POLYTOPE_QUAD_PRISM_TENSOR:
536127f02ce8SMatthew G. Knepley         ierr = DMPlexTransitiveClosure_Hybrid_Internal(dm, point, 27, &np, &pts);CHKERRQ(ierr);
536227f02ce8SMatthew G. Knepley         break;
536327f02ce8SMatthew G. Knepley       default:
536427f02ce8SMatthew G. Knepley         ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &np, &pts);CHKERRQ(ierr);
536527f02ce8SMatthew G. Knepley     }
536627f02ce8SMatthew G. Knepley     ierr = CompressPoints_Private(section, &np, pts);CHKERRQ(ierr);
5367923c78e0SToby Isaac   }
5368923c78e0SToby Isaac   *numPoints = np;
5369923c78e0SToby Isaac   *points    = pts;
5370923c78e0SToby Isaac   *clp       = cla;
5371923c78e0SToby Isaac   PetscFunctionReturn(0);
5372923c78e0SToby Isaac }
5373923c78e0SToby Isaac 
53741dc59d61SMatthew G. Knepley PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp)
5375923c78e0SToby Isaac {
5376923c78e0SToby Isaac   PetscErrorCode ierr;
5377923c78e0SToby Isaac 
5378923c78e0SToby Isaac   PetscFunctionBeginHot;
5379923c78e0SToby Isaac   if (!*clPoints) {
5380923c78e0SToby Isaac     ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points);CHKERRQ(ierr);
5381923c78e0SToby Isaac   } else {
5382923c78e0SToby Isaac     ierr = ISRestoreIndices(*clPoints, clp);CHKERRQ(ierr);
5383923c78e0SToby Isaac   }
5384923c78e0SToby Isaac   *numPoints = 0;
5385923c78e0SToby Isaac   *points    = NULL;
5386923c78e0SToby Isaac   *clSec     = NULL;
5387923c78e0SToby Isaac   *clPoints  = NULL;
5388923c78e0SToby Isaac   *clp       = NULL;
5389923c78e0SToby Isaac   PetscFunctionReturn(0);
5390923c78e0SToby Isaac }
5391923c78e0SToby Isaac 
539297e99dd9SToby Isaac PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Static(DM dm, PetscSection section, PetscInt numPoints, const PetscInt points[], const PetscInt clperm[], const PetscScalar vArray[], PetscInt *size, PetscScalar array[])
53931a271a75SMatthew G. Knepley {
53941a271a75SMatthew G. Knepley   PetscInt          offset = 0, p;
539597e99dd9SToby Isaac   const PetscInt    **perms = NULL;
539697e99dd9SToby Isaac   const PetscScalar **flips = NULL;
53971a271a75SMatthew G. Knepley   PetscErrorCode    ierr;
53981a271a75SMatthew G. Knepley 
53991a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
5400fe02ba77SJed Brown   *size = 0;
540197e99dd9SToby Isaac   ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr);
540297e99dd9SToby Isaac   for (p = 0; p < numPoints; p++) {
540397e99dd9SToby Isaac     const PetscInt    point = points[2*p];
540497e99dd9SToby Isaac     const PetscInt    *perm = perms ? perms[p] : NULL;
540597e99dd9SToby Isaac     const PetscScalar *flip = flips ? flips[p] : NULL;
54061a271a75SMatthew G. Knepley     PetscInt          dof, off, d;
54071a271a75SMatthew G. Knepley     const PetscScalar *varr;
54081a271a75SMatthew G. Knepley 
54091a271a75SMatthew G. Knepley     ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr);
54101a271a75SMatthew G. Knepley     ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr);
54111a271a75SMatthew G. Knepley     varr = &vArray[off];
541297e99dd9SToby Isaac     if (clperm) {
541397e99dd9SToby Isaac       if (perm) {
541497e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]]  = varr[d];
54151a271a75SMatthew G. Knepley       } else {
541697e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset +      d ]]  = varr[d];
541797e99dd9SToby Isaac       }
541897e99dd9SToby Isaac       if (flip) {
541997e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset +      d ]] *= flip[d];
542097e99dd9SToby Isaac       }
542197e99dd9SToby Isaac     } else {
542297e99dd9SToby Isaac       if (perm) {
542397e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset + perm[d]]  = varr[d];
542497e99dd9SToby Isaac       } else {
542597e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset +      d ]  = varr[d];
542697e99dd9SToby Isaac       }
542797e99dd9SToby Isaac       if (flip) {
542897e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset +      d ] *= flip[d];
54291a271a75SMatthew G. Knepley       }
54301a271a75SMatthew G. Knepley     }
543197e99dd9SToby Isaac     offset += dof;
543297e99dd9SToby Isaac   }
543397e99dd9SToby Isaac   ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr);
54341a271a75SMatthew G. Knepley   *size = offset;
54351a271a75SMatthew G. Knepley   PetscFunctionReturn(0);
54361a271a75SMatthew G. Knepley }
54371a271a75SMatthew G. Knepley 
543897e99dd9SToby Isaac PETSC_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[])
54391a271a75SMatthew G. Knepley {
54401a271a75SMatthew G. Knepley   PetscInt          offset = 0, f;
54411a271a75SMatthew G. Knepley   PetscErrorCode    ierr;
54421a271a75SMatthew G. Knepley 
54431a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
5444fe02ba77SJed Brown   *size = 0;
54451a271a75SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
544697e99dd9SToby Isaac     PetscInt          p;
544797e99dd9SToby Isaac     const PetscInt    **perms = NULL;
544897e99dd9SToby Isaac     const PetscScalar **flips = NULL;
54491a271a75SMatthew G. Knepley 
545097e99dd9SToby Isaac     ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr);
545197e99dd9SToby Isaac     for (p = 0; p < numPoints; p++) {
545297e99dd9SToby Isaac       const PetscInt    point = points[2*p];
545397e99dd9SToby Isaac       PetscInt          fdof, foff, b;
54541a271a75SMatthew G. Knepley       const PetscScalar *varr;
545597e99dd9SToby Isaac       const PetscInt    *perm = perms ? perms[p] : NULL;
545697e99dd9SToby Isaac       const PetscScalar *flip = flips ? flips[p] : NULL;
54571a271a75SMatthew G. Knepley 
54581a271a75SMatthew G. Knepley       ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr);
54591a271a75SMatthew G. Knepley       ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr);
54601a271a75SMatthew G. Knepley       varr = &vArray[foff];
546197e99dd9SToby Isaac       if (clperm) {
546297e99dd9SToby Isaac         if (perm) {for (b = 0; b < fdof; b++) {array[clperm[offset + perm[b]]]  = varr[b];}}
546397e99dd9SToby Isaac         else      {for (b = 0; b < fdof; b++) {array[clperm[offset +      b ]]  = varr[b];}}
546497e99dd9SToby Isaac         if (flip) {for (b = 0; b < fdof; b++) {array[clperm[offset +      b ]] *= flip[b];}}
54651a271a75SMatthew G. Knepley       } else {
546697e99dd9SToby Isaac         if (perm) {for (b = 0; b < fdof; b++) {array[offset + perm[b]]  = varr[b];}}
546797e99dd9SToby Isaac         else      {for (b = 0; b < fdof; b++) {array[offset +      b ]  = varr[b];}}
546897e99dd9SToby Isaac         if (flip) {for (b = 0; b < fdof; b++) {array[offset +      b ] *= flip[b];}}
54691a271a75SMatthew G. Knepley       }
547097e99dd9SToby Isaac       offset += fdof;
54711a271a75SMatthew G. Knepley     }
547297e99dd9SToby Isaac     ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr);
54731a271a75SMatthew G. Knepley   }
54741a271a75SMatthew G. Knepley   *size = offset;
54751a271a75SMatthew G. Knepley   PetscFunctionReturn(0);
54761a271a75SMatthew G. Knepley }
54771a271a75SMatthew G. Knepley 
5478552f7358SJed Brown /*@C
5479552f7358SJed Brown   DMPlexVecGetClosure - Get an array of the values on the closure of 'point'
5480552f7358SJed Brown 
5481552f7358SJed Brown   Not collective
5482552f7358SJed Brown 
5483552f7358SJed Brown   Input Parameters:
5484552f7358SJed Brown + dm - The DM
5485552f7358SJed Brown . section - The section describing the layout in v, or NULL to use the default section
5486552f7358SJed Brown . v - The local vector
548722c1ee49SMatthew G. Knepley . point - The point in the DM
548822c1ee49SMatthew G. Knepley . csize - The size of the input values array, or NULL
548922c1ee49SMatthew G. Knepley - values - An array to use for the values, or NULL to have it allocated automatically
5490552f7358SJed Brown 
5491552f7358SJed Brown   Output Parameters:
549222c1ee49SMatthew G. Knepley + csize - The number of values in the closure
549322c1ee49SMatthew G. Knepley - values - The array of values. If the user provided NULL, it is a borrowed array and should not be freed
549422c1ee49SMatthew G. Knepley 
549522c1ee49SMatthew G. Knepley $ Note that DMPlexVecGetClosure/DMPlexVecRestoreClosure only allocates the values array if it set to NULL in the
549622c1ee49SMatthew G. Knepley $ calling function. This is because DMPlexVecGetClosure() is typically called in the inner loop of a Vec or Mat
549722c1ee49SMatthew G. Knepley $ assembly function, and a user may already have allocated storage for this operation.
549822c1ee49SMatthew G. Knepley $
549922c1ee49SMatthew G. Knepley $ A typical use could be
550022c1ee49SMatthew G. Knepley $
550122c1ee49SMatthew G. Knepley $  values = NULL;
550222c1ee49SMatthew G. Knepley $  ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr);
550322c1ee49SMatthew G. Knepley $  for (cl = 0; cl < clSize; ++cl) {
550422c1ee49SMatthew G. Knepley $    <Compute on closure>
550522c1ee49SMatthew G. Knepley $  }
550622c1ee49SMatthew G. Knepley $  ierr = DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr);
550722c1ee49SMatthew G. Knepley $
550822c1ee49SMatthew G. Knepley $ or
550922c1ee49SMatthew G. Knepley $
551022c1ee49SMatthew G. Knepley $  PetscMalloc1(clMaxSize, &values);
551122c1ee49SMatthew G. Knepley $  for (p = pStart; p < pEnd; ++p) {
551222c1ee49SMatthew G. Knepley $    clSize = clMaxSize;
551322c1ee49SMatthew G. Knepley $    ierr = DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values);CHKERRQ(ierr);
551422c1ee49SMatthew G. Knepley $    for (cl = 0; cl < clSize; ++cl) {
551522c1ee49SMatthew G. Knepley $      <Compute on closure>
551622c1ee49SMatthew G. Knepley $    }
551722c1ee49SMatthew G. Knepley $  }
551822c1ee49SMatthew G. Knepley $  PetscFree(values);
5519552f7358SJed Brown 
5520552f7358SJed Brown   Fortran Notes:
5521552f7358SJed Brown   Since it returns an array, this routine is only available in Fortran 90, and you must
5522552f7358SJed Brown   include petsc.h90 in your code.
5523552f7358SJed Brown 
5524552f7358SJed Brown   The csize argument is not present in the Fortran 90 binding since it is internal to the array.
5525552f7358SJed Brown 
5526552f7358SJed Brown   Level: intermediate
5527552f7358SJed Brown 
5528552f7358SJed Brown .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure()
5529552f7358SJed Brown @*/
5530552f7358SJed Brown PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
5531552f7358SJed Brown {
5532552f7358SJed Brown   PetscSection       clSection;
5533d9917b9dSMatthew G. Knepley   IS                 clPoints;
5534552f7358SJed Brown   PetscInt          *points = NULL;
5535c459fbc1SJed Brown   const PetscInt    *clp, *perm;
5536c459fbc1SJed Brown   PetscInt           depth, numFields, numPoints, asize;
5537552f7358SJed Brown   PetscErrorCode     ierr;
5538552f7358SJed Brown 
5539d9917b9dSMatthew G. Knepley   PetscFunctionBeginHot;
5540552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
554192fd8e1eSJed Brown   if (!section) {ierr = DMGetLocalSection(dm, &section);CHKERRQ(ierr);}
55421a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
55431a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
5544552f7358SJed Brown   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
5545552f7358SJed Brown   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
5546552f7358SJed Brown   if (depth == 1 && numFields < 2) {
55471a271a75SMatthew G. Knepley     ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr);
5548552f7358SJed Brown     PetscFunctionReturn(0);
5549552f7358SJed Brown   }
55501a271a75SMatthew G. Knepley   /* Get points */
5551923c78e0SToby Isaac   ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr);
5552c459fbc1SJed Brown   /* Get sizes */
5553c459fbc1SJed Brown   asize = 0;
5554c459fbc1SJed Brown   for (PetscInt p = 0; p < numPoints*2; p += 2) {
5555c459fbc1SJed Brown     PetscInt dof;
5556552f7358SJed Brown     ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr);
55571a271a75SMatthew G. Knepley     asize += dof;
5558552f7358SJed Brown   }
5559c459fbc1SJed Brown   if (values) {
5560c459fbc1SJed Brown     const PetscScalar *vArray;
5561c459fbc1SJed Brown     PetscInt          size;
5562c459fbc1SJed Brown 
5563c459fbc1SJed Brown     if (*values) {
5564c459fbc1SJed Brown       if (PetscUnlikely(*csize < asize)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Provided array size %D not sufficient to hold closure size %D", *csize, asize);
5565c459fbc1SJed Brown     } else {ierr = DMGetWorkArray(dm, asize, MPIU_SCALAR, values);CHKERRQ(ierr);}
5566c459fbc1SJed Brown     ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, asize, &perm);CHKERRQ(ierr);
55678a84db2dSMatthew G. Knepley     ierr = VecGetArrayRead(v, &vArray);CHKERRQ(ierr);
55681a271a75SMatthew G. Knepley     /* Get values */
5569c459fbc1SJed Brown     if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values);CHKERRQ(ierr);}
5570c459fbc1SJed Brown     else               {ierr = DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values);CHKERRQ(ierr);}
5571c459fbc1SJed Brown     if (PetscUnlikely(asize != size)) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Section size %D does not match Vec closure size %D", asize, size);
55721a271a75SMatthew G. Knepley     /* Cleanup array */
55738a84db2dSMatthew G. Knepley     ierr = VecRestoreArrayRead(v, &vArray);CHKERRQ(ierr);
5574d0f6b257SMatthew G. Knepley   }
5575c459fbc1SJed Brown   if (csize) *csize = asize;
5576c459fbc1SJed Brown   /* Cleanup points */
5577c459fbc1SJed Brown   ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr);
5578552f7358SJed Brown   PetscFunctionReturn(0);
5579552f7358SJed Brown }
5580552f7358SJed Brown 
5581e5c487bfSMatthew G. Knepley PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[])
5582e5c487bfSMatthew G. Knepley {
5583e5c487bfSMatthew G. Knepley   DMLabel            depthLabel;
5584e5c487bfSMatthew G. Knepley   PetscSection       clSection;
5585e5c487bfSMatthew G. Knepley   IS                 clPoints;
5586e5c487bfSMatthew G. Knepley   PetscScalar       *array;
5587e5c487bfSMatthew G. Knepley   const PetscScalar *vArray;
5588e5c487bfSMatthew G. Knepley   PetscInt          *points = NULL;
5589c459fbc1SJed Brown   const PetscInt    *clp, *perm = NULL;
5590c459fbc1SJed Brown   PetscInt           mdepth, numFields, numPoints, Np = 0, p, clsize, size;
5591e5c487bfSMatthew G. Knepley   PetscErrorCode     ierr;
5592e5c487bfSMatthew G. Knepley 
5593e5c487bfSMatthew G. Knepley   PetscFunctionBeginHot;
5594e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5595e5c487bfSMatthew G. Knepley   if (!section) {ierr = DMGetLocalSection(dm, &section);CHKERRQ(ierr);}
5596e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
5597e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
5598e5c487bfSMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &mdepth);CHKERRQ(ierr);
5599e5c487bfSMatthew G. Knepley   ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr);
5600e5c487bfSMatthew G. Knepley   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
5601e5c487bfSMatthew G. Knepley   if (mdepth == 1 && numFields < 2) {
5602e5c487bfSMatthew G. Knepley     ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr);
5603e5c487bfSMatthew G. Knepley     PetscFunctionReturn(0);
5604e5c487bfSMatthew G. Knepley   }
5605e5c487bfSMatthew G. Knepley   /* Get points */
5606e5c487bfSMatthew G. Knepley   ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr);
5607c459fbc1SJed Brown   for (clsize=0,p=0; p<Np; p++) {
5608c459fbc1SJed Brown     PetscInt dof;
5609c459fbc1SJed Brown     ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr);
5610c459fbc1SJed Brown     clsize += dof;
5611c459fbc1SJed Brown   }
5612c459fbc1SJed Brown   ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &perm);CHKERRQ(ierr);
5613e5c487bfSMatthew G. Knepley   /* Filter points */
5614e5c487bfSMatthew G. Knepley   for (p = 0; p < numPoints*2; p += 2) {
5615e5c487bfSMatthew G. Knepley     PetscInt dep;
5616e5c487bfSMatthew G. Knepley 
5617e5c487bfSMatthew G. Knepley     ierr = DMLabelGetValue(depthLabel, points[p], &dep);CHKERRQ(ierr);
5618e5c487bfSMatthew G. Knepley     if (dep != depth) continue;
5619e5c487bfSMatthew G. Knepley     points[Np*2+0] = points[p];
5620e5c487bfSMatthew G. Knepley     points[Np*2+1] = points[p+1];
5621e5c487bfSMatthew G. Knepley     ++Np;
5622e5c487bfSMatthew G. Knepley   }
5623e5c487bfSMatthew G. Knepley   /* Get array */
5624e5c487bfSMatthew G. Knepley   if (!values || !*values) {
5625e5c487bfSMatthew G. Knepley     PetscInt asize = 0, dof;
5626e5c487bfSMatthew G. Knepley 
5627e5c487bfSMatthew G. Knepley     for (p = 0; p < Np*2; p += 2) {
5628e5c487bfSMatthew G. Knepley       ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr);
5629e5c487bfSMatthew G. Knepley       asize += dof;
5630e5c487bfSMatthew G. Knepley     }
5631e5c487bfSMatthew G. Knepley     if (!values) {
5632e5c487bfSMatthew G. Knepley       ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr);
5633e5c487bfSMatthew G. Knepley       if (csize) *csize = asize;
5634e5c487bfSMatthew G. Knepley       PetscFunctionReturn(0);
5635e5c487bfSMatthew G. Knepley     }
5636e5c487bfSMatthew G. Knepley     ierr = DMGetWorkArray(dm, asize, MPIU_SCALAR, &array);CHKERRQ(ierr);
5637e5c487bfSMatthew G. Knepley   } else {
5638e5c487bfSMatthew G. Knepley     array = *values;
5639e5c487bfSMatthew G. Knepley   }
5640e5c487bfSMatthew G. Knepley   ierr = VecGetArrayRead(v, &vArray);CHKERRQ(ierr);
5641e5c487bfSMatthew G. Knepley   /* Get values */
5642e5c487bfSMatthew G. Knepley   if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array);CHKERRQ(ierr);}
5643e5c487bfSMatthew G. Knepley   else               {ierr = DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array);CHKERRQ(ierr);}
5644e5c487bfSMatthew G. Knepley   /* Cleanup points */
5645e5c487bfSMatthew G. Knepley   ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr);
5646e5c487bfSMatthew G. Knepley   /* Cleanup array */
5647e5c487bfSMatthew G. Knepley   ierr = VecRestoreArrayRead(v, &vArray);CHKERRQ(ierr);
5648e5c487bfSMatthew G. Knepley   if (!*values) {
5649e5c487bfSMatthew G. Knepley     if (csize) *csize = size;
5650e5c487bfSMatthew G. Knepley     *values = array;
5651e5c487bfSMatthew G. Knepley   } else {
5652e5c487bfSMatthew G. Knepley     if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size);
5653e5c487bfSMatthew G. Knepley     *csize = size;
5654e5c487bfSMatthew G. Knepley   }
5655e5c487bfSMatthew G. Knepley   PetscFunctionReturn(0);
5656e5c487bfSMatthew G. Knepley }
5657e5c487bfSMatthew G. Knepley 
5658552f7358SJed Brown /*@C
5659552f7358SJed Brown   DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point'
5660552f7358SJed Brown 
5661552f7358SJed Brown   Not collective
5662552f7358SJed Brown 
5663552f7358SJed Brown   Input Parameters:
5664552f7358SJed Brown + dm - The DM
56650298fd71SBarry Smith . section - The section describing the layout in v, or NULL to use the default section
5666552f7358SJed Brown . v - The local vector
5667eaf898f9SPatrick Sanan . point - The point in the DM
56680298fd71SBarry Smith . csize - The number of values in the closure, or NULL
5669552f7358SJed Brown - values - The array of values, which is a borrowed array and should not be freed
5670552f7358SJed Brown 
567122c1ee49SMatthew 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()
567222c1ee49SMatthew G. Knepley 
56733813dfbdSMatthew G Knepley   Fortran Notes:
56743813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
56753813dfbdSMatthew G Knepley   include petsc.h90 in your code.
56763813dfbdSMatthew G Knepley 
56773813dfbdSMatthew G Knepley   The csize argument is not present in the Fortran 90 binding since it is internal to the array.
56783813dfbdSMatthew G Knepley 
5679552f7358SJed Brown   Level: intermediate
5680552f7358SJed Brown 
5681552f7358SJed Brown .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure()
5682552f7358SJed Brown @*/
56837c1f9639SMatthew G Knepley PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
5684a6dfd86eSKarl Rupp {
5685552f7358SJed Brown   PetscInt       size = 0;
5686552f7358SJed Brown   PetscErrorCode ierr;
5687552f7358SJed Brown 
5688552f7358SJed Brown   PetscFunctionBegin;
5689552f7358SJed Brown   /* Should work without recalculating size */
569069291d52SBarry Smith   ierr = DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void*) values);CHKERRQ(ierr);
5691c9fdaa05SMatthew G. Knepley   *values = NULL;
5692552f7358SJed Brown   PetscFunctionReturn(0);
5693552f7358SJed Brown }
5694552f7358SJed Brown 
5695552f7358SJed Brown PETSC_STATIC_INLINE void add   (PetscScalar *x, PetscScalar y) {*x += y;}
5696552f7358SJed Brown PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x  = y;}
5697552f7358SJed Brown 
569897e99dd9SToby Isaac PETSC_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[])
5699552f7358SJed Brown {
5700552f7358SJed Brown   PetscInt        cdof;   /* The number of constraints on this point */
5701552f7358SJed Brown   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
5702552f7358SJed Brown   PetscScalar    *a;
5703552f7358SJed Brown   PetscInt        off, cind = 0, k;
5704552f7358SJed Brown   PetscErrorCode  ierr;
5705552f7358SJed Brown 
5706552f7358SJed Brown   PetscFunctionBegin;
5707552f7358SJed Brown   ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr);
5708552f7358SJed Brown   ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr);
5709552f7358SJed Brown   a    = &array[off];
5710552f7358SJed Brown   if (!cdof || setBC) {
571197e99dd9SToby Isaac     if (clperm) {
571297e99dd9SToby Isaac       if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));}}
571397e99dd9SToby Isaac       else      {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+     k ]] * (flip ? flip[     k ] : 1.));}}
5714552f7358SJed Brown     } else {
571597e99dd9SToby Isaac       if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));}}
571697e99dd9SToby Isaac       else      {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+     k ] * (flip ? flip[     k ] : 1.));}}
5717552f7358SJed Brown     }
5718552f7358SJed Brown   } else {
5719552f7358SJed Brown     ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr);
572097e99dd9SToby Isaac     if (clperm) {
572197e99dd9SToby Isaac       if (perm) {for (k = 0; k < dof; ++k) {
5722552f7358SJed Brown           if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
572397e99dd9SToby Isaac           fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));
5724552f7358SJed Brown         }
5725552f7358SJed Brown       } else {
5726552f7358SJed Brown         for (k = 0; k < dof; ++k) {
5727552f7358SJed Brown           if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
572897e99dd9SToby Isaac           fuse(&a[k], values[clperm[offset+     k ]] * (flip ? flip[     k ] : 1.));
572997e99dd9SToby Isaac         }
573097e99dd9SToby Isaac       }
573197e99dd9SToby Isaac     } else {
573297e99dd9SToby Isaac       if (perm) {
573397e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
573497e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
573597e99dd9SToby Isaac           fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));
573697e99dd9SToby Isaac         }
573797e99dd9SToby Isaac       } else {
573897e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
573997e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
574097e99dd9SToby Isaac           fuse(&a[k], values[offset+     k ] * (flip ? flip[     k ] : 1.));
574197e99dd9SToby Isaac         }
5742552f7358SJed Brown       }
5743552f7358SJed Brown     }
5744552f7358SJed Brown   }
5745552f7358SJed Brown   PetscFunctionReturn(0);
5746552f7358SJed Brown }
5747552f7358SJed Brown 
574897e99dd9SToby Isaac PETSC_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[])
5749a5e93ea8SMatthew G. Knepley {
5750a5e93ea8SMatthew G. Knepley   PetscInt        cdof;   /* The number of constraints on this point */
5751a5e93ea8SMatthew G. Knepley   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
5752a5e93ea8SMatthew G. Knepley   PetscScalar    *a;
5753a5e93ea8SMatthew G. Knepley   PetscInt        off, cind = 0, k;
5754a5e93ea8SMatthew G. Knepley   PetscErrorCode  ierr;
5755a5e93ea8SMatthew G. Knepley 
5756a5e93ea8SMatthew G. Knepley   PetscFunctionBegin;
5757a5e93ea8SMatthew G. Knepley   ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr);
5758a5e93ea8SMatthew G. Knepley   ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr);
5759a5e93ea8SMatthew G. Knepley   a    = &array[off];
5760a5e93ea8SMatthew G. Knepley   if (cdof) {
5761a5e93ea8SMatthew G. Knepley     ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr);
576297e99dd9SToby Isaac     if (clperm) {
576397e99dd9SToby Isaac       if (perm) {
5764a5e93ea8SMatthew G. Knepley         for (k = 0; k < dof; ++k) {
5765a5e93ea8SMatthew G. Knepley           if ((cind < cdof) && (k == cdofs[cind])) {
576697e99dd9SToby Isaac             fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));
576797e99dd9SToby Isaac             cind++;
5768a5e93ea8SMatthew G. Knepley           }
5769a5e93ea8SMatthew G. Knepley         }
5770a5e93ea8SMatthew G. Knepley       } else {
5771a5e93ea8SMatthew G. Knepley         for (k = 0; k < dof; ++k) {
5772a5e93ea8SMatthew G. Knepley           if ((cind < cdof) && (k == cdofs[cind])) {
577397e99dd9SToby Isaac             fuse(&a[k], values[clperm[offset+     k ]] * (flip ? flip[     k ] : 1.));
577497e99dd9SToby Isaac             cind++;
577597e99dd9SToby Isaac           }
577697e99dd9SToby Isaac         }
577797e99dd9SToby Isaac       }
577897e99dd9SToby Isaac     } else {
577997e99dd9SToby Isaac       if (perm) {
578097e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
578197e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {
578297e99dd9SToby Isaac             fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));
578397e99dd9SToby Isaac             cind++;
578497e99dd9SToby Isaac           }
578597e99dd9SToby Isaac         }
578697e99dd9SToby Isaac       } else {
578797e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
578897e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {
578997e99dd9SToby Isaac             fuse(&a[k], values[offset+     k ] * (flip ? flip[     k ] : 1.));
579097e99dd9SToby Isaac             cind++;
579197e99dd9SToby Isaac           }
5792a5e93ea8SMatthew G. Knepley         }
5793a5e93ea8SMatthew G. Knepley       }
5794a5e93ea8SMatthew G. Knepley     }
5795a5e93ea8SMatthew G. Knepley   }
5796a5e93ea8SMatthew G. Knepley   PetscFunctionReturn(0);
5797a5e93ea8SMatthew G. Knepley }
5798a5e93ea8SMatthew G. Knepley 
579997e99dd9SToby Isaac PETSC_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[])
5800a6dfd86eSKarl Rupp {
5801552f7358SJed Brown   PetscScalar    *a;
58021a271a75SMatthew G. Knepley   PetscInt        fdof, foff, fcdof, foffset = *offset;
58031a271a75SMatthew G. Knepley   const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
580497e99dd9SToby Isaac   PetscInt        cind = 0, b;
5805552f7358SJed Brown   PetscErrorCode  ierr;
5806552f7358SJed Brown 
5807552f7358SJed Brown   PetscFunctionBegin;
5808552f7358SJed Brown   ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr);
5809552f7358SJed Brown   ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr);
58101a271a75SMatthew G. Knepley   ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr);
58111a271a75SMatthew G. Knepley   a    = &array[foff];
5812552f7358SJed Brown   if (!fcdof || setBC) {
581397e99dd9SToby Isaac     if (clperm) {
581497e99dd9SToby Isaac       if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));}}
581597e99dd9SToby Isaac       else      {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+     b ]] * (flip ? flip[     b ] : 1.));}}
5816552f7358SJed Brown     } else {
581797e99dd9SToby Isaac       if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));}}
581897e99dd9SToby Isaac       else      {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+     b ] * (flip ? flip[     b ] : 1.));}}
5819552f7358SJed Brown     }
5820552f7358SJed Brown   } else {
5821552f7358SJed Brown     ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr);
582297e99dd9SToby Isaac     if (clperm) {
582397e99dd9SToby Isaac       if (perm) {
582497e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
582597e99dd9SToby Isaac           if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;}
582697e99dd9SToby Isaac           fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));
5827552f7358SJed Brown         }
5828552f7358SJed Brown       } else {
582997e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
583097e99dd9SToby Isaac           if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;}
583197e99dd9SToby Isaac           fuse(&a[b], values[clperm[foffset+     b ]] * (flip ? flip[     b ] : 1.));
583297e99dd9SToby Isaac         }
583397e99dd9SToby Isaac       }
583497e99dd9SToby Isaac     } else {
583597e99dd9SToby Isaac       if (perm) {
583697e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
583797e99dd9SToby Isaac           if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;}
583897e99dd9SToby Isaac           fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));
583997e99dd9SToby Isaac         }
584097e99dd9SToby Isaac       } else {
584197e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
584297e99dd9SToby Isaac           if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;}
584397e99dd9SToby Isaac           fuse(&a[b], values[foffset+     b ] * (flip ? flip[     b ] : 1.));
5844552f7358SJed Brown         }
5845552f7358SJed Brown       }
5846552f7358SJed Brown     }
5847552f7358SJed Brown   }
58481a271a75SMatthew G. Knepley   *offset += fdof;
5849552f7358SJed Brown   PetscFunctionReturn(0);
5850552f7358SJed Brown }
5851552f7358SJed Brown 
5852ba322698SMatthew G. Knepley PETSC_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[])
5853a5e93ea8SMatthew G. Knepley {
5854a5e93ea8SMatthew G. Knepley   PetscScalar    *a;
58551a271a75SMatthew G. Knepley   PetscInt        fdof, foff, fcdof, foffset = *offset;
58561a271a75SMatthew G. Knepley   const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
58575da9d227SMatthew G. Knepley   PetscInt        Nc, cind = 0, ncind = 0, b;
5858ba322698SMatthew G. Knepley   PetscBool       ncSet, fcSet;
5859a5e93ea8SMatthew G. Knepley   PetscErrorCode  ierr;
5860a5e93ea8SMatthew G. Knepley 
5861a5e93ea8SMatthew G. Knepley   PetscFunctionBegin;
58625da9d227SMatthew G. Knepley   ierr = PetscSectionGetFieldComponents(section, f, &Nc);CHKERRQ(ierr);
5863a5e93ea8SMatthew G. Knepley   ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr);
5864a5e93ea8SMatthew G. Knepley   ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr);
58651a271a75SMatthew G. Knepley   ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr);
58661a271a75SMatthew G. Knepley   a    = &array[foff];
5867a5e93ea8SMatthew G. Knepley   if (fcdof) {
5868ba322698SMatthew G. Knepley     /* We just override fcdof and fcdofs with Ncc and comps */
5869a5e93ea8SMatthew G. Knepley     ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr);
587097e99dd9SToby Isaac     if (clperm) {
587197e99dd9SToby Isaac       if (perm) {
5872ba322698SMatthew G. Knepley         if (comps) {
5873ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
5874ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
58755da9d227SMatthew G. Knepley             if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;}
5876ba322698SMatthew G. Knepley             if ((cind < fcdof) && (b == fcdofs[cind])) {++cind;  fcSet = PETSC_TRUE;}
5877ba322698SMatthew G. Knepley             if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));}
5878ba322698SMatthew G. Knepley           }
5879ba322698SMatthew G. Knepley         } else {
588097e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
588197e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
588297e99dd9SToby Isaac               fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));
5883a5e93ea8SMatthew G. Knepley               ++cind;
5884a5e93ea8SMatthew G. Knepley             }
5885a5e93ea8SMatthew G. Knepley           }
5886ba322698SMatthew G. Knepley         }
5887ba322698SMatthew G. Knepley       } else {
5888ba322698SMatthew G. Knepley         if (comps) {
5889ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
5890ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
58915da9d227SMatthew G. Knepley             if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;}
5892ba322698SMatthew G. Knepley             if ((cind < fcdof) && (b == fcdofs[cind])) {++cind;  fcSet = PETSC_TRUE;}
5893ba322698SMatthew G. Knepley             if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+     b ]] * (flip ? flip[     b ] : 1.));}
5894ba322698SMatthew G. Knepley           }
5895a5e93ea8SMatthew G. Knepley         } else {
589697e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
589797e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
589897e99dd9SToby Isaac               fuse(&a[b], values[clperm[foffset+     b ]] * (flip ? flip[     b ] : 1.));
589997e99dd9SToby Isaac               ++cind;
590097e99dd9SToby Isaac             }
590197e99dd9SToby Isaac           }
590297e99dd9SToby Isaac         }
5903ba322698SMatthew G. Knepley       }
590497e99dd9SToby Isaac     } else {
590597e99dd9SToby Isaac       if (perm) {
5906ba322698SMatthew G. Knepley         if (comps) {
5907ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
5908ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
59095da9d227SMatthew G. Knepley             if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;}
5910ba322698SMatthew G. Knepley             if ((cind < fcdof) && (b == fcdofs[cind])) {++cind;  fcSet = PETSC_TRUE;}
5911ba322698SMatthew G. Knepley             if (ncSet && fcSet) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));}
5912ba322698SMatthew G. Knepley           }
5913ba322698SMatthew G. Knepley         } else {
591497e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
591597e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
591697e99dd9SToby Isaac               fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));
591797e99dd9SToby Isaac               ++cind;
591897e99dd9SToby Isaac             }
591997e99dd9SToby Isaac           }
5920ba322698SMatthew G. Knepley         }
5921ba322698SMatthew G. Knepley       } else {
5922ba322698SMatthew G. Knepley         if (comps) {
5923ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
5924ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
59255da9d227SMatthew G. Knepley             if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;}
5926ba322698SMatthew G. Knepley             if ((cind < fcdof) && (b == fcdofs[cind])) {++cind;  fcSet = PETSC_TRUE;}
5927ba322698SMatthew G. Knepley             if (ncSet && fcSet) {fuse(&a[b], values[foffset+     b ] * (flip ? flip[     b ] : 1.));}
5928ba322698SMatthew G. Knepley           }
592997e99dd9SToby Isaac         } else {
593097e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
593197e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
593297e99dd9SToby Isaac               fuse(&a[b], values[foffset+     b ] * (flip ? flip[     b ] : 1.));
5933a5e93ea8SMatthew G. Knepley               ++cind;
5934a5e93ea8SMatthew G. Knepley             }
5935a5e93ea8SMatthew G. Knepley           }
5936a5e93ea8SMatthew G. Knepley         }
5937a5e93ea8SMatthew G. Knepley       }
5938a5e93ea8SMatthew G. Knepley     }
5939ba322698SMatthew G. Knepley   }
59401a271a75SMatthew G. Knepley   *offset += fdof;
5941a5e93ea8SMatthew G. Knepley   PetscFunctionReturn(0);
5942a5e93ea8SMatthew G. Knepley }
5943a5e93ea8SMatthew G. Knepley 
59448f3be42fSMatthew G. Knepley PETSC_STATIC_INLINE PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode)
5945a6dfd86eSKarl Rupp {
5946552f7358SJed Brown   PetscScalar    *array;
59471b406b76SMatthew G. Knepley   const PetscInt *cone, *coneO;
59481b406b76SMatthew G. Knepley   PetscInt        pStart, pEnd, p, numPoints, off, dof;
5949552f7358SJed Brown   PetscErrorCode  ierr;
5950552f7358SJed Brown 
59511b406b76SMatthew G. Knepley   PetscFunctionBeginHot;
5952b6ebb6e6SMatthew G. Knepley   ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr);
5953b6ebb6e6SMatthew G. Knepley   ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr);
5954b6ebb6e6SMatthew G. Knepley   ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr);
5955b6ebb6e6SMatthew G. Knepley   ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr);
5956b6ebb6e6SMatthew G. Knepley   ierr = VecGetArray(v, &array);CHKERRQ(ierr);
5957b6ebb6e6SMatthew G. Knepley   for (p = 0, off = 0; p <= numPoints; ++p, off += dof) {
5958b6ebb6e6SMatthew G. Knepley     const PetscInt cp = !p ? point : cone[p-1];
5959b6ebb6e6SMatthew G. Knepley     const PetscInt o  = !p ? 0     : coneO[p-1];
5960b6ebb6e6SMatthew G. Knepley 
5961b6ebb6e6SMatthew G. Knepley     if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;}
5962b6ebb6e6SMatthew G. Knepley     ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr);
5963b6ebb6e6SMatthew G. Knepley     /* ADD_VALUES */
5964b6ebb6e6SMatthew G. Knepley     {
5965b6ebb6e6SMatthew G. Knepley       const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
5966b6ebb6e6SMatthew G. Knepley       PetscScalar    *a;
5967b6ebb6e6SMatthew G. Knepley       PetscInt        cdof, coff, cind = 0, k;
5968b6ebb6e6SMatthew G. Knepley 
5969b6ebb6e6SMatthew G. Knepley       ierr = PetscSectionGetConstraintDof(section, cp, &cdof);CHKERRQ(ierr);
5970b6ebb6e6SMatthew G. Knepley       ierr = PetscSectionGetOffset(section, cp, &coff);CHKERRQ(ierr);
5971b6ebb6e6SMatthew G. Knepley       a    = &array[coff];
5972b6ebb6e6SMatthew G. Knepley       if (!cdof) {
5973b6ebb6e6SMatthew G. Knepley         if (o >= 0) {
5974b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
5975b6ebb6e6SMatthew G. Knepley             a[k] += values[off+k];
5976b6ebb6e6SMatthew G. Knepley           }
5977b6ebb6e6SMatthew G. Knepley         } else {
5978b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
5979b6ebb6e6SMatthew G. Knepley             a[k] += values[off+dof-k-1];
5980b6ebb6e6SMatthew G. Knepley           }
5981b6ebb6e6SMatthew G. Knepley         }
5982b6ebb6e6SMatthew G. Knepley       } else {
5983b6ebb6e6SMatthew G. Knepley         ierr = PetscSectionGetConstraintIndices(section, cp, &cdofs);CHKERRQ(ierr);
5984b6ebb6e6SMatthew G. Knepley         if (o >= 0) {
5985b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
5986b6ebb6e6SMatthew G. Knepley             if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
5987b6ebb6e6SMatthew G. Knepley             a[k] += values[off+k];
5988b6ebb6e6SMatthew G. Knepley           }
5989b6ebb6e6SMatthew G. Knepley         } else {
5990b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
5991b6ebb6e6SMatthew G. Knepley             if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
5992b6ebb6e6SMatthew G. Knepley             a[k] += values[off+dof-k-1];
5993b6ebb6e6SMatthew G. Knepley           }
5994b6ebb6e6SMatthew G. Knepley         }
5995b6ebb6e6SMatthew G. Knepley       }
5996b6ebb6e6SMatthew G. Knepley     }
5997b6ebb6e6SMatthew G. Knepley   }
5998b6ebb6e6SMatthew G. Knepley   ierr = VecRestoreArray(v, &array);CHKERRQ(ierr);
5999b6ebb6e6SMatthew G. Knepley   PetscFunctionReturn(0);
6000b6ebb6e6SMatthew G. Knepley }
60011b406b76SMatthew G. Knepley 
60021b406b76SMatthew G. Knepley /*@C
60031b406b76SMatthew G. Knepley   DMPlexVecSetClosure - Set an array of the values on the closure of 'point'
60041b406b76SMatthew G. Knepley 
60051b406b76SMatthew G. Knepley   Not collective
60061b406b76SMatthew G. Knepley 
60071b406b76SMatthew G. Knepley   Input Parameters:
60081b406b76SMatthew G. Knepley + dm - The DM
60091b406b76SMatthew G. Knepley . section - The section describing the layout in v, or NULL to use the default section
60101b406b76SMatthew G. Knepley . v - The local vector
6011eaf898f9SPatrick Sanan . point - The point in the DM
60121b406b76SMatthew G. Knepley . values - The array of values
601322c1ee49SMatthew 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,
601422c1ee49SMatthew G. Knepley          where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions.
60151b406b76SMatthew G. Knepley 
60161b406b76SMatthew G. Knepley   Fortran Notes:
60171b406b76SMatthew G. Knepley   This routine is only available in Fortran 90, and you must include petsc.h90 in your code.
60181b406b76SMatthew G. Knepley 
60191b406b76SMatthew G. Knepley   Level: intermediate
60201b406b76SMatthew G. Knepley 
60211b406b76SMatthew G. Knepley .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure()
60221b406b76SMatthew G. Knepley @*/
60231b406b76SMatthew G. Knepley PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode)
60241b406b76SMatthew G. Knepley {
60251b406b76SMatthew G. Knepley   PetscSection    clSection;
60261b406b76SMatthew G. Knepley   IS              clPoints;
60271b406b76SMatthew G. Knepley   PetscScalar    *array;
60281b406b76SMatthew G. Knepley   PetscInt       *points = NULL;
602927f02ce8SMatthew G. Knepley   const PetscInt *clp, *clperm = NULL;
6030c459fbc1SJed Brown   PetscInt        depth, numFields, numPoints, p, clsize;
60311b406b76SMatthew G. Knepley   PetscErrorCode  ierr;
60321b406b76SMatthew G. Knepley 
60331a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
60341b406b76SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
603592fd8e1eSJed Brown   if (!section) {ierr = DMGetLocalSection(dm, &section);CHKERRQ(ierr);}
60361a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
60371a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
60381b406b76SMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
60391b406b76SMatthew G. Knepley   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
60401b406b76SMatthew G. Knepley   if (depth == 1 && numFields < 2 && mode == ADD_VALUES) {
60418f3be42fSMatthew G. Knepley     ierr = DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode);CHKERRQ(ierr);
60421b406b76SMatthew G. Knepley     PetscFunctionReturn(0);
60431b406b76SMatthew G. Knepley   }
60441a271a75SMatthew G. Knepley   /* Get points */
6045923c78e0SToby Isaac   ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr);
6046c459fbc1SJed Brown   for (clsize=0,p=0; p<numPoints; p++) {
6047c459fbc1SJed Brown     PetscInt dof;
6048c459fbc1SJed Brown     ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr);
6049c459fbc1SJed Brown     clsize += dof;
6050c459fbc1SJed Brown   }
6051c459fbc1SJed Brown   ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm);CHKERRQ(ierr);
60521a271a75SMatthew G. Knepley   /* Get array */
6053552f7358SJed Brown   ierr = VecGetArray(v, &array);CHKERRQ(ierr);
60541a271a75SMatthew G. Knepley   /* Get values */
6055ef90cfe2SMatthew G. Knepley   if (numFields > 0) {
605697e99dd9SToby Isaac     PetscInt offset = 0, f;
6057552f7358SJed Brown     for (f = 0; f < numFields; ++f) {
605897e99dd9SToby Isaac       const PetscInt    **perms = NULL;
605997e99dd9SToby Isaac       const PetscScalar **flips = NULL;
606097e99dd9SToby Isaac 
606197e99dd9SToby Isaac       ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr);
6062552f7358SJed Brown       switch (mode) {
6063552f7358SJed Brown       case INSERT_VALUES:
606497e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
606597e99dd9SToby Isaac           const PetscInt    point = points[2*p];
606697e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
606797e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
606897e99dd9SToby Isaac           updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array);
6069552f7358SJed Brown         } break;
6070552f7358SJed Brown       case INSERT_ALL_VALUES:
607197e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
607297e99dd9SToby Isaac           const PetscInt    point = points[2*p];
607397e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
607497e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
607597e99dd9SToby Isaac           updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array);
6076552f7358SJed Brown         } break;
6077a5e93ea8SMatthew G. Knepley       case INSERT_BC_VALUES:
607897e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
607997e99dd9SToby Isaac           const PetscInt    point = points[2*p];
608097e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
608197e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
6082ba322698SMatthew G. Knepley           updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array);
6083a5e93ea8SMatthew G. Knepley         } break;
6084552f7358SJed Brown       case ADD_VALUES:
608597e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
608697e99dd9SToby Isaac           const PetscInt    point = points[2*p];
608797e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
608897e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
608997e99dd9SToby Isaac           updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array);
6090552f7358SJed Brown         } break;
6091552f7358SJed Brown       case ADD_ALL_VALUES:
609297e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
609397e99dd9SToby Isaac           const PetscInt    point = points[2*p];
609497e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
609597e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
609697e99dd9SToby Isaac           updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array);
6097552f7358SJed Brown         } break;
6098304ab55fSMatthew G. Knepley       case ADD_BC_VALUES:
609997e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
610097e99dd9SToby Isaac           const PetscInt    point = points[2*p];
610197e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
610297e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
6103ba322698SMatthew G. Knepley           updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array);
6104304ab55fSMatthew G. Knepley         } break;
6105552f7358SJed Brown       default:
6106f347f43bSBarry Smith         SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
6107552f7358SJed Brown       }
610897e99dd9SToby Isaac       ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr);
61091a271a75SMatthew G. Knepley     }
6110552f7358SJed Brown   } else {
61111a271a75SMatthew G. Knepley     PetscInt dof, off;
611297e99dd9SToby Isaac     const PetscInt    **perms = NULL;
611397e99dd9SToby Isaac     const PetscScalar **flips = NULL;
61141a271a75SMatthew G. Knepley 
611597e99dd9SToby Isaac     ierr = PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr);
6116552f7358SJed Brown     switch (mode) {
6117552f7358SJed Brown     case INSERT_VALUES:
611897e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
611997e99dd9SToby Isaac         const PetscInt    point = points[2*p];
612097e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
612197e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
612297e99dd9SToby Isaac         ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr);
612397e99dd9SToby Isaac         updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array);
6124552f7358SJed Brown       } break;
6125552f7358SJed Brown     case INSERT_ALL_VALUES:
612697e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
612797e99dd9SToby Isaac         const PetscInt    point = points[2*p];
612897e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
612997e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
613097e99dd9SToby Isaac         ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr);
613197e99dd9SToby Isaac         updatePoint_private(section, point, dof, insert, PETSC_TRUE,  perm, flip, clperm, values, off, array);
6132552f7358SJed Brown       } break;
6133a5e93ea8SMatthew G. Knepley     case INSERT_BC_VALUES:
613497e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
613597e99dd9SToby Isaac         const PetscInt    point = points[2*p];
613697e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
613797e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
613897e99dd9SToby Isaac         ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr);
613997e99dd9SToby Isaac         updatePointBC_private(section, point, dof, insert,  perm, flip, clperm, values, off, array);
6140a5e93ea8SMatthew G. Knepley       } break;
6141552f7358SJed Brown     case ADD_VALUES:
614297e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
614397e99dd9SToby Isaac         const PetscInt    point = points[2*p];
614497e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
614597e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
614697e99dd9SToby Isaac         ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr);
614797e99dd9SToby Isaac         updatePoint_private(section, point, dof, add,    PETSC_FALSE, perm, flip, clperm, values, off, array);
6148552f7358SJed Brown       } break;
6149552f7358SJed Brown     case ADD_ALL_VALUES:
615097e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
615197e99dd9SToby Isaac         const PetscInt    point = points[2*p];
615297e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
615397e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
615497e99dd9SToby Isaac         ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr);
615597e99dd9SToby Isaac         updatePoint_private(section, point, dof, add,    PETSC_TRUE,  perm, flip, clperm, values, off, array);
6156552f7358SJed Brown       } break;
6157304ab55fSMatthew G. Knepley     case ADD_BC_VALUES:
615897e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
615997e99dd9SToby Isaac         const PetscInt    point = points[2*p];
616097e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
616197e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
616297e99dd9SToby Isaac         ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr);
616397e99dd9SToby Isaac         updatePointBC_private(section, point, dof, add,  perm, flip, clperm, values, off, array);
6164304ab55fSMatthew G. Knepley       } break;
6165552f7358SJed Brown     default:
6166f347f43bSBarry Smith       SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
6167552f7358SJed Brown     }
616897e99dd9SToby Isaac     ierr = PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips);CHKERRQ(ierr);
6169552f7358SJed Brown   }
61701a271a75SMatthew G. Knepley   /* Cleanup points */
6171923c78e0SToby Isaac   ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr);
61721a271a75SMatthew G. Knepley   /* Cleanup array */
6173552f7358SJed Brown   ierr = VecRestoreArray(v, &array);CHKERRQ(ierr);
6174552f7358SJed Brown   PetscFunctionReturn(0);
6175552f7358SJed Brown }
6176552f7358SJed Brown 
61775f790a90SMatthew G. Knepley /* Check whether the given point is in the label. If not, update the offset to skip this point */
61785f790a90SMatthew G. Knepley PETSC_STATIC_INLINE PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset)
61795f790a90SMatthew G. Knepley {
61805f790a90SMatthew G. Knepley   PetscFunctionBegin;
61815f790a90SMatthew G. Knepley   if (label) {
61825f790a90SMatthew G. Knepley     PetscInt       val, fdof;
61835f790a90SMatthew G. Knepley     PetscErrorCode ierr;
61845f790a90SMatthew G. Knepley 
61855f790a90SMatthew G. Knepley     /* There is a problem with this:
61865f790a90SMatthew 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
61875f790a90SMatthew 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.
61885f790a90SMatthew G. Knepley        Thus I am only going to check val != -1, not val != labelId
61895f790a90SMatthew G. Knepley     */
61905f790a90SMatthew G. Knepley     ierr = DMLabelGetValue(label, point, &val);CHKERRQ(ierr);
61915f790a90SMatthew G. Knepley     if (val < 0) {
61925f790a90SMatthew G. Knepley       ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr);
61935f790a90SMatthew G. Knepley       *offset += fdof;
61945f790a90SMatthew G. Knepley       PetscFunctionReturn(1);
61955f790a90SMatthew G. Knepley     }
61965f790a90SMatthew G. Knepley   }
61975f790a90SMatthew G. Knepley   PetscFunctionReturn(0);
61985f790a90SMatthew G. Knepley }
61995f790a90SMatthew G. Knepley 
620097529cf3SJed Brown /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */
62015f790a90SMatthew 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)
6202e07394fbSMatthew G. Knepley {
6203e07394fbSMatthew G. Knepley   PetscSection      clSection;
6204e07394fbSMatthew G. Knepley   IS                clPoints;
6205e07394fbSMatthew G. Knepley   PetscScalar       *array;
6206e07394fbSMatthew G. Knepley   PetscInt          *points = NULL;
620797529cf3SJed Brown   const PetscInt    *clp;
6208e07394fbSMatthew G. Knepley   PetscInt          numFields, numPoints, p;
620997e99dd9SToby Isaac   PetscInt          offset = 0, f;
6210e07394fbSMatthew G. Knepley   PetscErrorCode    ierr;
6211e07394fbSMatthew G. Knepley 
6212e07394fbSMatthew G. Knepley   PetscFunctionBeginHot;
6213e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
621492fd8e1eSJed Brown   if (!section) {ierr = DMGetLocalSection(dm, &section);CHKERRQ(ierr);}
6215e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
6216e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
6217e07394fbSMatthew G. Knepley   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
6218e07394fbSMatthew G. Knepley   /* Get points */
6219923c78e0SToby Isaac   ierr = DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr);
6220e07394fbSMatthew G. Knepley   /* Get array */
6221e07394fbSMatthew G. Knepley   ierr = VecGetArray(v, &array);CHKERRQ(ierr);
6222e07394fbSMatthew G. Knepley   /* Get values */
6223e07394fbSMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
622497e99dd9SToby Isaac     const PetscInt    **perms = NULL;
622597e99dd9SToby Isaac     const PetscScalar **flips = NULL;
622697e99dd9SToby Isaac 
6227e07394fbSMatthew G. Knepley     if (!fieldActive[f]) {
6228e07394fbSMatthew G. Knepley       for (p = 0; p < numPoints*2; p += 2) {
6229e07394fbSMatthew G. Knepley         PetscInt fdof;
6230e07394fbSMatthew G. Knepley         ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr);
6231e07394fbSMatthew G. Knepley         offset += fdof;
6232e07394fbSMatthew G. Knepley       }
6233e07394fbSMatthew G. Knepley       continue;
6234e07394fbSMatthew G. Knepley     }
623597e99dd9SToby Isaac     ierr = PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr);
6236e07394fbSMatthew G. Knepley     switch (mode) {
6237e07394fbSMatthew G. Knepley     case INSERT_VALUES:
623897e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
623997e99dd9SToby Isaac         const PetscInt    point = points[2*p];
624097e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
624197e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
62425f790a90SMatthew G. Knepley         ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue;
624397529cf3SJed Brown         updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array);
6244e07394fbSMatthew G. Knepley       } break;
6245e07394fbSMatthew G. Knepley     case INSERT_ALL_VALUES:
624697e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
624797e99dd9SToby Isaac         const PetscInt    point = points[2*p];
624897e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
624997e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
62505f790a90SMatthew G. Knepley         ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue;
625197529cf3SJed Brown         updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array);
6252e07394fbSMatthew G. Knepley       } break;
6253e07394fbSMatthew G. Knepley     case INSERT_BC_VALUES:
625497e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
625597e99dd9SToby Isaac         const PetscInt    point = points[2*p];
625697e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
625797e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
62585f790a90SMatthew G. Knepley         ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue;
625997529cf3SJed Brown         updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array);
6260e07394fbSMatthew G. Knepley       } break;
6261e07394fbSMatthew G. Knepley     case ADD_VALUES:
626297e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
626397e99dd9SToby Isaac         const PetscInt    point = points[2*p];
626497e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
626597e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
62665f790a90SMatthew G. Knepley         ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue;
626797529cf3SJed Brown         updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array);
6268e07394fbSMatthew G. Knepley       } break;
6269e07394fbSMatthew G. Knepley     case ADD_ALL_VALUES:
627097e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
627197e99dd9SToby Isaac         const PetscInt    point = points[2*p];
627297e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
627397e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
62745f790a90SMatthew G. Knepley         ierr = CheckPoint_Private(label, labelId, section, point, f, &offset); if (ierr) continue;
627597529cf3SJed Brown         updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array);
6276e07394fbSMatthew G. Knepley       } break;
6277e07394fbSMatthew G. Knepley     default:
6278f347f43bSBarry Smith       SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
6279e07394fbSMatthew G. Knepley     }
628097e99dd9SToby Isaac     ierr = PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips);CHKERRQ(ierr);
6281e07394fbSMatthew G. Knepley   }
6282e07394fbSMatthew G. Knepley   /* Cleanup points */
6283923c78e0SToby Isaac   ierr = DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp);CHKERRQ(ierr);
6284e07394fbSMatthew G. Knepley   /* Cleanup array */
6285e07394fbSMatthew G. Knepley   ierr = VecRestoreArray(v, &array);CHKERRQ(ierr);
6286e07394fbSMatthew G. Knepley   PetscFunctionReturn(0);
6287e07394fbSMatthew G. Knepley }
6288e07394fbSMatthew G. Knepley 
62897cd05799SMatthew G. Knepley static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[])
6290552f7358SJed Brown {
6291552f7358SJed Brown   PetscMPIInt    rank;
6292552f7358SJed Brown   PetscInt       i, j;
6293552f7358SJed Brown   PetscErrorCode ierr;
6294552f7358SJed Brown 
6295552f7358SJed Brown   PetscFunctionBegin;
6296ffc4695bSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr);
6297eaf898f9SPatrick Sanan   ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat for point %D\n", rank, point);CHKERRQ(ierr);
6298e4b003c7SBarry Smith   for (i = 0; i < numRIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%D] = %D\n", rank, i, rindices[i]);CHKERRQ(ierr);}
6299e4b003c7SBarry Smith   for (i = 0; i < numCIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%D] = %D\n", rank, i, cindices[i]);CHKERRQ(ierr);}
6300b0ecff45SMatthew G. Knepley   numCIndices = numCIndices ? numCIndices : numRIndices;
6301557cf195SMatthew G. Knepley   if (!values) PetscFunctionReturn(0);
6302b0ecff45SMatthew G. Knepley   for (i = 0; i < numRIndices; i++) {
6303e4b003c7SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer, "[%d]", rank);CHKERRQ(ierr);
6304b0ecff45SMatthew G. Knepley     for (j = 0; j < numCIndices; j++) {
6305519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX)
63067eba1a17SMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j]));CHKERRQ(ierr);
6307552f7358SJed Brown #else
6308b0ecff45SMatthew G. Knepley       ierr = PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j]);CHKERRQ(ierr);
6309552f7358SJed Brown #endif
6310552f7358SJed Brown     }
631177a6746dSMatthew G Knepley     ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr);
6312552f7358SJed Brown   }
6313552f7358SJed Brown   PetscFunctionReturn(0);
6314552f7358SJed Brown }
6315552f7358SJed Brown 
631605586334SMatthew G. Knepley /*
631705586334SMatthew G. Knepley   DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array
631805586334SMatthew G. Knepley 
631905586334SMatthew G. Knepley   Input Parameters:
632005586334SMatthew G. Knepley + section - The section for this data layout
632136fa2b79SJed Brown . islocal - Is the section (and thus indices being requested) local or global?
632205586334SMatthew G. Knepley . point   - The point contributing dofs with these indices
632305586334SMatthew G. Knepley . off     - The global offset of this point
632405586334SMatthew G. Knepley . loff    - The local offset of each field
632505586334SMatthew G. Knepley . setBC   - The flag determining whether to include indices of bounsary values
632605586334SMatthew G. Knepley . perm    - A permutation of the dofs on this point, or NULL
632705586334SMatthew G. Knepley - indperm - A permutation of the entire indices array, or NULL
632805586334SMatthew G. Knepley 
632905586334SMatthew G. Knepley   Output Parameter:
633005586334SMatthew G. Knepley . indices - Indices for dofs on this point
633105586334SMatthew G. Knepley 
633205586334SMatthew G. Knepley   Level: developer
633305586334SMatthew G. Knepley 
633405586334SMatthew G. Knepley   Note: The indices could be local or global, depending on the value of 'off'.
633505586334SMatthew G. Knepley */
633636fa2b79SJed Brown PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal,PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[])
6337a6dfd86eSKarl Rupp {
6338e6ccafaeSMatthew G Knepley   PetscInt        dof;   /* The number of unknowns on this point */
6339552f7358SJed Brown   PetscInt        cdof;  /* The number of constraints on this point */
6340552f7358SJed Brown   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6341552f7358SJed Brown   PetscInt        cind = 0, k;
6342552f7358SJed Brown   PetscErrorCode  ierr;
6343552f7358SJed Brown 
6344552f7358SJed Brown   PetscFunctionBegin;
634536fa2b79SJed Brown   if (!islocal && setBC) SETERRQ(PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC");
6346552f7358SJed Brown   ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr);
6347552f7358SJed Brown   ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr);
6348552f7358SJed Brown   if (!cdof || setBC) {
634905586334SMatthew G. Knepley     for (k = 0; k < dof; ++k) {
635005586334SMatthew G. Knepley       const PetscInt preind = perm ? *loff+perm[k] : *loff+k;
635105586334SMatthew G. Knepley       const PetscInt ind    = indperm ? indperm[preind] : preind;
635205586334SMatthew G. Knepley 
635305586334SMatthew G. Knepley       indices[ind] = off + k;
6354552f7358SJed Brown     }
6355552f7358SJed Brown   } else {
6356552f7358SJed Brown     ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr);
63574acb8e1eSToby Isaac     for (k = 0; k < dof; ++k) {
635805586334SMatthew G. Knepley       const PetscInt preind = perm ? *loff+perm[k] : *loff+k;
635905586334SMatthew G. Knepley       const PetscInt ind    = indperm ? indperm[preind] : preind;
636005586334SMatthew G. Knepley 
63614acb8e1eSToby Isaac       if ((cind < cdof) && (k == cdofs[cind])) {
63624acb8e1eSToby Isaac         /* Insert check for returning constrained indices */
636305586334SMatthew G. Knepley         indices[ind] = -(off+k+1);
63644acb8e1eSToby Isaac         ++cind;
63654acb8e1eSToby Isaac       } else {
636636fa2b79SJed Brown         indices[ind] = off + k - (islocal ? 0 : cind);
6367552f7358SJed Brown       }
6368552f7358SJed Brown     }
6369552f7358SJed Brown   }
6370e6ccafaeSMatthew G Knepley   *loff += dof;
6371552f7358SJed Brown   PetscFunctionReturn(0);
6372552f7358SJed Brown }
6373552f7358SJed Brown 
63747e29afd2SMatthew G. Knepley /*
637536fa2b79SJed Brown  DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering.
63767e29afd2SMatthew G. Knepley 
637736fa2b79SJed Brown  Input Parameters:
637836fa2b79SJed Brown + section - a section (global or local)
637936fa2b79SJed Brown - islocal - PETSC_TRUE if requesting local indices (i.e., section is local); PETSC_FALSE for global
638036fa2b79SJed Brown . point - point within section
638136fa2b79SJed Brown . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section
638236fa2b79SJed Brown . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field
638336fa2b79SJed Brown . setBC - identify constrained (boundary condition) points via involution.
638436fa2b79SJed Brown . perms - perms[f][permsoff][:] is a permutation of dofs within each field
638536fa2b79SJed Brown . permsoff - offset
638636fa2b79SJed Brown - indperm - index permutation
638736fa2b79SJed Brown 
638836fa2b79SJed Brown  Output Parameter:
638936fa2b79SJed Brown . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field
639036fa2b79SJed Brown . indices - array to hold indices (as defined by section) of each dof associated with point
639136fa2b79SJed Brown 
639236fa2b79SJed Brown  Notes:
639336fa2b79SJed Brown  If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs.
639436fa2b79SJed Brown  If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position
639536fa2b79SJed Brown  in the local vector.
639636fa2b79SJed Brown 
639736fa2b79SJed Brown  If section is global and setBC=false, the indices for constrained points are negative (and their value is not
639836fa2b79SJed Brown  significant).  It is invalid to call with a global section and setBC=true.
639936fa2b79SJed Brown 
640036fa2b79SJed Brown  Developer Note:
640136fa2b79SJed Brown  The section is only used for field layout, so islocal is technically a statement about the offset (off).  At some point
640236fa2b79SJed Brown  in the future, global sections may have fields set, in which case we could pass the global section and obtain the
640336fa2b79SJed Brown  offset could be obtained from the section instead of passing it explicitly as we do now.
640436fa2b79SJed Brown 
640536fa2b79SJed Brown  Example:
640636fa2b79SJed Brown  Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}.
640736fa2b79SJed Brown  When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE).
640836fa2b79SJed Brown  Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices.
640936fa2b79SJed 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.
641036fa2b79SJed Brown 
641136fa2b79SJed Brown  Level: developer
64127e29afd2SMatthew G. Knepley */
641336fa2b79SJed 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[])
6414a6dfd86eSKarl Rupp {
6415552f7358SJed Brown   PetscInt       numFields, foff, f;
6416552f7358SJed Brown   PetscErrorCode ierr;
6417552f7358SJed Brown 
6418552f7358SJed Brown   PetscFunctionBegin;
641936fa2b79SJed Brown   if (!islocal && setBC) SETERRQ(PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC");
6420552f7358SJed Brown   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
6421552f7358SJed Brown   for (f = 0, foff = 0; f < numFields; ++f) {
64224acb8e1eSToby Isaac     PetscInt        fdof, cfdof;
6423552f7358SJed Brown     const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
64244acb8e1eSToby Isaac     PetscInt        cind = 0, b;
64254acb8e1eSToby Isaac     const PetscInt  *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL;
6426552f7358SJed Brown 
6427552f7358SJed Brown     ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr);
6428552f7358SJed Brown     ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr);
6429552f7358SJed Brown     if (!cfdof || setBC) {
643005586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
643105586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b;
643205586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
643305586334SMatthew G. Knepley 
643405586334SMatthew G. Knepley         indices[ind] = off+foff+b;
643505586334SMatthew G. Knepley       }
6436552f7358SJed Brown     } else {
6437552f7358SJed Brown       ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr);
643805586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
643905586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b;
644005586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
644105586334SMatthew G. Knepley 
64424acb8e1eSToby Isaac         if ((cind < cfdof) && (b == fcdofs[cind])) {
644305586334SMatthew G. Knepley           indices[ind] = -(off+foff+b+1);
6444552f7358SJed Brown           ++cind;
6445552f7358SJed Brown         } else {
644636fa2b79SJed Brown           indices[ind] = off + foff + b - (islocal ? 0 : cind);
6447552f7358SJed Brown         }
6448552f7358SJed Brown       }
6449552f7358SJed Brown     }
645036fa2b79SJed Brown     foff     += (setBC || islocal ? fdof : (fdof - cfdof));
6451552f7358SJed Brown     foffs[f] += fdof;
6452552f7358SJed Brown   }
6453552f7358SJed Brown   PetscFunctionReturn(0);
6454552f7358SJed Brown }
6455552f7358SJed Brown 
64567e29afd2SMatthew G. Knepley /*
64577e29afd2SMatthew G. Knepley   This version believes the globalSection offsets for each field, rather than just the point offset
64587e29afd2SMatthew G. Knepley 
64597e29afd2SMatthew G. Knepley  . foffs - The offset into 'indices' for each field, since it is segregated by field
6460645102dcSJed Brown 
6461645102dcSJed Brown  Notes:
6462645102dcSJed Brown  The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal.
6463645102dcSJed Brown  Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists.
64647e29afd2SMatthew G. Knepley */
6465645102dcSJed Brown static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[])
64667e29afd2SMatthew G. Knepley {
64677e29afd2SMatthew G. Knepley   PetscInt       numFields, foff, f;
64687e29afd2SMatthew G. Knepley   PetscErrorCode ierr;
64697e29afd2SMatthew G. Knepley 
64707e29afd2SMatthew G. Knepley   PetscFunctionBegin;
64717e29afd2SMatthew G. Knepley   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
64727e29afd2SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
64737e29afd2SMatthew G. Knepley     PetscInt        fdof, cfdof;
64747e29afd2SMatthew G. Knepley     const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
64757e29afd2SMatthew G. Knepley     PetscInt        cind = 0, b;
64767e29afd2SMatthew G. Knepley     const PetscInt  *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL;
64777e29afd2SMatthew G. Knepley 
64787e29afd2SMatthew G. Knepley     ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr);
64797e29afd2SMatthew G. Knepley     ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr);
64807e29afd2SMatthew G. Knepley     ierr = PetscSectionGetFieldOffset(globalSection, point, f, &foff);CHKERRQ(ierr);
6481645102dcSJed Brown     if (!cfdof) {
648205586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
648305586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b;
648405586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
648505586334SMatthew G. Knepley 
648605586334SMatthew G. Knepley         indices[ind] = foff+b;
648705586334SMatthew G. Knepley       }
64887e29afd2SMatthew G. Knepley     } else {
64897e29afd2SMatthew G. Knepley       ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr);
649005586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
649105586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b;
649205586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
649305586334SMatthew G. Knepley 
64947e29afd2SMatthew G. Knepley         if ((cind < cfdof) && (b == fcdofs[cind])) {
649505586334SMatthew G. Knepley           indices[ind] = -(foff+b+1);
64967e29afd2SMatthew G. Knepley           ++cind;
64977e29afd2SMatthew G. Knepley         } else {
649805586334SMatthew G. Knepley           indices[ind] = foff+b-cind;
64997e29afd2SMatthew G. Knepley         }
65007e29afd2SMatthew G. Knepley       }
65017e29afd2SMatthew G. Knepley     }
65027e29afd2SMatthew G. Knepley     foffs[f] += fdof;
65037e29afd2SMatthew G. Knepley   }
65047e29afd2SMatthew G. Knepley   PetscFunctionReturn(0);
65057e29afd2SMatthew G. Knepley }
65067e29afd2SMatthew G. Knepley 
65074acb8e1eSToby 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)
6508d3d1a6afSToby Isaac {
6509d3d1a6afSToby Isaac   Mat             cMat;
6510d3d1a6afSToby Isaac   PetscSection    aSec, cSec;
6511d3d1a6afSToby Isaac   IS              aIS;
6512d3d1a6afSToby Isaac   PetscInt        aStart = -1, aEnd = -1;
6513d3d1a6afSToby Isaac   const PetscInt  *anchors;
6514e17c06e0SMatthew G. Knepley   PetscInt        numFields, f, p, q, newP = 0;
6515d3d1a6afSToby Isaac   PetscInt        newNumPoints = 0, newNumIndices = 0;
6516d3d1a6afSToby Isaac   PetscInt        *newPoints, *indices, *newIndices;
6517d3d1a6afSToby Isaac   PetscInt        maxAnchor, maxDof;
6518d3d1a6afSToby Isaac   PetscInt        newOffsets[32];
6519d3d1a6afSToby Isaac   PetscInt        *pointMatOffsets[32];
6520d3d1a6afSToby Isaac   PetscInt        *newPointOffsets[32];
6521d3d1a6afSToby Isaac   PetscScalar     *pointMat[32];
65226ecaa68aSToby Isaac   PetscScalar     *newValues=NULL,*tmpValues;
6523d3d1a6afSToby Isaac   PetscBool       anyConstrained = PETSC_FALSE;
6524d3d1a6afSToby Isaac   PetscErrorCode  ierr;
6525d3d1a6afSToby Isaac 
6526d3d1a6afSToby Isaac   PetscFunctionBegin;
6527d3d1a6afSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6528d3d1a6afSToby Isaac   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
6529d3d1a6afSToby Isaac   ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr);
6530d3d1a6afSToby Isaac 
6531a17985deSToby Isaac   ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr);
6532d3d1a6afSToby Isaac   /* if there are point-to-point constraints */
6533d3d1a6afSToby Isaac   if (aSec) {
6534580bdb30SBarry Smith     ierr = PetscArrayzero(newOffsets, 32);CHKERRQ(ierr);
6535d3d1a6afSToby Isaac     ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr);
6536d3d1a6afSToby Isaac     ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr);
6537d3d1a6afSToby Isaac     /* figure out how many points are going to be in the new element matrix
6538d3d1a6afSToby Isaac      * (we allow double counting, because it's all just going to be summed
6539d3d1a6afSToby Isaac      * into the global matrix anyway) */
6540d3d1a6afSToby Isaac     for (p = 0; p < 2*numPoints; p+=2) {
6541d3d1a6afSToby Isaac       PetscInt b    = points[p];
65424b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
6543d3d1a6afSToby Isaac 
65444b2f2278SToby Isaac       ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr);
65454b2f2278SToby Isaac       if (!bSecDof) {
65464b2f2278SToby Isaac         continue;
65474b2f2278SToby Isaac       }
6548d3d1a6afSToby Isaac       if (b >= aStart && b < aEnd) {
6549d3d1a6afSToby Isaac         ierr = PetscSectionGetDof(aSec,b,&bDof);CHKERRQ(ierr);
6550d3d1a6afSToby Isaac       }
6551d3d1a6afSToby Isaac       if (bDof) {
6552d3d1a6afSToby Isaac         /* this point is constrained */
6553d3d1a6afSToby Isaac         /* it is going to be replaced by its anchors */
6554d3d1a6afSToby Isaac         PetscInt bOff, q;
6555d3d1a6afSToby Isaac 
6556d3d1a6afSToby Isaac         anyConstrained = PETSC_TRUE;
6557d3d1a6afSToby Isaac         newNumPoints  += bDof;
6558d3d1a6afSToby Isaac         ierr = PetscSectionGetOffset(aSec,b,&bOff);CHKERRQ(ierr);
6559d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
6560d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q];
6561d3d1a6afSToby Isaac           PetscInt aDof;
6562d3d1a6afSToby Isaac 
6563d3d1a6afSToby Isaac           ierr           = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr);
6564d3d1a6afSToby Isaac           newNumIndices += aDof;
6565d3d1a6afSToby Isaac           for (f = 0; f < numFields; ++f) {
6566d3d1a6afSToby Isaac             PetscInt fDof;
6567d3d1a6afSToby Isaac 
6568d3d1a6afSToby Isaac             ierr             = PetscSectionGetFieldDof(section, a, f, &fDof);CHKERRQ(ierr);
6569d3d1a6afSToby Isaac             newOffsets[f+1] += fDof;
6570d3d1a6afSToby Isaac           }
6571d3d1a6afSToby Isaac         }
6572d3d1a6afSToby Isaac       }
6573d3d1a6afSToby Isaac       else {
6574d3d1a6afSToby Isaac         /* this point is not constrained */
6575d3d1a6afSToby Isaac         newNumPoints++;
65764b2f2278SToby Isaac         newNumIndices += bSecDof;
6577d3d1a6afSToby Isaac         for (f = 0; f < numFields; ++f) {
6578d3d1a6afSToby Isaac           PetscInt fDof;
6579d3d1a6afSToby Isaac 
6580d3d1a6afSToby Isaac           ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr);
6581d3d1a6afSToby Isaac           newOffsets[f+1] += fDof;
6582d3d1a6afSToby Isaac         }
6583d3d1a6afSToby Isaac       }
6584d3d1a6afSToby Isaac     }
6585d3d1a6afSToby Isaac   }
6586d3d1a6afSToby Isaac   if (!anyConstrained) {
658772b80496SMatthew G. Knepley     if (outNumPoints)  *outNumPoints  = 0;
658872b80496SMatthew G. Knepley     if (outNumIndices) *outNumIndices = 0;
658972b80496SMatthew G. Knepley     if (outPoints)     *outPoints     = NULL;
659072b80496SMatthew G. Knepley     if (outValues)     *outValues     = NULL;
659172b80496SMatthew G. Knepley     if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);}
6592d3d1a6afSToby Isaac     PetscFunctionReturn(0);
6593d3d1a6afSToby Isaac   }
6594d3d1a6afSToby Isaac 
65956ecaa68aSToby Isaac   if (outNumPoints)  *outNumPoints  = newNumPoints;
65966ecaa68aSToby Isaac   if (outNumIndices) *outNumIndices = newNumIndices;
65976ecaa68aSToby Isaac 
6598f13f9184SToby Isaac   for (f = 0; f < numFields; ++f) newOffsets[f+1] += newOffsets[f];
6599d3d1a6afSToby Isaac 
66006ecaa68aSToby Isaac   if (!outPoints && !outValues) {
66016ecaa68aSToby Isaac     if (offsets) {
66026ecaa68aSToby Isaac       for (f = 0; f <= numFields; f++) {
66036ecaa68aSToby Isaac         offsets[f] = newOffsets[f];
66046ecaa68aSToby Isaac       }
66056ecaa68aSToby Isaac     }
66066ecaa68aSToby Isaac     if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);}
66076ecaa68aSToby Isaac     PetscFunctionReturn(0);
66086ecaa68aSToby Isaac   }
66096ecaa68aSToby Isaac 
6610f347f43bSBarry Smith   if (numFields && newOffsets[numFields] != newNumIndices) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", newOffsets[numFields], newNumIndices);
6611d3d1a6afSToby Isaac 
6612f7c74593SToby Isaac   ierr = DMGetDefaultConstraints(dm, &cSec, &cMat);CHKERRQ(ierr);
6613d3d1a6afSToby Isaac 
6614d3d1a6afSToby Isaac   /* workspaces */
6615d3d1a6afSToby Isaac   if (numFields) {
6616d3d1a6afSToby Isaac     for (f = 0; f < numFields; f++) {
661769291d52SBarry Smith       ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr);
661869291d52SBarry Smith       ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr);
6619d3d1a6afSToby Isaac     }
6620d3d1a6afSToby Isaac   }
6621d3d1a6afSToby Isaac   else {
662269291d52SBarry Smith     ierr = DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr);
662369291d52SBarry Smith     ierr = DMGetWorkArray(dm,numPoints,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr);
6624d3d1a6afSToby Isaac   }
6625d3d1a6afSToby Isaac 
6626d3d1a6afSToby Isaac   /* get workspaces for the point-to-point matrices */
6627d3d1a6afSToby Isaac   if (numFields) {
66284b2f2278SToby Isaac     PetscInt totalOffset, totalMatOffset;
66294b2f2278SToby Isaac 
6630d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
6631d3d1a6afSToby Isaac       PetscInt b    = points[2*p];
66324b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
6633d3d1a6afSToby Isaac 
66344b2f2278SToby Isaac       ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr);
66354b2f2278SToby Isaac       if (!bSecDof) {
66364b2f2278SToby Isaac         for (f = 0; f < numFields; f++) {
66374b2f2278SToby Isaac           newPointOffsets[f][p + 1] = 0;
66384b2f2278SToby Isaac           pointMatOffsets[f][p + 1] = 0;
66394b2f2278SToby Isaac         }
66404b2f2278SToby Isaac         continue;
66414b2f2278SToby Isaac       }
6642d3d1a6afSToby Isaac       if (b >= aStart && b < aEnd) {
6643d3d1a6afSToby Isaac         ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr);
6644d3d1a6afSToby Isaac       }
6645d3d1a6afSToby Isaac       if (bDof) {
6646d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
6647d3d1a6afSToby Isaac           PetscInt fDof, q, bOff, allFDof = 0;
6648d3d1a6afSToby Isaac 
6649d3d1a6afSToby Isaac           ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr);
6650d3d1a6afSToby Isaac           ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr);
6651d3d1a6afSToby Isaac           for (q = 0; q < bDof; q++) {
6652d3d1a6afSToby Isaac             PetscInt a = anchors[bOff + q];
6653d3d1a6afSToby Isaac             PetscInt aFDof;
6654d3d1a6afSToby Isaac 
6655d3d1a6afSToby Isaac             ierr     = PetscSectionGetFieldDof(section, a, f, &aFDof);CHKERRQ(ierr);
6656d3d1a6afSToby Isaac             allFDof += aFDof;
6657d3d1a6afSToby Isaac           }
6658d3d1a6afSToby Isaac           newPointOffsets[f][p+1] = allFDof;
6659d3d1a6afSToby Isaac           pointMatOffsets[f][p+1] = fDof * allFDof;
6660d3d1a6afSToby Isaac         }
6661d3d1a6afSToby Isaac       }
6662d3d1a6afSToby Isaac       else {
6663d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
6664d3d1a6afSToby Isaac           PetscInt fDof;
6665d3d1a6afSToby Isaac 
6666d3d1a6afSToby Isaac           ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr);
6667d3d1a6afSToby Isaac           newPointOffsets[f][p+1] = fDof;
6668d3d1a6afSToby Isaac           pointMatOffsets[f][p+1] = 0;
6669d3d1a6afSToby Isaac         }
6670d3d1a6afSToby Isaac       }
6671d3d1a6afSToby Isaac     }
66724b2f2278SToby Isaac     for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) {
66734b2f2278SToby Isaac       newPointOffsets[f][0] = totalOffset;
66744b2f2278SToby Isaac       pointMatOffsets[f][0] = totalMatOffset;
6675d3d1a6afSToby Isaac       for (p = 0; p < numPoints; p++) {
6676d3d1a6afSToby Isaac         newPointOffsets[f][p+1] += newPointOffsets[f][p];
6677d3d1a6afSToby Isaac         pointMatOffsets[f][p+1] += pointMatOffsets[f][p];
6678d3d1a6afSToby Isaac       }
667919f70fd5SToby Isaac       totalOffset    = newPointOffsets[f][numPoints];
668019f70fd5SToby Isaac       totalMatOffset = pointMatOffsets[f][numPoints];
668169291d52SBarry Smith       ierr = DMGetWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr);
6682d3d1a6afSToby Isaac     }
6683d3d1a6afSToby Isaac   }
6684d3d1a6afSToby Isaac   else {
6685d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
6686d3d1a6afSToby Isaac       PetscInt b    = points[2*p];
66874b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
6688d3d1a6afSToby Isaac 
66894b2f2278SToby Isaac       ierr = PetscSectionGetDof(section,b,&bSecDof);CHKERRQ(ierr);
66904b2f2278SToby Isaac       if (!bSecDof) {
66914b2f2278SToby Isaac         newPointOffsets[0][p + 1] = 0;
66924b2f2278SToby Isaac         pointMatOffsets[0][p + 1] = 0;
66934b2f2278SToby Isaac         continue;
66944b2f2278SToby Isaac       }
6695d3d1a6afSToby Isaac       if (b >= aStart && b < aEnd) {
6696d3d1a6afSToby Isaac         ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr);
6697d3d1a6afSToby Isaac       }
6698d3d1a6afSToby Isaac       if (bDof) {
66994b2f2278SToby Isaac         PetscInt bOff, q, allDof = 0;
6700d3d1a6afSToby Isaac 
6701d3d1a6afSToby Isaac         ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr);
6702d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
6703d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aDof;
6704d3d1a6afSToby Isaac 
6705d3d1a6afSToby Isaac           ierr    = PetscSectionGetDof(section, a, &aDof);CHKERRQ(ierr);
6706d3d1a6afSToby Isaac           allDof += aDof;
6707d3d1a6afSToby Isaac         }
6708d3d1a6afSToby Isaac         newPointOffsets[0][p+1] = allDof;
67094b2f2278SToby Isaac         pointMatOffsets[0][p+1] = bSecDof * allDof;
6710d3d1a6afSToby Isaac       }
6711d3d1a6afSToby Isaac       else {
67124b2f2278SToby Isaac         newPointOffsets[0][p+1] = bSecDof;
6713d3d1a6afSToby Isaac         pointMatOffsets[0][p+1] = 0;
6714d3d1a6afSToby Isaac       }
6715d3d1a6afSToby Isaac     }
6716d3d1a6afSToby Isaac     newPointOffsets[0][0] = 0;
6717d3d1a6afSToby Isaac     pointMatOffsets[0][0] = 0;
6718d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
6719d3d1a6afSToby Isaac       newPointOffsets[0][p+1] += newPointOffsets[0][p];
6720d3d1a6afSToby Isaac       pointMatOffsets[0][p+1] += pointMatOffsets[0][p];
6721d3d1a6afSToby Isaac     }
672269291d52SBarry Smith     ierr = DMGetWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr);
6723d3d1a6afSToby Isaac   }
6724d3d1a6afSToby Isaac 
67256ecaa68aSToby Isaac   /* output arrays */
672669291d52SBarry Smith   ierr = DMGetWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr);
67276ecaa68aSToby Isaac 
6728d3d1a6afSToby Isaac   /* get the point-to-point matrices; construct newPoints */
6729d3d1a6afSToby Isaac   ierr = PetscSectionGetMaxDof(aSec, &maxAnchor);CHKERRQ(ierr);
6730d3d1a6afSToby Isaac   ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr);
673169291d52SBarry Smith   ierr = DMGetWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr);
673269291d52SBarry Smith   ierr = DMGetWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr);
6733d3d1a6afSToby Isaac   if (numFields) {
6734d3d1a6afSToby Isaac     for (p = 0, newP = 0; p < numPoints; p++) {
6735d3d1a6afSToby Isaac       PetscInt b    = points[2*p];
6736d3d1a6afSToby Isaac       PetscInt o    = points[2*p+1];
67374b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
6738d3d1a6afSToby Isaac 
67394b2f2278SToby Isaac       ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr);
67404b2f2278SToby Isaac       if (!bSecDof) {
67414b2f2278SToby Isaac         continue;
67424b2f2278SToby Isaac       }
6743d3d1a6afSToby Isaac       if (b >= aStart && b < aEnd) {
6744d3d1a6afSToby Isaac         ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr);
6745d3d1a6afSToby Isaac       }
6746d3d1a6afSToby Isaac       if (bDof) {
6747d3d1a6afSToby Isaac         PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q;
6748d3d1a6afSToby Isaac 
6749d3d1a6afSToby Isaac         fStart[0] = 0;
6750d3d1a6afSToby Isaac         fEnd[0]   = 0;
6751d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
6752d3d1a6afSToby Isaac           PetscInt fDof;
6753d3d1a6afSToby Isaac 
6754d3d1a6afSToby Isaac           ierr        = PetscSectionGetFieldDof(cSec, b, f, &fDof);CHKERRQ(ierr);
6755d3d1a6afSToby Isaac           fStart[f+1] = fStart[f] + fDof;
6756d3d1a6afSToby Isaac           fEnd[f+1]   = fStart[f+1];
6757d3d1a6afSToby Isaac         }
6758d3d1a6afSToby Isaac         ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr);
675936fa2b79SJed Brown         ierr = DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices);CHKERRQ(ierr);
6760d3d1a6afSToby Isaac 
6761d3d1a6afSToby Isaac         fAnchorStart[0] = 0;
6762d3d1a6afSToby Isaac         fAnchorEnd[0]   = 0;
6763d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
6764d3d1a6afSToby Isaac           PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p];
6765d3d1a6afSToby Isaac 
6766d3d1a6afSToby Isaac           fAnchorStart[f+1] = fAnchorStart[f] + fDof;
6767d3d1a6afSToby Isaac           fAnchorEnd[f+1]   = fAnchorStart[f + 1];
6768d3d1a6afSToby Isaac         }
6769d3d1a6afSToby Isaac         ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr);
6770d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
6771d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aOff;
6772d3d1a6afSToby Isaac 
6773d3d1a6afSToby 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 */
6774d3d1a6afSToby Isaac           newPoints[2*(newP + q)]     = a;
6775d3d1a6afSToby Isaac           newPoints[2*(newP + q) + 1] = 0;
6776302440fdSBarry Smith           ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr);
677736fa2b79SJed Brown           ierr = DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices);CHKERRQ(ierr);
6778d3d1a6afSToby Isaac         }
6779d3d1a6afSToby Isaac         newP += bDof;
6780d3d1a6afSToby Isaac 
67816ecaa68aSToby Isaac         if (outValues) {
6782d3d1a6afSToby Isaac           /* get the point-to-point submatrix */
6783d3d1a6afSToby Isaac           for (f = 0; f < numFields; f++) {
6784d3d1a6afSToby 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);
6785d3d1a6afSToby Isaac           }
6786d3d1a6afSToby Isaac         }
67876ecaa68aSToby Isaac       }
6788d3d1a6afSToby Isaac       else {
6789d3d1a6afSToby Isaac         newPoints[2 * newP]     = b;
6790d3d1a6afSToby Isaac         newPoints[2 * newP + 1] = o;
6791d3d1a6afSToby Isaac         newP++;
6792d3d1a6afSToby Isaac       }
6793d3d1a6afSToby Isaac     }
6794d3d1a6afSToby Isaac   } else {
6795d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
6796d3d1a6afSToby Isaac       PetscInt b    = points[2*p];
6797d3d1a6afSToby Isaac       PetscInt o    = points[2*p+1];
67984b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
6799d3d1a6afSToby Isaac 
68004b2f2278SToby Isaac       ierr = PetscSectionGetDof(section, b, &bSecDof);CHKERRQ(ierr);
68014b2f2278SToby Isaac       if (!bSecDof) {
68024b2f2278SToby Isaac         continue;
68034b2f2278SToby Isaac       }
6804d3d1a6afSToby Isaac       if (b >= aStart && b < aEnd) {
6805d3d1a6afSToby Isaac         ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr);
6806d3d1a6afSToby Isaac       }
6807d3d1a6afSToby Isaac       if (bDof) {
6808d3d1a6afSToby Isaac         PetscInt bEnd = 0, bAnchorEnd = 0, bOff;
6809d3d1a6afSToby Isaac 
6810d3d1a6afSToby Isaac         ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr);
681136fa2b79SJed Brown         ierr = DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices);CHKERRQ(ierr);
6812d3d1a6afSToby Isaac 
6813d3d1a6afSToby Isaac         ierr = PetscSectionGetOffset (aSec, b, &bOff);CHKERRQ(ierr);
6814d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
6815d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aOff;
6816d3d1a6afSToby Isaac 
6817d3d1a6afSToby 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 */
6818d3d1a6afSToby Isaac 
6819d3d1a6afSToby Isaac           newPoints[2*(newP + q)]     = a;
6820d3d1a6afSToby Isaac           newPoints[2*(newP + q) + 1] = 0;
6821302440fdSBarry Smith           ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr);
682236fa2b79SJed Brown           ierr = DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices);CHKERRQ(ierr);
6823d3d1a6afSToby Isaac         }
6824d3d1a6afSToby Isaac         newP += bDof;
6825d3d1a6afSToby Isaac 
6826d3d1a6afSToby Isaac         /* get the point-to-point submatrix */
68276ecaa68aSToby Isaac         if (outValues) {
6828d3d1a6afSToby Isaac           ierr = MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p]);CHKERRQ(ierr);
6829d3d1a6afSToby Isaac         }
68306ecaa68aSToby Isaac       }
6831d3d1a6afSToby Isaac       else {
6832d3d1a6afSToby Isaac         newPoints[2 * newP]     = b;
6833d3d1a6afSToby Isaac         newPoints[2 * newP + 1] = o;
6834d3d1a6afSToby Isaac         newP++;
6835d3d1a6afSToby Isaac       }
6836d3d1a6afSToby Isaac     }
6837d3d1a6afSToby Isaac   }
6838d3d1a6afSToby Isaac 
68396ecaa68aSToby Isaac   if (outValues) {
684069291d52SBarry Smith     ierr = DMGetWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr);
6841580bdb30SBarry Smith     ierr = PetscArrayzero(tmpValues,newNumIndices*numIndices);CHKERRQ(ierr);
6842d3d1a6afSToby Isaac     /* multiply constraints on the right */
6843d3d1a6afSToby Isaac     if (numFields) {
6844d3d1a6afSToby Isaac       for (f = 0; f < numFields; f++) {
6845d3d1a6afSToby Isaac         PetscInt oldOff = offsets[f];
6846d3d1a6afSToby Isaac 
6847d3d1a6afSToby Isaac         for (p = 0; p < numPoints; p++) {
6848d3d1a6afSToby Isaac           PetscInt cStart = newPointOffsets[f][p];
6849d3d1a6afSToby Isaac           PetscInt b      = points[2 * p];
6850d3d1a6afSToby Isaac           PetscInt c, r, k;
6851d3d1a6afSToby Isaac           PetscInt dof;
6852d3d1a6afSToby Isaac 
6853d3d1a6afSToby Isaac           ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr);
68544b2f2278SToby Isaac           if (!dof) {
68554b2f2278SToby Isaac             continue;
68564b2f2278SToby Isaac           }
6857d3d1a6afSToby Isaac           if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) {
6858d3d1a6afSToby Isaac             PetscInt nCols         = newPointOffsets[f][p+1]-cStart;
6859d3d1a6afSToby Isaac             const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p];
6860d3d1a6afSToby Isaac 
6861d3d1a6afSToby Isaac             for (r = 0; r < numIndices; r++) {
6862d3d1a6afSToby Isaac               for (c = 0; c < nCols; c++) {
6863d3d1a6afSToby Isaac                 for (k = 0; k < dof; k++) {
68644acb8e1eSToby Isaac                   tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c];
6865d3d1a6afSToby Isaac                 }
6866d3d1a6afSToby Isaac               }
6867d3d1a6afSToby Isaac             }
6868d3d1a6afSToby Isaac           }
6869d3d1a6afSToby Isaac           else {
6870d3d1a6afSToby Isaac             /* copy this column as is */
6871d3d1a6afSToby Isaac             for (r = 0; r < numIndices; r++) {
6872d3d1a6afSToby Isaac               for (c = 0; c < dof; c++) {
6873d3d1a6afSToby Isaac                 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c];
6874d3d1a6afSToby Isaac               }
6875d3d1a6afSToby Isaac             }
6876d3d1a6afSToby Isaac           }
6877d3d1a6afSToby Isaac           oldOff += dof;
6878d3d1a6afSToby Isaac         }
6879d3d1a6afSToby Isaac       }
6880d3d1a6afSToby Isaac     }
6881d3d1a6afSToby Isaac     else {
6882d3d1a6afSToby Isaac       PetscInt oldOff = 0;
6883d3d1a6afSToby Isaac       for (p = 0; p < numPoints; p++) {
6884d3d1a6afSToby Isaac         PetscInt cStart = newPointOffsets[0][p];
6885d3d1a6afSToby Isaac         PetscInt b      = points[2 * p];
6886d3d1a6afSToby Isaac         PetscInt c, r, k;
6887d3d1a6afSToby Isaac         PetscInt dof;
6888d3d1a6afSToby Isaac 
6889d3d1a6afSToby Isaac         ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr);
68904b2f2278SToby Isaac         if (!dof) {
68914b2f2278SToby Isaac           continue;
68924b2f2278SToby Isaac         }
6893d3d1a6afSToby Isaac         if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) {
6894d3d1a6afSToby Isaac           PetscInt nCols         = newPointOffsets[0][p+1]-cStart;
6895d3d1a6afSToby Isaac           const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p];
6896d3d1a6afSToby Isaac 
6897d3d1a6afSToby Isaac           for (r = 0; r < numIndices; r++) {
6898d3d1a6afSToby Isaac             for (c = 0; c < nCols; c++) {
6899d3d1a6afSToby Isaac               for (k = 0; k < dof; k++) {
6900d3d1a6afSToby Isaac                 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k];
6901d3d1a6afSToby Isaac               }
6902d3d1a6afSToby Isaac             }
6903d3d1a6afSToby Isaac           }
6904d3d1a6afSToby Isaac         }
6905d3d1a6afSToby Isaac         else {
6906d3d1a6afSToby Isaac           /* copy this column as is */
6907d3d1a6afSToby Isaac           for (r = 0; r < numIndices; r++) {
6908d3d1a6afSToby Isaac             for (c = 0; c < dof; c++) {
6909d3d1a6afSToby Isaac               tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c];
6910d3d1a6afSToby Isaac             }
6911d3d1a6afSToby Isaac           }
6912d3d1a6afSToby Isaac         }
6913d3d1a6afSToby Isaac         oldOff += dof;
6914d3d1a6afSToby Isaac       }
6915d3d1a6afSToby Isaac     }
6916d3d1a6afSToby Isaac 
69176ecaa68aSToby Isaac     if (multiplyLeft) {
691869291d52SBarry Smith       ierr = DMGetWorkArray(dm,newNumIndices*newNumIndices,MPIU_SCALAR,&newValues);CHKERRQ(ierr);
6919580bdb30SBarry Smith       ierr = PetscArrayzero(newValues,newNumIndices*newNumIndices);CHKERRQ(ierr);
6920d3d1a6afSToby Isaac       /* multiply constraints transpose on the left */
6921d3d1a6afSToby Isaac       if (numFields) {
6922d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
6923d3d1a6afSToby Isaac           PetscInt oldOff = offsets[f];
6924d3d1a6afSToby Isaac 
6925d3d1a6afSToby Isaac           for (p = 0; p < numPoints; p++) {
6926d3d1a6afSToby Isaac             PetscInt rStart = newPointOffsets[f][p];
6927d3d1a6afSToby Isaac             PetscInt b      = points[2 * p];
6928d3d1a6afSToby Isaac             PetscInt c, r, k;
6929d3d1a6afSToby Isaac             PetscInt dof;
6930d3d1a6afSToby Isaac 
6931d3d1a6afSToby Isaac             ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr);
6932d3d1a6afSToby Isaac             if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) {
6933d3d1a6afSToby Isaac               PetscInt nRows                        = newPointOffsets[f][p+1]-rStart;
6934d3d1a6afSToby Isaac               const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p];
6935d3d1a6afSToby Isaac 
6936d3d1a6afSToby Isaac               for (r = 0; r < nRows; r++) {
6937d3d1a6afSToby Isaac                 for (c = 0; c < newNumIndices; c++) {
6938d3d1a6afSToby Isaac                   for (k = 0; k < dof; k++) {
6939d3d1a6afSToby Isaac                     newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c];
6940d3d1a6afSToby Isaac                   }
6941d3d1a6afSToby Isaac                 }
6942d3d1a6afSToby Isaac               }
6943d3d1a6afSToby Isaac             }
6944d3d1a6afSToby Isaac             else {
6945d3d1a6afSToby Isaac               /* copy this row as is */
6946d3d1a6afSToby Isaac               for (r = 0; r < dof; r++) {
6947d3d1a6afSToby Isaac                 for (c = 0; c < newNumIndices; c++) {
6948d3d1a6afSToby Isaac                   newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c];
6949d3d1a6afSToby Isaac                 }
6950d3d1a6afSToby Isaac               }
6951d3d1a6afSToby Isaac             }
6952d3d1a6afSToby Isaac             oldOff += dof;
6953d3d1a6afSToby Isaac           }
6954d3d1a6afSToby Isaac         }
6955d3d1a6afSToby Isaac       }
6956d3d1a6afSToby Isaac       else {
6957d3d1a6afSToby Isaac         PetscInt oldOff = 0;
6958d3d1a6afSToby Isaac 
6959d3d1a6afSToby Isaac         for (p = 0; p < numPoints; p++) {
6960d3d1a6afSToby Isaac           PetscInt rStart = newPointOffsets[0][p];
6961d3d1a6afSToby Isaac           PetscInt b      = points[2 * p];
6962d3d1a6afSToby Isaac           PetscInt c, r, k;
6963d3d1a6afSToby Isaac           PetscInt dof;
6964d3d1a6afSToby Isaac 
6965d3d1a6afSToby Isaac           ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr);
6966d3d1a6afSToby Isaac           if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) {
6967d3d1a6afSToby Isaac             PetscInt nRows                        = newPointOffsets[0][p+1]-rStart;
6968d3d1a6afSToby Isaac             const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p];
6969d3d1a6afSToby Isaac 
6970d3d1a6afSToby Isaac             for (r = 0; r < nRows; r++) {
6971d3d1a6afSToby Isaac               for (c = 0; c < newNumIndices; c++) {
6972d3d1a6afSToby Isaac                 for (k = 0; k < dof; k++) {
6973d3d1a6afSToby Isaac                   newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c];
6974d3d1a6afSToby Isaac                 }
6975d3d1a6afSToby Isaac               }
6976d3d1a6afSToby Isaac             }
6977d3d1a6afSToby Isaac           }
6978d3d1a6afSToby Isaac           else {
6979d3d1a6afSToby Isaac             /* copy this row as is */
69809fc93327SToby Isaac             for (r = 0; r < dof; r++) {
6981d3d1a6afSToby Isaac               for (c = 0; c < newNumIndices; c++) {
6982d3d1a6afSToby Isaac                 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c];
6983d3d1a6afSToby Isaac               }
6984d3d1a6afSToby Isaac             }
6985d3d1a6afSToby Isaac           }
6986d3d1a6afSToby Isaac           oldOff += dof;
6987d3d1a6afSToby Isaac         }
6988d3d1a6afSToby Isaac       }
6989d3d1a6afSToby Isaac 
699069291d52SBarry Smith       ierr = DMRestoreWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues);CHKERRQ(ierr);
69916ecaa68aSToby Isaac     }
69926ecaa68aSToby Isaac     else {
69936ecaa68aSToby Isaac       newValues = tmpValues;
69946ecaa68aSToby Isaac     }
69956ecaa68aSToby Isaac   }
69966ecaa68aSToby Isaac 
6997d3d1a6afSToby Isaac   /* clean up */
699869291d52SBarry Smith   ierr = DMRestoreWorkArray(dm,maxDof,MPIU_INT,&indices);CHKERRQ(ierr);
699969291d52SBarry Smith   ierr = DMRestoreWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices);CHKERRQ(ierr);
70006ecaa68aSToby Isaac 
7001d3d1a6afSToby Isaac   if (numFields) {
7002d3d1a6afSToby Isaac     for (f = 0; f < numFields; f++) {
700369291d52SBarry Smith       ierr = DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]);CHKERRQ(ierr);
700469291d52SBarry Smith       ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]);CHKERRQ(ierr);
700569291d52SBarry Smith       ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]);CHKERRQ(ierr);
7006d3d1a6afSToby Isaac     }
7007d3d1a6afSToby Isaac   }
7008d3d1a6afSToby Isaac   else {
700969291d52SBarry Smith     ierr = DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]);CHKERRQ(ierr);
701069291d52SBarry Smith     ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]);CHKERRQ(ierr);
701169291d52SBarry Smith     ierr = DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[0]);CHKERRQ(ierr);
7012d3d1a6afSToby Isaac   }
7013d3d1a6afSToby Isaac   ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);
7014d3d1a6afSToby Isaac 
7015d3d1a6afSToby Isaac   /* output */
70166ecaa68aSToby Isaac   if (outPoints) {
7017d3d1a6afSToby Isaac     *outPoints = newPoints;
70186ecaa68aSToby Isaac   }
70196ecaa68aSToby Isaac   else {
702069291d52SBarry Smith     ierr = DMRestoreWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints);CHKERRQ(ierr);
70216ecaa68aSToby Isaac   }
702231620726SToby Isaac   if (outValues) {
7023d3d1a6afSToby Isaac     *outValues = newValues;
70246ecaa68aSToby Isaac   }
70256ecaa68aSToby Isaac   for (f = 0; f <= numFields; f++) {
7026d3d1a6afSToby Isaac     offsets[f] = newOffsets[f];
7027d3d1a6afSToby Isaac   }
7028d3d1a6afSToby Isaac   PetscFunctionReturn(0);
7029d3d1a6afSToby Isaac }
7030d3d1a6afSToby Isaac 
70314a1e0b3eSMatthew G. Knepley /*@C
703271f0bbf9SMatthew G. Knepley   DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections.
70337cd05799SMatthew G. Knepley 
70347cd05799SMatthew G. Knepley   Not collective
70357cd05799SMatthew G. Knepley 
70367cd05799SMatthew G. Knepley   Input Parameters:
70377cd05799SMatthew G. Knepley + dm         - The DM
703871f0bbf9SMatthew G. Knepley . section    - The PetscSection describing the points (a local section)
703971f0bbf9SMatthew G. Knepley . idxSection - The PetscSection from which to obtain indices (may be local or global)
704071f0bbf9SMatthew G. Knepley . point      - The point defining the closure
704171f0bbf9SMatthew G. Knepley - useClPerm  - Use the closure point permutation if available
70427cd05799SMatthew G. Knepley 
704371f0bbf9SMatthew G. Knepley   Output Parameters:
704471f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections
704571f0bbf9SMatthew G. Knepley . indices    - The dof indices
704671f0bbf9SMatthew G. Knepley . outOffsets - Array to write the field offsets into, or NULL
704771f0bbf9SMatthew G. Knepley - values     - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL
70487cd05799SMatthew G. Knepley 
704936fa2b79SJed Brown   Notes:
705036fa2b79SJed Brown   Must call DMPlexRestoreClosureIndices() to free allocated memory
705136fa2b79SJed Brown 
705236fa2b79SJed Brown   If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices.  The value
705336fa2b79SJed Brown   of those indices is not significant.  If idxSection is local, the constrained dofs will yield the involution -(idx+1)
705436fa2b79SJed Brown   of their index in a local vector.  A caller who does not wish to distinguish those points may recover the nonnegative
705536fa2b79SJed Brown   indices via involution, -(-(idx+1)+1)==idx.  Local indices are provided when idxSection == section, otherwise global
705636fa2b79SJed Brown   indices (with the above semantics) are implied.
70577cd05799SMatthew G. Knepley 
70587cd05799SMatthew G. Knepley   Level: advanced
70597cd05799SMatthew G. Knepley 
706036fa2b79SJed Brown .seealso DMPlexRestoreClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure(), DMGetLocalSection(), DMGetGlobalSection()
70614a1e0b3eSMatthew G. Knepley @*/
706271f0bbf9SMatthew G. Knepley PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm,
706371f0bbf9SMatthew G. Knepley                                        PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[])
70647773e69fSMatthew G. Knepley {
706571f0bbf9SMatthew G. Knepley   /* Closure ordering */
70667773e69fSMatthew G. Knepley   PetscSection        clSection;
70677773e69fSMatthew G. Knepley   IS                  clPoints;
706871f0bbf9SMatthew G. Knepley   const PetscInt     *clp;
706971f0bbf9SMatthew G. Knepley   PetscInt           *points;
707071f0bbf9SMatthew G. Knepley   const PetscInt     *clperm = NULL;
707171f0bbf9SMatthew G. Knepley   /* Dof permutation and sign flips */
70724acb8e1eSToby Isaac   const PetscInt    **perms[32] = {NULL};
707371f0bbf9SMatthew G. Knepley   const PetscScalar **flips[32] = {NULL};
707471f0bbf9SMatthew G. Knepley   PetscScalar        *valCopy   = NULL;
707571f0bbf9SMatthew G. Knepley   /* Hanging node constraints */
707671f0bbf9SMatthew G. Knepley   PetscInt           *pointsC = NULL;
707771f0bbf9SMatthew G. Knepley   PetscScalar        *valuesC = NULL;
707871f0bbf9SMatthew G. Knepley   PetscInt            NclC, NiC;
707971f0bbf9SMatthew G. Knepley 
708071f0bbf9SMatthew G. Knepley   PetscInt           *idx;
708171f0bbf9SMatthew G. Knepley   PetscInt            Nf, Ncl, Ni = 0, offsets[32], p, f;
708271f0bbf9SMatthew G. Knepley   PetscBool           isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE;
70837773e69fSMatthew G. Knepley   PetscErrorCode      ierr;
70847773e69fSMatthew G. Knepley 
708571f0bbf9SMatthew G. Knepley   PetscFunctionBeginHot;
70867773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
70877773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
708836fa2b79SJed Brown   PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3);
708971f0bbf9SMatthew G. Knepley   if (numIndices) PetscValidPointer(numIndices, 6);
709071f0bbf9SMatthew G. Knepley   if (indices)    PetscValidPointer(indices, 7);
709171f0bbf9SMatthew G. Knepley   if (outOffsets) PetscValidPointer(outOffsets, 8);
709271f0bbf9SMatthew G. Knepley   if (values)     PetscValidPointer(values, 9);
70937773e69fSMatthew G. Knepley   ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr);
70947773e69fSMatthew G. Knepley   if (Nf > 31) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", Nf);
7095580bdb30SBarry Smith   ierr = PetscArrayzero(offsets, 32);CHKERRQ(ierr);
709671f0bbf9SMatthew G. Knepley   /* 1) Get points in closure */
709771f0bbf9SMatthew G. Knepley   ierr = DMPlexGetCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr);
7098c459fbc1SJed Brown   if (useClPerm) {
7099c459fbc1SJed Brown     PetscInt depth, clsize;
7100c459fbc1SJed Brown     ierr = DMPlexGetPointDepth(dm, point, &depth);CHKERRQ(ierr);
7101c459fbc1SJed Brown     for (clsize=0,p=0; p<Ncl; p++) {
7102c459fbc1SJed Brown       PetscInt dof;
7103c459fbc1SJed Brown       ierr = PetscSectionGetDof(section, points[2*p], &dof);CHKERRQ(ierr);
7104c459fbc1SJed Brown       clsize += dof;
7105c459fbc1SJed Brown     }
7106c459fbc1SJed Brown     ierr = PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm);CHKERRQ(ierr);
7107c459fbc1SJed Brown   }
710871f0bbf9SMatthew G. Knepley   /* 2) Get number of indices on these points and field offsets from section */
710971f0bbf9SMatthew G. Knepley   for (p = 0; p < Ncl*2; p += 2) {
71107773e69fSMatthew G. Knepley     PetscInt dof, fdof;
71117773e69fSMatthew G. Knepley 
71127773e69fSMatthew G. Knepley     ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr);
71137773e69fSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
71147773e69fSMatthew G. Knepley       ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr);
71157773e69fSMatthew G. Knepley       offsets[f+1] += fdof;
71167773e69fSMatthew G. Knepley     }
711771f0bbf9SMatthew G. Knepley     Ni += dof;
71187773e69fSMatthew G. Knepley   }
71197773e69fSMatthew G. Knepley   for (f = 1; f < Nf; ++f) offsets[f+1] += offsets[f];
712071f0bbf9SMatthew G. Knepley   if (Nf && offsets[Nf] != Ni) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", offsets[Nf], Ni);
712171f0bbf9SMatthew G. Knepley   /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */
712271f0bbf9SMatthew G. Knepley   for (f = 0; f < PetscMax(1, Nf); ++f) {
712371f0bbf9SMatthew G. Knepley     if (Nf) {ierr = PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);}
712471f0bbf9SMatthew G. Knepley     else    {ierr = PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);}
712571f0bbf9SMatthew G. Knepley     /* may need to apply sign changes to the element matrix */
712671f0bbf9SMatthew G. Knepley     if (values && flips[f]) {
712771f0bbf9SMatthew G. Knepley       PetscInt foffset = offsets[f];
71286ecaa68aSToby Isaac 
712971f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
713071f0bbf9SMatthew G. Knepley         PetscInt           pnt  = points[2*p], fdof;
713171f0bbf9SMatthew G. Knepley         const PetscScalar *flip = flips[f] ? flips[f][p] : NULL;
713271f0bbf9SMatthew G. Knepley 
713371f0bbf9SMatthew G. Knepley         if (!Nf) {ierr = PetscSectionGetDof(section, pnt, &fdof);CHKERRQ(ierr);}
713471f0bbf9SMatthew G. Knepley         else     {ierr = PetscSectionGetFieldDof(section, pnt, f, &fdof);CHKERRQ(ierr);}
713571f0bbf9SMatthew G. Knepley         if (flip) {
713671f0bbf9SMatthew G. Knepley           PetscInt i, j, k;
713771f0bbf9SMatthew G. Knepley 
713871f0bbf9SMatthew G. Knepley           if (!valCopy) {
713971f0bbf9SMatthew G. Knepley             ierr = DMGetWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy);CHKERRQ(ierr);
714071f0bbf9SMatthew G. Knepley             for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j];
714171f0bbf9SMatthew G. Knepley             *values = valCopy;
714271f0bbf9SMatthew G. Knepley           }
714371f0bbf9SMatthew G. Knepley           for (i = 0; i < fdof; ++i) {
714471f0bbf9SMatthew G. Knepley             PetscScalar fval = flip[i];
714571f0bbf9SMatthew G. Knepley 
714671f0bbf9SMatthew G. Knepley             for (k = 0; k < Ni; ++k) {
714771f0bbf9SMatthew G. Knepley               valCopy[Ni * (foffset + i) + k] *= fval;
714871f0bbf9SMatthew G. Knepley               valCopy[Ni * k + (foffset + i)] *= fval;
71496ecaa68aSToby Isaac             }
71506ecaa68aSToby Isaac           }
715171f0bbf9SMatthew G. Knepley         }
715271f0bbf9SMatthew G. Knepley         foffset += fdof;
715371f0bbf9SMatthew G. Knepley       }
715471f0bbf9SMatthew G. Knepley     }
715571f0bbf9SMatthew G. Knepley   }
715671f0bbf9SMatthew G. Knepley   /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */
715771f0bbf9SMatthew G. Knepley   ierr = DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE);CHKERRQ(ierr);
715871f0bbf9SMatthew G. Knepley   if (NclC) {
715971f0bbf9SMatthew G. Knepley     if (valCopy) {ierr = DMRestoreWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy);CHKERRQ(ierr);}
716071f0bbf9SMatthew G. Knepley     for (f = 0; f < PetscMax(1, Nf); ++f) {
716171f0bbf9SMatthew G. Knepley       if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);}
716271f0bbf9SMatthew G. Knepley       else    {ierr = PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);}
716371f0bbf9SMatthew G. Knepley     }
716471f0bbf9SMatthew G. Knepley     for (f = 0; f < PetscMax(1, Nf); ++f) {
716571f0bbf9SMatthew G. Knepley       if (Nf) {ierr = PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f]);CHKERRQ(ierr);}
716671f0bbf9SMatthew G. Knepley       else    {ierr = PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f]);CHKERRQ(ierr);}
716771f0bbf9SMatthew G. Knepley     }
716871f0bbf9SMatthew G. Knepley     ierr = DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr);
716971f0bbf9SMatthew G. Knepley     Ncl     = NclC;
717071f0bbf9SMatthew G. Knepley     Ni      = NiC;
717171f0bbf9SMatthew G. Knepley     points  = pointsC;
717271f0bbf9SMatthew G. Knepley     if (values) *values = valuesC;
717371f0bbf9SMatthew G. Knepley   }
717471f0bbf9SMatthew G. Knepley   /* 5) Calculate indices */
717571f0bbf9SMatthew G. Knepley   ierr = DMGetWorkArray(dm, Ni, MPIU_INT, &idx);CHKERRQ(ierr);
717671f0bbf9SMatthew G. Knepley   if (Nf) {
717771f0bbf9SMatthew G. Knepley     PetscInt  idxOff;
717871f0bbf9SMatthew G. Knepley     PetscBool useFieldOffsets;
717971f0bbf9SMatthew G. Knepley 
718071f0bbf9SMatthew G. Knepley     if (outOffsets) {for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f];}
718171f0bbf9SMatthew G. Knepley     ierr = PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets);CHKERRQ(ierr);
718271f0bbf9SMatthew G. Knepley     if (useFieldOffsets) {
718371f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
718471f0bbf9SMatthew G. Knepley         const PetscInt pnt = points[p*2];
718571f0bbf9SMatthew G. Knepley 
718671f0bbf9SMatthew G. Knepley         ierr = DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx);CHKERRQ(ierr);
71877773e69fSMatthew G. Knepley       }
71887773e69fSMatthew G. Knepley     } else {
718971f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
719071f0bbf9SMatthew G. Knepley         const PetscInt pnt = points[p*2];
719171f0bbf9SMatthew G. Knepley 
719271f0bbf9SMatthew G. Knepley         ierr = PetscSectionGetOffset(idxSection, pnt, &idxOff);CHKERRQ(ierr);
719371f0bbf9SMatthew G. Knepley         /* Note that we pass a local section even though we're using global offsets.  This is because global sections do
719471f0bbf9SMatthew G. Knepley          * not (at the time of this writing) have fields set. They probably should, in which case we would pass the
719571f0bbf9SMatthew G. Knepley          * global section. */
719671f0bbf9SMatthew G. Knepley         ierr = DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx);CHKERRQ(ierr);
719771f0bbf9SMatthew G. Knepley       }
719871f0bbf9SMatthew G. Knepley     }
719971f0bbf9SMatthew G. Knepley   } else {
720071f0bbf9SMatthew G. Knepley     PetscInt off = 0, idxOff;
720171f0bbf9SMatthew G. Knepley 
720271f0bbf9SMatthew G. Knepley     for (p = 0; p < Ncl; ++p) {
720371f0bbf9SMatthew G. Knepley       const PetscInt  pnt  = points[p*2];
72044acb8e1eSToby Isaac       const PetscInt *perm = perms[0] ? perms[0][p] : NULL;
72054acb8e1eSToby Isaac 
720671f0bbf9SMatthew G. Knepley       ierr = PetscSectionGetOffset(idxSection, pnt, &idxOff);CHKERRQ(ierr);
720771f0bbf9SMatthew G. Knepley       /* Note that we pass a local section even though we're using global offsets.  This is because global sections do
720871f0bbf9SMatthew G. Knepley        * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */
720971f0bbf9SMatthew G. Knepley       ierr = DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx);CHKERRQ(ierr);
72107773e69fSMatthew G. Knepley     }
72117773e69fSMatthew G. Knepley   }
721271f0bbf9SMatthew G. Knepley   /* 6) Cleanup */
721371f0bbf9SMatthew G. Knepley   for (f = 0; f < PetscMax(1, Nf); ++f) {
721471f0bbf9SMatthew G. Knepley     if (Nf) {ierr = PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);}
721571f0bbf9SMatthew G. Knepley     else    {ierr = PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]);CHKERRQ(ierr);}
72164acb8e1eSToby Isaac   }
721771f0bbf9SMatthew G. Knepley   if (NclC) {
721871f0bbf9SMatthew G. Knepley     ierr = DMRestoreWorkArray(dm, NclC*2, MPIU_INT, &pointsC);CHKERRQ(ierr);
72197773e69fSMatthew G. Knepley   } else {
722071f0bbf9SMatthew G. Knepley     ierr = DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp);CHKERRQ(ierr);
72217773e69fSMatthew G. Knepley   }
722271f0bbf9SMatthew G. Knepley 
722371f0bbf9SMatthew G. Knepley   if (numIndices) *numIndices = Ni;
722471f0bbf9SMatthew G. Knepley   if (indices)    *indices    = idx;
72257773e69fSMatthew G. Knepley   PetscFunctionReturn(0);
72267773e69fSMatthew G. Knepley }
72277773e69fSMatthew G. Knepley 
72287cd05799SMatthew G. Knepley /*@C
722971f0bbf9SMatthew G. Knepley   DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections.
72307cd05799SMatthew G. Knepley 
72317cd05799SMatthew G. Knepley   Not collective
72327cd05799SMatthew G. Knepley 
72337cd05799SMatthew G. Knepley   Input Parameters:
72347cd05799SMatthew G. Knepley + dm         - The DM
723571f0bbf9SMatthew G. Knepley . section    - The PetscSection describing the points (a local section)
723671f0bbf9SMatthew G. Knepley . idxSection - The PetscSection from which to obtain indices (may be local or global)
723771f0bbf9SMatthew G. Knepley . point      - The point defining the closure
723871f0bbf9SMatthew G. Knepley - useClPerm  - Use the closure point permutation if available
723971f0bbf9SMatthew G. Knepley 
724071f0bbf9SMatthew G. Knepley   Output Parameters:
724171f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections
724271f0bbf9SMatthew G. Knepley . indices    - The dof indices
724371f0bbf9SMatthew G. Knepley . outOffsets - Array to write the field offsets into, or NULL
724471f0bbf9SMatthew G. Knepley - values     - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL
724571f0bbf9SMatthew G. Knepley 
724671f0bbf9SMatthew G. Knepley   Notes:
724771f0bbf9SMatthew G. Knepley   If values were modified, the user is responsible for calling DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values).
724871f0bbf9SMatthew G. Knepley 
724971f0bbf9SMatthew G. Knepley   If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices.  The value
725071f0bbf9SMatthew G. Knepley   of those indices is not significant.  If idxSection is local, the constrained dofs will yield the involution -(idx+1)
725171f0bbf9SMatthew G. Knepley   of their index in a local vector.  A caller who does not wish to distinguish those points may recover the nonnegative
725271f0bbf9SMatthew G. Knepley   indices via involution, -(-(idx+1)+1)==idx.  Local indices are provided when idxSection == section, otherwise global
725371f0bbf9SMatthew G. Knepley   indices (with the above semantics) are implied.
72547cd05799SMatthew G. Knepley 
72557cd05799SMatthew G. Knepley   Level: advanced
72567cd05799SMatthew G. Knepley 
725771f0bbf9SMatthew G. Knepley .seealso DMPlexGetClosureIndices(), DMPlexVecGetClosure(), DMPlexMatSetClosure(), DMGetLocalSection(), DMGetGlobalSection()
72587cd05799SMatthew G. Knepley @*/
725971f0bbf9SMatthew G. Knepley PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm,
726071f0bbf9SMatthew G. Knepley                                            PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[])
72617773e69fSMatthew G. Knepley {
72627773e69fSMatthew G. Knepley   PetscErrorCode ierr;
72637773e69fSMatthew G. Knepley 
72647773e69fSMatthew G. Knepley   PetscFunctionBegin;
72657773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7266064a246eSJacob Faibussowitsch   PetscValidPointer(indices, 7);
726769291d52SBarry Smith   ierr = DMRestoreWorkArray(dm, 0, MPIU_INT, indices);CHKERRQ(ierr);
72687773e69fSMatthew G. Knepley   PetscFunctionReturn(0);
72697773e69fSMatthew G. Knepley }
72707773e69fSMatthew G. Knepley 
72717f5d1fdeSMatthew G. Knepley /*@C
72727f5d1fdeSMatthew G. Knepley   DMPlexMatSetClosure - Set an array of the values on the closure of 'point'
72737f5d1fdeSMatthew G. Knepley 
72747f5d1fdeSMatthew G. Knepley   Not collective
72757f5d1fdeSMatthew G. Knepley 
72767f5d1fdeSMatthew G. Knepley   Input Parameters:
72777f5d1fdeSMatthew G. Knepley + dm - The DM
7278ebd6d717SJed Brown . section - The section describing the layout in v, or NULL to use the default section
7279ebd6d717SJed Brown . globalSection - The section describing the layout in v, or NULL to use the default global section
72807f5d1fdeSMatthew G. Knepley . A - The matrix
7281eaf898f9SPatrick Sanan . point - The point in the DM
72827f5d1fdeSMatthew G. Knepley . values - The array of values
72837f5d1fdeSMatthew G. Knepley - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions
72847f5d1fdeSMatthew G. Knepley 
72857f5d1fdeSMatthew G. Knepley   Fortran Notes:
72867f5d1fdeSMatthew G. Knepley   This routine is only available in Fortran 90, and you must include petsc.h90 in your code.
72877f5d1fdeSMatthew G. Knepley 
72887f5d1fdeSMatthew G. Knepley   Level: intermediate
72897f5d1fdeSMatthew G. Knepley 
72904a1e0b3eSMatthew G. Knepley .seealso DMPlexMatSetClosureGeneral(), DMPlexVecGetClosure(), DMPlexVecSetClosure()
72917f5d1fdeSMatthew G. Knepley @*/
72927c1f9639SMatthew G Knepley PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
7293552f7358SJed Brown {
7294552f7358SJed Brown   DM_Plex           *mesh = (DM_Plex*) dm->data;
7295552f7358SJed Brown   PetscInt          *indices;
729671f0bbf9SMatthew G. Knepley   PetscInt           numIndices;
729771f0bbf9SMatthew G. Knepley   const PetscScalar *valuesOrig = values;
7298552f7358SJed Brown   PetscErrorCode     ierr;
7299552f7358SJed Brown 
7300552f7358SJed Brown   PetscFunctionBegin;
7301552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
730292fd8e1eSJed Brown   if (!section) {ierr = DMGetLocalSection(dm, &section);CHKERRQ(ierr);}
73033dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
7304e87a4003SBarry Smith   if (!globalSection) {ierr = DMGetGlobalSection(dm, &globalSection);CHKERRQ(ierr);}
73053dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3);
73063dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 4);
7307552f7358SJed Brown 
730871f0bbf9SMatthew G. Knepley   ierr = DMPlexGetClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr);
73090d644c17SKarl Rupp 
7310b0ecff45SMatthew G. Knepley   if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr);}
73114a1e0b3eSMatthew G. Knepley   ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode);
7312552f7358SJed Brown   if (ierr) {
7313552f7358SJed Brown     PetscMPIInt    rank;
7314552f7358SJed Brown     PetscErrorCode ierr2;
7315552f7358SJed Brown 
731655b25c41SPierre Jolivet     ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2);
7317e4b003c7SBarry Smith     ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2);
7318b0ecff45SMatthew G. Knepley     ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr2);
731971f0bbf9SMatthew G. Knepley     ierr2 = DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr2);
732071f0bbf9SMatthew G. Knepley     if (values != valuesOrig) {ierr2 = DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values);CHKERRQ(ierr2);}
7321552f7358SJed Brown     CHKERRQ(ierr);
7322552f7358SJed Brown   }
73234a1e0b3eSMatthew G. Knepley   if (mesh->printFEM > 1) {
73244a1e0b3eSMatthew G. Knepley     PetscInt i;
73254a1e0b3eSMatthew G. Knepley     ierr = PetscPrintf(PETSC_COMM_SELF, "  Indices:");CHKERRQ(ierr);
73264a1e0b3eSMatthew G. Knepley     for (i = 0; i < numIndices; ++i) {ierr = PetscPrintf(PETSC_COMM_SELF, " %D", indices[i]);CHKERRQ(ierr);}
73274a1e0b3eSMatthew G. Knepley     ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr);
73284a1e0b3eSMatthew G. Knepley   }
732971f0bbf9SMatthew G. Knepley 
733071f0bbf9SMatthew G. Knepley   ierr = DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values);CHKERRQ(ierr);
733171f0bbf9SMatthew G. Knepley   if (values != valuesOrig) {ierr = DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values);CHKERRQ(ierr);}
733271f0bbf9SMatthew G. Knepley   PetscFunctionReturn(0);
73334acb8e1eSToby Isaac }
733471f0bbf9SMatthew G. Knepley 
73354a1e0b3eSMatthew G. Knepley /*@C
73364a1e0b3eSMatthew G. Knepley   DMPlexMatSetClosure - Set an array of the values on the closure of 'point' using a different row and column section
73374a1e0b3eSMatthew G. Knepley 
73384a1e0b3eSMatthew G. Knepley   Not collective
73394a1e0b3eSMatthew G. Knepley 
73404a1e0b3eSMatthew G. Knepley   Input Parameters:
73414a1e0b3eSMatthew G. Knepley + dmRow - The DM for the row fields
73424a1e0b3eSMatthew G. Knepley . sectionRow - The section describing the layout, or NULL to use the default section in dmRow
73434a1e0b3eSMatthew G. Knepley . globalSectionRow - The section describing the layout, or NULL to use the default global section in dmRow
73444a1e0b3eSMatthew G. Knepley . dmCol - The DM for the column fields
73454a1e0b3eSMatthew G. Knepley . sectionCol - The section describing the layout, or NULL to use the default section in dmCol
73464a1e0b3eSMatthew G. Knepley . globalSectionCol - The section describing the layout, or NULL to use the default global section in dmCol
73474a1e0b3eSMatthew G. Knepley . A - The matrix
73484a1e0b3eSMatthew G. Knepley . point - The point in the DMs
73494a1e0b3eSMatthew G. Knepley . values - The array of values
73504a1e0b3eSMatthew G. Knepley - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions
73514a1e0b3eSMatthew G. Knepley 
73524a1e0b3eSMatthew G. Knepley   Level: intermediate
73534a1e0b3eSMatthew G. Knepley 
73544a1e0b3eSMatthew G. Knepley .seealso DMPlexMatSetClosure(), DMPlexVecGetClosure(), DMPlexVecSetClosure()
73554a1e0b3eSMatthew G. Knepley @*/
735671f0bbf9SMatthew 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)
735771f0bbf9SMatthew G. Knepley {
735871f0bbf9SMatthew G. Knepley   DM_Plex           *mesh = (DM_Plex*) dmRow->data;
735971f0bbf9SMatthew G. Knepley   PetscInt          *indicesRow, *indicesCol;
736071f0bbf9SMatthew G. Knepley   PetscInt           numIndicesRow, numIndicesCol;
736171f0bbf9SMatthew G. Knepley   const PetscScalar *valuesOrig = values;
736271f0bbf9SMatthew G. Knepley   PetscErrorCode     ierr;
736371f0bbf9SMatthew G. Knepley 
736471f0bbf9SMatthew G. Knepley   PetscFunctionBegin;
736571f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1);
736671f0bbf9SMatthew G. Knepley   if (!sectionRow) {ierr = DMGetLocalSection(dmRow, &sectionRow);CHKERRQ(ierr);}
736771f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2);
736871f0bbf9SMatthew G. Knepley   if (!globalSectionRow) {ierr = DMGetGlobalSection(dmRow, &globalSectionRow);CHKERRQ(ierr);}
736971f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3);
737071f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(dmCol, DM_CLASSID, 4);
737171f0bbf9SMatthew G. Knepley   if (!sectionCol) {ierr = DMGetLocalSection(dmCol, &sectionCol);CHKERRQ(ierr);}
737271f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 5);
737371f0bbf9SMatthew G. Knepley   if (!globalSectionCol) {ierr = DMGetGlobalSection(dmCol, &globalSectionCol);CHKERRQ(ierr);}
737471f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 6);
737571f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 7);
737671f0bbf9SMatthew G. Knepley 
737771f0bbf9SMatthew G. Knepley   ierr = DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr);
737871f0bbf9SMatthew G. Knepley   ierr = DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values);CHKERRQ(ierr);
737971f0bbf9SMatthew G. Knepley 
738071f0bbf9SMatthew G. Knepley   if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values);CHKERRQ(ierr);}
73814a1e0b3eSMatthew G. Knepley   ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode);
738271f0bbf9SMatthew G. Knepley   if (ierr) {
738371f0bbf9SMatthew G. Knepley     PetscMPIInt    rank;
738471f0bbf9SMatthew G. Knepley     PetscErrorCode ierr2;
738571f0bbf9SMatthew G. Knepley 
738655b25c41SPierre Jolivet     ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2);
738771f0bbf9SMatthew G. Knepley     ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2);
738871f0bbf9SMatthew G. Knepley     ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values);CHKERRQ(ierr2);
738971f0bbf9SMatthew G. Knepley     ierr2 = DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr2);
739071f0bbf9SMatthew G. Knepley     ierr2 = DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr2);
739171f0bbf9SMatthew G. Knepley     if (values != valuesOrig) {ierr2 = DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values);CHKERRQ(ierr2);}
739271f0bbf9SMatthew G. Knepley     CHKERRQ(ierr);
7393d3d1a6afSToby Isaac   }
739471f0bbf9SMatthew G. Knepley 
739571f0bbf9SMatthew G. Knepley   ierr = DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values);CHKERRQ(ierr);
739671f0bbf9SMatthew G. Knepley   ierr = DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values);CHKERRQ(ierr);
739771f0bbf9SMatthew G. Knepley   if (values != valuesOrig) {ierr = DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values);CHKERRQ(ierr);}
7398552f7358SJed Brown   PetscFunctionReturn(0);
7399552f7358SJed Brown }
7400552f7358SJed Brown 
7401de41b84cSMatthew 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)
7402de41b84cSMatthew G. Knepley {
7403de41b84cSMatthew G. Knepley   DM_Plex        *mesh   = (DM_Plex*) dmf->data;
7404de41b84cSMatthew G. Knepley   PetscInt       *fpoints = NULL, *ftotpoints = NULL;
7405de41b84cSMatthew G. Knepley   PetscInt       *cpoints = NULL;
7406de41b84cSMatthew G. Knepley   PetscInt       *findices, *cindices;
740717c0192bSMatthew G. Knepley   const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */
7408de41b84cSMatthew G. Knepley   PetscInt        foffsets[32], coffsets[32];
7409412e9a14SMatthew G. Knepley   DMPolytopeType  ct;
74104ca5e9f5SMatthew G. Knepley   PetscInt        numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f;
7411de41b84cSMatthew G. Knepley   PetscErrorCode  ierr;
7412de41b84cSMatthew G. Knepley 
7413de41b84cSMatthew G. Knepley   PetscFunctionBegin;
7414de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 1);
7415de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 4);
741692fd8e1eSJed Brown   if (!fsection) {ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);}
7417de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2);
741892fd8e1eSJed Brown   if (!csection) {ierr = DMGetLocalSection(dmc, &csection);CHKERRQ(ierr);}
7419de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5);
7420e87a4003SBarry Smith   if (!globalFSection) {ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);}
7421de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3);
7422e87a4003SBarry Smith   if (!globalCSection) {ierr = DMGetGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);}
7423de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6);
7424de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 7);
7425de41b84cSMatthew G. Knepley   ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr);
7426de41b84cSMatthew G. Knepley   if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields);
7427580bdb30SBarry Smith   ierr = PetscArrayzero(foffsets, 32);CHKERRQ(ierr);
7428580bdb30SBarry Smith   ierr = PetscArrayzero(coffsets, 32);CHKERRQ(ierr);
7429de41b84cSMatthew G. Knepley   /* Column indices */
7430de41b84cSMatthew G. Knepley   ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr);
74314ca5e9f5SMatthew G. Knepley   maxFPoints = numCPoints;
7432de41b84cSMatthew G. Knepley   /* Compress out points not in the section */
7433de41b84cSMatthew G. Knepley   /*   TODO: Squeeze out points with 0 dof as well */
7434de41b84cSMatthew G. Knepley   ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr);
7435de41b84cSMatthew G. Knepley   for (p = 0, q = 0; p < numCPoints*2; p += 2) {
7436de41b84cSMatthew G. Knepley     if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) {
7437de41b84cSMatthew G. Knepley       cpoints[q*2]   = cpoints[p];
7438de41b84cSMatthew G. Knepley       cpoints[q*2+1] = cpoints[p+1];
7439de41b84cSMatthew G. Knepley       ++q;
7440de41b84cSMatthew G. Knepley     }
7441de41b84cSMatthew G. Knepley   }
7442de41b84cSMatthew G. Knepley   numCPoints = q;
7443de41b84cSMatthew G. Knepley   for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) {
7444de41b84cSMatthew G. Knepley     PetscInt fdof;
7445de41b84cSMatthew G. Knepley 
7446de41b84cSMatthew G. Knepley     ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr);
74474ca5e9f5SMatthew G. Knepley     if (!dof) continue;
7448de41b84cSMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
7449de41b84cSMatthew G. Knepley       ierr           = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr);
7450de41b84cSMatthew G. Knepley       coffsets[f+1] += fdof;
7451de41b84cSMatthew G. Knepley     }
7452de41b84cSMatthew G. Knepley     numCIndices += dof;
7453de41b84cSMatthew G. Knepley   }
7454de41b84cSMatthew G. Knepley   for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f];
7455de41b84cSMatthew G. Knepley   /* Row indices */
7456412e9a14SMatthew G. Knepley   ierr = DMPlexGetCellType(dmc, point, &ct);CHKERRQ(ierr);
7457412e9a14SMatthew G. Knepley   {
7458412e9a14SMatthew G. Knepley     DMPlexCellRefiner cr;
7459412e9a14SMatthew G. Knepley     ierr = DMPlexCellRefinerCreate(dmc, &cr);CHKERRQ(ierr);
7460412e9a14SMatthew G. Knepley     ierr = DMPlexCellRefinerGetAffineTransforms(cr, ct, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr);
7461412e9a14SMatthew G. Knepley     ierr = DMPlexCellRefinerDestroy(&cr);CHKERRQ(ierr);
7462412e9a14SMatthew G. Knepley   }
746369291d52SBarry Smith   ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr);
7464de41b84cSMatthew G. Knepley   for (r = 0, q = 0; r < numSubcells; ++r) {
7465de41b84cSMatthew G. Knepley     /* TODO Map from coarse to fine cells */
7466de41b84cSMatthew G. Knepley     ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr);
7467de41b84cSMatthew G. Knepley     /* Compress out points not in the section */
7468de41b84cSMatthew G. Knepley     ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr);
7469de41b84cSMatthew G. Knepley     for (p = 0; p < numFPoints*2; p += 2) {
7470de41b84cSMatthew G. Knepley       if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) {
74714ca5e9f5SMatthew G. Knepley         ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr);
74724ca5e9f5SMatthew G. Knepley         if (!dof) continue;
74734ca5e9f5SMatthew G. Knepley         for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break;
74744ca5e9f5SMatthew G. Knepley         if (s < q) continue;
7475de41b84cSMatthew G. Knepley         ftotpoints[q*2]   = fpoints[p];
7476de41b84cSMatthew G. Knepley         ftotpoints[q*2+1] = fpoints[p+1];
7477de41b84cSMatthew G. Knepley         ++q;
7478de41b84cSMatthew G. Knepley       }
7479de41b84cSMatthew G. Knepley     }
7480de41b84cSMatthew G. Knepley     ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr);
7481de41b84cSMatthew G. Knepley   }
7482de41b84cSMatthew G. Knepley   numFPoints = q;
7483de41b84cSMatthew G. Knepley   for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) {
7484de41b84cSMatthew G. Knepley     PetscInt fdof;
7485de41b84cSMatthew G. Knepley 
7486de41b84cSMatthew G. Knepley     ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr);
74874ca5e9f5SMatthew G. Knepley     if (!dof) continue;
7488de41b84cSMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
7489de41b84cSMatthew G. Knepley       ierr           = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr);
7490de41b84cSMatthew G. Knepley       foffsets[f+1] += fdof;
7491de41b84cSMatthew G. Knepley     }
7492de41b84cSMatthew G. Knepley     numFIndices += dof;
7493de41b84cSMatthew G. Knepley   }
7494de41b84cSMatthew G. Knepley   for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f];
7495de41b84cSMatthew G. Knepley 
74968ccfff9cSToby Isaac   if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices);
74978ccfff9cSToby Isaac   if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices);
749869291d52SBarry Smith   ierr = DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr);
749969291d52SBarry Smith   ierr = DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr);
7500de41b84cSMatthew G. Knepley   if (numFields) {
75014acb8e1eSToby Isaac     const PetscInt **permsF[32] = {NULL};
75024acb8e1eSToby Isaac     const PetscInt **permsC[32] = {NULL};
75034acb8e1eSToby Isaac 
75044acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
75054acb8e1eSToby Isaac       ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr);
75064acb8e1eSToby Isaac       ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr);
7507de41b84cSMatthew G. Knepley     }
75084acb8e1eSToby Isaac     for (p = 0; p < numFPoints; p++) {
75094acb8e1eSToby Isaac       ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr);
751036fa2b79SJed Brown       ierr = DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices);CHKERRQ(ierr);
75114acb8e1eSToby Isaac     }
75124acb8e1eSToby Isaac     for (p = 0; p < numCPoints; p++) {
75134acb8e1eSToby Isaac       ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr);
751436fa2b79SJed Brown       ierr = DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices);CHKERRQ(ierr);
75154acb8e1eSToby Isaac     }
75164acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
75174acb8e1eSToby Isaac       ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr);
75184acb8e1eSToby Isaac       ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr);
7519de41b84cSMatthew G. Knepley     }
7520de41b84cSMatthew G. Knepley   } else {
75214acb8e1eSToby Isaac     const PetscInt **permsF = NULL;
75224acb8e1eSToby Isaac     const PetscInt **permsC = NULL;
75234acb8e1eSToby Isaac 
75244acb8e1eSToby Isaac     ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr);
75254acb8e1eSToby Isaac     ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr);
75264acb8e1eSToby Isaac     for (p = 0, off = 0; p < numFPoints; p++) {
75274acb8e1eSToby Isaac       const PetscInt *perm = permsF ? permsF[p] : NULL;
75284acb8e1eSToby Isaac 
75294acb8e1eSToby Isaac       ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr);
753036fa2b79SJed Brown       ierr = DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices);CHKERRQ(ierr);
7531de41b84cSMatthew G. Knepley     }
75324acb8e1eSToby Isaac     for (p = 0, off = 0; p < numCPoints; p++) {
75334acb8e1eSToby Isaac       const PetscInt *perm = permsC ? permsC[p] : NULL;
75344acb8e1eSToby Isaac 
75354acb8e1eSToby Isaac       ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr);
753636fa2b79SJed Brown       ierr = DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices);CHKERRQ(ierr);
7537de41b84cSMatthew G. Knepley     }
75384acb8e1eSToby Isaac     ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr);
75394acb8e1eSToby Isaac     ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr);
7540de41b84cSMatthew G. Knepley   }
7541de41b84cSMatthew G. Knepley   if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr);}
75424acb8e1eSToby Isaac   /* TODO: flips */
7543de41b84cSMatthew G. Knepley   ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode);
7544de41b84cSMatthew G. Knepley   if (ierr) {
7545de41b84cSMatthew G. Knepley     PetscMPIInt    rank;
7546de41b84cSMatthew G. Knepley     PetscErrorCode ierr2;
7547de41b84cSMatthew G. Knepley 
754855b25c41SPierre Jolivet     ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRMPI(ierr2);
7549e4b003c7SBarry Smith     ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2);
7550de41b84cSMatthew G. Knepley     ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr2);
755169291d52SBarry Smith     ierr2 = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr2);
755269291d52SBarry Smith     ierr2 = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr2);
7553de41b84cSMatthew G. Knepley     CHKERRQ(ierr);
7554de41b84cSMatthew G. Knepley   }
755569291d52SBarry Smith   ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr);
7556de41b84cSMatthew G. Knepley   ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr);
755769291d52SBarry Smith   ierr = DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices);CHKERRQ(ierr);
755869291d52SBarry Smith   ierr = DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices);CHKERRQ(ierr);
7559de41b84cSMatthew G. Knepley   PetscFunctionReturn(0);
7560de41b84cSMatthew G. Knepley }
7561de41b84cSMatthew G. Knepley 
75627c927364SMatthew G. Knepley PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[])
75637c927364SMatthew G. Knepley {
75647c927364SMatthew G. Knepley   PetscInt      *fpoints = NULL, *ftotpoints = NULL;
75657c927364SMatthew G. Knepley   PetscInt      *cpoints = NULL;
75667c927364SMatthew G. Knepley   PetscInt       foffsets[32], coffsets[32];
756717c0192bSMatthew G. Knepley   const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */
7568412e9a14SMatthew G. Knepley   DMPolytopeType ct;
75697c927364SMatthew G. Knepley   PetscInt       numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f;
75707c927364SMatthew G. Knepley   PetscErrorCode ierr;
75717c927364SMatthew G. Knepley 
75727c927364SMatthew G. Knepley   PetscFunctionBegin;
75737c927364SMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 1);
75747c927364SMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 4);
757592fd8e1eSJed Brown   if (!fsection) {ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);}
75767c927364SMatthew G. Knepley   PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2);
757792fd8e1eSJed Brown   if (!csection) {ierr = DMGetLocalSection(dmc, &csection);CHKERRQ(ierr);}
75787c927364SMatthew G. Knepley   PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5);
7579e87a4003SBarry Smith   if (!globalFSection) {ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);}
75807c927364SMatthew G. Knepley   PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3);
7581e87a4003SBarry Smith   if (!globalCSection) {ierr = DMGetGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);}
75827c927364SMatthew G. Knepley   PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6);
75837c927364SMatthew G. Knepley   ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr);
75847c927364SMatthew G. Knepley   if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields);
7585580bdb30SBarry Smith   ierr = PetscArrayzero(foffsets, 32);CHKERRQ(ierr);
7586580bdb30SBarry Smith   ierr = PetscArrayzero(coffsets, 32);CHKERRQ(ierr);
75877c927364SMatthew G. Knepley   /* Column indices */
75887c927364SMatthew G. Knepley   ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr);
75897c927364SMatthew G. Knepley   maxFPoints = numCPoints;
75907c927364SMatthew G. Knepley   /* Compress out points not in the section */
75917c927364SMatthew G. Knepley   /*   TODO: Squeeze out points with 0 dof as well */
75927c927364SMatthew G. Knepley   ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr);
75937c927364SMatthew G. Knepley   for (p = 0, q = 0; p < numCPoints*2; p += 2) {
75947c927364SMatthew G. Knepley     if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) {
75957c927364SMatthew G. Knepley       cpoints[q*2]   = cpoints[p];
75967c927364SMatthew G. Knepley       cpoints[q*2+1] = cpoints[p+1];
75977c927364SMatthew G. Knepley       ++q;
75987c927364SMatthew G. Knepley     }
75997c927364SMatthew G. Knepley   }
76007c927364SMatthew G. Knepley   numCPoints = q;
76017c927364SMatthew G. Knepley   for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) {
76027c927364SMatthew G. Knepley     PetscInt fdof;
76037c927364SMatthew G. Knepley 
76047c927364SMatthew G. Knepley     ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr);
76057c927364SMatthew G. Knepley     if (!dof) continue;
76067c927364SMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
76077c927364SMatthew G. Knepley       ierr           = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr);
76087c927364SMatthew G. Knepley       coffsets[f+1] += fdof;
76097c927364SMatthew G. Knepley     }
76107c927364SMatthew G. Knepley     numCIndices += dof;
76117c927364SMatthew G. Knepley   }
76127c927364SMatthew G. Knepley   for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f];
76137c927364SMatthew G. Knepley   /* Row indices */
7614412e9a14SMatthew G. Knepley   ierr = DMPlexGetCellType(dmc, point, &ct);CHKERRQ(ierr);
7615412e9a14SMatthew G. Knepley   {
7616412e9a14SMatthew G. Knepley     DMPlexCellRefiner cr;
7617412e9a14SMatthew G. Knepley     ierr = DMPlexCellRefinerCreate(dmc, &cr);CHKERRQ(ierr);
7618412e9a14SMatthew G. Knepley     ierr = DMPlexCellRefinerGetAffineTransforms(cr, ct, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr);
7619412e9a14SMatthew G. Knepley     ierr = DMPlexCellRefinerDestroy(&cr);CHKERRQ(ierr);
7620412e9a14SMatthew G. Knepley   }
762169291d52SBarry Smith   ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints);CHKERRQ(ierr);
76227c927364SMatthew G. Knepley   for (r = 0, q = 0; r < numSubcells; ++r) {
76237c927364SMatthew G. Knepley     /* TODO Map from coarse to fine cells */
76247c927364SMatthew G. Knepley     ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr);
76257c927364SMatthew G. Knepley     /* Compress out points not in the section */
76267c927364SMatthew G. Knepley     ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr);
76277c927364SMatthew G. Knepley     for (p = 0; p < numFPoints*2; p += 2) {
76287c927364SMatthew G. Knepley       if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) {
76297c927364SMatthew G. Knepley         ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr);
76307c927364SMatthew G. Knepley         if (!dof) continue;
76317c927364SMatthew G. Knepley         for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break;
76327c927364SMatthew G. Knepley         if (s < q) continue;
76337c927364SMatthew G. Knepley         ftotpoints[q*2]   = fpoints[p];
76347c927364SMatthew G. Knepley         ftotpoints[q*2+1] = fpoints[p+1];
76357c927364SMatthew G. Knepley         ++q;
76367c927364SMatthew G. Knepley       }
76377c927364SMatthew G. Knepley     }
76387c927364SMatthew G. Knepley     ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr);
76397c927364SMatthew G. Knepley   }
76407c927364SMatthew G. Knepley   numFPoints = q;
76417c927364SMatthew G. Knepley   for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) {
76427c927364SMatthew G. Knepley     PetscInt fdof;
76437c927364SMatthew G. Knepley 
76447c927364SMatthew G. Knepley     ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr);
76457c927364SMatthew G. Knepley     if (!dof) continue;
76467c927364SMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
76477c927364SMatthew G. Knepley       ierr           = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr);
76487c927364SMatthew G. Knepley       foffsets[f+1] += fdof;
76497c927364SMatthew G. Knepley     }
76507c927364SMatthew G. Knepley     numFIndices += dof;
76517c927364SMatthew G. Knepley   }
76527c927364SMatthew G. Knepley   for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f];
76537c927364SMatthew G. Knepley 
76548ccfff9cSToby Isaac   if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", foffsets[numFields], numFIndices);
76558ccfff9cSToby Isaac   if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", coffsets[numFields], numCIndices);
76567c927364SMatthew G. Knepley   if (numFields) {
76574acb8e1eSToby Isaac     const PetscInt **permsF[32] = {NULL};
76584acb8e1eSToby Isaac     const PetscInt **permsC[32] = {NULL};
76594acb8e1eSToby Isaac 
76604acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
76614acb8e1eSToby Isaac       ierr = PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr);
76624acb8e1eSToby Isaac       ierr = PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr);
76637c927364SMatthew G. Knepley     }
76644acb8e1eSToby Isaac     for (p = 0; p < numFPoints; p++) {
76654acb8e1eSToby Isaac       ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr);
766636fa2b79SJed Brown       ierr = DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices);CHKERRQ(ierr);
76674acb8e1eSToby Isaac     }
76684acb8e1eSToby Isaac     for (p = 0; p < numCPoints; p++) {
76694acb8e1eSToby Isaac       ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr);
767036fa2b79SJed Brown       ierr = DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices);CHKERRQ(ierr);
76714acb8e1eSToby Isaac     }
76724acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
76734acb8e1eSToby Isaac       ierr = PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL);CHKERRQ(ierr);
76744acb8e1eSToby Isaac       ierr = PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL);CHKERRQ(ierr);
76757c927364SMatthew G. Knepley     }
76767c927364SMatthew G. Knepley   } else {
76774acb8e1eSToby Isaac     const PetscInt **permsF = NULL;
76784acb8e1eSToby Isaac     const PetscInt **permsC = NULL;
76794acb8e1eSToby Isaac 
76804acb8e1eSToby Isaac     ierr = PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr);
76814acb8e1eSToby Isaac     ierr = PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr);
76824acb8e1eSToby Isaac     for (p = 0, off = 0; p < numFPoints; p++) {
76834acb8e1eSToby Isaac       const PetscInt *perm = permsF ? permsF[p] : NULL;
76844acb8e1eSToby Isaac 
76854acb8e1eSToby Isaac       ierr = PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff);CHKERRQ(ierr);
768636fa2b79SJed Brown       ierr = DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices);CHKERRQ(ierr);
76877c927364SMatthew G. Knepley     }
76884acb8e1eSToby Isaac     for (p = 0, off = 0; p < numCPoints; p++) {
76894acb8e1eSToby Isaac       const PetscInt *perm = permsC ? permsC[p] : NULL;
76904acb8e1eSToby Isaac 
76914acb8e1eSToby Isaac       ierr = PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff);CHKERRQ(ierr);
769236fa2b79SJed Brown       ierr = DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices);CHKERRQ(ierr);
76937c927364SMatthew G. Knepley     }
76944acb8e1eSToby Isaac     ierr = PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL);CHKERRQ(ierr);
76954acb8e1eSToby Isaac     ierr = PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL);CHKERRQ(ierr);
76967c927364SMatthew G. Knepley   }
769769291d52SBarry Smith   ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints);CHKERRQ(ierr);
76987c927364SMatthew G. Knepley   ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr);
76997c927364SMatthew G. Knepley   PetscFunctionReturn(0);
77007c927364SMatthew G. Knepley }
77017c927364SMatthew G. Knepley 
77027cd05799SMatthew G. Knepley /*@C
77037cd05799SMatthew G. Knepley   DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0)
77047cd05799SMatthew G. Knepley 
77057cd05799SMatthew G. Knepley   Input Parameter:
77067cd05799SMatthew G. Knepley . dm   - The DMPlex object
77077cd05799SMatthew G. Knepley 
77087cd05799SMatthew G. Knepley   Output Parameter:
77097cd05799SMatthew G. Knepley . cellHeight - The height of a cell
77107cd05799SMatthew G. Knepley 
77117cd05799SMatthew G. Knepley   Level: developer
77127cd05799SMatthew G. Knepley 
77137cd05799SMatthew G. Knepley .seealso DMPlexSetVTKCellHeight()
77147cd05799SMatthew G. Knepley @*/
7715552f7358SJed Brown PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight)
7716552f7358SJed Brown {
7717552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
7718552f7358SJed Brown 
7719552f7358SJed Brown   PetscFunctionBegin;
7720552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7721552f7358SJed Brown   PetscValidPointer(cellHeight, 2);
7722552f7358SJed Brown   *cellHeight = mesh->vtkCellHeight;
7723552f7358SJed Brown   PetscFunctionReturn(0);
7724552f7358SJed Brown }
7725552f7358SJed Brown 
77267cd05799SMatthew G. Knepley /*@C
77277cd05799SMatthew G. Knepley   DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0)
77287cd05799SMatthew G. Knepley 
77297cd05799SMatthew G. Knepley   Input Parameters:
77307cd05799SMatthew G. Knepley + dm   - The DMPlex object
77317cd05799SMatthew G. Knepley - cellHeight - The height of a cell
77327cd05799SMatthew G. Knepley 
77337cd05799SMatthew G. Knepley   Level: developer
77347cd05799SMatthew G. Knepley 
77357cd05799SMatthew G. Knepley .seealso DMPlexGetVTKCellHeight()
77367cd05799SMatthew G. Knepley @*/
7737552f7358SJed Brown PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight)
7738552f7358SJed Brown {
7739552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
7740552f7358SJed Brown 
7741552f7358SJed Brown   PetscFunctionBegin;
7742552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7743552f7358SJed Brown   mesh->vtkCellHeight = cellHeight;
7744552f7358SJed Brown   PetscFunctionReturn(0);
7745552f7358SJed Brown }
7746552f7358SJed Brown 
7747e6139122SMatthew G. Knepley /*@
7748e6139122SMatthew G. Knepley   DMPlexGetGhostCellStratum - Get the range of cells which are used to enforce FV boundary conditions
7749e6139122SMatthew G. Knepley 
7750e6139122SMatthew G. Knepley   Input Parameter:
7751e6139122SMatthew G. Knepley . dm - The DMPlex object
7752e6139122SMatthew G. Knepley 
7753e6139122SMatthew G. Knepley   Output Parameters:
77542a9f31c0SMatthew G. Knepley + gcStart - The first ghost cell, or NULL
77552a9f31c0SMatthew G. Knepley - gcEnd   - The upper bound on ghost cells, or NULL
7756e6139122SMatthew G. Knepley 
77572a9f31c0SMatthew G. Knepley   Level: advanced
7758e6139122SMatthew G. Knepley 
77598065b584SMatthew Knepley .seealso DMPlexConstructGhostCells(), DMPlexGetGhostCellStratum()
7760e6139122SMatthew G. Knepley @*/
7761e6139122SMatthew G. Knepley PetscErrorCode DMPlexGetGhostCellStratum(DM dm, PetscInt *gcStart, PetscInt *gcEnd)
7762e6139122SMatthew G. Knepley {
7763412e9a14SMatthew G. Knepley   DMLabel        ctLabel;
7764e6139122SMatthew G. Knepley   PetscErrorCode ierr;
7765e6139122SMatthew G. Knepley 
7766e6139122SMatthew G. Knepley   PetscFunctionBegin;
7767e6139122SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7768412e9a14SMatthew G. Knepley   ierr = DMPlexGetCellTypeLabel(dm, &ctLabel);CHKERRQ(ierr);
7769412e9a14SMatthew G. Knepley   ierr = DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_FV_GHOST, gcStart, gcEnd);CHKERRQ(ierr);
7770e6139122SMatthew G. Knepley   PetscFunctionReturn(0);
7771e6139122SMatthew G. Knepley }
7772e6139122SMatthew G. Knepley 
7773552f7358SJed Brown /* We can easily have a form that takes an IS instead */
77749886b8cfSStefano Zampini PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering)
7775552f7358SJed Brown {
7776552f7358SJed Brown   PetscSection   section, globalSection;
7777552f7358SJed Brown   PetscInt      *numbers, p;
7778552f7358SJed Brown   PetscErrorCode ierr;
7779552f7358SJed Brown 
7780552f7358SJed Brown   PetscFunctionBegin;
778182f516ccSBarry Smith   ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section);CHKERRQ(ierr);
7782552f7358SJed Brown   ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr);
7783552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
7784552f7358SJed Brown     ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr);
7785552f7358SJed Brown   }
7786552f7358SJed Brown   ierr = PetscSectionSetUp(section);CHKERRQ(ierr);
778715b58121SMatthew G. Knepley   ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection);CHKERRQ(ierr);
7788854ce69bSBarry Smith   ierr = PetscMalloc1(pEnd - pStart, &numbers);CHKERRQ(ierr);
7789552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
7790552f7358SJed Brown     ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr);
7791ef48cebcSMatthew G. Knepley     if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift;
7792ef48cebcSMatthew G. Knepley     else                       numbers[p-pStart] += shift;
7793552f7358SJed Brown   }
779482f516ccSBarry Smith   ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr);
7795ef48cebcSMatthew G. Knepley   if (globalSize) {
7796ef48cebcSMatthew G. Knepley     PetscLayout layout;
7797ef48cebcSMatthew G. Knepley     ierr = PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout);CHKERRQ(ierr);
7798ef48cebcSMatthew G. Knepley     ierr = PetscLayoutGetSize(layout, globalSize);CHKERRQ(ierr);
7799ef48cebcSMatthew G. Knepley     ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr);
7800ef48cebcSMatthew G. Knepley   }
7801552f7358SJed Brown   ierr = PetscSectionDestroy(&section);CHKERRQ(ierr);
7802552f7358SJed Brown   ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr);
7803552f7358SJed Brown   PetscFunctionReturn(0);
7804552f7358SJed Brown }
7805552f7358SJed Brown 
780681ed3555SMatthew G. Knepley PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers)
7807552f7358SJed Brown {
7808412e9a14SMatthew G. Knepley   PetscInt       cellHeight, cStart, cEnd;
7809552f7358SJed Brown   PetscErrorCode ierr;
7810552f7358SJed Brown 
7811552f7358SJed Brown   PetscFunctionBegin;
7812552f7358SJed Brown   ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr);
7813412e9a14SMatthew G. Knepley   if (includeHybrid) {ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);}
7814412e9a14SMatthew G. Knepley   else               {ierr = DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);}
78159886b8cfSStefano Zampini   ierr = DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers);CHKERRQ(ierr);
781681ed3555SMatthew G. Knepley   PetscFunctionReturn(0);
7817552f7358SJed Brown }
781881ed3555SMatthew G. Knepley 
78198dab3259SMatthew G. Knepley /*@
78207cd05799SMatthew G. Knepley   DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process
78217cd05799SMatthew G. Knepley 
78227cd05799SMatthew G. Knepley   Input Parameter:
78237cd05799SMatthew G. Knepley . dm   - The DMPlex object
78247cd05799SMatthew G. Knepley 
78257cd05799SMatthew G. Knepley   Output Parameter:
78267cd05799SMatthew G. Knepley . globalCellNumbers - Global cell numbers for all cells on this process
78277cd05799SMatthew G. Knepley 
78287cd05799SMatthew G. Knepley   Level: developer
78297cd05799SMatthew G. Knepley 
78307cd05799SMatthew G. Knepley .seealso DMPlexGetVertexNumbering()
78317cd05799SMatthew G. Knepley @*/
783281ed3555SMatthew G. Knepley PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers)
783381ed3555SMatthew G. Knepley {
783481ed3555SMatthew G. Knepley   DM_Plex       *mesh = (DM_Plex*) dm->data;
783581ed3555SMatthew G. Knepley   PetscErrorCode ierr;
783681ed3555SMatthew G. Knepley 
783781ed3555SMatthew G. Knepley   PetscFunctionBegin;
783881ed3555SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
783981ed3555SMatthew G. Knepley   if (!mesh->globalCellNumbers) {ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers);CHKERRQ(ierr);}
7840552f7358SJed Brown   *globalCellNumbers = mesh->globalCellNumbers;
7841552f7358SJed Brown   PetscFunctionReturn(0);
7842552f7358SJed Brown }
7843552f7358SJed Brown 
784481ed3555SMatthew G. Knepley PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers)
784581ed3555SMatthew G. Knepley {
7846412e9a14SMatthew G. Knepley   PetscInt       vStart, vEnd;
784781ed3555SMatthew G. Knepley   PetscErrorCode ierr;
784881ed3555SMatthew G. Knepley 
784981ed3555SMatthew G. Knepley   PetscFunctionBegin;
785081ed3555SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
785181ed3555SMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
78529886b8cfSStefano Zampini   ierr = DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers);CHKERRQ(ierr);
785381ed3555SMatthew G. Knepley   PetscFunctionReturn(0);
785481ed3555SMatthew G. Knepley }
785581ed3555SMatthew G. Knepley 
78568dab3259SMatthew G. Knepley /*@
78576aa51ba9SJacob Faibussowitsch   DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process
78587cd05799SMatthew G. Knepley 
78597cd05799SMatthew G. Knepley   Input Parameter:
78607cd05799SMatthew G. Knepley . dm   - The DMPlex object
78617cd05799SMatthew G. Knepley 
78627cd05799SMatthew G. Knepley   Output Parameter:
78637cd05799SMatthew G. Knepley . globalVertexNumbers - Global vertex numbers for all vertices on this process
78647cd05799SMatthew G. Knepley 
78657cd05799SMatthew G. Knepley   Level: developer
78667cd05799SMatthew G. Knepley 
78677cd05799SMatthew G. Knepley .seealso DMPlexGetCellNumbering()
78687cd05799SMatthew G. Knepley @*/
7869552f7358SJed Brown PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers)
7870552f7358SJed Brown {
7871552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
7872552f7358SJed Brown   PetscErrorCode ierr;
7873552f7358SJed Brown 
7874552f7358SJed Brown   PetscFunctionBegin;
7875552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
787681ed3555SMatthew G. Knepley   if (!mesh->globalVertexNumbers) {ierr = DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers);CHKERRQ(ierr);}
7877552f7358SJed Brown   *globalVertexNumbers = mesh->globalVertexNumbers;
7878552f7358SJed Brown   PetscFunctionReturn(0);
7879552f7358SJed Brown }
7880552f7358SJed Brown 
78818dab3259SMatthew G. Knepley /*@
78827cd05799SMatthew G. Knepley   DMPlexCreatePointNumbering - Create a global numbering for all points on this process
78837cd05799SMatthew G. Knepley 
78847cd05799SMatthew G. Knepley   Input Parameter:
78857cd05799SMatthew G. Knepley . dm   - The DMPlex object
78867cd05799SMatthew G. Knepley 
78877cd05799SMatthew G. Knepley   Output Parameter:
78887cd05799SMatthew G. Knepley . globalPointNumbers - Global numbers for all points on this process
78897cd05799SMatthew G. Knepley 
78907cd05799SMatthew G. Knepley   Level: developer
78917cd05799SMatthew G. Knepley 
78927cd05799SMatthew G. Knepley .seealso DMPlexGetCellNumbering()
78937cd05799SMatthew G. Knepley @*/
7894ef48cebcSMatthew G. Knepley PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers)
7895ef48cebcSMatthew G. Knepley {
7896ef48cebcSMatthew G. Knepley   IS             nums[4];
7897862913ffSStefano Zampini   PetscInt       depths[4], gdepths[4], starts[4];
7898ef48cebcSMatthew G. Knepley   PetscInt       depth, d, shift = 0;
7899ef48cebcSMatthew G. Knepley   PetscErrorCode ierr;
7900ef48cebcSMatthew G. Knepley 
7901ef48cebcSMatthew G. Knepley   PetscFunctionBegin;
7902ef48cebcSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7903ef48cebcSMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
79048abc87a0SMichael Lange   /* For unstratified meshes use dim instead of depth */
79058abc87a0SMichael Lange   if (depth < 0) {ierr = DMGetDimension(dm, &depth);CHKERRQ(ierr);}
7906862913ffSStefano Zampini   for (d = 0; d <= depth; ++d) {
7907862913ffSStefano Zampini     PetscInt end;
7908862913ffSStefano Zampini 
7909862913ffSStefano Zampini     depths[d] = depth-d;
7910862913ffSStefano Zampini     ierr = DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end);CHKERRQ(ierr);
7911862913ffSStefano Zampini     if (!(starts[d]-end)) { starts[d] = depths[d] = -1; }
7912862913ffSStefano Zampini   }
7913862913ffSStefano Zampini   ierr = PetscSortIntWithArray(depth+1, starts, depths);CHKERRQ(ierr);
7914820f2d46SBarry Smith   ierr = MPIU_Allreduce(depths, gdepths, depth+1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr);
7915862913ffSStefano Zampini   for (d = 0; d <= depth; ++d) {
7916862913ffSStefano Zampini     if (starts[d] >= 0 && depths[d] != gdepths[d]) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Expected depth %D, found %D",depths[d],gdepths[d]);
7917862913ffSStefano Zampini   }
7918ef48cebcSMatthew G. Knepley   for (d = 0; d <= depth; ++d) {
7919ef48cebcSMatthew G. Knepley     PetscInt pStart, pEnd, gsize;
7920ef48cebcSMatthew G. Knepley 
7921862913ffSStefano Zampini     ierr = DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd);CHKERRQ(ierr);
79229886b8cfSStefano Zampini     ierr = DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]);CHKERRQ(ierr);
7923ef48cebcSMatthew G. Knepley     shift += gsize;
7924ef48cebcSMatthew G. Knepley   }
7925302440fdSBarry Smith   ierr = ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers);CHKERRQ(ierr);
7926ef48cebcSMatthew G. Knepley   for (d = 0; d <= depth; ++d) {ierr = ISDestroy(&nums[d]);CHKERRQ(ierr);}
7927ef48cebcSMatthew G. Knepley   PetscFunctionReturn(0);
7928ef48cebcSMatthew G. Knepley }
7929ef48cebcSMatthew G. Knepley 
793008a22f4bSMatthew G. Knepley /*@
793108a22f4bSMatthew G. Knepley   DMPlexCreateRankField - Create a cell field whose value is the rank of the owner
793208a22f4bSMatthew G. Knepley 
793308a22f4bSMatthew G. Knepley   Input Parameter:
793408a22f4bSMatthew G. Knepley . dm - The DMPlex object
793508a22f4bSMatthew G. Knepley 
793608a22f4bSMatthew G. Knepley   Output Parameter:
793708a22f4bSMatthew G. Knepley . ranks - The rank field
793808a22f4bSMatthew G. Knepley 
793908a22f4bSMatthew G. Knepley   Options Database Keys:
794008a22f4bSMatthew G. Knepley . -dm_partition_view - Adds the rank field into the DM output from -dm_view using the same viewer
794108a22f4bSMatthew G. Knepley 
794208a22f4bSMatthew G. Knepley   Level: intermediate
794308a22f4bSMatthew G. Knepley 
794408a22f4bSMatthew G. Knepley .seealso: DMView()
794508a22f4bSMatthew G. Knepley @*/
794608a22f4bSMatthew G. Knepley PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks)
794708a22f4bSMatthew G. Knepley {
794808a22f4bSMatthew G. Knepley   DM             rdm;
794908a22f4bSMatthew G. Knepley   PetscFE        fe;
795008a22f4bSMatthew G. Knepley   PetscScalar   *r;
795108a22f4bSMatthew G. Knepley   PetscMPIInt    rank;
7952a55f9a55SMatthew G. Knepley   DMPolytopeType ct;
795308a22f4bSMatthew G. Knepley   PetscInt       dim, cStart, cEnd, c;
7954a55f9a55SMatthew G. Knepley   PetscBool      simplex;
795508a22f4bSMatthew G. Knepley   PetscErrorCode ierr;
795608a22f4bSMatthew G. Knepley 
795708a22f4bSMatthew G. Knepley   PetscFunctionBeginUser;
7958f95ace6aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7959f95ace6aSMatthew G. Knepley   PetscValidPointer(ranks, 2);
7960ffc4695bSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank);CHKERRMPI(ierr);
796108a22f4bSMatthew G. Knepley   ierr = DMClone(dm, &rdm);CHKERRQ(ierr);
796208a22f4bSMatthew G. Knepley   ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr);
7963a55f9a55SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr);
7964a55f9a55SMatthew G. Knepley   ierr = DMPlexGetCellType(dm, cStart, &ct);CHKERRQ(ierr);
7965a55f9a55SMatthew G. Knepley   simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE;
7966a55f9a55SMatthew G. Knepley   ierr = PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe);CHKERRQ(ierr);
796708a22f4bSMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) fe, "rank");CHKERRQ(ierr);
7968e5e52638SMatthew G. Knepley   ierr = DMSetField(rdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr);
796908a22f4bSMatthew G. Knepley   ierr = PetscFEDestroy(&fe);CHKERRQ(ierr);
7970e5e52638SMatthew G. Knepley   ierr = DMCreateDS(rdm);CHKERRQ(ierr);
797108a22f4bSMatthew G. Knepley   ierr = DMCreateGlobalVector(rdm, ranks);CHKERRQ(ierr);
797208a22f4bSMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) *ranks, "partition");CHKERRQ(ierr);
797308a22f4bSMatthew G. Knepley   ierr = VecGetArray(*ranks, &r);CHKERRQ(ierr);
797408a22f4bSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
797508a22f4bSMatthew G. Knepley     PetscScalar *lr;
797608a22f4bSMatthew G. Knepley 
797708a22f4bSMatthew G. Knepley     ierr = DMPlexPointGlobalRef(rdm, c, r, &lr);CHKERRQ(ierr);
797871f09efeSPierre Jolivet     if (lr) *lr = rank;
797908a22f4bSMatthew G. Knepley   }
798008a22f4bSMatthew G. Knepley   ierr = VecRestoreArray(*ranks, &r);CHKERRQ(ierr);
798108a22f4bSMatthew G. Knepley   ierr = DMDestroy(&rdm);CHKERRQ(ierr);
798208a22f4bSMatthew G. Knepley   PetscFunctionReturn(0);
798308a22f4bSMatthew G. Knepley }
798408a22f4bSMatthew G. Knepley 
7985ca8062c8SMatthew G. Knepley /*@
798618e14f0cSMatthew G. Knepley   DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell
798718e14f0cSMatthew G. Knepley 
798818e14f0cSMatthew G. Knepley   Input Parameters:
798918e14f0cSMatthew G. Knepley + dm    - The DMPlex
799018e14f0cSMatthew G. Knepley - label - The DMLabel
799118e14f0cSMatthew G. Knepley 
799218e14f0cSMatthew G. Knepley   Output Parameter:
799318e14f0cSMatthew G. Knepley . val - The label value field
799418e14f0cSMatthew G. Knepley 
799518e14f0cSMatthew G. Knepley   Options Database Keys:
799618e14f0cSMatthew G. Knepley . -dm_label_view - Adds the label value field into the DM output from -dm_view using the same viewer
799718e14f0cSMatthew G. Knepley 
799818e14f0cSMatthew G. Knepley   Level: intermediate
799918e14f0cSMatthew G. Knepley 
800018e14f0cSMatthew G. Knepley .seealso: DMView()
800118e14f0cSMatthew G. Knepley @*/
800218e14f0cSMatthew G. Knepley PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val)
800318e14f0cSMatthew G. Knepley {
800418e14f0cSMatthew G. Knepley   DM             rdm;
800518e14f0cSMatthew G. Knepley   PetscFE        fe;
800618e14f0cSMatthew G. Knepley   PetscScalar   *v;
800718e14f0cSMatthew G. Knepley   PetscInt       dim, cStart, cEnd, c;
800818e14f0cSMatthew G. Knepley   PetscErrorCode ierr;
800918e14f0cSMatthew G. Knepley 
801018e14f0cSMatthew G. Knepley   PetscFunctionBeginUser;
801118e14f0cSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
801218e14f0cSMatthew G. Knepley   PetscValidPointer(label, 2);
801318e14f0cSMatthew G. Knepley   PetscValidPointer(val, 3);
801418e14f0cSMatthew G. Knepley   ierr = DMClone(dm, &rdm);CHKERRQ(ierr);
801518e14f0cSMatthew G. Knepley   ierr = DMGetDimension(rdm, &dim);CHKERRQ(ierr);
801618e14f0cSMatthew G. Knepley   ierr = PetscFECreateDefault(PetscObjectComm((PetscObject) rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe);CHKERRQ(ierr);
801718e14f0cSMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) fe, "label_value");CHKERRQ(ierr);
8018e5e52638SMatthew G. Knepley   ierr = DMSetField(rdm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr);
801918e14f0cSMatthew G. Knepley   ierr = PetscFEDestroy(&fe);CHKERRQ(ierr);
8020e5e52638SMatthew G. Knepley   ierr = DMCreateDS(rdm);CHKERRQ(ierr);
802118e14f0cSMatthew G. Knepley   ierr = DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd);CHKERRQ(ierr);
802218e14f0cSMatthew G. Knepley   ierr = DMCreateGlobalVector(rdm, val);CHKERRQ(ierr);
8023effbd7cbSMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) *val, "label_value");CHKERRQ(ierr);
802418e14f0cSMatthew G. Knepley   ierr = VecGetArray(*val, &v);CHKERRQ(ierr);
802518e14f0cSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
802618e14f0cSMatthew G. Knepley     PetscScalar *lv;
802718e14f0cSMatthew G. Knepley     PetscInt     cval;
802818e14f0cSMatthew G. Knepley 
802918e14f0cSMatthew G. Knepley     ierr = DMPlexPointGlobalRef(rdm, c, v, &lv);CHKERRQ(ierr);
803018e14f0cSMatthew G. Knepley     ierr = DMLabelGetValue(label, c, &cval);CHKERRQ(ierr);
803118e14f0cSMatthew G. Knepley     *lv = cval;
803218e14f0cSMatthew G. Knepley   }
803318e14f0cSMatthew G. Knepley   ierr = VecRestoreArray(*val, &v);CHKERRQ(ierr);
803418e14f0cSMatthew G. Knepley   ierr = DMDestroy(&rdm);CHKERRQ(ierr);
803518e14f0cSMatthew G. Knepley   PetscFunctionReturn(0);
803618e14f0cSMatthew G. Knepley }
803718e14f0cSMatthew G. Knepley 
803818e14f0cSMatthew G. Knepley /*@
8039ca8062c8SMatthew G. Knepley   DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric.
8040ca8062c8SMatthew G. Knepley 
804169916449SMatthew G. Knepley   Input Parameter:
804269916449SMatthew G. Knepley . dm - The DMPlex object
8043ca8062c8SMatthew G. Knepley 
804495eb5ee5SVaclav Hapla   Notes:
804595eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
804695eb5ee5SVaclav Hapla 
804795eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
8048ca8062c8SMatthew G. Knepley 
8049ca8062c8SMatthew G. Knepley   Level: developer
8050ca8062c8SMatthew G. Knepley 
805195eb5ee5SVaclav Hapla .seealso: DMCreate(), DMSetFromOptions()
8052ca8062c8SMatthew G. Knepley @*/
8053ca8062c8SMatthew G. Knepley PetscErrorCode DMPlexCheckSymmetry(DM dm)
8054ca8062c8SMatthew G. Knepley {
8055ca8062c8SMatthew G. Knepley   PetscSection    coneSection, supportSection;
8056ca8062c8SMatthew G. Knepley   const PetscInt *cone, *support;
8057ca8062c8SMatthew G. Knepley   PetscInt        coneSize, c, supportSize, s;
805857beb4faSStefano Zampini   PetscInt        pStart, pEnd, p, pp, csize, ssize;
805957beb4faSStefano Zampini   PetscBool       storagecheck = PETSC_TRUE;
8060ca8062c8SMatthew G. Knepley   PetscErrorCode  ierr;
8061ca8062c8SMatthew G. Knepley 
8062ca8062c8SMatthew G. Knepley   PetscFunctionBegin;
8063ca8062c8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8064412e9a14SMatthew G. Knepley   ierr = DMViewFromOptions(dm, NULL, "-sym_dm_view");CHKERRQ(ierr);
8065ca8062c8SMatthew G. Knepley   ierr = DMPlexGetConeSection(dm, &coneSection);CHKERRQ(ierr);
8066ca8062c8SMatthew G. Knepley   ierr = DMPlexGetSupportSection(dm, &supportSection);CHKERRQ(ierr);
8067ca8062c8SMatthew G. Knepley   /* Check that point p is found in the support of its cone points, and vice versa */
8068ca8062c8SMatthew G. Knepley   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
8069ca8062c8SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
8070ca8062c8SMatthew G. Knepley     ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr);
8071ca8062c8SMatthew G. Knepley     ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr);
8072ca8062c8SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
807342e66dfaSMatthew G. Knepley       PetscBool dup = PETSC_FALSE;
807442e66dfaSMatthew G. Knepley       PetscInt  d;
807542e66dfaSMatthew G. Knepley       for (d = c-1; d >= 0; --d) {
807642e66dfaSMatthew G. Knepley         if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;}
807742e66dfaSMatthew G. Knepley       }
8078ca8062c8SMatthew G. Knepley       ierr = DMPlexGetSupportSize(dm, cone[c], &supportSize);CHKERRQ(ierr);
8079ca8062c8SMatthew G. Knepley       ierr = DMPlexGetSupport(dm, cone[c], &support);CHKERRQ(ierr);
8080ca8062c8SMatthew G. Knepley       for (s = 0; s < supportSize; ++s) {
8081ca8062c8SMatthew G. Knepley         if (support[s] == p) break;
8082ca8062c8SMatthew G. Knepley       }
808342e66dfaSMatthew G. Knepley       if ((s >= supportSize) || (dup && (support[s+1] != p))) {
80848ccfff9cSToby Isaac         ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", p);CHKERRQ(ierr);
8085ca8062c8SMatthew G. Knepley         for (s = 0; s < coneSize; ++s) {
80868ccfff9cSToby Isaac           ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[s]);CHKERRQ(ierr);
8087ca8062c8SMatthew G. Knepley         }
8088302440fdSBarry Smith         ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr);
80898ccfff9cSToby Isaac         ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", cone[c]);CHKERRQ(ierr);
8090ca8062c8SMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
80918ccfff9cSToby Isaac           ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[s]);CHKERRQ(ierr);
8092ca8062c8SMatthew G. Knepley         }
8093302440fdSBarry Smith         ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr);
80948ccfff9cSToby Isaac         if (dup) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not repeatedly found in support of repeated cone point %D", p, cone[c]);
80958ccfff9cSToby Isaac         else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in support of cone point %D", p, cone[c]);
8096ca8062c8SMatthew G. Knepley       }
809742e66dfaSMatthew G. Knepley     }
809857beb4faSStefano Zampini     ierr = DMPlexGetTreeParent(dm, p, &pp, NULL);CHKERRQ(ierr);
809957beb4faSStefano Zampini     if (p != pp) { storagecheck = PETSC_FALSE; continue; }
8100ca8062c8SMatthew G. Knepley     ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr);
8101ca8062c8SMatthew G. Knepley     ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr);
8102ca8062c8SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
8103ca8062c8SMatthew G. Knepley       ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr);
8104ca8062c8SMatthew G. Knepley       ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr);
8105ca8062c8SMatthew G. Knepley       for (c = 0; c < coneSize; ++c) {
810657beb4faSStefano Zampini         ierr = DMPlexGetTreeParent(dm, cone[c], &pp, NULL);CHKERRQ(ierr);
810757beb4faSStefano Zampini         if (cone[c] != pp) { c = 0; break; }
8108ca8062c8SMatthew G. Knepley         if (cone[c] == p) break;
8109ca8062c8SMatthew G. Knepley       }
8110ca8062c8SMatthew G. Knepley       if (c >= coneSize) {
81118ccfff9cSToby Isaac         ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D support: ", p);CHKERRQ(ierr);
8112ca8062c8SMatthew G. Knepley         for (c = 0; c < supportSize; ++c) {
81138ccfff9cSToby Isaac           ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", support[c]);CHKERRQ(ierr);
8114ca8062c8SMatthew G. Knepley         }
8115302440fdSBarry Smith         ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr);
81168ccfff9cSToby Isaac         ierr = PetscPrintf(PETSC_COMM_SELF, "p: %D cone: ", support[s]);CHKERRQ(ierr);
8117ca8062c8SMatthew G. Knepley         for (c = 0; c < coneSize; ++c) {
81188ccfff9cSToby Isaac           ierr = PetscPrintf(PETSC_COMM_SELF, "%D, ", cone[c]);CHKERRQ(ierr);
8119ca8062c8SMatthew G. Knepley         }
8120302440fdSBarry Smith         ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr);
81218ccfff9cSToby Isaac         SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %D not found in cone of support point %D", p, support[s]);
8122ca8062c8SMatthew G. Knepley       }
8123ca8062c8SMatthew G. Knepley     }
8124ca8062c8SMatthew G. Knepley   }
812557beb4faSStefano Zampini   if (storagecheck) {
8126ca8062c8SMatthew G. Knepley     ierr = PetscSectionGetStorageSize(coneSection, &csize);CHKERRQ(ierr);
8127ca8062c8SMatthew G. Knepley     ierr = PetscSectionGetStorageSize(supportSection, &ssize);CHKERRQ(ierr);
81288ccfff9cSToby Isaac     if (csize != ssize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %D != Total support size %D", csize, ssize);
812957beb4faSStefano Zampini   }
8130ca8062c8SMatthew G. Knepley   PetscFunctionReturn(0);
8131ca8062c8SMatthew G. Knepley }
8132ca8062c8SMatthew G. Knepley 
8133412e9a14SMatthew G. Knepley /*
8134412e9a14SMatthew 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.
8135412e9a14SMatthew G. Knepley */
8136412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit)
8137412e9a14SMatthew G. Knepley {
8138412e9a14SMatthew G. Knepley   DMPolytopeType  cct;
8139412e9a14SMatthew G. Knepley   PetscInt        ptpoints[4];
8140412e9a14SMatthew G. Knepley   const PetscInt *cone, *ccone, *ptcone;
8141412e9a14SMatthew G. Knepley   PetscInt        coneSize, cp, cconeSize, ccp, npt = 0, pt;
8142412e9a14SMatthew G. Knepley   PetscErrorCode  ierr;
8143412e9a14SMatthew G. Knepley 
8144412e9a14SMatthew G. Knepley   PetscFunctionBegin;
8145412e9a14SMatthew G. Knepley   *unsplit = 0;
8146412e9a14SMatthew G. Knepley   switch (ct) {
8147412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEG_PRISM_TENSOR:
8148412e9a14SMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
8149412e9a14SMatthew G. Knepley       ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr);
8150412e9a14SMatthew G. Knepley       for (cp = 0; cp < coneSize; ++cp) {
8151412e9a14SMatthew G. Knepley         ierr = DMPlexGetCellType(dm, cone[cp], &cct);CHKERRQ(ierr);
8152412e9a14SMatthew G. Knepley         if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp];
8153412e9a14SMatthew G. Knepley       }
8154412e9a14SMatthew G. Knepley       break;
8155412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:
8156412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
8157412e9a14SMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
8158412e9a14SMatthew G. Knepley       ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr);
8159412e9a14SMatthew G. Knepley       for (cp = 0; cp < coneSize; ++cp) {
8160412e9a14SMatthew G. Knepley         ierr = DMPlexGetCone(dm, cone[cp], &ccone);CHKERRQ(ierr);
8161412e9a14SMatthew G. Knepley         ierr = DMPlexGetConeSize(dm, cone[cp], &cconeSize);CHKERRQ(ierr);
8162412e9a14SMatthew G. Knepley         for (ccp = 0; ccp < cconeSize; ++ccp) {
8163412e9a14SMatthew G. Knepley           ierr = DMPlexGetCellType(dm, ccone[ccp], &cct);CHKERRQ(ierr);
8164412e9a14SMatthew G. Knepley           if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) {
8165412e9a14SMatthew G. Knepley             PetscInt p;
8166412e9a14SMatthew G. Knepley             for (p = 0; p < npt; ++p) if (ptpoints[p] == ccone[ccp]) break;
8167412e9a14SMatthew G. Knepley             if (p == npt) ptpoints[npt++] = ccone[ccp];
8168412e9a14SMatthew G. Knepley           }
8169412e9a14SMatthew G. Knepley         }
8170412e9a14SMatthew G. Knepley       }
8171412e9a14SMatthew G. Knepley       break;
8172412e9a14SMatthew G. Knepley     default: break;
8173412e9a14SMatthew G. Knepley   }
8174412e9a14SMatthew G. Knepley   for (pt = 0; pt < npt; ++pt) {
8175412e9a14SMatthew G. Knepley     ierr = DMPlexGetCone(dm, ptpoints[pt], &ptcone);CHKERRQ(ierr);
8176412e9a14SMatthew G. Knepley     if (ptcone[0] == ptcone[1]) ++(*unsplit);
8177412e9a14SMatthew G. Knepley   }
8178412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
8179412e9a14SMatthew G. Knepley }
8180412e9a14SMatthew G. Knepley 
8181ca8062c8SMatthew G. Knepley /*@
8182ca8062c8SMatthew G. Knepley   DMPlexCheckSkeleton - Check that each cell has the correct number of vertices
8183ca8062c8SMatthew G. Knepley 
8184ca8062c8SMatthew G. Knepley   Input Parameters:
8185ca8062c8SMatthew G. Knepley + dm - The DMPlex object
818658723a97SMatthew G. Knepley - cellHeight - Normally 0
8187ca8062c8SMatthew G. Knepley 
818895eb5ee5SVaclav Hapla   Notes:
818995eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
819025c50c26SVaclav Hapla   Currently applicable only to homogeneous simplex or tensor meshes.
8191ca8062c8SMatthew G. Knepley 
819295eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
819395eb5ee5SVaclav Hapla 
8194ca8062c8SMatthew G. Knepley   Level: developer
8195ca8062c8SMatthew G. Knepley 
819695eb5ee5SVaclav Hapla .seealso: DMCreate(), DMSetFromOptions()
8197ca8062c8SMatthew G. Knepley @*/
819825c50c26SVaclav Hapla PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight)
8199ca8062c8SMatthew G. Knepley {
8200412e9a14SMatthew G. Knepley   DMPlexInterpolatedFlag interp;
8201412e9a14SMatthew G. Knepley   DMPolytopeType         ct;
8202412e9a14SMatthew G. Knepley   PetscInt               vStart, vEnd, cStart, cEnd, c;
8203ca8062c8SMatthew G. Knepley   PetscErrorCode         ierr;
8204ca8062c8SMatthew G. Knepley 
8205ca8062c8SMatthew G. Knepley   PetscFunctionBegin;
8206ca8062c8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8207412e9a14SMatthew G. Knepley   ierr = DMPlexIsInterpolated(dm, &interp);CHKERRQ(ierr);
820825c50c26SVaclav Hapla   ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);
820958723a97SMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
8210412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
8211412e9a14SMatthew G. Knepley     PetscInt *closure = NULL;
8212412e9a14SMatthew G. Knepley     PetscInt  coneSize, closureSize, cl, Nv = 0;
821358723a97SMatthew G. Knepley 
8214412e9a14SMatthew G. Knepley     ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr);
8215412e9a14SMatthew G. Knepley     if ((PetscInt) ct < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D has no cell type", c);
8216412e9a14SMatthew G. Knepley     if (ct == DM_POLYTOPE_UNKNOWN) continue;
8217412e9a14SMatthew G. Knepley     if (interp == DMPLEX_INTERPOLATED_FULL) {
8218412e9a14SMatthew G. Knepley       ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr);
8219d4961f80SStefano Zampini       if (coneSize != DMPolytopeTypeGetConeSize(ct)) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D of type %s has cone size %D != %D", c, DMPolytopeTypes[ct], coneSize, DMPolytopeTypeGetConeSize(ct));
8220412e9a14SMatthew G. Knepley     }
822158723a97SMatthew G. Knepley     ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
822258723a97SMatthew G. Knepley     for (cl = 0; cl < closureSize*2; cl += 2) {
822358723a97SMatthew G. Knepley       const PetscInt p = closure[cl];
8224412e9a14SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) ++Nv;
822558723a97SMatthew G. Knepley     }
822658723a97SMatthew G. Knepley     ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
8227412e9a14SMatthew G. Knepley     /* Special Case: Tensor faces with identified vertices */
8228412e9a14SMatthew G. Knepley     if (Nv < DMPolytopeTypeGetNumVertices(ct)) {
8229412e9a14SMatthew G. Knepley       PetscInt unsplit;
823042363296SMatthew G. Knepley 
8231412e9a14SMatthew G. Knepley       ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr);
8232412e9a14SMatthew G. Knepley       if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue;
823342363296SMatthew G. Knepley     }
8234d4961f80SStefano Zampini     if (Nv != DMPolytopeTypeGetNumVertices(ct)) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D of type %s has %D vertices != %D", c, DMPolytopeTypes[ct], Nv, DMPolytopeTypeGetNumVertices(ct));
823542363296SMatthew G. Knepley   }
8236ca8062c8SMatthew G. Knepley   PetscFunctionReturn(0);
8237ca8062c8SMatthew G. Knepley }
82389bf0dad6SMatthew G. Knepley 
82399bf0dad6SMatthew G. Knepley /*@
82409bf0dad6SMatthew 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
82419bf0dad6SMatthew G. Knepley 
8242899ea2b8SJacob Faibussowitsch   Not Collective
8243899ea2b8SJacob Faibussowitsch 
82449bf0dad6SMatthew G. Knepley   Input Parameters:
82459bf0dad6SMatthew G. Knepley + dm - The DMPlex object
82469bf0dad6SMatthew G. Knepley - cellHeight - Normally 0
82479bf0dad6SMatthew G. Knepley 
824845da879fSVaclav Hapla   Notes:
824945da879fSVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
825045da879fSVaclav Hapla   This routine is only relevant for meshes that are fully interpolated across all ranks.
825145da879fSVaclav Hapla   It will error out if a partially interpolated mesh is given on some rank.
825245da879fSVaclav Hapla   It will do nothing for locally uninterpolated mesh (as there is nothing to check).
82539bf0dad6SMatthew G. Knepley 
825495eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
825595eb5ee5SVaclav Hapla 
82569bf0dad6SMatthew G. Knepley   Level: developer
82579bf0dad6SMatthew G. Knepley 
825895eb5ee5SVaclav Hapla .seealso: DMCreate(), DMPlexGetVTKCellHeight(), DMSetFromOptions()
82599bf0dad6SMatthew G. Knepley @*/
826025c50c26SVaclav Hapla PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight)
82619bf0dad6SMatthew G. Knepley {
8262ab91121cSMatthew G. Knepley   PetscInt       dim, depth, vStart, vEnd, cStart, cEnd, c, h;
82639bf0dad6SMatthew G. Knepley   PetscErrorCode ierr;
8264899ea2b8SJacob Faibussowitsch   DMPlexInterpolatedFlag interpEnum;
82659bf0dad6SMatthew G. Knepley 
82669bf0dad6SMatthew G. Knepley   PetscFunctionBegin;
82679bf0dad6SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8268899ea2b8SJacob Faibussowitsch   ierr = DMPlexIsInterpolated(dm, &interpEnum);CHKERRQ(ierr);
826945da879fSVaclav Hapla   if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(0);
827045da879fSVaclav Hapla   if (interpEnum == DMPLEX_INTERPOLATED_PARTIAL) {
8271899ea2b8SJacob Faibussowitsch     PetscMPIInt rank;
8272899ea2b8SJacob Faibussowitsch     MPI_Comm    comm;
8273899ea2b8SJacob Faibussowitsch 
8274899ea2b8SJacob Faibussowitsch     ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr);
8275ffc4695bSBarry Smith     ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
827645da879fSVaclav Hapla     SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_SUP, "Mesh is only partially interpolated on rank %d, this is currently not supported", rank);
8277899ea2b8SJacob Faibussowitsch   }
8278899ea2b8SJacob Faibussowitsch 
8279c73cfb54SMatthew G. Knepley   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
8280ab91121cSMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
82819bf0dad6SMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
8282ab91121cSMatthew G. Knepley   for (h = cellHeight; h < PetscMin(depth, dim); ++h) {
82833554e41dSMatthew G. Knepley     ierr = DMPlexGetHeightStratum(dm, h, &cStart, &cEnd);CHKERRQ(ierr);
82843554e41dSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
8285412e9a14SMatthew G. Knepley       const PetscInt      *cone, *ornt, *faceSizes, *faces;
8286412e9a14SMatthew G. Knepley       const DMPolytopeType *faceTypes;
8287ba2698f1SMatthew G. Knepley       DMPolytopeType        ct;
8288412e9a14SMatthew G. Knepley       PetscInt              numFaces, coneSize, f;
8289412e9a14SMatthew G. Knepley       PetscInt             *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit;
82909bf0dad6SMatthew G. Knepley 
8291ba2698f1SMatthew G. Knepley       ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr);
8292412e9a14SMatthew G. Knepley       ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr);
8293412e9a14SMatthew G. Knepley       if (unsplit) continue;
82949bf0dad6SMatthew G. Knepley       ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr);
82959bf0dad6SMatthew G. Knepley       ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr);
82969bf0dad6SMatthew G. Knepley       ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr);
82979bf0dad6SMatthew G. Knepley       ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
82989bf0dad6SMatthew G. Knepley       for (cl = 0; cl < closureSize*2; cl += 2) {
82999bf0dad6SMatthew G. Knepley         const PetscInt p = closure[cl];
83009bf0dad6SMatthew G. Knepley         if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p;
83019bf0dad6SMatthew G. Knepley       }
8302412e9a14SMatthew G. Knepley       ierr = DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr);
8303d4961f80SStefano Zampini       if (coneSize != numFaces) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %D of type %s has %D faces but should have %D", c, DMPolytopeTypes[ct], coneSize, numFaces);
83049bf0dad6SMatthew G. Knepley       for (f = 0; f < numFaces; ++f) {
8305d4961f80SStefano Zampini         DMPolytopeType fct;
83069bf0dad6SMatthew G. Knepley         PetscInt       *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v;
83079bf0dad6SMatthew G. Knepley 
8308d4961f80SStefano Zampini         ierr = DMPlexGetCellType(dm, cone[f], &fct);CHKERRQ(ierr);
83099bf0dad6SMatthew G. Knepley         ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr);
83109bf0dad6SMatthew G. Knepley         for (cl = 0; cl < fclosureSize*2; cl += 2) {
83119bf0dad6SMatthew G. Knepley           const PetscInt p = fclosure[cl];
83129bf0dad6SMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p;
83139bf0dad6SMatthew G. Knepley         }
8314d4961f80SStefano Zampini         if (fnumCorners != faceSizes[f]) SETERRQ7(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]);
83159bf0dad6SMatthew G. Knepley         for (v = 0; v < fnumCorners; ++v) {
8316d4961f80SStefano Zampini           if (fclosure[v] != faces[fOff+v]) SETERRQ8(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %D of type %s (cone idx %d) of cell %D of type %s vertex %D, %D != %D", cone[f], DMPolytopeTypes[fct], f, c, DMPolytopeTypes[ct], v, fclosure[v], faces[fOff+v]);
83179bf0dad6SMatthew G. Knepley         }
83189bf0dad6SMatthew G. Knepley         ierr = DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr);
8319412e9a14SMatthew G. Knepley         fOff += faceSizes[f];
83209bf0dad6SMatthew G. Knepley       }
8321412e9a14SMatthew G. Knepley       ierr = DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces);CHKERRQ(ierr);
83229bf0dad6SMatthew G. Knepley       ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
83239bf0dad6SMatthew G. Knepley     }
83243554e41dSMatthew G. Knepley   }
8325552f7358SJed Brown   PetscFunctionReturn(0);
8326552f7358SJed Brown }
83273913d7c8SMatthew G. Knepley 
8328bb6a34a8SMatthew G. Knepley /*@
8329bb6a34a8SMatthew G. Knepley   DMPlexCheckGeometry - Check the geometry of mesh cells
8330bb6a34a8SMatthew G. Knepley 
8331bb6a34a8SMatthew G. Knepley   Input Parameter:
8332bb6a34a8SMatthew G. Knepley . dm - The DMPlex object
8333bb6a34a8SMatthew G. Knepley 
833495eb5ee5SVaclav Hapla   Notes:
833595eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
833695eb5ee5SVaclav Hapla 
833795eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
8338bb6a34a8SMatthew G. Knepley 
8339bb6a34a8SMatthew G. Knepley   Level: developer
8340bb6a34a8SMatthew G. Knepley 
834195eb5ee5SVaclav Hapla .seealso: DMCreate(), DMSetFromOptions()
8342bb6a34a8SMatthew G. Knepley @*/
8343bb6a34a8SMatthew G. Knepley PetscErrorCode DMPlexCheckGeometry(DM dm)
8344bb6a34a8SMatthew G. Knepley {
8345a2a9e04cSMatthew G. Knepley   Vec            coordinates;
8346bb6a34a8SMatthew G. Knepley   PetscReal      detJ, J[9], refVol = 1.0;
8347bb6a34a8SMatthew G. Knepley   PetscReal      vol;
8348412e9a14SMatthew G. Knepley   PetscBool      periodic;
834951a74b61SMatthew G. Knepley   PetscInt       dim, depth, dE, d, cStart, cEnd, c;
8350bb6a34a8SMatthew G. Knepley   PetscErrorCode ierr;
8351bb6a34a8SMatthew G. Knepley 
8352bb6a34a8SMatthew G. Knepley   PetscFunctionBegin;
8353bb6a34a8SMatthew G. Knepley   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
835451a74b61SMatthew G. Knepley   ierr = DMGetCoordinateDim(dm, &dE);CHKERRQ(ierr);
835551a74b61SMatthew G. Knepley   if (dim != dE) PetscFunctionReturn(0);
8356bb6a34a8SMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
8357412e9a14SMatthew G. Knepley   ierr = DMGetPeriodicity(dm, &periodic, NULL, NULL, NULL);CHKERRQ(ierr);
8358bb6a34a8SMatthew G. Knepley   for (d = 0; d < dim; ++d) refVol *= 2.0;
8359bb6a34a8SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
8360a2a9e04cSMatthew G. Knepley   /* Make sure local coordinates are created, because that step is collective */
8361a2a9e04cSMatthew G. Knepley   ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr);
8362412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
8363412e9a14SMatthew G. Knepley     DMPolytopeType ct;
8364412e9a14SMatthew G. Knepley     PetscInt       unsplit;
8365412e9a14SMatthew G. Knepley     PetscBool      ignoreZeroVol = PETSC_FALSE;
8366412e9a14SMatthew G. Knepley 
8367412e9a14SMatthew G. Knepley     ierr = DMPlexGetCellType(dm, c, &ct);CHKERRQ(ierr);
8368412e9a14SMatthew G. Knepley     switch (ct) {
8369412e9a14SMatthew G. Knepley       case DM_POLYTOPE_SEG_PRISM_TENSOR:
8370412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM_TENSOR:
8371412e9a14SMatthew G. Knepley       case DM_POLYTOPE_QUAD_PRISM_TENSOR:
8372412e9a14SMatthew G. Knepley         ignoreZeroVol = PETSC_TRUE; break;
8373412e9a14SMatthew G. Knepley       default: break;
8374412e9a14SMatthew G. Knepley     }
8375412e9a14SMatthew G. Knepley     switch (ct) {
8376412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM:
8377412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM_TENSOR:
8378412e9a14SMatthew G. Knepley       case DM_POLYTOPE_QUAD_PRISM_TENSOR:
8379a2a9e04cSMatthew G. Knepley       case DM_POLYTOPE_PYRAMID:
8380412e9a14SMatthew G. Knepley         continue;
8381412e9a14SMatthew G. Knepley       default: break;
8382412e9a14SMatthew G. Knepley     }
8383412e9a14SMatthew G. Knepley     ierr = DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit);CHKERRQ(ierr);
8384412e9a14SMatthew G. Knepley     if (unsplit) continue;
8385bb6a34a8SMatthew G. Knepley     ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ);CHKERRQ(ierr);
8386d4961f80SStefano Zampini     if (detJ < -PETSC_SMALL || (detJ <= 0.0 && !ignoreZeroVol)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %D of type %s is inverted, |J| = %g", c, DMPolytopeTypes[ct], (double) detJ);
8387bb6a34a8SMatthew G. Knepley     ierr = PetscInfo2(dm, "Cell %D FEM Volume %g\n", c, (double) detJ*refVol);CHKERRQ(ierr);
8388412e9a14SMatthew G. Knepley     if (depth > 1 && !periodic) {
8389bb6a34a8SMatthew G. Knepley       ierr = DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL);CHKERRQ(ierr);
8390d4961f80SStefano Zampini       if (vol < -PETSC_SMALL || (vol <= 0.0 && !ignoreZeroVol)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %D of type %s is inverted, vol = %g", c, DMPolytopeTypes[ct], (double) vol);
8391bb6a34a8SMatthew G. Knepley       ierr = PetscInfo2(dm, "Cell %D FVM Volume %g\n", c, (double) vol);CHKERRQ(ierr);
8392bb6a34a8SMatthew G. Knepley     }
8393bb6a34a8SMatthew G. Knepley   }
8394bb6a34a8SMatthew G. Knepley   PetscFunctionReturn(0);
8395bb6a34a8SMatthew G. Knepley }
8396bb6a34a8SMatthew G. Knepley 
839703da9461SVaclav Hapla /*@
8398e83a0d2dSVaclav Hapla   DMPlexCheckPointSF - Check that several necessary conditions are met for the point SF of this plex.
839903da9461SVaclav Hapla 
840003da9461SVaclav Hapla   Input Parameters:
840103da9461SVaclav Hapla . dm - The DMPlex object
840203da9461SVaclav Hapla 
8403e83a0d2dSVaclav Hapla   Notes:
8404e83a0d2dSVaclav Hapla   This is mainly intended for debugging/testing purposes.
84058918e3e2SVaclav Hapla   It currently checks only meshes with no partition overlapping.
840603da9461SVaclav Hapla 
840795eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
840895eb5ee5SVaclav Hapla 
840903da9461SVaclav Hapla   Level: developer
841003da9461SVaclav Hapla 
841195eb5ee5SVaclav Hapla .seealso: DMGetPointSF(), DMSetFromOptions()
841203da9461SVaclav Hapla @*/
841303da9461SVaclav Hapla PetscErrorCode DMPlexCheckPointSF(DM dm)
841403da9461SVaclav Hapla {
8415f0cfc026SVaclav Hapla   PetscSF         pointSF;
8416f5869d18SMatthew G. Knepley   PetscInt        cellHeight, cStart, cEnd, l, nleaves, nroots, overlap;
8417f5869d18SMatthew G. Knepley   const PetscInt *locals, *rootdegree;
8418f0cfc026SVaclav Hapla   PetscBool       distributed;
841903da9461SVaclav Hapla   PetscErrorCode  ierr;
842003da9461SVaclav Hapla 
842103da9461SVaclav Hapla   PetscFunctionBegin;
842203da9461SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8423f0cfc026SVaclav Hapla   ierr = DMGetPointSF(dm, &pointSF);CHKERRQ(ierr);
8424f0cfc026SVaclav Hapla   ierr = DMPlexIsDistributed(dm, &distributed);CHKERRQ(ierr);
8425f0cfc026SVaclav Hapla   if (!distributed) PetscFunctionReturn(0);
8426f0cfc026SVaclav Hapla   ierr = DMPlexGetOverlap(dm, &overlap);CHKERRQ(ierr);
8427f0cfc026SVaclav Hapla   if (overlap) {
84281e1ea65dSPierre Jolivet     ierr = PetscPrintf(PetscObjectComm((PetscObject)dm), "Warning: DMPlexCheckPointSF() is currently not implemented for meshes with partition overlapping");CHKERRQ(ierr);
84298918e3e2SVaclav Hapla     PetscFunctionReturn(0);
84308918e3e2SVaclav Hapla   }
8431f0cfc026SVaclav Hapla   if (!pointSF) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but does not have PointSF attached");
8432f0cfc026SVaclav Hapla   ierr = PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, NULL);CHKERRQ(ierr);
8433f0cfc026SVaclav Hapla   if (nroots < 0) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but its PointSF has no graph set");
8434f5869d18SMatthew G. Knepley   ierr = PetscSFComputeDegreeBegin(pointSF, &rootdegree);CHKERRQ(ierr);
8435f5869d18SMatthew G. Knepley   ierr = PetscSFComputeDegreeEnd(pointSF, &rootdegree);CHKERRQ(ierr);
843603da9461SVaclav Hapla 
8437ece87651SVaclav Hapla   /* 1) check there are no faces in 2D, cells in 3D, in interface */
8438f5869d18SMatthew G. Knepley   ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr);
8439f5869d18SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);
8440f5869d18SMatthew G. Knepley   for (l = 0; l < nleaves; ++l) {
8441f5869d18SMatthew G. Knepley     const PetscInt point = locals[l];
8442f5869d18SMatthew G. Knepley 
8443f5869d18SMatthew G. Knepley     if (point >= cStart && point < cEnd) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %D which is a cell", point);
844403da9461SVaclav Hapla   }
8445ece87651SVaclav Hapla 
8446f5869d18SMatthew G. Knepley   /* 2) if some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */
8447f5869d18SMatthew G. Knepley   for (l = 0; l < nleaves; ++l) {
8448f5869d18SMatthew G. Knepley     const PetscInt  point = locals[l];
8449f5869d18SMatthew G. Knepley     const PetscInt *cone;
8450f5869d18SMatthew G. Knepley     PetscInt        coneSize, c, idx;
8451f5869d18SMatthew G. Knepley 
8452f5869d18SMatthew G. Knepley     ierr = DMPlexGetConeSize(dm, point, &coneSize);CHKERRQ(ierr);
8453f5869d18SMatthew G. Knepley     ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr);
8454f5869d18SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
8455f5869d18SMatthew G. Knepley       if (!rootdegree[cone[c]]) {
8456f5869d18SMatthew G. Knepley         ierr = PetscFindInt(cone[c], nleaves, locals, &idx);CHKERRQ(ierr);
8457f5869d18SMatthew G. Knepley         if (idx < 0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %D but not %D from its cone", point, cone[c]);
8458f5869d18SMatthew G. Knepley       }
8459f5869d18SMatthew G. Knepley     }
8460ece87651SVaclav Hapla   }
846103da9461SVaclav Hapla   PetscFunctionReturn(0);
846203da9461SVaclav Hapla }
846303da9461SVaclav Hapla 
8464068a5610SStefano Zampini typedef struct cell_stats
8465068a5610SStefano Zampini {
8466068a5610SStefano Zampini   PetscReal min, max, sum, squaresum;
8467068a5610SStefano Zampini   PetscInt  count;
8468068a5610SStefano Zampini } cell_stats_t;
8469068a5610SStefano Zampini 
847025befc3bSSatish Balay static void MPIAPI cell_stats_reduce(void *a, void *b, int * len, MPI_Datatype *datatype)
8471068a5610SStefano Zampini {
8472068a5610SStefano Zampini   PetscInt i, N = *len;
8473068a5610SStefano Zampini 
8474068a5610SStefano Zampini   for (i = 0; i < N; i++) {
8475068a5610SStefano Zampini     cell_stats_t *A = (cell_stats_t *) a;
8476068a5610SStefano Zampini     cell_stats_t *B = (cell_stats_t *) b;
8477068a5610SStefano Zampini 
8478068a5610SStefano Zampini     B->min = PetscMin(A->min,B->min);
8479068a5610SStefano Zampini     B->max = PetscMax(A->max,B->max);
8480068a5610SStefano Zampini     B->sum += A->sum;
8481068a5610SStefano Zampini     B->squaresum += A->squaresum;
8482068a5610SStefano Zampini     B->count += A->count;
8483068a5610SStefano Zampini   }
8484068a5610SStefano Zampini }
8485068a5610SStefano Zampini 
8486068a5610SStefano Zampini /*@
848743fa8764SMatthew G. Knepley   DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics.
8488068a5610SStefano Zampini 
84898261a58bSMatthew G. Knepley   Collective on dm
84908261a58bSMatthew G. Knepley 
8491068a5610SStefano Zampini   Input Parameters:
8492068a5610SStefano Zampini + dm        - The DMPlex object
849343fa8764SMatthew G. Knepley . output    - If true, statistics will be displayed on stdout
849443fa8764SMatthew G. Knepley - condLimit - Display all cells above this condition number, or PETSC_DETERMINE for no cell output
8495068a5610SStefano Zampini 
849695eb5ee5SVaclav Hapla   Notes:
849795eb5ee5SVaclav Hapla   This is mainly intended for debugging/testing purposes.
849895eb5ee5SVaclav Hapla 
849995eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
8500068a5610SStefano Zampini 
8501068a5610SStefano Zampini   Level: developer
8502068a5610SStefano Zampini 
8503f108dbd7SJacob Faibussowitsch .seealso: DMSetFromOptions(), DMPlexComputeOrthogonalQuality()
8504068a5610SStefano Zampini @*/
850543fa8764SMatthew G. Knepley PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit)
8506068a5610SStefano Zampini {
8507068a5610SStefano Zampini   DM             dmCoarse;
850843fa8764SMatthew G. Knepley   cell_stats_t   stats, globalStats;
850943fa8764SMatthew G. Knepley   MPI_Comm       comm = PetscObjectComm((PetscObject)dm);
851043fa8764SMatthew G. Knepley   PetscReal      *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0;
851143fa8764SMatthew G. Knepley   PetscReal      limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL;
8512412e9a14SMatthew G. Knepley   PetscInt       cdim, cStart, cEnd, c, eStart, eEnd, count = 0;
851343fa8764SMatthew G. Knepley   PetscMPIInt    rank,size;
8514068a5610SStefano Zampini   PetscErrorCode ierr;
8515068a5610SStefano Zampini 
8516068a5610SStefano Zampini   PetscFunctionBegin;
8517068a5610SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8518068a5610SStefano Zampini   stats.min   = PETSC_MAX_REAL;
8519068a5610SStefano Zampini   stats.max   = PETSC_MIN_REAL;
8520068a5610SStefano Zampini   stats.sum   = stats.squaresum = 0.;
8521068a5610SStefano Zampini   stats.count = 0;
8522068a5610SStefano Zampini 
8523ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr);
8524ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
852543fa8764SMatthew G. Knepley   ierr = DMGetCoordinateDim(dm,&cdim);CHKERRQ(ierr);
852643fa8764SMatthew G. Knepley   ierr = PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ);CHKERRQ(ierr);
8527412e9a14SMatthew G. Knepley   ierr = DMPlexGetSimplexOrBoxCells(dm,0,&cStart,&cEnd);CHKERRQ(ierr);
852843fa8764SMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm,1,&eStart,&eEnd);CHKERRQ(ierr);
8529412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; c++) {
8530068a5610SStefano Zampini     PetscInt  i;
8531068a5610SStefano Zampini     PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ;
8532068a5610SStefano Zampini 
8533068a5610SStefano Zampini     ierr = DMPlexComputeCellGeometryAffineFEM(dm,c,NULL,J,invJ,&detJ);CHKERRQ(ierr);
8534068a5610SStefano Zampini     if (detJ < 0.0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %D is inverted", c);
853543fa8764SMatthew G. Knepley     for (i = 0; i < PetscSqr(cdim); ++i) {
8536068a5610SStefano Zampini       frobJ    += J[i] * J[i];
8537068a5610SStefano Zampini       frobInvJ += invJ[i] * invJ[i];
8538068a5610SStefano Zampini     }
8539068a5610SStefano Zampini     cond2 = frobJ * frobInvJ;
8540068a5610SStefano Zampini     cond  = PetscSqrtReal(cond2);
8541068a5610SStefano Zampini 
8542068a5610SStefano Zampini     stats.min        = PetscMin(stats.min,cond);
8543068a5610SStefano Zampini     stats.max        = PetscMax(stats.max,cond);
8544068a5610SStefano Zampini     stats.sum       += cond;
8545068a5610SStefano Zampini     stats.squaresum += cond2;
8546068a5610SStefano Zampini     stats.count++;
85478261a58bSMatthew G. Knepley     if (output && cond > limit) {
854843fa8764SMatthew G. Knepley       PetscSection coordSection;
854943fa8764SMatthew G. Knepley       Vec          coordsLocal;
855043fa8764SMatthew G. Knepley       PetscScalar *coords = NULL;
855143fa8764SMatthew G. Knepley       PetscInt     Nv, d, clSize, cl, *closure = NULL;
855243fa8764SMatthew G. Knepley 
855343fa8764SMatthew G. Knepley       ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr);
855443fa8764SMatthew G. Knepley       ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr);
855543fa8764SMatthew G. Knepley       ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords);CHKERRQ(ierr);
8556087ef6b2SMatthew G. Knepley       ierr = PetscSynchronizedPrintf(comm, "[%d] Cell %D cond %g\n", rank, c, (double) cond);CHKERRQ(ierr);
855743fa8764SMatthew G. Knepley       for (i = 0; i < Nv/cdim; ++i) {
855843fa8764SMatthew G. Knepley         ierr = PetscSynchronizedPrintf(comm, "  Vertex %D: (", i);CHKERRQ(ierr);
855943fa8764SMatthew G. Knepley         for (d = 0; d < cdim; ++d) {
856043fa8764SMatthew G. Knepley           if (d > 0) {ierr = PetscSynchronizedPrintf(comm, ", ");CHKERRQ(ierr);}
856148afe810SSatish Balay           ierr = PetscSynchronizedPrintf(comm, "%g", (double) PetscRealPart(coords[i*cdim+d]));CHKERRQ(ierr);
856243fa8764SMatthew G. Knepley         }
856343fa8764SMatthew G. Knepley         ierr = PetscSynchronizedPrintf(comm, ")\n");CHKERRQ(ierr);
856443fa8764SMatthew G. Knepley       }
856543fa8764SMatthew G. Knepley       ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr);
856643fa8764SMatthew G. Knepley       for (cl = 0; cl < clSize*2; cl += 2) {
856743fa8764SMatthew G. Knepley         const PetscInt edge = closure[cl];
856843fa8764SMatthew G. Knepley 
856943fa8764SMatthew G. Knepley         if ((edge >= eStart) && (edge < eEnd)) {
857043fa8764SMatthew G. Knepley           PetscReal len;
857143fa8764SMatthew G. Knepley 
857243fa8764SMatthew G. Knepley           ierr = DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL);CHKERRQ(ierr);
8573087ef6b2SMatthew G. Knepley           ierr = PetscSynchronizedPrintf(comm, "  Edge %D: length %g\n", edge, (double) len);CHKERRQ(ierr);
857443fa8764SMatthew G. Knepley         }
857543fa8764SMatthew G. Knepley       }
857643fa8764SMatthew G. Knepley       ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure);CHKERRQ(ierr);
857743fa8764SMatthew G. Knepley       ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords);CHKERRQ(ierr);
857843fa8764SMatthew G. Knepley     }
8579068a5610SStefano Zampini   }
85808261a58bSMatthew G. Knepley   if (output) {ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);}
8581068a5610SStefano Zampini 
8582068a5610SStefano Zampini   if (size > 1) {
8583068a5610SStefano Zampini     PetscMPIInt   blockLengths[2] = {4,1};
8584068a5610SStefano Zampini     MPI_Aint      blockOffsets[2] = {offsetof(cell_stats_t,min),offsetof(cell_stats_t,count)};
8585068a5610SStefano Zampini     MPI_Datatype  blockTypes[2]   = {MPIU_REAL,MPIU_INT}, statType;
8586068a5610SStefano Zampini     MPI_Op        statReduce;
8587068a5610SStefano Zampini 
8588ffc4695bSBarry Smith     ierr = MPI_Type_create_struct(2,blockLengths,blockOffsets,blockTypes,&statType);CHKERRMPI(ierr);
8589ffc4695bSBarry Smith     ierr = MPI_Type_commit(&statType);CHKERRMPI(ierr);
8590ffc4695bSBarry Smith     ierr = MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce);CHKERRMPI(ierr);
8591ffc4695bSBarry Smith     ierr = MPI_Reduce(&stats,&globalStats,1,statType,statReduce,0,comm);CHKERRMPI(ierr);
8592ffc4695bSBarry Smith     ierr = MPI_Op_free(&statReduce);CHKERRMPI(ierr);
8593ffc4695bSBarry Smith     ierr = MPI_Type_free(&statType);CHKERRMPI(ierr);
8594068a5610SStefano Zampini   } else {
8595580bdb30SBarry Smith     ierr = PetscArraycpy(&globalStats,&stats,1);CHKERRQ(ierr);
8596068a5610SStefano Zampini   }
8597068a5610SStefano Zampini   if (!rank) {
8598068a5610SStefano Zampini     count = globalStats.count;
8599068a5610SStefano Zampini     min   = globalStats.min;
8600068a5610SStefano Zampini     max   = globalStats.max;
8601068a5610SStefano Zampini     mean  = globalStats.sum / globalStats.count;
8602068a5610SStefano Zampini     stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1),0)) : 0.0;
8603068a5610SStefano Zampini   }
8604068a5610SStefano Zampini 
8605068a5610SStefano Zampini   if (output) {
8606068a5610SStefano 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);
8607068a5610SStefano Zampini   }
8608068a5610SStefano Zampini   ierr = PetscFree2(J,invJ);CHKERRQ(ierr);
8609068a5610SStefano Zampini 
8610068a5610SStefano Zampini   ierr = DMGetCoarseDM(dm,&dmCoarse);CHKERRQ(ierr);
8611068a5610SStefano Zampini   if (dmCoarse) {
8612068a5610SStefano Zampini     PetscBool isplex;
8613068a5610SStefano Zampini 
8614068a5610SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)dmCoarse,DMPLEX,&isplex);CHKERRQ(ierr);
8615068a5610SStefano Zampini     if (isplex) {
861643fa8764SMatthew G. Knepley       ierr = DMPlexCheckCellShape(dmCoarse,output,condLimit);CHKERRQ(ierr);
8617068a5610SStefano Zampini     }
8618068a5610SStefano Zampini   }
8619068a5610SStefano Zampini   PetscFunctionReturn(0);
8620068a5610SStefano Zampini }
8621068a5610SStefano Zampini 
8622f108dbd7SJacob Faibussowitsch /*@
8623f108dbd7SJacob Faibussowitsch   DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with
8624f108dbd7SJacob Faibussowitsch   orthogonal quality below given tolerance.
8625f108dbd7SJacob Faibussowitsch 
86266ed19f2fSJacob Faibussowitsch   Collective on dm
8627f108dbd7SJacob Faibussowitsch 
8628f108dbd7SJacob Faibussowitsch   Input Parameters:
8629f108dbd7SJacob Faibussowitsch + dm   - The DMPlex object
8630f108dbd7SJacob Faibussowitsch . fv   - Optional PetscFV object for pre-computed cell/face centroid information
8631f108dbd7SJacob Faibussowitsch - atol - [0, 1] Absolute tolerance for tagging cells.
8632f108dbd7SJacob Faibussowitsch 
8633f108dbd7SJacob Faibussowitsch   Output Parameters:
8634f108dbd7SJacob Faibussowitsch + OrthQual      - Vec containing orthogonal quality per cell
8635f108dbd7SJacob Faibussowitsch - OrthQualLabel - DMLabel tagging cells below atol with DM_ADAPT_REFINE
8636f108dbd7SJacob Faibussowitsch 
8637f108dbd7SJacob Faibussowitsch   Options Database Keys:
8638f108dbd7SJacob Faibussowitsch + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only PETSCVIEWERASCII is
8639f108dbd7SJacob Faibussowitsch supported.
8640f108dbd7SJacob Faibussowitsch - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector.
8641f108dbd7SJacob Faibussowitsch 
8642f108dbd7SJacob Faibussowitsch   Notes:
8643f108dbd7SJacob Faibussowitsch   Orthogonal quality is given by the following formula:
8644f108dbd7SJacob Faibussowitsch 
8645f108dbd7SJacob Faibussowitsch   \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right]
8646f108dbd7SJacob Faibussowitsch 
8647f108dbd7SJacob 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
8648f108dbd7SJacob Faibussowitsch   is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the
8649f108dbd7SJacob Faibussowitsch   current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by
8650f108dbd7SJacob Faibussowitsch   calculating the cosine of the angle between these vectors.
8651f108dbd7SJacob Faibussowitsch 
8652f108dbd7SJacob Faibussowitsch   Orthogonal quality ranges from 1 (best) to 0 (worst).
8653f108dbd7SJacob Faibussowitsch 
8654f108dbd7SJacob Faibussowitsch   This routine is mainly useful for FVM, however is not restricted to only FVM. The PetscFV object is optionally used to check for
8655f108dbd7SJacob Faibussowitsch   pre-computed FVM cell data, but if it is not passed in then this data will be computed.
8656f108dbd7SJacob Faibussowitsch 
8657f108dbd7SJacob Faibussowitsch   Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance.
8658f108dbd7SJacob Faibussowitsch 
8659f108dbd7SJacob Faibussowitsch   Level: intermediate
8660f108dbd7SJacob Faibussowitsch 
8661f108dbd7SJacob Faibussowitsch .seealso: DMPlexCheckCellShape(), DMCreateLabel()
8662f108dbd7SJacob Faibussowitsch @*/
8663f108dbd7SJacob Faibussowitsch PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel)
8664f108dbd7SJacob Faibussowitsch {
86656ed19f2fSJacob Faibussowitsch   PetscInt                nc, cellHeight, cStart, cEnd, cell, cellIter = 0;
86666ed19f2fSJacob Faibussowitsch   PetscInt                *idx;
86676ed19f2fSJacob Faibussowitsch   PetscScalar             *oqVals;
8668f108dbd7SJacob Faibussowitsch   const PetscScalar       *cellGeomArr, *faceGeomArr;
86696ed19f2fSJacob Faibussowitsch   PetscReal               *ci, *fi, *Ai;
8670f108dbd7SJacob Faibussowitsch   MPI_Comm                comm;
8671f108dbd7SJacob Faibussowitsch   Vec                     cellgeom, facegeom;
8672f108dbd7SJacob Faibussowitsch   DM                      dmFace, dmCell;
8673f108dbd7SJacob Faibussowitsch   IS                      glob;
8674f108dbd7SJacob Faibussowitsch   ISLocalToGlobalMapping  ltog;
8675f108dbd7SJacob Faibussowitsch   PetscViewer             vwr;
8676f108dbd7SJacob Faibussowitsch   PetscErrorCode          ierr;
8677f108dbd7SJacob Faibussowitsch 
8678f108dbd7SJacob Faibussowitsch   PetscFunctionBegin;
8679f108dbd7SJacob Faibussowitsch   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
86806ed19f2fSJacob Faibussowitsch   if (fv) {PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2);}
8681f108dbd7SJacob Faibussowitsch   PetscValidPointer(OrthQual, 4);
86826ed19f2fSJacob Faibussowitsch   if (PetscUnlikelyDebug(atol < 0.0 || atol > 1.0)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Absolute tolerance %g not in [0,1]",(double)atol);
8683f108dbd7SJacob Faibussowitsch   ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr);
8684f108dbd7SJacob Faibussowitsch   ierr = DMGetDimension(dm, &nc);CHKERRQ(ierr);
86856ed19f2fSJacob Faibussowitsch   if (nc < 2) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %D)", nc);
86866ed19f2fSJacob Faibussowitsch   {
86876ed19f2fSJacob Faibussowitsch     DMPlexInterpolatedFlag interpFlag;
86886ed19f2fSJacob Faibussowitsch 
8689f108dbd7SJacob Faibussowitsch     ierr = DMPlexIsInterpolated(dm, &interpFlag);CHKERRQ(ierr);
8690f108dbd7SJacob Faibussowitsch     if (interpFlag != DMPLEX_INTERPOLATED_FULL) {
8691f108dbd7SJacob Faibussowitsch       PetscMPIInt rank;
8692f108dbd7SJacob Faibussowitsch 
8693ffc4695bSBarry Smith       ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
8694f108dbd7SJacob Faibussowitsch       SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank);
8695f108dbd7SJacob Faibussowitsch     }
86966ed19f2fSJacob Faibussowitsch   }
8697f108dbd7SJacob Faibussowitsch   if (OrthQualLabel) {
8698f108dbd7SJacob Faibussowitsch     PetscValidPointer(OrthQualLabel, 5);
8699f108dbd7SJacob Faibussowitsch     ierr = DMCreateLabel(dm, "Orthogonal_Quality");CHKERRQ(ierr);
8700f108dbd7SJacob Faibussowitsch     ierr = DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel);CHKERRQ(ierr);
87016ed19f2fSJacob Faibussowitsch   } else {*OrthQualLabel = NULL;}
8702f108dbd7SJacob Faibussowitsch   ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr);
8703f108dbd7SJacob Faibussowitsch   ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr);
8704f108dbd7SJacob Faibussowitsch   ierr = DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob);CHKERRQ(ierr);
8705f108dbd7SJacob Faibussowitsch   ierr = ISLocalToGlobalMappingCreateIS(glob, &ltog);CHKERRQ(ierr);
8706f108dbd7SJacob Faibussowitsch   ierr = ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr);
8707f108dbd7SJacob Faibussowitsch   ierr = VecCreate(comm, OrthQual);CHKERRQ(ierr);
8708f108dbd7SJacob Faibussowitsch   ierr = VecSetType(*OrthQual, VECSTANDARD);CHKERRQ(ierr);
8709f108dbd7SJacob Faibussowitsch   ierr = VecSetSizes(*OrthQual, cEnd-cStart, PETSC_DETERMINE);CHKERRQ(ierr);
8710f108dbd7SJacob Faibussowitsch   ierr = VecSetLocalToGlobalMapping(*OrthQual, ltog);CHKERRQ(ierr);
8711f108dbd7SJacob Faibussowitsch   ierr = VecSetUp(*OrthQual);CHKERRQ(ierr);
8712f108dbd7SJacob Faibussowitsch   ierr = ISDestroy(&glob);CHKERRQ(ierr);
8713f108dbd7SJacob Faibussowitsch   ierr = ISLocalToGlobalMappingDestroy(&ltog);CHKERRQ(ierr);
8714f108dbd7SJacob Faibussowitsch   ierr = DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL);CHKERRQ(ierr);
8715f108dbd7SJacob Faibussowitsch   ierr = VecGetArrayRead(cellgeom, &cellGeomArr);CHKERRQ(ierr);
8716f108dbd7SJacob Faibussowitsch   ierr = VecGetArrayRead(facegeom, &faceGeomArr);CHKERRQ(ierr);
8717f108dbd7SJacob Faibussowitsch   ierr = VecGetDM(cellgeom, &dmCell);CHKERRQ(ierr);
8718f108dbd7SJacob Faibussowitsch   ierr = VecGetDM(facegeom, &dmFace);CHKERRQ(ierr);
87196ed19f2fSJacob Faibussowitsch   ierr = PetscMalloc5(cEnd-cStart, &idx, cEnd-cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai);CHKERRQ(ierr);
87206ed19f2fSJacob Faibussowitsch   for (cell = cStart; cell < cEnd; cellIter++,cell++) {
87216ed19f2fSJacob Faibussowitsch     PetscInt           cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE;
8722f108dbd7SJacob Faibussowitsch     PetscInt           cellarr[2], *adj = NULL;
8723f108dbd7SJacob Faibussowitsch     PetscScalar        *cArr, *fArr;
8724898cd552SSatish Balay     PetscReal          minvalc = 1.0, minvalf = 1.0;
8725f108dbd7SJacob Faibussowitsch     PetscFVCellGeom    *cg;
8726f108dbd7SJacob Faibussowitsch 
87276ed19f2fSJacob Faibussowitsch     idx[cellIter] = cell-cStart;
8728f108dbd7SJacob Faibussowitsch     cellarr[0] = cell;
8729f108dbd7SJacob Faibussowitsch     /* Make indexing into cellGeom easier */
8730f108dbd7SJacob Faibussowitsch     ierr = DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg);CHKERRQ(ierr);
8731f108dbd7SJacob Faibussowitsch     ierr = DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj);CHKERRQ(ierr);
8732f108dbd7SJacob Faibussowitsch     /* Technically 1 too big, but easier than fiddling with empty adjacency array */
8733f108dbd7SJacob Faibussowitsch     ierr = PetscCalloc2(adjSize, &cArr, adjSize, &fArr);CHKERRQ(ierr);
87346ed19f2fSJacob Faibussowitsch     for (cellneigh = 0; cellneigh < adjSize; cellneighiter++,cellneigh++) {
87356ed19f2fSJacob Faibussowitsch       PetscInt         i;
87366ed19f2fSJacob Faibussowitsch       const PetscInt   neigh = adj[cellneigh];
8737f108dbd7SJacob Faibussowitsch       PetscReal        normci = 0, normfi = 0, normai = 0;
8738f108dbd7SJacob Faibussowitsch       PetscFVCellGeom  *cgneigh;
8739f108dbd7SJacob Faibussowitsch       PetscFVFaceGeom  *fg;
8740f108dbd7SJacob Faibussowitsch 
8741f108dbd7SJacob Faibussowitsch       /* Don't count ourselves in the neighbor list */
8742f108dbd7SJacob Faibussowitsch       if (neigh == cell) continue;
8743f108dbd7SJacob Faibussowitsch       ierr = DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh);CHKERRQ(ierr);
8744f108dbd7SJacob Faibussowitsch       cellarr[1] = neigh;
87456ed19f2fSJacob Faibussowitsch       {
87466ed19f2fSJacob Faibussowitsch         PetscInt       numcovpts;
87476ed19f2fSJacob Faibussowitsch         const PetscInt *covpts;
87486ed19f2fSJacob Faibussowitsch 
8749f108dbd7SJacob Faibussowitsch         ierr = DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts);CHKERRQ(ierr);
8750f108dbd7SJacob Faibussowitsch         ierr = DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg);CHKERRQ(ierr);
8751f108dbd7SJacob Faibussowitsch         ierr = DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts);CHKERRQ(ierr);
87526ed19f2fSJacob Faibussowitsch       }
8753f108dbd7SJacob Faibussowitsch 
8754f108dbd7SJacob Faibussowitsch       /* Compute c_i, f_i and their norms */
8755f108dbd7SJacob Faibussowitsch       for (i = 0; i < nc; i++) {
8756f108dbd7SJacob Faibussowitsch         ci[i] = cgneigh->centroid[i] - cg->centroid[i];
8757f108dbd7SJacob Faibussowitsch         fi[i] = fg->centroid[i] - cg->centroid[i];
8758f108dbd7SJacob Faibussowitsch         Ai[i] = fg->normal[i];
8759addd1e01SJunchao Zhang         normci += PetscPowReal(ci[i], 2);
8760addd1e01SJunchao Zhang         normfi += PetscPowReal(fi[i], 2);
8761addd1e01SJunchao Zhang         normai += PetscPowReal(Ai[i], 2);
8762f108dbd7SJacob Faibussowitsch       }
8763addd1e01SJunchao Zhang       normci = PetscSqrtReal(normci);
8764addd1e01SJunchao Zhang       normfi = PetscSqrtReal(normfi);
8765addd1e01SJunchao Zhang       normai = PetscSqrtReal(normai);
8766f108dbd7SJacob Faibussowitsch 
8767f108dbd7SJacob Faibussowitsch       /* Normalize and compute for each face-cell-normal pair */
8768f108dbd7SJacob Faibussowitsch       for (i = 0; i < nc; i++) {
8769f108dbd7SJacob Faibussowitsch         ci[i] = ci[i]/normci;
8770f108dbd7SJacob Faibussowitsch         fi[i] = fi[i]/normfi;
8771f108dbd7SJacob Faibussowitsch         Ai[i] = Ai[i]/normai;
8772f108dbd7SJacob Faibussowitsch         /* PetscAbs because I don't know if normals are guaranteed to point out */
8773f108dbd7SJacob Faibussowitsch         cArr[cellneighiter] += PetscAbs(Ai[i]*ci[i]);
8774f108dbd7SJacob Faibussowitsch         fArr[cellneighiter] += PetscAbs(Ai[i]*fi[i]);
8775f108dbd7SJacob Faibussowitsch       }
8776f108dbd7SJacob Faibussowitsch       if (PetscRealPart(cArr[cellneighiter]) < minvalc) {
8777f108dbd7SJacob Faibussowitsch         minvalc = PetscRealPart(cArr[cellneighiter]);
8778f108dbd7SJacob Faibussowitsch       }
8779f108dbd7SJacob Faibussowitsch       if (PetscRealPart(fArr[cellneighiter]) < minvalf) {
8780f108dbd7SJacob Faibussowitsch         minvalf = PetscRealPart(fArr[cellneighiter]);
8781f108dbd7SJacob Faibussowitsch       }
8782f108dbd7SJacob Faibussowitsch     }
8783f108dbd7SJacob Faibussowitsch     ierr = PetscFree(adj);CHKERRQ(ierr);
8784f108dbd7SJacob Faibussowitsch     ierr = PetscFree2(cArr, fArr);CHKERRQ(ierr);
8785f108dbd7SJacob Faibussowitsch     /* Defer to cell if they're equal */
87866ed19f2fSJacob Faibussowitsch     oqVals[cellIter] = PetscMin(minvalf, minvalc);
8787f108dbd7SJacob Faibussowitsch     if (OrthQualLabel) {
87886ed19f2fSJacob Faibussowitsch       if (PetscRealPart(oqVals[cellIter]) <= atol) {ierr = DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE);CHKERRQ(ierr);}
8789f108dbd7SJacob Faibussowitsch     }
8790f108dbd7SJacob Faibussowitsch   }
87916ed19f2fSJacob Faibussowitsch   ierr = VecSetValuesLocal(*OrthQual, cEnd-cStart, idx, oqVals, INSERT_VALUES);CHKERRQ(ierr);
8792f108dbd7SJacob Faibussowitsch   ierr = VecAssemblyBegin(*OrthQual);CHKERRQ(ierr);
8793f108dbd7SJacob Faibussowitsch   ierr = VecAssemblyEnd(*OrthQual);CHKERRQ(ierr);
8794f108dbd7SJacob Faibussowitsch   ierr = VecRestoreArrayRead(cellgeom, &cellGeomArr);CHKERRQ(ierr);
8795f108dbd7SJacob Faibussowitsch   ierr = VecRestoreArrayRead(facegeom, &faceGeomArr);CHKERRQ(ierr);
8796f108dbd7SJacob Faibussowitsch   ierr = PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL);CHKERRQ(ierr);
8797f108dbd7SJacob Faibussowitsch   if (OrthQualLabel) {
87986ed19f2fSJacob Faibussowitsch     if (vwr) {ierr = DMLabelView(*OrthQualLabel, vwr);CHKERRQ(ierr);}
8799f108dbd7SJacob Faibussowitsch   }
88006ed19f2fSJacob Faibussowitsch   ierr = PetscFree5(idx, oqVals, ci, fi, Ai);CHKERRQ(ierr);
8801f108dbd7SJacob Faibussowitsch   ierr = PetscViewerDestroy(&vwr);CHKERRQ(ierr);
8802f108dbd7SJacob Faibussowitsch   ierr = VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view");CHKERRQ(ierr);
8803f108dbd7SJacob Faibussowitsch   PetscFunctionReturn(0);
8804f108dbd7SJacob Faibussowitsch }
8805f108dbd7SJacob Faibussowitsch 
88061eb70e55SToby Isaac /* this is here insead of DMGetOutputDM because output DM still has constraints in the local indices that affect
88071eb70e55SToby Isaac  * interpolator construction */
88081eb70e55SToby Isaac static PetscErrorCode DMGetFullDM(DM dm, DM *odm)
88091eb70e55SToby Isaac {
88101eb70e55SToby Isaac   PetscSection   section, newSection, gsection;
88111eb70e55SToby Isaac   PetscSF        sf;
88121eb70e55SToby Isaac   PetscBool      hasConstraints, ghasConstraints;
88131eb70e55SToby Isaac   PetscErrorCode ierr;
88141eb70e55SToby Isaac 
88151eb70e55SToby Isaac   PetscFunctionBegin;
88161eb70e55SToby Isaac   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
88171eb70e55SToby Isaac   PetscValidPointer(odm,2);
88181eb70e55SToby Isaac   ierr = DMGetLocalSection(dm, &section);CHKERRQ(ierr);
88191eb70e55SToby Isaac   ierr = PetscSectionHasConstraints(section, &hasConstraints);CHKERRQ(ierr);
88201eb70e55SToby Isaac   ierr = MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm));CHKERRMPI(ierr);
88211eb70e55SToby Isaac   if (!ghasConstraints) {
88221eb70e55SToby Isaac     ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr);
88231eb70e55SToby Isaac     *odm = dm;
88241eb70e55SToby Isaac     PetscFunctionReturn(0);
88251eb70e55SToby Isaac   }
88261eb70e55SToby Isaac   ierr = DMClone(dm, odm);CHKERRQ(ierr);
88271eb70e55SToby Isaac   ierr = DMCopyFields(dm, *odm);CHKERRQ(ierr);
88281eb70e55SToby Isaac   ierr = DMGetLocalSection(*odm, &newSection);CHKERRQ(ierr);
88291eb70e55SToby Isaac   ierr = DMGetPointSF(*odm, &sf);CHKERRQ(ierr);
88301eb70e55SToby Isaac   ierr = PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_FALSE, &gsection);CHKERRQ(ierr);
88311eb70e55SToby Isaac   ierr = DMSetGlobalSection(*odm, gsection);CHKERRQ(ierr);
88321eb70e55SToby Isaac   ierr = PetscSectionDestroy(&gsection);CHKERRQ(ierr);
88331eb70e55SToby Isaac   PetscFunctionReturn(0);
88341eb70e55SToby Isaac }
88351eb70e55SToby Isaac 
88361eb70e55SToby Isaac static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift)
88371eb70e55SToby Isaac {
88381eb70e55SToby Isaac   DM             dmco, dmfo;
88391eb70e55SToby Isaac   Mat            interpo;
88401eb70e55SToby Isaac   Vec            rscale;
88411eb70e55SToby Isaac   Vec            cglobalo, clocal;
88421eb70e55SToby Isaac   Vec            fglobal, fglobalo, flocal;
88431eb70e55SToby Isaac   PetscBool      regular;
88441eb70e55SToby Isaac   PetscErrorCode ierr;
88451eb70e55SToby Isaac 
88461eb70e55SToby Isaac   PetscFunctionBegin;
88471eb70e55SToby Isaac   ierr = DMGetFullDM(dmc, &dmco);CHKERRQ(ierr);
88481eb70e55SToby Isaac   ierr = DMGetFullDM(dmf, &dmfo);CHKERRQ(ierr);
88491eb70e55SToby Isaac   ierr = DMSetCoarseDM(dmfo, dmco);CHKERRQ(ierr);
88501eb70e55SToby Isaac   ierr = DMPlexGetRegularRefinement(dmf, &regular);CHKERRQ(ierr);
88511eb70e55SToby Isaac   ierr = DMPlexSetRegularRefinement(dmfo, regular);CHKERRQ(ierr);
88521eb70e55SToby Isaac   ierr = DMCreateInterpolation(dmco, dmfo, &interpo, &rscale);CHKERRQ(ierr);
88531eb70e55SToby Isaac   ierr = DMCreateGlobalVector(dmco, &cglobalo);CHKERRQ(ierr);
88541eb70e55SToby Isaac   ierr = DMCreateLocalVector(dmc, &clocal);CHKERRQ(ierr);
88551eb70e55SToby Isaac   ierr = VecSet(cglobalo, 0.);CHKERRQ(ierr);
88561eb70e55SToby Isaac   ierr = VecSet(clocal, 0.);CHKERRQ(ierr);
88571eb70e55SToby Isaac   ierr = DMCreateGlobalVector(dmf, &fglobal);CHKERRQ(ierr);
88581eb70e55SToby Isaac   ierr = DMCreateGlobalVector(dmfo, &fglobalo);CHKERRQ(ierr);
88591eb70e55SToby Isaac   ierr = DMCreateLocalVector(dmf, &flocal);CHKERRQ(ierr);
88601eb70e55SToby Isaac   ierr = VecSet(fglobal, 0.);CHKERRQ(ierr);
88611eb70e55SToby Isaac   ierr = VecSet(fglobalo, 0.);CHKERRQ(ierr);
88621eb70e55SToby Isaac   ierr = VecSet(flocal, 0.);CHKERRQ(ierr);
88631eb70e55SToby Isaac   ierr = DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL);CHKERRQ(ierr);
88641eb70e55SToby Isaac   ierr = DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo);CHKERRQ(ierr);
88651eb70e55SToby Isaac   ierr = DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo);CHKERRQ(ierr);
88661eb70e55SToby Isaac   ierr = MatMult(interpo, cglobalo, fglobalo);CHKERRQ(ierr);
88671eb70e55SToby Isaac   ierr = DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal);CHKERRQ(ierr);
88681eb70e55SToby Isaac   ierr = DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal);CHKERRQ(ierr);
88691eb70e55SToby Isaac   ierr = DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal);CHKERRQ(ierr);
88701eb70e55SToby Isaac   ierr = DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal);CHKERRQ(ierr);
88711eb70e55SToby Isaac   *shift = fglobal;
88721eb70e55SToby Isaac   ierr = VecDestroy(&flocal);CHKERRQ(ierr);
88731eb70e55SToby Isaac   ierr = VecDestroy(&fglobalo);CHKERRQ(ierr);
88741eb70e55SToby Isaac   ierr = VecDestroy(&clocal);CHKERRQ(ierr);
88751eb70e55SToby Isaac   ierr = VecDestroy(&cglobalo);CHKERRQ(ierr);
88761eb70e55SToby Isaac   ierr = VecDestroy(&rscale);CHKERRQ(ierr);
88771eb70e55SToby Isaac   ierr = MatDestroy(&interpo);CHKERRQ(ierr);
88781eb70e55SToby Isaac   ierr = DMDestroy(&dmfo);CHKERRQ(ierr);
88791eb70e55SToby Isaac   ierr = DMDestroy(&dmco);CHKERRQ(ierr);
88801eb70e55SToby Isaac   PetscFunctionReturn(0);
88811eb70e55SToby Isaac }
88821eb70e55SToby Isaac 
88831eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol)
88841eb70e55SToby Isaac {
88851eb70e55SToby Isaac   PetscObject    shifto;
88861eb70e55SToby Isaac   Vec            shift;
88871eb70e55SToby Isaac 
88881eb70e55SToby Isaac   PetscErrorCode ierr;
88891eb70e55SToby Isaac 
88901eb70e55SToby Isaac   PetscFunctionBegin;
88911eb70e55SToby Isaac   if (!interp) {
88921eb70e55SToby Isaac     Vec rscale;
88931eb70e55SToby Isaac 
88941eb70e55SToby Isaac     ierr = DMCreateInterpolation(coarse, fine, &interp, &rscale);CHKERRQ(ierr);
88951eb70e55SToby Isaac     ierr = VecDestroy(&rscale);CHKERRQ(ierr);
88961eb70e55SToby Isaac   } else {
88971eb70e55SToby Isaac     ierr = PetscObjectReference((PetscObject)interp);CHKERRQ(ierr);
88981eb70e55SToby Isaac   }
88991eb70e55SToby Isaac   ierr = PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto);CHKERRQ(ierr);
89001eb70e55SToby Isaac   if (!shifto) {
89011eb70e55SToby Isaac     ierr = DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift);CHKERRQ(ierr);
89021eb70e55SToby Isaac     ierr = PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject) shift);CHKERRQ(ierr);
89031eb70e55SToby Isaac     shifto = (PetscObject) shift;
89041eb70e55SToby Isaac     ierr = VecDestroy(&shift);CHKERRQ(ierr);
89051eb70e55SToby Isaac   }
89061eb70e55SToby Isaac   shift = (Vec) shifto;
89071eb70e55SToby Isaac   ierr = MatInterpolate(interp, coarseSol, fineSol);CHKERRQ(ierr);
89081eb70e55SToby Isaac   ierr = VecAXPY(fineSol, 1.0, shift);CHKERRQ(ierr);
89091eb70e55SToby Isaac   ierr = MatDestroy(&interp);CHKERRQ(ierr);
89101eb70e55SToby Isaac   PetscFunctionReturn(0);
89111eb70e55SToby Isaac }
89121eb70e55SToby Isaac 
8913bceba477SMatthew G. Knepley /* Pointwise interpolation
8914bceba477SMatthew G. Knepley      Just code FEM for now
8915bceba477SMatthew G. Knepley      u^f = I u^c
89164ca5e9f5SMatthew G. Knepley      sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j
89174ca5e9f5SMatthew G. Knepley      u^f_i = sum_j psi^f_i I phi^c_j u^c_j
89184ca5e9f5SMatthew G. Knepley      I_{ij} = psi^f_i phi^c_j
8919bceba477SMatthew G. Knepley */
8920bceba477SMatthew G. Knepley PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling)
8921bceba477SMatthew G. Knepley {
8922bceba477SMatthew G. Knepley   PetscSection   gsc, gsf;
8923bceba477SMatthew G. Knepley   PetscInt       m, n;
8924a063dac3SMatthew G. Knepley   void          *ctx;
892568132eb9SMatthew G. Knepley   DM             cdm;
8926cf51de39SMatthew G. Knepley   PetscBool      regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE;
8927bceba477SMatthew G. Knepley   PetscErrorCode ierr;
8928bceba477SMatthew G. Knepley 
8929bceba477SMatthew G. Knepley   PetscFunctionBegin;
8930e87a4003SBarry Smith   ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr);
8931bceba477SMatthew G. Knepley   ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr);
8932e87a4003SBarry Smith   ierr = DMGetGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr);
8933bceba477SMatthew G. Knepley   ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr);
893468132eb9SMatthew G. Knepley 
8935fd194bc8SStefano Zampini   ierr = PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis);CHKERRQ(ierr);
8936bceba477SMatthew G. Knepley   ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation);CHKERRQ(ierr);
8937bceba477SMatthew G. Knepley   ierr = MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
8938fd194bc8SStefano Zampini   ierr = MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype);CHKERRQ(ierr);
8939a063dac3SMatthew G. Knepley   ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr);
894068132eb9SMatthew G. Knepley 
8941a8fb8f29SToby Isaac   ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr);
894268132eb9SMatthew G. Knepley   ierr = DMPlexGetRegularRefinement(dmFine, &regular);CHKERRQ(ierr);
8943cf51de39SMatthew G. Knepley   if (!isRefined || (regular && cdm == dmCoarse)) {ierr = DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx);CHKERRQ(ierr);}
894468132eb9SMatthew G. Knepley   else                                            {ierr = DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);}
894568132eb9SMatthew G. Knepley   ierr = MatViewFromOptions(*interpolation, NULL, "-interp_mat_view");CHKERRQ(ierr);
89464db47ee9SStefano Zampini   if (scaling) {
89475d1c2e58SMatthew G. Knepley     /* Use naive scaling */
89485d1c2e58SMatthew G. Knepley     ierr = DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling);CHKERRQ(ierr);
89494db47ee9SStefano Zampini   }
8950a063dac3SMatthew G. Knepley   PetscFunctionReturn(0);
8951a063dac3SMatthew G. Knepley }
8952bceba477SMatthew G. Knepley 
89536dbf9973SLawrence Mitchell PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat)
8954a063dac3SMatthew G. Knepley {
895590748bafSMatthew G. Knepley   PetscErrorCode ierr;
89566dbf9973SLawrence Mitchell   VecScatter     ctx;
895790748bafSMatthew G. Knepley 
8958a063dac3SMatthew G. Knepley   PetscFunctionBegin;
89596dbf9973SLawrence Mitchell   ierr = DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL);CHKERRQ(ierr);
89606dbf9973SLawrence Mitchell   ierr = MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat);CHKERRQ(ierr);
89616dbf9973SLawrence Mitchell   ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr);
8962bceba477SMatthew G. Knepley   PetscFunctionReturn(0);
8963bceba477SMatthew G. Knepley }
8964bceba477SMatthew G. Knepley 
89653e9753d6SMatthew G. Knepley static void g0_identity_private(PetscInt dim, PetscInt Nf, PetscInt NfAux,
89663e9753d6SMatthew G. Knepley                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
89673e9753d6SMatthew G. Knepley                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
89683e9753d6SMatthew G. Knepley                                 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[])
89693e9753d6SMatthew G. Knepley {
89703e9753d6SMatthew G. Knepley   g0[0] = 1.0;
89713e9753d6SMatthew G. Knepley }
89723e9753d6SMatthew G. Knepley 
8973bd041c0cSMatthew G. Knepley PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass)
8974bd041c0cSMatthew G. Knepley {
8975bd041c0cSMatthew G. Knepley   PetscSection   gsc, gsf;
8976bd041c0cSMatthew G. Knepley   PetscInt       m, n;
8977bd041c0cSMatthew G. Knepley   void          *ctx;
8978bd041c0cSMatthew G. Knepley   DM             cdm;
8979bd041c0cSMatthew G. Knepley   PetscBool      regular;
8980bd041c0cSMatthew G. Knepley   PetscErrorCode ierr;
8981bd041c0cSMatthew G. Knepley 
8982bd041c0cSMatthew G. Knepley   PetscFunctionBegin;
89833e9753d6SMatthew G. Knepley   if (dmFine == dmCoarse) {
89843e9753d6SMatthew G. Knepley     DM       dmc;
89853e9753d6SMatthew G. Knepley     PetscDS  ds;
89863e9753d6SMatthew G. Knepley     Vec      u;
89873e9753d6SMatthew G. Knepley     IS       cellIS;
898806ad1575SMatthew G. Knepley     PetscFormKey key;
89893e9753d6SMatthew G. Knepley     PetscInt depth;
89903e9753d6SMatthew G. Knepley 
89913e9753d6SMatthew G. Knepley     ierr = DMClone(dmFine, &dmc);CHKERRQ(ierr);
89923e9753d6SMatthew G. Knepley     ierr = DMCopyDisc(dmFine, dmc);CHKERRQ(ierr);
89933e9753d6SMatthew G. Knepley     ierr = DMGetDS(dmc, &ds);CHKERRQ(ierr);
89943e9753d6SMatthew G. Knepley     ierr = PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL);CHKERRQ(ierr);
89953e9753d6SMatthew G. Knepley     ierr = DMCreateMatrix(dmc, mass);CHKERRQ(ierr);
89963e9753d6SMatthew G. Knepley     ierr = DMGetGlobalVector(dmc, &u);CHKERRQ(ierr);
89973e9753d6SMatthew G. Knepley     ierr = DMPlexGetDepth(dmc, &depth);CHKERRQ(ierr);
89983e9753d6SMatthew G. Knepley     ierr = DMGetStratumIS(dmc, "depth", depth, &cellIS);CHKERRQ(ierr);
89993e9753d6SMatthew G. Knepley     ierr = MatZeroEntries(*mass);CHKERRQ(ierr);
90006528b96dSMatthew G. Knepley     key.label = NULL;
90016528b96dSMatthew G. Knepley     key.value = 0;
90026528b96dSMatthew G. Knepley     key.field = 0;
900306ad1575SMatthew G. Knepley     key.part  = 0;
90046528b96dSMatthew G. Knepley     ierr = DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL);CHKERRQ(ierr);
90053e9753d6SMatthew G. Knepley     ierr = ISDestroy(&cellIS);CHKERRQ(ierr);
90063e9753d6SMatthew G. Knepley     ierr = DMRestoreGlobalVector(dmc, &u);CHKERRQ(ierr);
90073e9753d6SMatthew G. Knepley     ierr = DMDestroy(&dmc);CHKERRQ(ierr);
90083e9753d6SMatthew G. Knepley   } else {
9009e87a4003SBarry Smith     ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr);
9010bd041c0cSMatthew G. Knepley     ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr);
9011e87a4003SBarry Smith     ierr = DMGetGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr);
9012bd041c0cSMatthew G. Knepley     ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr);
9013bd041c0cSMatthew G. Knepley 
9014bd041c0cSMatthew G. Knepley     ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass);CHKERRQ(ierr);
9015bd041c0cSMatthew G. Knepley     ierr = MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
9016bd041c0cSMatthew G. Knepley     ierr = MatSetType(*mass, dmCoarse->mattype);CHKERRQ(ierr);
9017bd041c0cSMatthew G. Knepley     ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr);
9018bd041c0cSMatthew G. Knepley 
9019bd041c0cSMatthew G. Knepley     ierr = DMGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr);
9020bd041c0cSMatthew G. Knepley     ierr = DMPlexGetRegularRefinement(dmFine, &regular);CHKERRQ(ierr);
9021bd041c0cSMatthew G. Knepley     if (regular && cdm == dmCoarse) {ierr = DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);}
9022bd041c0cSMatthew G. Knepley     else                            {ierr = DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);}
90233e9753d6SMatthew G. Knepley   }
9024bd041c0cSMatthew G. Knepley   ierr = MatViewFromOptions(*mass, NULL, "-mass_mat_view");CHKERRQ(ierr);
9025bd041c0cSMatthew G. Knepley   PetscFunctionReturn(0);
9026bd041c0cSMatthew G. Knepley }
9027bd041c0cSMatthew G. Knepley 
90280aef6b92SMatthew G. Knepley /*@
90290aef6b92SMatthew G. Knepley   DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh
90300aef6b92SMatthew G. Knepley 
90310aef6b92SMatthew G. Knepley   Input Parameter:
90320aef6b92SMatthew G. Knepley . dm - The DMPlex object
90330aef6b92SMatthew G. Knepley 
90340aef6b92SMatthew G. Knepley   Output Parameter:
90350aef6b92SMatthew G. Knepley . regular - The flag
90360aef6b92SMatthew G. Knepley 
90370aef6b92SMatthew G. Knepley   Level: intermediate
90380aef6b92SMatthew G. Knepley 
90390aef6b92SMatthew G. Knepley .seealso: DMPlexSetRegularRefinement()
90400aef6b92SMatthew G. Knepley @*/
90410aef6b92SMatthew G. Knepley PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular)
90420aef6b92SMatthew G. Knepley {
90430aef6b92SMatthew G. Knepley   PetscFunctionBegin;
90440aef6b92SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
90450aef6b92SMatthew G. Knepley   PetscValidPointer(regular, 2);
90460aef6b92SMatthew G. Knepley   *regular = ((DM_Plex *) dm->data)->regularRefinement;
90470aef6b92SMatthew G. Knepley   PetscFunctionReturn(0);
90480aef6b92SMatthew G. Knepley }
90490aef6b92SMatthew G. Knepley 
90500aef6b92SMatthew G. Knepley /*@
90510aef6b92SMatthew G. Knepley   DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh
90520aef6b92SMatthew G. Knepley 
90530aef6b92SMatthew G. Knepley   Input Parameters:
90540aef6b92SMatthew G. Knepley + dm - The DMPlex object
90550aef6b92SMatthew G. Knepley - regular - The flag
90560aef6b92SMatthew G. Knepley 
90570aef6b92SMatthew G. Knepley   Level: intermediate
90580aef6b92SMatthew G. Knepley 
90590aef6b92SMatthew G. Knepley .seealso: DMPlexGetRegularRefinement()
90600aef6b92SMatthew G. Knepley @*/
90610aef6b92SMatthew G. Knepley PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular)
90620aef6b92SMatthew G. Knepley {
90630aef6b92SMatthew G. Knepley   PetscFunctionBegin;
90640aef6b92SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
90650aef6b92SMatthew G. Knepley   ((DM_Plex *) dm->data)->regularRefinement = regular;
90660aef6b92SMatthew G. Knepley   PetscFunctionReturn(0);
90670aef6b92SMatthew G. Knepley }
90680aef6b92SMatthew G. Knepley 
9069412e9a14SMatthew G. Knepley /*@
9070412e9a14SMatthew G. Knepley   DMPlexGetCellRefinerType - Get the strategy for refining a cell
9071412e9a14SMatthew G. Knepley 
9072412e9a14SMatthew G. Knepley   Input Parameter:
9073412e9a14SMatthew G. Knepley . dm - The DMPlex object
9074412e9a14SMatthew G. Knepley 
9075412e9a14SMatthew G. Knepley   Output Parameter:
9076412e9a14SMatthew G. Knepley . cr - The strategy number
9077412e9a14SMatthew G. Knepley 
9078412e9a14SMatthew G. Knepley   Level: intermediate
9079412e9a14SMatthew G. Knepley 
9080412e9a14SMatthew G. Knepley .seealso: DMPlexSetCellRefinerType(), DMPlexSetRegularRefinement()
9081412e9a14SMatthew G. Knepley @*/
9082412e9a14SMatthew G. Knepley PetscErrorCode DMPlexGetCellRefinerType(DM dm, DMPlexCellRefinerType *cr)
9083412e9a14SMatthew G. Knepley {
9084412e9a14SMatthew G. Knepley   PetscFunctionBegin;
9085412e9a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9086412e9a14SMatthew G. Knepley   PetscValidPointer(cr, 2);
9087412e9a14SMatthew G. Knepley   *cr = ((DM_Plex *) dm->data)->cellRefiner;
9088412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
9089412e9a14SMatthew G. Knepley }
9090412e9a14SMatthew G. Knepley 
9091412e9a14SMatthew G. Knepley /*@
9092412e9a14SMatthew G. Knepley   DMPlexSetCellRefinerType - Set the strategy for refining a cell
9093412e9a14SMatthew G. Knepley 
9094412e9a14SMatthew G. Knepley   Input Parameters:
9095412e9a14SMatthew G. Knepley + dm - The DMPlex object
9096412e9a14SMatthew G. Knepley - cr - The strategy number
9097412e9a14SMatthew G. Knepley 
9098412e9a14SMatthew G. Knepley   Level: intermediate
9099412e9a14SMatthew G. Knepley 
9100412e9a14SMatthew G. Knepley .seealso: DMPlexGetCellRefinerType(), DMPlexGetRegularRefinement()
9101412e9a14SMatthew G. Knepley @*/
9102412e9a14SMatthew G. Knepley PetscErrorCode DMPlexSetCellRefinerType(DM dm, DMPlexCellRefinerType cr)
9103412e9a14SMatthew G. Knepley {
9104412e9a14SMatthew G. Knepley   PetscFunctionBegin;
9105412e9a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9106412e9a14SMatthew G. Knepley   ((DM_Plex *) dm->data)->cellRefiner = cr;
9107412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
9108412e9a14SMatthew G. Knepley }
9109412e9a14SMatthew G. Knepley 
9110f7c74593SToby Isaac /* anchors */
9111a68b90caSToby Isaac /*@
9112f7c74593SToby Isaac   DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints.  Typically, the user will not have to
9113f7c74593SToby Isaac   call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetConstraints().
9114a68b90caSToby Isaac 
9115e228b242SToby Isaac   not collective
9116a68b90caSToby Isaac 
9117a68b90caSToby Isaac   Input Parameters:
9118a68b90caSToby Isaac . dm - The DMPlex object
9119a68b90caSToby Isaac 
9120a68b90caSToby Isaac   Output Parameters:
9121a68b90caSToby Isaac + anchorSection - If not NULL, set to the section describing which points anchor the constrained points.
9122a68b90caSToby Isaac - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection
9123a68b90caSToby Isaac 
9124a68b90caSToby Isaac   Level: intermediate
9125a68b90caSToby Isaac 
9126f7c74593SToby Isaac .seealso: DMPlexSetAnchors(), DMGetConstraints(), DMSetConstraints()
9127a68b90caSToby Isaac @*/
9128a17985deSToby Isaac PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS)
9129a68b90caSToby Isaac {
9130a68b90caSToby Isaac   DM_Plex *plex = (DM_Plex *)dm->data;
913141e6d900SToby Isaac   PetscErrorCode ierr;
9132a68b90caSToby Isaac 
9133a68b90caSToby Isaac   PetscFunctionBegin;
9134a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
913541e6d900SToby Isaac   if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) {ierr = (*plex->createanchors)(dm);CHKERRQ(ierr);}
9136a68b90caSToby Isaac   if (anchorSection) *anchorSection = plex->anchorSection;
9137a68b90caSToby Isaac   if (anchorIS) *anchorIS = plex->anchorIS;
9138a68b90caSToby Isaac   PetscFunctionReturn(0);
9139a68b90caSToby Isaac }
9140a68b90caSToby Isaac 
9141a68b90caSToby Isaac /*@
9142f7c74593SToby Isaac   DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints.  Unlike boundary conditions,
9143f7c74593SToby Isaac   when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a
9144a68b90caSToby Isaac   point's degrees of freedom to be a linear combination of other points' degrees of freedom.
9145a68b90caSToby Isaac 
9146a17985deSToby Isaac   After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling
9147f7c74593SToby Isaac   DMGetConstraints() and filling in the entries in the constraint matrix.
9148a68b90caSToby Isaac 
9149e228b242SToby Isaac   collective on dm
9150a68b90caSToby Isaac 
9151a68b90caSToby Isaac   Input Parameters:
9152a68b90caSToby Isaac + dm - The DMPlex object
9153e228b242SToby 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).
9154e228b242SToby Isaac - anchorIS - The list of all anchor points.  Must have a local communicator (PETSC_COMM_SELF or derivative).
9155a68b90caSToby Isaac 
9156a68b90caSToby Isaac   The reference counts of anchorSection and anchorIS are incremented.
9157a68b90caSToby Isaac 
9158a68b90caSToby Isaac   Level: intermediate
9159a68b90caSToby Isaac 
9160f7c74593SToby Isaac .seealso: DMPlexGetAnchors(), DMGetConstraints(), DMSetConstraints()
9161a68b90caSToby Isaac @*/
9162a17985deSToby Isaac PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS)
9163a68b90caSToby Isaac {
9164a68b90caSToby Isaac   DM_Plex        *plex = (DM_Plex *)dm->data;
9165e228b242SToby Isaac   PetscMPIInt    result;
9166a68b90caSToby Isaac   PetscErrorCode ierr;
9167a68b90caSToby Isaac 
9168a68b90caSToby Isaac   PetscFunctionBegin;
9169a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9170e228b242SToby Isaac   if (anchorSection) {
9171e228b242SToby Isaac     PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2);
9172ffc4695bSBarry Smith     ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result);CHKERRMPI(ierr);
9173f6a3d38cSToby Isaac     if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator");
9174e228b242SToby Isaac   }
9175e228b242SToby Isaac   if (anchorIS) {
9176e228b242SToby Isaac     PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3);
9177ffc4695bSBarry Smith     ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result);CHKERRMPI(ierr);
9178f6a3d38cSToby Isaac     if (result != MPI_CONGRUENT && result != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator");
9179e228b242SToby Isaac   }
9180a68b90caSToby Isaac 
9181a68b90caSToby Isaac   ierr = PetscObjectReference((PetscObject)anchorSection);CHKERRQ(ierr);
9182a68b90caSToby Isaac   ierr = PetscSectionDestroy(&plex->anchorSection);CHKERRQ(ierr);
9183a68b90caSToby Isaac   plex->anchorSection = anchorSection;
9184a68b90caSToby Isaac 
9185a68b90caSToby Isaac   ierr = PetscObjectReference((PetscObject)anchorIS);CHKERRQ(ierr);
9186a68b90caSToby Isaac   ierr = ISDestroy(&plex->anchorIS);CHKERRQ(ierr);
9187a68b90caSToby Isaac   plex->anchorIS = anchorIS;
9188a68b90caSToby Isaac 
9189cf9c20a2SJed Brown   if (PetscUnlikelyDebug(anchorIS && anchorSection)) {
9190a68b90caSToby Isaac     PetscInt size, a, pStart, pEnd;
9191a68b90caSToby Isaac     const PetscInt *anchors;
9192a68b90caSToby Isaac 
9193a68b90caSToby Isaac     ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr);
9194a68b90caSToby Isaac     ierr = ISGetLocalSize(anchorIS,&size);CHKERRQ(ierr);
9195a68b90caSToby Isaac     ierr = ISGetIndices(anchorIS,&anchors);CHKERRQ(ierr);
9196a68b90caSToby Isaac     for (a = 0; a < size; a++) {
9197a68b90caSToby Isaac       PetscInt p;
9198a68b90caSToby Isaac 
9199a68b90caSToby Isaac       p = anchors[a];
9200a68b90caSToby Isaac       if (p >= pStart && p < pEnd) {
9201a68b90caSToby Isaac         PetscInt dof;
9202a68b90caSToby Isaac 
9203a68b90caSToby Isaac         ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr);
9204a68b90caSToby Isaac         if (dof) {
9205a68b90caSToby Isaac           PetscErrorCode ierr2;
9206a68b90caSToby Isaac 
9207a68b90caSToby Isaac           ierr2 = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr2);
92088ccfff9cSToby Isaac           SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %D cannot be constrained and an anchor",p);
9209a68b90caSToby Isaac         }
9210a68b90caSToby Isaac       }
9211a68b90caSToby Isaac     }
9212a68b90caSToby Isaac     ierr = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr);
9213a68b90caSToby Isaac   }
9214f7c74593SToby Isaac   /* reset the generic constraints */
9215f7c74593SToby Isaac   ierr = DMSetDefaultConstraints(dm,NULL,NULL);CHKERRQ(ierr);
9216a68b90caSToby Isaac   PetscFunctionReturn(0);
9217a68b90caSToby Isaac }
9218a68b90caSToby Isaac 
9219f7c74593SToby Isaac static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec)
9220a68b90caSToby Isaac {
9221f7c74593SToby Isaac   PetscSection anchorSection;
92226995de1eSToby Isaac   PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f;
9223a68b90caSToby Isaac   PetscErrorCode ierr;
9224a68b90caSToby Isaac 
9225a68b90caSToby Isaac   PetscFunctionBegin;
9226a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9227a17985deSToby Isaac   ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr);
9228e228b242SToby Isaac   ierr = PetscSectionCreate(PETSC_COMM_SELF,cSec);CHKERRQ(ierr);
9229a68b90caSToby Isaac   ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr);
92306995de1eSToby Isaac   if (numFields) {
9231719ab38cSToby Isaac     PetscInt f;
9232a68b90caSToby Isaac     ierr = PetscSectionSetNumFields(*cSec,numFields);CHKERRQ(ierr);
9233719ab38cSToby Isaac 
9234719ab38cSToby Isaac     for (f = 0; f < numFields; f++) {
9235719ab38cSToby Isaac       PetscInt numComp;
9236719ab38cSToby Isaac 
9237719ab38cSToby Isaac       ierr = PetscSectionGetFieldComponents(section,f,&numComp);CHKERRQ(ierr);
9238719ab38cSToby Isaac       ierr = PetscSectionSetFieldComponents(*cSec,f,numComp);CHKERRQ(ierr);
9239719ab38cSToby Isaac     }
92406995de1eSToby Isaac   }
9241a68b90caSToby Isaac   ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr);
92426995de1eSToby Isaac   ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr);
92436995de1eSToby Isaac   pStart = PetscMax(pStart,sStart);
92446995de1eSToby Isaac   pEnd   = PetscMin(pEnd,sEnd);
92456995de1eSToby Isaac   pEnd   = PetscMax(pStart,pEnd);
9246a68b90caSToby Isaac   ierr = PetscSectionSetChart(*cSec,pStart,pEnd);CHKERRQ(ierr);
9247a68b90caSToby Isaac   for (p = pStart; p < pEnd; p++) {
9248a68b90caSToby Isaac     ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr);
9249a68b90caSToby Isaac     if (dof) {
9250a68b90caSToby Isaac       ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr);
9251a68b90caSToby Isaac       ierr = PetscSectionSetDof(*cSec,p,dof);CHKERRQ(ierr);
9252a68b90caSToby Isaac       for (f = 0; f < numFields; f++) {
9253a68b90caSToby Isaac         ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr);
9254a68b90caSToby Isaac         ierr = PetscSectionSetFieldDof(*cSec,p,f,dof);CHKERRQ(ierr);
9255a68b90caSToby Isaac       }
9256a68b90caSToby Isaac     }
9257a68b90caSToby Isaac   }
9258a68b90caSToby Isaac   ierr = PetscSectionSetUp(*cSec);CHKERRQ(ierr);
9259ae65431dSMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) *cSec, "Constraint Section");CHKERRQ(ierr);
9260a68b90caSToby Isaac   PetscFunctionReturn(0);
9261a68b90caSToby Isaac }
9262a68b90caSToby Isaac 
9263f7c74593SToby Isaac static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat)
9264a68b90caSToby Isaac {
9265f7c74593SToby Isaac   PetscSection   aSec;
9266ae65431dSMatthew G. Knepley   PetscInt       pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j;
92670ac89760SToby Isaac   const PetscInt *anchors;
92680ac89760SToby Isaac   PetscInt       numFields, f;
926966ad2231SToby Isaac   IS             aIS;
92700ac89760SToby Isaac   PetscErrorCode ierr;
9271e19f7ee6SMark Adams   MatType        mtype;
9272e19f7ee6SMark Adams   PetscBool      iscuda,iskokkos;
92730ac89760SToby Isaac 
92740ac89760SToby Isaac   PetscFunctionBegin;
92750ac89760SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
92760ac89760SToby Isaac   ierr = PetscSectionGetStorageSize(cSec, &m);CHKERRQ(ierr);
92770ac89760SToby Isaac   ierr = PetscSectionGetStorageSize(section, &n);CHKERRQ(ierr);
92780ac89760SToby Isaac   ierr = MatCreate(PETSC_COMM_SELF,cMat);CHKERRQ(ierr);
92790ac89760SToby Isaac   ierr = MatSetSizes(*cMat,m,n,m,n);CHKERRQ(ierr);
9280e19f7ee6SMark Adams   ierr = PetscStrcmp(dm->mattype,MATSEQAIJCUSPARSE,&iscuda);CHKERRQ(ierr);
9281e19f7ee6SMark Adams   if (!iscuda) { ierr = PetscStrcmp(dm->mattype,MATMPIAIJCUSPARSE,&iscuda);CHKERRQ(ierr); }
9282e19f7ee6SMark Adams   ierr = PetscStrcmp(dm->mattype,MATSEQAIJKOKKOS,&iskokkos);CHKERRQ(ierr);
9283e19f7ee6SMark Adams   if (!iskokkos) { ierr = PetscStrcmp(dm->mattype,MATMPIAIJKOKKOS,&iskokkos);CHKERRQ(ierr); }
9284e19f7ee6SMark Adams   if (iscuda) mtype = MATSEQAIJCUSPARSE;
9285e19f7ee6SMark Adams   else if (iskokkos) mtype = MATSEQAIJKOKKOS;
9286e19f7ee6SMark Adams   else mtype = MATSEQAIJ;
9287e19f7ee6SMark Adams   ierr = MatSetType(*cMat,mtype);CHKERRQ(ierr);
9288a17985deSToby Isaac   ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr);
928966ad2231SToby Isaac   ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr);
92906995de1eSToby Isaac   /* cSec will be a subset of aSec and section */
92916995de1eSToby Isaac   ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr);
9292ae65431dSMatthew G. Knepley   ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr);
92930ac89760SToby Isaac   ierr = PetscMalloc1(m+1,&i);CHKERRQ(ierr);
92940ac89760SToby Isaac   i[0] = 0;
92950ac89760SToby Isaac   ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr);
92960ac89760SToby Isaac   for (p = pStart; p < pEnd; p++) {
9297f19733c5SToby Isaac     PetscInt rDof, rOff, r;
9298f19733c5SToby Isaac 
9299f19733c5SToby Isaac     ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr);
9300f19733c5SToby Isaac     if (!rDof) continue;
9301f19733c5SToby Isaac     ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr);
93020ac89760SToby Isaac     if (numFields) {
93030ac89760SToby Isaac       for (f = 0; f < numFields; f++) {
93040ac89760SToby Isaac         annz = 0;
9305f19733c5SToby Isaac         for (r = 0; r < rDof; r++) {
9306f19733c5SToby Isaac           a = anchors[rOff + r];
9307ae65431dSMatthew G. Knepley           if (a < sStart || a >= sEnd) continue;
93080ac89760SToby Isaac           ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr);
93090ac89760SToby Isaac           annz += aDof;
93100ac89760SToby Isaac         }
93110ac89760SToby Isaac         ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr);
93120ac89760SToby Isaac         ierr = PetscSectionGetFieldOffset(cSec,p,f,&off);CHKERRQ(ierr);
93130ac89760SToby Isaac         for (q = 0; q < dof; q++) {
93140ac89760SToby Isaac           i[off + q + 1] = i[off + q] + annz;
93150ac89760SToby Isaac         }
93160ac89760SToby Isaac       }
93170ac89760SToby Isaac     }
93180ac89760SToby Isaac     else {
93190ac89760SToby Isaac       annz = 0;
9320326b8f31SMatthew G. Knepley       ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr);
93210ac89760SToby Isaac       for (q = 0; q < dof; q++) {
9322ae65431dSMatthew G. Knepley         a = anchors[rOff + q];
9323ae65431dSMatthew G. Knepley         if (a < sStart || a >= sEnd) continue;
93240ac89760SToby Isaac         ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr);
93250ac89760SToby Isaac         annz += aDof;
93260ac89760SToby Isaac       }
93270ac89760SToby Isaac       ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr);
93280ac89760SToby Isaac       ierr = PetscSectionGetOffset(cSec,p,&off);CHKERRQ(ierr);
93290ac89760SToby Isaac       for (q = 0; q < dof; q++) {
93300ac89760SToby Isaac         i[off + q + 1] = i[off + q] + annz;
93310ac89760SToby Isaac       }
93320ac89760SToby Isaac     }
93330ac89760SToby Isaac   }
93340ac89760SToby Isaac   nnz = i[m];
93350ac89760SToby Isaac   ierr = PetscMalloc1(nnz,&j);CHKERRQ(ierr);
93360ac89760SToby Isaac   offset = 0;
93370ac89760SToby Isaac   for (p = pStart; p < pEnd; p++) {
93380ac89760SToby Isaac     if (numFields) {
93390ac89760SToby Isaac       for (f = 0; f < numFields; f++) {
93400ac89760SToby Isaac         ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr);
93410ac89760SToby Isaac         for (q = 0; q < dof; q++) {
93420ac89760SToby Isaac           PetscInt rDof, rOff, r;
93430ac89760SToby Isaac           ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr);
93440ac89760SToby Isaac           ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr);
93450ac89760SToby Isaac           for (r = 0; r < rDof; r++) {
93460ac89760SToby Isaac             PetscInt s;
93470ac89760SToby Isaac 
93480ac89760SToby Isaac             a = anchors[rOff + r];
9349ae65431dSMatthew G. Knepley             if (a < sStart || a >= sEnd) continue;
93500ac89760SToby Isaac             ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr);
93510ac89760SToby Isaac             ierr = PetscSectionGetFieldOffset(section,a,f,&aOff);CHKERRQ(ierr);
93520ac89760SToby Isaac             for (s = 0; s < aDof; s++) {
93530ac89760SToby Isaac               j[offset++] = aOff + s;
93540ac89760SToby Isaac             }
93550ac89760SToby Isaac           }
93560ac89760SToby Isaac         }
93570ac89760SToby Isaac       }
93580ac89760SToby Isaac     }
93590ac89760SToby Isaac     else {
93600ac89760SToby Isaac       ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr);
93610ac89760SToby Isaac       for (q = 0; q < dof; q++) {
93620ac89760SToby Isaac         PetscInt rDof, rOff, r;
93630ac89760SToby Isaac         ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr);
93640ac89760SToby Isaac         ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr);
93650ac89760SToby Isaac         for (r = 0; r < rDof; r++) {
93660ac89760SToby Isaac           PetscInt s;
93670ac89760SToby Isaac 
93680ac89760SToby Isaac           a = anchors[rOff + r];
9369ae65431dSMatthew G. Knepley           if (a < sStart || a >= sEnd) continue;
93700ac89760SToby Isaac           ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr);
93710ac89760SToby Isaac           ierr = PetscSectionGetOffset(section,a,&aOff);CHKERRQ(ierr);
93720ac89760SToby Isaac           for (s = 0; s < aDof; s++) {
93730ac89760SToby Isaac             j[offset++] = aOff + s;
93740ac89760SToby Isaac           }
93750ac89760SToby Isaac         }
93760ac89760SToby Isaac       }
93770ac89760SToby Isaac     }
93780ac89760SToby Isaac   }
93790ac89760SToby Isaac   ierr = MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL);CHKERRQ(ierr);
938025570a81SToby Isaac   ierr = PetscFree(i);CHKERRQ(ierr);
938125570a81SToby Isaac   ierr = PetscFree(j);CHKERRQ(ierr);
938266ad2231SToby Isaac   ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);
93830ac89760SToby Isaac   PetscFunctionReturn(0);
93840ac89760SToby Isaac }
93850ac89760SToby Isaac 
938666ad2231SToby Isaac PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm)
938766ad2231SToby Isaac {
9388f7c74593SToby Isaac   DM_Plex        *plex = (DM_Plex *)dm->data;
9389f7c74593SToby Isaac   PetscSection   anchorSection, section, cSec;
939066ad2231SToby Isaac   Mat            cMat;
939166ad2231SToby Isaac   PetscErrorCode ierr;
939266ad2231SToby Isaac 
939366ad2231SToby Isaac   PetscFunctionBegin;
939466ad2231SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9395a17985deSToby Isaac   ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr);
939666ad2231SToby Isaac   if (anchorSection) {
939744a7f3ddSMatthew G. Knepley     PetscInt Nf;
9398e228b242SToby Isaac 
939992fd8e1eSJed Brown     ierr = DMGetLocalSection(dm,&section);CHKERRQ(ierr);
9400f7c74593SToby Isaac     ierr = DMPlexCreateConstraintSection_Anchors(dm,section,&cSec);CHKERRQ(ierr);
9401f7c74593SToby Isaac     ierr = DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat);CHKERRQ(ierr);
940244a7f3ddSMatthew G. Knepley     ierr = DMGetNumFields(dm,&Nf);CHKERRQ(ierr);
940344a7f3ddSMatthew G. Knepley     if (Nf && plex->computeanchormatrix) {ierr = (*plex->computeanchormatrix)(dm,section,cSec,cMat);CHKERRQ(ierr);}
940466ad2231SToby Isaac     ierr = DMSetDefaultConstraints(dm,cSec,cMat);CHKERRQ(ierr);
940566ad2231SToby Isaac     ierr = PetscSectionDestroy(&cSec);CHKERRQ(ierr);
940666ad2231SToby Isaac     ierr = MatDestroy(&cMat);CHKERRQ(ierr);
940766ad2231SToby Isaac   }
940866ad2231SToby Isaac   PetscFunctionReturn(0);
940966ad2231SToby Isaac }
9410a93c429eSMatthew G. Knepley 
9411a93c429eSMatthew G. Knepley PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm)
9412a93c429eSMatthew G. Knepley {
9413a93c429eSMatthew G. Knepley   IS             subis;
9414a93c429eSMatthew G. Knepley   PetscSection   section, subsection;
9415a93c429eSMatthew G. Knepley   PetscErrorCode ierr;
9416a93c429eSMatthew G. Knepley 
9417a93c429eSMatthew G. Knepley   PetscFunctionBegin;
941892fd8e1eSJed Brown   ierr = DMGetLocalSection(dm, &section);CHKERRQ(ierr);
9419a93c429eSMatthew G. Knepley   if (!section) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain");
9420a93c429eSMatthew G. Knepley   if (!subdm)   SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain");
9421a93c429eSMatthew G. Knepley   /* Create subdomain */
9422a93c429eSMatthew G. Knepley   ierr = DMPlexFilter(dm, label, value, subdm);CHKERRQ(ierr);
9423a93c429eSMatthew G. Knepley   /* Create submodel */
942497d8846cSMatthew Knepley   ierr = DMPlexGetSubpointIS(*subdm, &subis);CHKERRQ(ierr);
9425a93c429eSMatthew G. Knepley   ierr = PetscSectionCreateSubmeshSection(section, subis, &subsection);CHKERRQ(ierr);
942692fd8e1eSJed Brown   ierr = DMSetLocalSection(*subdm, subsection);CHKERRQ(ierr);
9427a93c429eSMatthew G. Knepley   ierr = PetscSectionDestroy(&subsection);CHKERRQ(ierr);
9428e5e52638SMatthew G. Knepley   ierr = DMCopyDisc(dm, *subdm);CHKERRQ(ierr);
9429a93c429eSMatthew G. Knepley   /* Create map from submodel to global model */
9430a93c429eSMatthew G. Knepley   if (is) {
9431a93c429eSMatthew G. Knepley     PetscSection    sectionGlobal, subsectionGlobal;
9432a93c429eSMatthew G. Knepley     IS              spIS;
9433a93c429eSMatthew G. Knepley     const PetscInt *spmap;
9434a93c429eSMatthew G. Knepley     PetscInt       *subIndices;
9435a93c429eSMatthew G. Knepley     PetscInt        subSize = 0, subOff = 0, pStart, pEnd, p;
9436a93c429eSMatthew G. Knepley     PetscInt        Nf, f, bs = -1, bsLocal[2], bsMinMax[2];
9437a93c429eSMatthew G. Knepley 
943897d8846cSMatthew Knepley     ierr = DMPlexGetSubpointIS(*subdm, &spIS);CHKERRQ(ierr);
9439a93c429eSMatthew G. Knepley     ierr = ISGetIndices(spIS, &spmap);CHKERRQ(ierr);
9440a93c429eSMatthew G. Knepley     ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr);
94416f0eb057SJed Brown     ierr = DMGetGlobalSection(dm, &sectionGlobal);CHKERRQ(ierr);
94426f0eb057SJed Brown     ierr = DMGetGlobalSection(*subdm, &subsectionGlobal);CHKERRQ(ierr);
9443a93c429eSMatthew G. Knepley     ierr = PetscSectionGetChart(subsection, &pStart, &pEnd);CHKERRQ(ierr);
9444a93c429eSMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
9445a93c429eSMatthew G. Knepley       PetscInt gdof, pSubSize  = 0;
9446a93c429eSMatthew G. Knepley 
9447a93c429eSMatthew G. Knepley       ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr);
9448a93c429eSMatthew G. Knepley       if (gdof > 0) {
9449a93c429eSMatthew G. Knepley         for (f = 0; f < Nf; ++f) {
9450a93c429eSMatthew G. Knepley           PetscInt fdof, fcdof;
9451a93c429eSMatthew G. Knepley 
9452a93c429eSMatthew G. Knepley           ierr     = PetscSectionGetFieldDof(subsection, p, f, &fdof);CHKERRQ(ierr);
9453a93c429eSMatthew G. Knepley           ierr     = PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof);CHKERRQ(ierr);
9454a93c429eSMatthew G. Knepley           pSubSize += fdof-fcdof;
9455a93c429eSMatthew G. Knepley         }
9456a93c429eSMatthew G. Knepley         subSize += pSubSize;
9457a93c429eSMatthew G. Knepley         if (pSubSize) {
9458a93c429eSMatthew G. Knepley           if (bs < 0) {
9459a93c429eSMatthew G. Knepley             bs = pSubSize;
9460a93c429eSMatthew G. Knepley           } else if (bs != pSubSize) {
9461a93c429eSMatthew G. Knepley             /* Layout does not admit a pointwise block size */
9462a93c429eSMatthew G. Knepley             bs = 1;
9463a93c429eSMatthew G. Knepley           }
9464a93c429eSMatthew G. Knepley         }
9465a93c429eSMatthew G. Knepley       }
9466a93c429eSMatthew G. Knepley     }
9467a93c429eSMatthew G. Knepley     /* Must have same blocksize on all procs (some might have no points) */
9468a93c429eSMatthew G. Knepley     bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs;
9469a93c429eSMatthew G. Knepley     ierr = PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);CHKERRQ(ierr);
9470a93c429eSMatthew G. Knepley     if (bsMinMax[0] != bsMinMax[1]) {bs = 1;}
9471a93c429eSMatthew G. Knepley     else                            {bs = bsMinMax[0];}
9472a93c429eSMatthew G. Knepley     ierr = PetscMalloc1(subSize, &subIndices);CHKERRQ(ierr);
9473a93c429eSMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
9474a93c429eSMatthew G. Knepley       PetscInt gdof, goff;
9475a93c429eSMatthew G. Knepley 
9476a93c429eSMatthew G. Knepley       ierr = PetscSectionGetDof(subsectionGlobal, p, &gdof);CHKERRQ(ierr);
9477a93c429eSMatthew G. Knepley       if (gdof > 0) {
9478a93c429eSMatthew G. Knepley         const PetscInt point = spmap[p];
9479a93c429eSMatthew G. Knepley 
9480a93c429eSMatthew G. Knepley         ierr = PetscSectionGetOffset(sectionGlobal, point, &goff);CHKERRQ(ierr);
9481a93c429eSMatthew G. Knepley         for (f = 0; f < Nf; ++f) {
9482a93c429eSMatthew G. Knepley           PetscInt fdof, fcdof, fc, f2, poff = 0;
9483a93c429eSMatthew G. Knepley 
9484a93c429eSMatthew G. Knepley           /* Can get rid of this loop by storing field information in the global section */
9485a93c429eSMatthew G. Knepley           for (f2 = 0; f2 < f; ++f2) {
9486a93c429eSMatthew G. Knepley             ierr  = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr);
9487a93c429eSMatthew G. Knepley             ierr  = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr);
9488a93c429eSMatthew G. Knepley             poff += fdof-fcdof;
9489a93c429eSMatthew G. Knepley           }
9490a93c429eSMatthew G. Knepley           ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr);
9491a93c429eSMatthew G. Knepley           ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr);
9492a93c429eSMatthew G. Knepley           for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) {
9493a93c429eSMatthew G. Knepley             subIndices[subOff] = goff+poff+fc;
9494a93c429eSMatthew G. Knepley           }
9495a93c429eSMatthew G. Knepley         }
9496a93c429eSMatthew G. Knepley       }
9497a93c429eSMatthew G. Knepley     }
9498a93c429eSMatthew G. Knepley     ierr = ISRestoreIndices(spIS, &spmap);CHKERRQ(ierr);
9499a93c429eSMatthew G. Knepley     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr);
9500a93c429eSMatthew G. Knepley     if (bs > 1) {
9501a93c429eSMatthew G. Knepley       /* We need to check that the block size does not come from non-contiguous fields */
9502a93c429eSMatthew G. Knepley       PetscInt i, j, set = 1;
9503a93c429eSMatthew G. Knepley       for (i = 0; i < subSize; i += bs) {
9504a93c429eSMatthew G. Knepley         for (j = 0; j < bs; ++j) {
9505a93c429eSMatthew G. Knepley           if (subIndices[i+j] != subIndices[i]+j) {set = 0; break;}
9506a93c429eSMatthew G. Knepley         }
9507a93c429eSMatthew G. Knepley       }
9508a93c429eSMatthew G. Knepley       if (set) {ierr = ISSetBlockSize(*is, bs);CHKERRQ(ierr);}
9509a93c429eSMatthew G. Knepley     }
9510a93c429eSMatthew G. Knepley     /* Attach nullspace */
9511a93c429eSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
9512a93c429eSMatthew G. Knepley       (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f];
9513a93c429eSMatthew G. Knepley       if ((*subdm)->nullspaceConstructors[f]) break;
9514a93c429eSMatthew G. Knepley     }
9515a93c429eSMatthew G. Knepley     if (f < Nf) {
9516a93c429eSMatthew G. Knepley       MatNullSpace nullSpace;
95178cda7954SMatthew G. Knepley       ierr = (*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace);CHKERRQ(ierr);
95186823f3c5SBlaise Bourdin 
9519a93c429eSMatthew G. Knepley       ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr);
9520a93c429eSMatthew G. Knepley       ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr);
9521a93c429eSMatthew G. Knepley     }
9522a93c429eSMatthew G. Knepley   }
9523a93c429eSMatthew G. Knepley   PetscFunctionReturn(0);
9524a93c429eSMatthew G. Knepley }
9525c0f0dcc3SMatthew G. Knepley 
9526c0f0dcc3SMatthew G. Knepley /*@
9527c0f0dcc3SMatthew G. Knepley   DMPlexMonitorThroughput - Report the cell throughput of FE integration
9528c0f0dcc3SMatthew G. Knepley 
9529c0f0dcc3SMatthew G. Knepley   Input Parameter:
9530c0f0dcc3SMatthew G. Knepley - dm - The DM
9531c0f0dcc3SMatthew G. Knepley 
9532c0f0dcc3SMatthew G. Knepley   Level: developer
9533c0f0dcc3SMatthew G. Knepley 
9534c0f0dcc3SMatthew G. Knepley   Options Database Keys:
9535c0f0dcc3SMatthew G. Knepley . -dm_plex_monitor_throughput - Activate the monitor
9536c0f0dcc3SMatthew G. Knepley 
9537c0f0dcc3SMatthew G. Knepley .seealso: DMSetFromOptions(), DMPlexCreate()
9538c0f0dcc3SMatthew G. Knepley @*/
9539c0f0dcc3SMatthew G. Knepley PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy)
9540c0f0dcc3SMatthew G. Knepley {
9541e5ed2c37SJose E. Roman #if defined(PETSC_USE_LOG)
9542c0f0dcc3SMatthew G. Knepley   PetscStageLog      stageLog;
9543c0f0dcc3SMatthew G. Knepley   PetscLogEvent      event;
9544c0f0dcc3SMatthew G. Knepley   PetscLogStage      stage;
9545c0f0dcc3SMatthew G. Knepley   PetscEventPerfInfo eventInfo;
9546c0f0dcc3SMatthew G. Knepley   PetscReal          cellRate, flopRate;
9547c0f0dcc3SMatthew G. Knepley   PetscInt           cStart, cEnd, Nf, N;
9548c0f0dcc3SMatthew G. Knepley   const char        *name;
9549c0f0dcc3SMatthew G. Knepley   PetscErrorCode     ierr;
9550e5ed2c37SJose E. Roman #endif
9551c0f0dcc3SMatthew G. Knepley 
9552c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
9553c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9554c0f0dcc3SMatthew G. Knepley #if defined(PETSC_USE_LOG)
9555c0f0dcc3SMatthew G. Knepley   ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr);
9556c0f0dcc3SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
9557c0f0dcc3SMatthew G. Knepley   ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr);
9558c0f0dcc3SMatthew G. Knepley   ierr = PetscLogGetStageLog(&stageLog);CHKERRQ(ierr);
9559c0f0dcc3SMatthew G. Knepley   ierr = PetscStageLogGetCurrent(stageLog, &stage);CHKERRQ(ierr);
9560c0f0dcc3SMatthew G. Knepley   ierr = PetscLogEventGetId("DMPlexResidualFE", &event);CHKERRQ(ierr);
9561c0f0dcc3SMatthew G. Knepley   ierr = PetscLogEventGetPerfInfo(stage, event, &eventInfo);CHKERRQ(ierr);
9562c0f0dcc3SMatthew G. Knepley   N        = (cEnd - cStart)*Nf*eventInfo.count;
9563c0f0dcc3SMatthew G. Knepley   flopRate = eventInfo.flops/eventInfo.time;
9564c0f0dcc3SMatthew G. Knepley   cellRate = N/eventInfo.time;
9565fae64647SBarry 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);
9566c0f0dcc3SMatthew G. Knepley #else
9567c0f0dcc3SMatthew G. Knepley   SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Plex Throughput Monitor is not supported if logging is turned off. Reconfigure using --with-log.");
9568c0f0dcc3SMatthew G. Knepley #endif
9569c0f0dcc3SMatthew G. Knepley   PetscFunctionReturn(0);
9570c0f0dcc3SMatthew G. Knepley }
9571