xref: /petsc/src/dm/impls/plex/plex.c (revision 695799ffa2f12317ee5880f0f106bd0968664309)
1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h>   /*I      "petscdmplex.h"   I*/
2*695799ffSMatthew G. Knepley #include <petsc/private/dmlabelimpl.h>
3af0996ceSBarry Smith #include <petsc/private/isimpl.h>
4e5c6e791SKarl Rupp #include <petsc/private/vecimpl.h>
58135c375SStefano Zampini #include <petsc/private/glvisvecimpl.h>
60c312b8eSJed Brown #include <petscsf.h>
7e228b242SToby Isaac #include <petscds.h>
8e412dcbdSMatthew G. Knepley #include <petscdraw.h>
9f19dbd58SToby Isaac #include <petscdmfield.h>
10012bc364SMatthew G. Knepley #include <petscdmplextransform.h>
11552f7358SJed Brown 
12552f7358SJed Brown /* Logging support */
1302f7d72cSksagiyam PetscLogEvent DMPLEX_Interpolate, DMPLEX_Partition, DMPLEX_Distribute, DMPLEX_DistributeCones, DMPLEX_DistributeLabels, DMPLEX_DistributeSF, DMPLEX_DistributeOverlap, DMPLEX_DistributeField, DMPLEX_DistributeData, DMPLEX_Migrate, DMPLEX_InterpolateSF, DMPLEX_GlobalToNaturalBegin, DMPLEX_GlobalToNaturalEnd, DMPLEX_NaturalToGlobalBegin, DMPLEX_NaturalToGlobalEnd, DMPLEX_Stratify, DMPLEX_Symmetrize, DMPLEX_Preallocate, DMPLEX_ResidualFEM, DMPLEX_JacobianFEM, DMPLEX_InterpolatorFEM, DMPLEX_InjectorFEM, DMPLEX_IntegralFEM, DMPLEX_CreateGmsh, DMPLEX_RebalanceSharedPoints, DMPLEX_PartSelf, DMPLEX_PartLabelInvert, DMPLEX_PartLabelCreateSF, DMPLEX_PartStratSF, DMPLEX_CreatePointSF,DMPLEX_LocatePoints,DMPLEX_TopologyView,DMPLEX_LabelsView,DMPLEX_CoordinatesView,DMPLEX_SectionView,DMPLEX_GlobalVectorView,DMPLEX_LocalVectorView,DMPLEX_TopologyLoad,DMPLEX_LabelsLoad,DMPLEX_CoordinatesLoad,DMPLEX_SectionLoad,DMPLEX_GlobalVectorLoad,DMPLEX_LocalVectorLoad;
14252a1336SBarry Smith PetscLogEvent DMPLEX_RebalBuildGraph,DMPLEX_RebalRewriteSF,DMPLEX_RebalGatherGraph, DMPLEX_RebalPartition, DMPLEX_RebalScatterPart;
15552f7358SJed Brown 
165a576424SJed Brown PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer);
17552f7358SJed Brown 
18e5337592SStefano Zampini /*@
199318fe57SMatthew G. Knepley   DMPlexIsSimplex - Is the first cell in this mesh a simplex?
209318fe57SMatthew G. Knepley 
219318fe57SMatthew G. Knepley   Input Parameter:
229318fe57SMatthew G. Knepley . dm      - The DMPlex object
239318fe57SMatthew G. Knepley 
249318fe57SMatthew G. Knepley   Output Parameter:
259318fe57SMatthew G. Knepley . simplex - Flag checking for a simplex
269318fe57SMatthew G. Knepley 
279318fe57SMatthew 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.
289318fe57SMatthew G. Knepley   If the mesh has no cells, this returns PETSC_FALSE.
299318fe57SMatthew G. Knepley 
309318fe57SMatthew G. Knepley   Level: intermediate
319318fe57SMatthew G. Knepley 
32db781477SPatrick Sanan .seealso `DMPlexGetSimplexOrBoxCells()`, `DMPlexGetCellType()`, `DMPlexGetHeightStratum()`, `DMPolytopeTypeGetNumVertices()`
339318fe57SMatthew G. Knepley @*/
349318fe57SMatthew G. Knepley PetscErrorCode DMPlexIsSimplex(DM dm, PetscBool *simplex)
359318fe57SMatthew G. Knepley {
369318fe57SMatthew G. Knepley   DMPolytopeType ct;
379318fe57SMatthew G. Knepley   PetscInt       cStart, cEnd;
389318fe57SMatthew G. Knepley 
399318fe57SMatthew G. Knepley   PetscFunctionBegin;
409566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
419318fe57SMatthew G. Knepley   if (cEnd <= cStart) {*simplex = PETSC_FALSE; PetscFunctionReturn(0);}
429566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cStart, &ct));
439318fe57SMatthew G. Knepley   *simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE;
449318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
459318fe57SMatthew G. Knepley }
469318fe57SMatthew G. Knepley 
479318fe57SMatthew G. Knepley /*@
48412e9a14SMatthew G. Knepley   DMPlexGetSimplexOrBoxCells - Get the range of cells which are neither prisms nor ghost FV cells
49e5337592SStefano Zampini 
50d8d19677SJose E. Roman   Input Parameters:
51412e9a14SMatthew G. Knepley + dm     - The DMPlex object
52412e9a14SMatthew G. Knepley - height - The cell height in the Plex, 0 is the default
53e5337592SStefano Zampini 
54e5337592SStefano Zampini   Output Parameters:
55412e9a14SMatthew G. Knepley + cStart - The first "normal" cell
56412e9a14SMatthew G. Knepley - cEnd   - The upper bound on "normal"" cells
57e5337592SStefano Zampini 
58412e9a14SMatthew 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.
59e5337592SStefano Zampini 
60412e9a14SMatthew G. Knepley   Level: developer
61e5337592SStefano Zampini 
62db781477SPatrick Sanan .seealso `DMPlexConstructGhostCells()`, `DMPlexGetGhostCellStratum()`
63e5337592SStefano Zampini @*/
64412e9a14SMatthew G. Knepley PetscErrorCode DMPlexGetSimplexOrBoxCells(DM dm, PetscInt height, PetscInt *cStart, PetscInt *cEnd)
65e5337592SStefano Zampini {
66412e9a14SMatthew G. Knepley   DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
67412e9a14SMatthew G. Knepley   PetscInt       cS, cE, c;
68e5337592SStefano Zampini 
69e5337592SStefano Zampini   PetscFunctionBegin;
709566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, PetscMax(height, 0), &cS, &cE));
71412e9a14SMatthew G. Knepley   for (c = cS; c < cE; ++c) {
72412e9a14SMatthew G. Knepley     DMPolytopeType cct;
73412e9a14SMatthew G. Knepley 
749566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &cct));
75412e9a14SMatthew G. Knepley     if ((PetscInt) cct < 0) break;
76412e9a14SMatthew G. Knepley     switch (cct) {
77ba2698f1SMatthew G. Knepley       case DM_POLYTOPE_POINT:
78ba2698f1SMatthew G. Knepley       case DM_POLYTOPE_SEGMENT:
79ba2698f1SMatthew G. Knepley       case DM_POLYTOPE_TRIANGLE:
80ba2698f1SMatthew G. Knepley       case DM_POLYTOPE_QUADRILATERAL:
81ba2698f1SMatthew G. Knepley       case DM_POLYTOPE_TETRAHEDRON:
82ba2698f1SMatthew G. Knepley       case DM_POLYTOPE_HEXAHEDRON:
83412e9a14SMatthew G. Knepley         ct = cct;
84e5337592SStefano Zampini         break;
85412e9a14SMatthew G. Knepley       default: break;
86e5337592SStefano Zampini     }
87412e9a14SMatthew G. Knepley     if (ct != DM_POLYTOPE_UNKNOWN) break;
88e5337592SStefano Zampini   }
89412e9a14SMatthew G. Knepley   if (ct != DM_POLYTOPE_UNKNOWN) {
90412e9a14SMatthew G. Knepley     DMLabel ctLabel;
91412e9a14SMatthew G. Knepley 
929566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel));
939566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumBounds(ctLabel, ct, &cS, &cE));
94*695799ffSMatthew G. Knepley     // Reset label for fast lookup
95*695799ffSMatthew G. Knepley     PetscCall(DMLabelMakeAllInvalid_Internal(ctLabel));
96e5337592SStefano Zampini   }
97412e9a14SMatthew G. Knepley   if (cStart) *cStart = cS;
98412e9a14SMatthew G. Knepley   if (cEnd)   *cEnd   = cE;
99e5337592SStefano Zampini   PetscFunctionReturn(0);
100e5337592SStefano Zampini }
101e5337592SStefano Zampini 
1027afe7537SMatthew G. Knepley PetscErrorCode DMPlexGetFieldType_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *sStart, PetscInt *sEnd, PetscViewerVTKFieldType *ft)
1037e42fee7SMatthew G. Knepley {
104412e9a14SMatthew G. Knepley   PetscInt       cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd;
105a99a26bcSAdrian Croucher   PetscInt       vcdof[2] = {0,0}, globalvcdof[2];
1067e42fee7SMatthew G. Knepley 
1077e42fee7SMatthew G. Knepley   PetscFunctionBegin;
108e630c359SToby Isaac   *ft  = PETSC_VTK_INVALID;
1099566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
1109566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
1119566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd));
1129566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
1137e42fee7SMatthew G. Knepley   if (field >= 0) {
1149566063dSJacob Faibussowitsch     if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, vStart, field, &vcdof[0]));
1159566063dSJacob Faibussowitsch     if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, cStart, field, &vcdof[1]));
1167e42fee7SMatthew G. Knepley   } else {
1179566063dSJacob Faibussowitsch     if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetDof(section, vStart, &vcdof[0]));
1189566063dSJacob Faibussowitsch     if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetDof(section, cStart, &vcdof[1]));
1197e42fee7SMatthew G. Knepley   }
1209566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allreduce(vcdof, globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
121a99a26bcSAdrian Croucher   if (globalvcdof[0]) {
1227e42fee7SMatthew G. Knepley     *sStart = vStart;
1237e42fee7SMatthew G. Knepley     *sEnd   = vEnd;
124f094498dSMatthew G. Knepley     if (globalvcdof[0] == cdim) *ft = PETSC_VTK_POINT_VECTOR_FIELD;
1257e42fee7SMatthew G. Knepley     else                        *ft = PETSC_VTK_POINT_FIELD;
126a99a26bcSAdrian Croucher   } else if (globalvcdof[1]) {
1277e42fee7SMatthew G. Knepley     *sStart = cStart;
1287e42fee7SMatthew G. Knepley     *sEnd   = cEnd;
129f094498dSMatthew G. Knepley     if (globalvcdof[1] == cdim) *ft = PETSC_VTK_CELL_VECTOR_FIELD;
1307e42fee7SMatthew G. Knepley     else                        *ft = PETSC_VTK_CELL_FIELD;
131e630c359SToby Isaac   } else {
132e630c359SToby Isaac     if (field >= 0) {
133e630c359SToby Isaac       const char *fieldname;
134e630c359SToby Isaac 
1359566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldName(section, field, &fieldname));
13663a3b9bcSJacob Faibussowitsch       PetscCall(PetscInfo((PetscObject) dm, "Could not classify VTK output type of section field %" PetscInt_FMT " \"%s\"\n", field, fieldname));
137e630c359SToby Isaac     } else {
13863a3b9bcSJacob Faibussowitsch       PetscCall(PetscInfo((PetscObject) dm, "Could not classify VTK output type of section\n"));
139e630c359SToby Isaac     }
140e630c359SToby Isaac   }
1417e42fee7SMatthew G. Knepley   PetscFunctionReturn(0);
1427e42fee7SMatthew G. Knepley }
1437e42fee7SMatthew G. Knepley 
1446913077dSMatthew G. Knepley /*@
1456913077dSMatthew G. Knepley   DMPlexVecView1D - Plot many 1D solutions on the same line graph
1466913077dSMatthew G. Knepley 
1476913077dSMatthew G. Knepley   Collective on dm
1486913077dSMatthew G. Knepley 
1496913077dSMatthew G. Knepley   Input Parameters:
1506913077dSMatthew G. Knepley + dm - The DMPlex
1516913077dSMatthew G. Knepley . n  - The number of vectors
1526913077dSMatthew G. Knepley . u  - The array of local vectors
1536913077dSMatthew G. Knepley - viewer - The Draw viewer
1546913077dSMatthew G. Knepley 
1556913077dSMatthew G. Knepley   Level: advanced
1566913077dSMatthew G. Knepley 
157db781477SPatrick Sanan .seealso: `VecViewFromOptions()`, `VecView()`
1586913077dSMatthew G. Knepley @*/
1596913077dSMatthew G. Knepley PetscErrorCode DMPlexVecView1D(DM dm, PetscInt n, Vec u[], PetscViewer viewer)
1606913077dSMatthew G. Knepley {
1616913077dSMatthew G. Knepley   PetscDS            ds;
1626913077dSMatthew G. Knepley   PetscDraw          draw = NULL;
1636913077dSMatthew G. Knepley   PetscDrawLG        lg;
1646913077dSMatthew G. Knepley   Vec                coordinates;
1656913077dSMatthew G. Knepley   const PetscScalar *coords, **sol;
1666913077dSMatthew G. Knepley   PetscReal         *vals;
1676913077dSMatthew G. Knepley   PetscInt          *Nc;
1686913077dSMatthew G. Knepley   PetscInt           Nf, f, c, Nl, l, i, vStart, vEnd, v;
1696913077dSMatthew G. Knepley   char             **names;
1706913077dSMatthew G. Knepley 
1716913077dSMatthew G. Knepley   PetscFunctionBegin;
1729566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &ds));
1739566063dSJacob Faibussowitsch   PetscCall(PetscDSGetNumFields(ds, &Nf));
1749566063dSJacob Faibussowitsch   PetscCall(PetscDSGetTotalComponents(ds, &Nl));
1759566063dSJacob Faibussowitsch   PetscCall(PetscDSGetComponents(ds, &Nc));
1766913077dSMatthew G. Knepley 
1779566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
1786913077dSMatthew G. Knepley   if (!draw) PetscFunctionReturn(0);
1799566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGCreate(draw, n*Nl, &lg));
1806913077dSMatthew G. Knepley 
1819566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(n, &sol, n*Nl, &names, n*Nl, &vals));
1826913077dSMatthew G. Knepley   for (i = 0, l = 0; i < n; ++i) {
1836913077dSMatthew G. Knepley     const char *vname;
1846913077dSMatthew G. Knepley 
1859566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject) u[i], &vname));
1866913077dSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
1876913077dSMatthew G. Knepley       PetscObject disc;
1886913077dSMatthew G. Knepley       const char *fname;
1896913077dSMatthew G. Knepley       char        tmpname[PETSC_MAX_PATH_LEN];
1906913077dSMatthew G. Knepley 
1919566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(ds, f, &disc));
1926913077dSMatthew G. Knepley       /* TODO Create names for components */
1936913077dSMatthew G. Knepley       for (c = 0; c < Nc[f]; ++c, ++l) {
1949566063dSJacob Faibussowitsch         PetscCall(PetscObjectGetName(disc, &fname));
1959566063dSJacob Faibussowitsch         PetscCall(PetscStrcpy(tmpname, vname));
1969566063dSJacob Faibussowitsch         PetscCall(PetscStrlcat(tmpname, ":", PETSC_MAX_PATH_LEN));
1979566063dSJacob Faibussowitsch         PetscCall(PetscStrlcat(tmpname, fname, PETSC_MAX_PATH_LEN));
1989566063dSJacob Faibussowitsch         PetscCall(PetscStrallocpy(tmpname, &names[l]));
1996913077dSMatthew G. Knepley       }
2006913077dSMatthew G. Knepley     }
2016913077dSMatthew G. Knepley   }
2029566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGSetLegend(lg, (const char *const *) names));
2036913077dSMatthew G. Knepley   /* Just add P_1 support for now */
2049566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
2059566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
2069566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(coordinates, &coords));
2079566063dSJacob Faibussowitsch   for (i = 0; i < n; ++i) PetscCall(VecGetArrayRead(u[i], &sol[i]));
2086913077dSMatthew G. Knepley   for (v = vStart; v < vEnd; ++v) {
2096913077dSMatthew G. Knepley     PetscScalar *x, *svals;
2106913077dSMatthew G. Knepley 
2119566063dSJacob Faibussowitsch     PetscCall(DMPlexPointLocalRead(dm, v, coords, &x));
2126913077dSMatthew G. Knepley     for (i = 0; i < n; ++i) {
2139566063dSJacob Faibussowitsch       PetscCall(DMPlexPointLocalRead(dm, v, sol[i], &svals));
2146913077dSMatthew G. Knepley       for (l = 0; l < Nl; ++l) vals[i*Nl + l] = PetscRealPart(svals[l]);
2156913077dSMatthew G. Knepley     }
2169566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGAddCommonPoint(lg, PetscRealPart(x[0]), vals));
2176913077dSMatthew G. Knepley   }
2189566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(coordinates, &coords));
2199566063dSJacob Faibussowitsch   for (i = 0; i < n; ++i) PetscCall(VecRestoreArrayRead(u[i], &sol[i]));
2209566063dSJacob Faibussowitsch   for (l = 0; l < n*Nl; ++l) PetscCall(PetscFree(names[l]));
2219566063dSJacob Faibussowitsch   PetscCall(PetscFree3(sol, names, vals));
2226913077dSMatthew G. Knepley 
2239566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGDraw(lg));
2249566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGDestroy(&lg));
2256913077dSMatthew G. Knepley   PetscFunctionReturn(0);
2266913077dSMatthew G. Knepley }
2276913077dSMatthew G. Knepley 
2286913077dSMatthew G. Knepley static PetscErrorCode VecView_Plex_Local_Draw_1D(Vec u, PetscViewer viewer)
2296913077dSMatthew G. Knepley {
2306913077dSMatthew G. Knepley   DM             dm;
2316913077dSMatthew G. Knepley 
2326913077dSMatthew G. Knepley   PetscFunctionBegin;
2339566063dSJacob Faibussowitsch   PetscCall(VecGetDM(u, &dm));
2349566063dSJacob Faibussowitsch   PetscCall(DMPlexVecView1D(dm, 1, &u, viewer));
2356913077dSMatthew G. Knepley   PetscFunctionReturn(0);
2366913077dSMatthew G. Knepley }
2376913077dSMatthew G. Knepley 
2386913077dSMatthew G. Knepley static PetscErrorCode VecView_Plex_Local_Draw_2D(Vec v, PetscViewer viewer)
239e412dcbdSMatthew G. Knepley {
240e412dcbdSMatthew G. Knepley   DM                 dm;
241d1df6f1dSMatthew G. Knepley   PetscSection       s;
242e412dcbdSMatthew G. Knepley   PetscDraw          draw, popup;
243e412dcbdSMatthew G. Knepley   DM                 cdm;
244e412dcbdSMatthew G. Knepley   PetscSection       coordSection;
245e412dcbdSMatthew G. Knepley   Vec                coordinates;
246e412dcbdSMatthew G. Knepley   const PetscScalar *coords, *array;
247e412dcbdSMatthew G. Knepley   PetscReal          bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL};
248339e3443SMatthew G. Knepley   PetscReal          vbound[2], time;
2496913077dSMatthew G. Knepley   PetscBool          flg;
250d1df6f1dSMatthew G. Knepley   PetscInt           dim, Nf, f, Nc, comp, vStart, vEnd, cStart, cEnd, c, N, level, step, w = 0;
251e412dcbdSMatthew G. Knepley   const char        *name;
252339e3443SMatthew G. Knepley   char               title[PETSC_MAX_PATH_LEN];
253e412dcbdSMatthew G. Knepley 
254e412dcbdSMatthew G. Knepley   PetscFunctionBegin;
2559566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
2569566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
2579566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dim));
2589566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &s));
2599566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(s, &Nf));
2609566063dSJacob Faibussowitsch   PetscCall(DMGetCoarsenLevel(dm, &level));
2619566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
2629566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(cdm, &coordSection));
2639566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
2649566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
2659566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
266e412dcbdSMatthew G. Knepley 
2679566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject) v, &name));
2689566063dSJacob Faibussowitsch   PetscCall(DMGetOutputSequenceNumber(dm, &step, &time));
269e412dcbdSMatthew G. Knepley 
2709566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(coordinates, &N));
2719566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(coordinates, &coords));
272e412dcbdSMatthew G. Knepley   for (c = 0; c < N; c += dim) {
2730c81f2a8SMatthew G. Knepley     bound[0] = PetscMin(bound[0], PetscRealPart(coords[c]));   bound[2] = PetscMax(bound[2], PetscRealPart(coords[c]));
2740c81f2a8SMatthew G. Knepley     bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1]));
275e412dcbdSMatthew G. Knepley   }
2769566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(coordinates, &coords));
2779566063dSJacob Faibussowitsch   PetscCall(PetscDrawClear(draw));
278e412dcbdSMatthew G. Knepley 
279d1df6f1dSMatthew G. Knepley   /* Could implement something like DMDASelectFields() */
280d1df6f1dSMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
281d1df6f1dSMatthew G. Knepley     DM   fdm = dm;
282d1df6f1dSMatthew G. Knepley     Vec  fv  = v;
283d1df6f1dSMatthew G. Knepley     IS   fis;
284d1df6f1dSMatthew G. Knepley     char prefix[PETSC_MAX_PATH_LEN];
285d1df6f1dSMatthew G. Knepley     const char *fname;
286d1df6f1dSMatthew G. Knepley 
2879566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldComponents(s, f, &Nc));
2889566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldName(s, f, &fname));
289d1df6f1dSMatthew G. Knepley 
2909566063dSJacob Faibussowitsch     if (v->hdr.prefix) PetscCall(PetscStrncpy(prefix, v->hdr.prefix,sizeof(prefix)));
291d1df6f1dSMatthew G. Knepley     else               {prefix[0] = '\0';}
292d1df6f1dSMatthew G. Knepley     if (Nf > 1) {
2939566063dSJacob Faibussowitsch       PetscCall(DMCreateSubDM(dm, 1, &f, &fis, &fdm));
2949566063dSJacob Faibussowitsch       PetscCall(VecGetSubVector(v, fis, &fv));
2959566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(prefix, fname,sizeof(prefix)));
2969566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(prefix, "_",sizeof(prefix)));
297d1df6f1dSMatthew G. Knepley     }
298d1df6f1dSMatthew G. Knepley     for (comp = 0; comp < Nc; ++comp, ++w) {
299d1df6f1dSMatthew G. Knepley       PetscInt nmax = 2;
300d1df6f1dSMatthew G. Knepley 
3019566063dSJacob Faibussowitsch       PetscCall(PetscViewerDrawGetDraw(viewer, w, &draw));
30263a3b9bcSJacob Faibussowitsch       if (Nc > 1) PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s_%" PetscInt_FMT " Step: %" PetscInt_FMT " Time: %.4g", name, fname, comp, step, (double)time));
30363a3b9bcSJacob Faibussowitsch       else        PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s Step: %" PetscInt_FMT " Time: %.4g", name, fname, step, (double)time));
3049566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetTitle(draw, title));
305d1df6f1dSMatthew G. Knepley 
306d1df6f1dSMatthew G. Knepley       /* TODO Get max and min only for this component */
3079566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetRealArray(NULL, prefix, "-vec_view_bounds", vbound, &nmax, &flg));
308339e3443SMatthew G. Knepley       if (!flg) {
3099566063dSJacob Faibussowitsch         PetscCall(VecMin(fv, NULL, &vbound[0]));
3109566063dSJacob Faibussowitsch         PetscCall(VecMax(fv, NULL, &vbound[1]));
311d1df6f1dSMatthew G. Knepley         if (vbound[1] <= vbound[0]) vbound[1] = vbound[0] + 1.0;
312339e3443SMatthew G. Knepley       }
3139566063dSJacob Faibussowitsch       PetscCall(PetscDrawGetPopup(draw, &popup));
3149566063dSJacob Faibussowitsch       PetscCall(PetscDrawScalePopup(popup, vbound[0], vbound[1]));
3159566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetCoordinates(draw, bound[0], bound[1], bound[2], bound[3]));
316e412dcbdSMatthew G. Knepley 
3179566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(fv, &array));
318e412dcbdSMatthew G. Knepley       for (c = cStart; c < cEnd; ++c) {
31999a2f7bcSMatthew G. Knepley         PetscScalar *coords = NULL, *a = NULL;
320e56f9228SJed Brown         PetscInt     numCoords, color[4] = {-1,-1,-1,-1};
321e412dcbdSMatthew G. Knepley 
3229566063dSJacob Faibussowitsch         PetscCall(DMPlexPointLocalRead(fdm, c, array, &a));
323339e3443SMatthew G. Knepley         if (a) {
324d1df6f1dSMatthew G. Knepley           color[0] = PetscDrawRealToColor(PetscRealPart(a[comp]), vbound[0], vbound[1]);
325339e3443SMatthew G. Knepley           color[1] = color[2] = color[3] = color[0];
326339e3443SMatthew G. Knepley         } else {
327339e3443SMatthew G. Knepley           PetscScalar *vals = NULL;
328339e3443SMatthew G. Knepley           PetscInt     numVals, va;
329339e3443SMatthew G. Knepley 
3309566063dSJacob Faibussowitsch           PetscCall(DMPlexVecGetClosure(fdm, NULL, fv, c, &numVals, &vals));
33163a3b9bcSJacob Faibussowitsch           PetscCheck(numVals % Nc == 0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The number of components %" PetscInt_FMT " does not divide the number of values in the closure %" PetscInt_FMT, Nc, numVals);
332d1df6f1dSMatthew G. Knepley           switch (numVals/Nc) {
333d1df6f1dSMatthew G. Knepley           case 3: /* P1 Triangle */
334d1df6f1dSMatthew G. Knepley           case 4: /* P1 Quadrangle */
335d1df6f1dSMatthew G. Knepley             for (va = 0; va < numVals/Nc; ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va*Nc+comp]), vbound[0], vbound[1]);
336339e3443SMatthew G. Knepley             break;
337d1df6f1dSMatthew G. Knepley           case 6: /* P2 Triangle */
338d1df6f1dSMatthew G. Knepley           case 8: /* P2 Quadrangle */
339d1df6f1dSMatthew 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]);
340d1df6f1dSMatthew G. Knepley             break;
34163a3b9bcSJacob Faibussowitsch           default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of values for cell closure %" PetscInt_FMT " cannot be handled", numVals/Nc);
342339e3443SMatthew G. Knepley           }
3439566063dSJacob Faibussowitsch           PetscCall(DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals));
344339e3443SMatthew G. Knepley         }
3459566063dSJacob Faibussowitsch         PetscCall(DMPlexVecGetClosure(dm, coordSection, coordinates, c, &numCoords, &coords));
346e412dcbdSMatthew G. Knepley         switch (numCoords) {
347e412dcbdSMatthew G. Knepley         case 6:
3489edc3542SMatthew Knepley         case 12: /* Localized triangle */
3499566063dSJacob Faibussowitsch           PetscCall(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]));
350e412dcbdSMatthew G. Knepley           break;
351e412dcbdSMatthew G. Knepley         case 8:
3529edc3542SMatthew Knepley         case 16: /* Localized quadrilateral */
3539566063dSJacob Faibussowitsch           PetscCall(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]));
3549566063dSJacob Faibussowitsch           PetscCall(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]));
355e412dcbdSMatthew G. Knepley           break;
35663a3b9bcSJacob Faibussowitsch         default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %" PetscInt_FMT " coordinates", numCoords);
357e412dcbdSMatthew G. Knepley         }
3589566063dSJacob Faibussowitsch         PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords));
359e412dcbdSMatthew G. Knepley       }
3609566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(fv, &array));
3619566063dSJacob Faibussowitsch       PetscCall(PetscDrawFlush(draw));
3629566063dSJacob Faibussowitsch       PetscCall(PetscDrawPause(draw));
3639566063dSJacob Faibussowitsch       PetscCall(PetscDrawSave(draw));
364d1df6f1dSMatthew G. Knepley     }
365d1df6f1dSMatthew G. Knepley     if (Nf > 1) {
3669566063dSJacob Faibussowitsch       PetscCall(VecRestoreSubVector(v, fis, &fv));
3679566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&fis));
3689566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&fdm));
369d1df6f1dSMatthew G. Knepley     }
370d1df6f1dSMatthew G. Knepley   }
371e412dcbdSMatthew G. Knepley   PetscFunctionReturn(0);
372e412dcbdSMatthew G. Knepley }
373e412dcbdSMatthew G. Knepley 
3746913077dSMatthew G. Knepley static PetscErrorCode VecView_Plex_Local_Draw(Vec v, PetscViewer viewer)
3756913077dSMatthew G. Knepley {
3766913077dSMatthew G. Knepley   DM        dm;
3776913077dSMatthew G. Knepley   PetscDraw draw;
3786913077dSMatthew G. Knepley   PetscInt  dim;
3796913077dSMatthew G. Knepley   PetscBool isnull;
3806913077dSMatthew G. Knepley 
3816913077dSMatthew G. Knepley   PetscFunctionBegin;
3829566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
3839566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
3846913077dSMatthew G. Knepley   if (isnull) PetscFunctionReturn(0);
3856913077dSMatthew G. Knepley 
3869566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
3879566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dim));
3886913077dSMatthew G. Knepley   switch (dim) {
3899566063dSJacob Faibussowitsch   case 1: PetscCall(VecView_Plex_Local_Draw_1D(v, viewer));break;
3909566063dSJacob Faibussowitsch   case 2: PetscCall(VecView_Plex_Local_Draw_2D(v, viewer));break;
3915f80ce2aSJacob Faibussowitsch   default: SETERRQ(PetscObjectComm((PetscObject) v), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT ". Try PETSCVIEWERGLVIS", dim);
3926913077dSMatthew G. Knepley   }
3936913077dSMatthew G. Knepley   PetscFunctionReturn(0);
3946913077dSMatthew G. Knepley }
3956913077dSMatthew G. Knepley 
396684b87d9SLisandro Dalcin static PetscErrorCode VecView_Plex_Local_VTK(Vec v, PetscViewer viewer)
397684b87d9SLisandro Dalcin {
398684b87d9SLisandro Dalcin   DM                      dm;
399684b87d9SLisandro Dalcin   Vec                     locv;
400684b87d9SLisandro Dalcin   const char              *name;
401684b87d9SLisandro Dalcin   PetscSection            section;
402684b87d9SLisandro Dalcin   PetscInt                pStart, pEnd;
403e630c359SToby Isaac   PetscInt                numFields;
404684b87d9SLisandro Dalcin   PetscViewerVTKFieldType ft;
405684b87d9SLisandro Dalcin 
406684b87d9SLisandro Dalcin   PetscFunctionBegin;
4079566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
4089566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dm, &locv)); /* VTK viewer requires exclusive ownership of the vector */
4099566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject) v, &name));
4109566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject) locv, name));
4119566063dSJacob Faibussowitsch   PetscCall(VecCopy(v, locv));
4129566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
4139566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
414e630c359SToby Isaac   if (!numFields) {
4159566063dSJacob Faibussowitsch     PetscCall(DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft));
4169566063dSJacob Faibussowitsch     PetscCall(PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, PETSC_TRUE,(PetscObject) locv));
417e630c359SToby Isaac   } else {
418e630c359SToby Isaac     PetscInt f;
419e630c359SToby Isaac 
420e630c359SToby Isaac     for (f = 0; f < numFields; f++) {
4219566063dSJacob Faibussowitsch       PetscCall(DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft));
422e630c359SToby Isaac       if (ft == PETSC_VTK_INVALID) continue;
4239566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)locv));
4249566063dSJacob Faibussowitsch       PetscCall(PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE,(PetscObject) locv));
425e630c359SToby Isaac     }
4269566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&locv));
427e630c359SToby Isaac   }
428684b87d9SLisandro Dalcin   PetscFunctionReturn(0);
429684b87d9SLisandro Dalcin }
430684b87d9SLisandro Dalcin 
431552f7358SJed Brown PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer)
432552f7358SJed Brown {
433552f7358SJed Brown   DM             dm;
434684b87d9SLisandro Dalcin   PetscBool      isvtk, ishdf5, isdraw, isglvis;
435552f7358SJed Brown 
436552f7358SJed Brown   PetscFunctionBegin;
4379566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
43828b400f6SJacob Faibussowitsch   PetscCheck(dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
4399566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK,   &isvtk));
4409566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,  &ishdf5));
4419566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW,  &isdraw));
4429566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis));
443684b87d9SLisandro Dalcin   if (isvtk || ishdf5 || isdraw || isglvis) {
444684b87d9SLisandro Dalcin     PetscInt    i,numFields;
445684b87d9SLisandro Dalcin     PetscObject fe;
446ef31f671SMatthew G. Knepley     PetscBool   fem = PETSC_FALSE;
447684b87d9SLisandro Dalcin     Vec         locv = v;
448684b87d9SLisandro Dalcin     const char  *name;
449684b87d9SLisandro Dalcin     PetscInt    step;
450684b87d9SLisandro Dalcin     PetscReal   time;
451ef31f671SMatthew G. Knepley 
4529566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &numFields));
453684b87d9SLisandro Dalcin     for (i=0; i<numFields; i++) {
4549566063dSJacob Faibussowitsch       PetscCall(DMGetField(dm, i, NULL, &fe));
455684b87d9SLisandro Dalcin       if (fe->classid == PETSCFE_CLASSID) { fem = PETSC_TRUE; break; }
456ef31f671SMatthew G. Knepley     }
457684b87d9SLisandro Dalcin     if (fem) {
458798534f6SMatthew G. Knepley       PetscObject isZero;
459798534f6SMatthew G. Knepley 
4609566063dSJacob Faibussowitsch       PetscCall(DMGetLocalVector(dm, &locv));
4619566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject) v, &name));
4629566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject) locv, name));
4639566063dSJacob Faibussowitsch       PetscCall(PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero));
4649566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero));
4659566063dSJacob Faibussowitsch       PetscCall(VecCopy(v, locv));
4669566063dSJacob Faibussowitsch       PetscCall(DMGetOutputSequenceNumber(dm, NULL, &time));
4679566063dSJacob Faibussowitsch       PetscCall(DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL));
468ef31f671SMatthew G. Knepley     }
469552f7358SJed Brown     if (isvtk) {
4709566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_VTK(locv, viewer));
471b136c2c9SMatthew G. Knepley     } else if (ishdf5) {
472b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
4739566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_HDF5_Internal(locv, viewer));
474b136c2c9SMatthew G. Knepley #else
475b136c2c9SMatthew G. Knepley       SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
476b136c2c9SMatthew G. Knepley #endif
477f13a32a3SMatthew G. Knepley     } else if (isdraw) {
4789566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_Draw(locv, viewer));
479684b87d9SLisandro Dalcin     } else if (isglvis) {
4809566063dSJacob Faibussowitsch       PetscCall(DMGetOutputSequenceNumber(dm, &step, NULL));
4819566063dSJacob Faibussowitsch       PetscCall(PetscViewerGLVisSetSnapId(viewer, step));
4829566063dSJacob Faibussowitsch       PetscCall(VecView_GLVis(locv, viewer));
483684b87d9SLisandro Dalcin     }
484798534f6SMatthew G. Knepley     if (fem) {
4859566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL));
4869566063dSJacob Faibussowitsch       PetscCall(DMRestoreLocalVector(dm, &locv));
487798534f6SMatthew G. Knepley     }
488552f7358SJed Brown   } else {
489684b87d9SLisandro Dalcin     PetscBool isseq;
490684b87d9SLisandro Dalcin 
4919566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq));
4929566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
4939566063dSJacob Faibussowitsch     else       PetscCall(VecView_MPI(v, viewer));
494552f7358SJed Brown   }
495552f7358SJed Brown   PetscFunctionReturn(0);
496552f7358SJed Brown }
497552f7358SJed Brown 
498552f7358SJed Brown PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer)
499552f7358SJed Brown {
500552f7358SJed Brown   DM        dm;
5016823f3c5SBlaise Bourdin   PetscBool isvtk, ishdf5, isdraw, isglvis, isexodusii;
502552f7358SJed Brown 
503552f7358SJed Brown   PetscFunctionBegin;
5049566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
50528b400f6SJacob Faibussowitsch   PetscCheck(dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
5069566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK,      &isvtk));
5079566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,     &ishdf5));
5089566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW,     &isdraw));
5099566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS,    &isglvis));
5109566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii));
511684b87d9SLisandro Dalcin   if (isvtk || isdraw || isglvis) {
512552f7358SJed Brown     Vec         locv;
513798534f6SMatthew G. Knepley     PetscObject isZero;
514552f7358SJed Brown     const char *name;
515552f7358SJed Brown 
5169566063dSJacob Faibussowitsch     PetscCall(DMGetLocalVector(dm, &locv));
5179566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject) v, &name));
5189566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject) locv, name));
5199566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv));
5209566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv));
5219566063dSJacob Faibussowitsch     PetscCall(PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero));
5229566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero));
5239566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_Local(locv, viewer));
5249566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL));
5259566063dSJacob Faibussowitsch     PetscCall(DMRestoreLocalVector(dm, &locv));
526b136c2c9SMatthew G. Knepley   } else if (ishdf5) {
527b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
5289566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_HDF5_Internal(v, viewer));
529b136c2c9SMatthew G. Knepley #else
530b136c2c9SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
531b136c2c9SMatthew G. Knepley #endif
5326823f3c5SBlaise Bourdin   } else if (isexodusii) {
5336823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII)
5349566063dSJacob Faibussowitsch     PetscCall(VecView_PlexExodusII_Internal(v, viewer));
5356823f3c5SBlaise Bourdin #else
5366823f3c5SBlaise Bourdin     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii");
5376823f3c5SBlaise Bourdin #endif
538552f7358SJed Brown   } else {
539684b87d9SLisandro Dalcin     PetscBool isseq;
540684b87d9SLisandro Dalcin 
5419566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq));
5429566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
5439566063dSJacob Faibussowitsch     else       PetscCall(VecView_MPI(v, viewer));
544552f7358SJed Brown   }
545552f7358SJed Brown   PetscFunctionReturn(0);
546552f7358SJed Brown }
547552f7358SJed Brown 
548d930f514SMatthew G. Knepley PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer)
549d930f514SMatthew G. Knepley {
550d930f514SMatthew G. Knepley   DM                dm;
551d930f514SMatthew G. Knepley   MPI_Comm          comm;
552d930f514SMatthew G. Knepley   PetscViewerFormat format;
553d930f514SMatthew G. Knepley   Vec               v;
554d930f514SMatthew G. Knepley   PetscBool         isvtk, ishdf5;
555d930f514SMatthew G. Knepley 
556d930f514SMatthew G. Knepley   PetscFunctionBegin;
5579566063dSJacob Faibussowitsch   PetscCall(VecGetDM(originalv, &dm));
5589566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject) originalv, &comm));
55928b400f6SJacob Faibussowitsch   PetscCheck(dm,comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
5609566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
5619566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
5629566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK,  &isvtk));
563d930f514SMatthew G. Knepley   if (format == PETSC_VIEWER_NATIVE) {
564a8ad634aSStefano Zampini     /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */
565a8ad634aSStefano Zampini     /* this need a better fix */
566a8ad634aSStefano Zampini     if (dm->useNatural) {
567a8ad634aSStefano Zampini       if (dm->sfNatural) {
568d930f514SMatthew G. Knepley         const char *vecname;
569d930f514SMatthew G. Knepley         PetscInt    n, nroots;
570d930f514SMatthew G. Knepley 
5719566063dSJacob Faibussowitsch         PetscCall(VecGetLocalSize(originalv, &n));
5729566063dSJacob Faibussowitsch         PetscCall(PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL));
573d930f514SMatthew G. Knepley         if (n == nroots) {
5749566063dSJacob Faibussowitsch           PetscCall(DMGetGlobalVector(dm, &v));
5759566063dSJacob Faibussowitsch           PetscCall(DMPlexGlobalToNaturalBegin(dm, originalv, v));
5769566063dSJacob Faibussowitsch           PetscCall(DMPlexGlobalToNaturalEnd(dm, originalv, v));
5779566063dSJacob Faibussowitsch           PetscCall(PetscObjectGetName((PetscObject) originalv, &vecname));
5789566063dSJacob Faibussowitsch           PetscCall(PetscObjectSetName((PetscObject) v, vecname));
579d930f514SMatthew G. Knepley         } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors");
580d930f514SMatthew G. Knepley       } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created");
581a8ad634aSStefano Zampini     } else v = originalv;
582a8ad634aSStefano Zampini   } else v = originalv;
583a8ad634aSStefano Zampini 
584d930f514SMatthew G. Knepley   if (ishdf5) {
585d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
5869566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_HDF5_Native_Internal(v, viewer));
587d930f514SMatthew G. Knepley #else
588d930f514SMatthew G. Knepley     SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
589d930f514SMatthew G. Knepley #endif
590d930f514SMatthew G. Knepley   } else if (isvtk) {
591d930f514SMatthew G. Knepley     SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5.");
592d930f514SMatthew G. Knepley   } else {
593d930f514SMatthew G. Knepley     PetscBool isseq;
594d930f514SMatthew G. Knepley 
5959566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq));
5969566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
5979566063dSJacob Faibussowitsch     else       PetscCall(VecView_MPI(v, viewer));
598d930f514SMatthew G. Knepley   }
5999566063dSJacob Faibussowitsch   if (v != originalv) PetscCall(DMRestoreGlobalVector(dm, &v));
600d930f514SMatthew G. Knepley   PetscFunctionReturn(0);
601d930f514SMatthew G. Knepley }
602d930f514SMatthew G. Knepley 
6032c40f234SMatthew G. Knepley PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer)
6042c40f234SMatthew G. Knepley {
6052c40f234SMatthew G. Knepley   DM             dm;
6062c40f234SMatthew G. Knepley   PetscBool      ishdf5;
6072c40f234SMatthew G. Knepley 
6082c40f234SMatthew G. Knepley   PetscFunctionBegin;
6099566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
61028b400f6SJacob Faibussowitsch   PetscCheck(dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
6119566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
6122c40f234SMatthew G. Knepley   if (ishdf5) {
6132c40f234SMatthew G. Knepley     DM          dmBC;
6142c40f234SMatthew G. Knepley     Vec         gv;
6152c40f234SMatthew G. Knepley     const char *name;
6162c40f234SMatthew G. Knepley 
6179566063dSJacob Faibussowitsch     PetscCall(DMGetOutputDM(dm, &dmBC));
6189566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalVector(dmBC, &gv));
6199566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject) v, &name));
6209566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject) gv, name));
6219566063dSJacob Faibussowitsch     PetscCall(VecLoad_Default(gv, viewer));
6229566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v));
6239566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v));
6249566063dSJacob Faibussowitsch     PetscCall(DMRestoreGlobalVector(dmBC, &gv));
6251baa6e33SBarry Smith   } else PetscCall(VecLoad_Default(v, viewer));
6262c40f234SMatthew G. Knepley   PetscFunctionReturn(0);
6272c40f234SMatthew G. Knepley }
6282c40f234SMatthew G. Knepley 
6292c40f234SMatthew G. Knepley PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer)
6302c40f234SMatthew G. Knepley {
6312c40f234SMatthew G. Knepley   DM             dm;
6326823f3c5SBlaise Bourdin   PetscBool      ishdf5,isexodusii;
6332c40f234SMatthew G. Knepley 
6342c40f234SMatthew G. Knepley   PetscFunctionBegin;
6359566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
63628b400f6SJacob Faibussowitsch   PetscCheck(dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
6379566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,     &ishdf5));
6389566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii));
6392c40f234SMatthew G. Knepley   if (ishdf5) {
640878b459fSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
6419566063dSJacob Faibussowitsch     PetscCall(VecLoad_Plex_HDF5_Internal(v, viewer));
642b136c2c9SMatthew G. Knepley #else
643b136c2c9SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
644878b459fSMatthew G. Knepley #endif
6456823f3c5SBlaise Bourdin   } else if (isexodusii) {
6466823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII)
6479566063dSJacob Faibussowitsch     PetscCall(VecLoad_PlexExodusII_Internal(v, viewer));
6486823f3c5SBlaise Bourdin #else
6496823f3c5SBlaise Bourdin     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii");
6506823f3c5SBlaise Bourdin #endif
6511baa6e33SBarry Smith   } else PetscCall(VecLoad_Default(v, viewer));
652552f7358SJed Brown   PetscFunctionReturn(0);
653552f7358SJed Brown }
654552f7358SJed Brown 
655d930f514SMatthew G. Knepley PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer)
656d930f514SMatthew G. Knepley {
657d930f514SMatthew G. Knepley   DM                dm;
658d930f514SMatthew G. Knepley   PetscViewerFormat format;
659d930f514SMatthew G. Knepley   PetscBool         ishdf5;
660d930f514SMatthew G. Knepley 
661d930f514SMatthew G. Knepley   PetscFunctionBegin;
6629566063dSJacob Faibussowitsch   PetscCall(VecGetDM(originalv, &dm));
66328b400f6SJacob Faibussowitsch   PetscCheck(dm,PetscObjectComm((PetscObject) originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
6649566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
6659566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
666d930f514SMatthew G. Knepley   if (format == PETSC_VIEWER_NATIVE) {
667a8ad634aSStefano Zampini     if (dm->useNatural) {
668d930f514SMatthew G. Knepley       if (dm->sfNatural) {
669d930f514SMatthew G. Knepley         if (ishdf5) {
670d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
671d930f514SMatthew G. Knepley           Vec         v;
672d930f514SMatthew G. Knepley           const char *vecname;
673d930f514SMatthew G. Knepley 
6749566063dSJacob Faibussowitsch           PetscCall(DMGetGlobalVector(dm, &v));
6759566063dSJacob Faibussowitsch           PetscCall(PetscObjectGetName((PetscObject) originalv, &vecname));
6769566063dSJacob Faibussowitsch           PetscCall(PetscObjectSetName((PetscObject) v, vecname));
6779566063dSJacob Faibussowitsch           PetscCall(VecLoad_Plex_HDF5_Native_Internal(v, viewer));
6789566063dSJacob Faibussowitsch           PetscCall(DMPlexNaturalToGlobalBegin(dm, v, originalv));
6799566063dSJacob Faibussowitsch           PetscCall(DMPlexNaturalToGlobalEnd(dm, v, originalv));
6809566063dSJacob Faibussowitsch           PetscCall(DMRestoreGlobalVector(dm, &v));
681d930f514SMatthew G. Knepley #else
682d930f514SMatthew G. Knepley           SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
683d930f514SMatthew G. Knepley #endif
684d930f514SMatthew G. Knepley         } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5.");
685d930f514SMatthew G. Knepley       }
6861baa6e33SBarry Smith     } else PetscCall(VecLoad_Default(originalv, viewer));
687d930f514SMatthew G. Knepley   }
688d930f514SMatthew G. Knepley   PetscFunctionReturn(0);
689d930f514SMatthew G. Knepley }
690d930f514SMatthew G. Knepley 
6917cd05799SMatthew G. Knepley PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer)
692731e8ddeSMatthew G. Knepley {
693731e8ddeSMatthew G. Knepley   PetscSection       coordSection;
694731e8ddeSMatthew G. Knepley   Vec                coordinates;
695ba2698f1SMatthew G. Knepley   DMLabel            depthLabel, celltypeLabel;
696731e8ddeSMatthew G. Knepley   const char        *name[4];
697731e8ddeSMatthew G. Knepley   const PetscScalar *a;
698731e8ddeSMatthew G. Knepley   PetscInt           dim, pStart, pEnd, cStart, cEnd, c;
699731e8ddeSMatthew G. Knepley 
700731e8ddeSMatthew G. Knepley   PetscFunctionBegin;
7019566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
7029566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
7039566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
7049566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
7059566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &celltypeLabel));
7069566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
7079566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(coordSection, &pStart, &pEnd));
7089566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(coordinates, &a));
709731e8ddeSMatthew G. Knepley   name[0]     = "vertex";
710731e8ddeSMatthew G. Knepley   name[1]     = "edge";
711731e8ddeSMatthew G. Knepley   name[dim-1] = "face";
712731e8ddeSMatthew G. Knepley   name[dim]   = "cell";
713731e8ddeSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
714731e8ddeSMatthew G. Knepley     PetscInt *closure = NULL;
715ba2698f1SMatthew G. Knepley     PetscInt  closureSize, cl, ct;
716731e8ddeSMatthew G. Knepley 
7179566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(celltypeLabel, c, &ct));
71863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Geometry for cell %" PetscInt_FMT " polytope type %s:\n", c, DMPolytopeTypes[ct]));
7199566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
7209566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
721731e8ddeSMatthew G. Knepley     for (cl = 0; cl < closureSize*2; cl += 2) {
722731e8ddeSMatthew G. Knepley       PetscInt point = closure[cl], depth, dof, off, d, p;
723731e8ddeSMatthew G. Knepley 
724731e8ddeSMatthew G. Knepley       if ((point < pStart) || (point >= pEnd)) continue;
7259566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(coordSection, point, &dof));
726731e8ddeSMatthew G. Knepley       if (!dof) continue;
7279566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(depthLabel, point, &depth));
7289566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, point, &off));
72963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s %" PetscInt_FMT " coords:", name[depth], point));
730731e8ddeSMatthew G. Knepley       for (p = 0; p < dof/dim; ++p) {
7319566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " ("));
732731e8ddeSMatthew G. Knepley         for (d = 0; d < dim; ++d) {
7339566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
7349566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "%g", (double) PetscRealPart(a[off+p*dim+d])));
735731e8ddeSMatthew G. Knepley         }
7369566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, ")"));
737731e8ddeSMatthew G. Knepley       }
7389566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
739731e8ddeSMatthew G. Knepley     }
7409566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
7419566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
742731e8ddeSMatthew G. Knepley   }
7439566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(coordinates, &a));
744731e8ddeSMatthew G. Knepley   PetscFunctionReturn(0);
745731e8ddeSMatthew G. Knepley }
746731e8ddeSMatthew G. Knepley 
74719ad8254SMatthew G. Knepley typedef enum {CS_CARTESIAN, CS_POLAR, CS_CYLINDRICAL, CS_SPHERICAL} CoordSystem;
74819ad8254SMatthew G. Knepley const char *CoordSystems[] = {"cartesian", "polar", "cylindrical", "spherical", "CoordSystem", "CS_", NULL};
74919ad8254SMatthew G. Knepley 
75019ad8254SMatthew G. Knepley static PetscErrorCode DMPlexView_Ascii_Coordinates(PetscViewer viewer, CoordSystem cs, PetscInt dim, const PetscScalar x[])
75119ad8254SMatthew G. Knepley {
75219ad8254SMatthew G. Knepley   PetscInt       i;
75319ad8254SMatthew G. Knepley 
75419ad8254SMatthew G. Knepley   PetscFunctionBegin;
75519ad8254SMatthew G. Knepley   if (dim > 3) {
7569566063dSJacob Faibussowitsch     for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double) PetscRealPart(x[i])));
75719ad8254SMatthew G. Knepley   } else {
758bd83fdcbSStefano Zampini     PetscReal coords[3], trcoords[3] = {0., 0., 0.};
75919ad8254SMatthew G. Knepley 
76019ad8254SMatthew G. Knepley     for (i = 0; i < dim; ++i) coords[i] = PetscRealPart(x[i]);
76119ad8254SMatthew G. Knepley     switch (cs) {
76219ad8254SMatthew G. Knepley       case CS_CARTESIAN: for (i = 0; i < dim; ++i) trcoords[i] = coords[i];break;
76319ad8254SMatthew G. Knepley       case CS_POLAR:
76463a3b9bcSJacob Faibussowitsch         PetscCheck(dim == 2,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Polar coordinates are for 2 dimension, not %" PetscInt_FMT, dim);
76519ad8254SMatthew G. Knepley         trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]));
76619ad8254SMatthew G. Knepley         trcoords[1] = PetscAtan2Real(coords[1], coords[0]);
76719ad8254SMatthew G. Knepley         break;
76819ad8254SMatthew G. Knepley       case CS_CYLINDRICAL:
76963a3b9bcSJacob Faibussowitsch         PetscCheck(dim == 3,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cylindrical coordinates are for 3 dimension, not %" PetscInt_FMT, dim);
77019ad8254SMatthew G. Knepley         trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]));
77119ad8254SMatthew G. Knepley         trcoords[1] = PetscAtan2Real(coords[1], coords[0]);
77219ad8254SMatthew G. Knepley         trcoords[2] = coords[2];
77319ad8254SMatthew G. Knepley         break;
77419ad8254SMatthew G. Knepley       case CS_SPHERICAL:
77563a3b9bcSJacob Faibussowitsch         PetscCheck(dim == 3,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Spherical coordinates are for 3 dimension, not %" PetscInt_FMT, dim);
77619ad8254SMatthew G. Knepley         trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]) + PetscSqr(coords[2]));
77719ad8254SMatthew G. Knepley         trcoords[1] = PetscAtan2Real(PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])), coords[2]);
77819ad8254SMatthew G. Knepley         trcoords[2] = PetscAtan2Real(coords[1], coords[0]);
77919ad8254SMatthew G. Knepley         break;
78019ad8254SMatthew G. Knepley     }
7819566063dSJacob Faibussowitsch     for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double) trcoords[i]));
78219ad8254SMatthew G. Knepley   }
78319ad8254SMatthew G. Knepley   PetscFunctionReturn(0);
78419ad8254SMatthew G. Knepley }
78519ad8254SMatthew G. Knepley 
7867cd05799SMatthew G. Knepley static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer)
787552f7358SJed Brown {
788552f7358SJed Brown   DM_Plex          *mesh = (DM_Plex*) dm->data;
7896858538eSMatthew G. Knepley   DM                cdm, cdmCell;
7906858538eSMatthew G. Knepley   PetscSection      coordSection, coordSectionCell;
7916858538eSMatthew G. Knepley   Vec               coordinates, coordinatesCell;
792552f7358SJed Brown   PetscViewerFormat format;
793552f7358SJed Brown 
794552f7358SJed Brown   PetscFunctionBegin;
7959566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
7966858538eSMatthew G. Knepley   PetscCall(DMGetCoordinateSection(dm, &coordSection));
7979566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
7986858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dm, &cdmCell));
7996858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell));
8006858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell));
8019566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
802552f7358SJed Brown   if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
803552f7358SJed Brown     const char *name;
804f73eea6eSMatthew G. Knepley     PetscInt    dim, cellHeight, maxConeSize, maxSupportSize;
8059318fe57SMatthew G. Knepley     PetscInt    pStart, pEnd, p, numLabels, l;
806552f7358SJed Brown     PetscMPIInt rank, size;
807552f7358SJed Brown 
8089566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
8099566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
8109566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject) dm, &name));
8119566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
8129566063dSJacob Faibussowitsch     PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
8139566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
8149566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
81563a3b9bcSJacob Faibussowitsch     if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s"));
81663a3b9bcSJacob Faibussowitsch     else      PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s"));
81763a3b9bcSJacob Faibussowitsch     if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, "  Cells are at height %" PetscInt_FMT "\n", cellHeight));
81863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Supports:\n"));
8199566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
82063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %" PetscInt_FMT "\n", rank, maxSupportSize));
821552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
822552f7358SJed Brown       PetscInt dof, off, s;
823552f7358SJed Brown 
8249566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
8259566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
826552f7358SJed Brown       for (s = off; s < off+dof; ++s) {
82763a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " ----> %" PetscInt_FMT "\n", rank, p, mesh->supports[s]));
828552f7358SJed Brown       }
829552f7358SJed Brown     }
8309566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
83163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Cones:\n"));
83263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %" PetscInt_FMT "\n", rank, maxConeSize));
833552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
834552f7358SJed Brown       PetscInt dof, off, c;
835552f7358SJed Brown 
8369566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
8379566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
838552f7358SJed Brown       for (c = off; c < off+dof; ++c) {
83963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " <---- %" PetscInt_FMT " (%" PetscInt_FMT ")\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]));
840552f7358SJed Brown       }
841552f7358SJed Brown     }
8429566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
8439566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
8443d2e540fSStefano Zampini     if (coordSection && coordinates) {
84519ad8254SMatthew G. Knepley       CoordSystem        cs = CS_CARTESIAN;
8466858538eSMatthew G. Knepley       const PetscScalar *array, *arrayCell = NULL;
8476858538eSMatthew G. Knepley       PetscInt           Nf, Nc, pvStart, pvEnd, pcStart = PETSC_MAX_INT, pcEnd = PETSC_MIN_INT, pStart, pEnd, p;
84819ad8254SMatthew G. Knepley       PetscMPIInt        rank;
84919ad8254SMatthew G. Knepley       const char        *name;
85019ad8254SMatthew G. Knepley 
8519566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetEnum(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_coord_system", CoordSystems, (PetscEnum *) &cs, NULL));
8529566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
8539566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetNumFields(coordSection, &Nf));
85463a3b9bcSJacob Faibussowitsch       PetscCheck(Nf == 1,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate section should have 1 field, not %" PetscInt_FMT, Nf);
8559566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldComponents(coordSection, 0, &Nc));
8566858538eSMatthew G. Knepley       PetscCall(PetscSectionGetChart(coordSection, &pvStart, &pvEnd));
8576858538eSMatthew G. Knepley       if (coordSectionCell) PetscCall(PetscSectionGetChart(coordSectionCell, &pcStart, &pcEnd));
8586858538eSMatthew G. Knepley       pStart =  PetscMin(pvStart, pcStart);
8596858538eSMatthew G. Knepley       pEnd   =  PetscMax(pvEnd,   pcEnd);
8609566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject) coordinates, &name));
86163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s with %" PetscInt_FMT " fields\n", name, Nf));
86263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  field 0 with %" PetscInt_FMT " components\n", Nc));
8639566063dSJacob Faibussowitsch       if (cs != CS_CARTESIAN) PetscCall(PetscViewerASCIIPrintf(viewer, "  output coordinate system: %s\n", CoordSystems[cs]));
86419ad8254SMatthew G. Knepley 
8659566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(coordinates, &array));
8666858538eSMatthew G. Knepley       if (coordinatesCell) PetscCall(VecGetArrayRead(coordinatesCell, &arrayCell));
8679566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushSynchronized(viewer));
8689566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank));
86919ad8254SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
87019ad8254SMatthew G. Knepley         PetscInt dof, off;
87119ad8254SMatthew G. Knepley 
8726858538eSMatthew G. Knepley         if (p >= pvStart && p < pvEnd) {
8739566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(coordSection, p, &dof));
8749566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(coordSection, p, &off));
8756858538eSMatthew G. Knepley           if (dof) {
87663a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "  (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off));
8779566063dSJacob Faibussowitsch             PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &array[off]));
8789566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
87919ad8254SMatthew G. Knepley           }
8806858538eSMatthew G. Knepley         }
8816858538eSMatthew G. Knepley         if (cdmCell && p >= pcStart && p < pcEnd) {
8826858538eSMatthew G. Knepley           PetscCall(PetscSectionGetDof(coordSectionCell, p, &dof));
8836858538eSMatthew G. Knepley           PetscCall(PetscSectionGetOffset(coordSectionCell, p, &off));
8846858538eSMatthew G. Knepley           if (dof) {
8856858538eSMatthew G. Knepley             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "  (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off));
8866858538eSMatthew G. Knepley             PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &arrayCell[off]));
8876858538eSMatthew G. Knepley             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
8886858538eSMatthew G. Knepley           }
8896858538eSMatthew G. Knepley         }
8906858538eSMatthew G. Knepley       }
8919566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
8929566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopSynchronized(viewer));
8939566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(coordinates, &array));
8946858538eSMatthew G. Knepley       if (coordinatesCell) PetscCall(VecRestoreArrayRead(coordinatesCell, &arrayCell));
8953d2e540fSStefano Zampini     }
8969566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
8979566063dSJacob Faibussowitsch     if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n"));
8989318fe57SMatthew G. Knepley     for (l = 0; l < numLabels; ++l) {
8999318fe57SMatthew G. Knepley       DMLabel     label;
9009318fe57SMatthew G. Knepley       PetscBool   isdepth;
9019318fe57SMatthew G. Knepley       const char *name;
9029318fe57SMatthew G. Knepley 
9039566063dSJacob Faibussowitsch       PetscCall(DMGetLabelName(dm, l, &name));
9049566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "depth", &isdepth));
9059318fe57SMatthew G. Knepley       if (isdepth) continue;
9069566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, name, &label));
9079566063dSJacob Faibussowitsch       PetscCall(DMLabelView(label, viewer));
9089318fe57SMatthew G. Knepley     }
909552f7358SJed Brown     if (size > 1) {
910552f7358SJed Brown       PetscSF sf;
911552f7358SJed Brown 
9129566063dSJacob Faibussowitsch       PetscCall(DMGetPointSF(dm, &sf));
9139566063dSJacob Faibussowitsch       PetscCall(PetscSFView(sf, viewer));
914552f7358SJed Brown     }
9159566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
916552f7358SJed Brown   } else if (format == PETSC_VIEWER_ASCII_LATEX) {
9170588280cSMatthew G. Knepley     const char  *name, *color;
9180588280cSMatthew G. Knepley     const char  *defcolors[3]  = {"gray", "orange", "green"};
9190588280cSMatthew G. Knepley     const char  *deflcolors[4] = {"blue", "cyan", "red", "magenta"};
920fe1cc32dSStefano Zampini     char         lname[PETSC_MAX_PATH_LEN];
921552f7358SJed Brown     PetscReal    scale         = 2.0;
92278081901SStefano Zampini     PetscReal    tikzscale     = 1.0;
923b7f6ffafSMatthew G. Knepley     PetscBool    useNumbers    = PETSC_TRUE, drawNumbers[4], drawColors[4], useLabels, useColors, plotEdges, drawHasse = PETSC_FALSE;
9240588280cSMatthew G. Knepley     double       tcoords[3];
925552f7358SJed Brown     PetscScalar *coords;
926b7f6ffafSMatthew G. Knepley     PetscInt     numLabels, l, numColors, numLColors, dim, d, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p, n;
927552f7358SJed Brown     PetscMPIInt  rank, size;
9280588280cSMatthew G. Knepley     char         **names, **colors, **lcolors;
929b7f6ffafSMatthew G. Knepley     PetscBool    flg, lflg;
930fe1cc32dSStefano Zampini     PetscBT      wp = NULL;
931fe1cc32dSStefano Zampini     PetscInt     pEnd, pStart;
932552f7358SJed Brown 
9339566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
9349566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dm, &depth));
9359566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
9360588280cSMatthew G. Knepley     numLabels  = PetscMax(numLabels, 10);
9370588280cSMatthew G. Knepley     numColors  = 10;
9380588280cSMatthew G. Knepley     numLColors = 10;
9399566063dSJacob Faibussowitsch     PetscCall(PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors));
9409566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_scale", &scale, NULL));
9419566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL));
9429566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL));
943b7f6ffafSMatthew G. Knepley     for (d = 0; d < 4; ++d) drawNumbers[d] = useNumbers;
944b7f6ffafSMatthew G. Knepley     for (d = 0; d < 4; ++d) drawColors[d]  = PETSC_TRUE;
945b7f6ffafSMatthew G. Knepley     n = 4;
9469566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBoolArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers_depth", drawNumbers, &n, &flg));
9471dca8a05SBarry Smith     PetscCheck(!flg || n == dim+1,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %" PetscInt_FMT " != %" PetscInt_FMT " dim+1", n, dim+1);
9489566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBoolArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors_depth", drawColors, &n, &flg));
9491dca8a05SBarry Smith     PetscCheck(!flg || n == dim+1,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %" PetscInt_FMT " != %" PetscInt_FMT " dim+1", n, dim+1);
9509566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels));
9510588280cSMatthew G. Knepley     if (!useLabels) numLabels = 0;
9529566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors));
9530588280cSMatthew G. Knepley     if (!useColors) {
9540588280cSMatthew G. Knepley       numColors = 3;
9559566063dSJacob Faibussowitsch       for (c = 0; c < numColors; ++c) PetscCall(PetscStrallocpy(defcolors[c], &colors[c]));
9560588280cSMatthew G. Knepley     }
9579566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors));
9580588280cSMatthew G. Knepley     if (!useColors) {
9590588280cSMatthew G. Knepley       numLColors = 4;
9609566063dSJacob Faibussowitsch       for (c = 0; c < numLColors; ++c) PetscCall(PetscStrallocpy(deflcolors[c], &lcolors[c]));
9610588280cSMatthew G. Knepley     }
9629566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetString(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg));
963b7f6ffafSMatthew G. Knepley     plotEdges = (PetscBool)(depth > 1 && drawNumbers[1] && dim < 3);
9649566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg));
9651dca8a05SBarry Smith     PetscCheck(!flg || !plotEdges || depth >= dim,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Mesh must be interpolated");
966202fd40aSStefano Zampini     if (depth < dim) plotEdges = PETSC_FALSE;
9679566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_hasse", &drawHasse, NULL));
968fe1cc32dSStefano Zampini 
969fe1cc32dSStefano Zampini     /* filter points with labelvalue != labeldefaultvalue */
9709566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
9719566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
9729566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd));
9739566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
974fe1cc32dSStefano Zampini     if (lflg) {
975fe1cc32dSStefano Zampini       DMLabel lbl;
976fe1cc32dSStefano Zampini 
9779566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, lname, &lbl));
978fe1cc32dSStefano Zampini       if (lbl) {
979fe1cc32dSStefano Zampini         PetscInt val, defval;
980fe1cc32dSStefano Zampini 
9819566063dSJacob Faibussowitsch         PetscCall(DMLabelGetDefaultValue(lbl, &defval));
9829566063dSJacob Faibussowitsch         PetscCall(PetscBTCreate(pEnd-pStart, &wp));
983fe1cc32dSStefano Zampini         for (c = pStart;  c < pEnd; c++) {
984fe1cc32dSStefano Zampini           PetscInt *closure = NULL;
985fe1cc32dSStefano Zampini           PetscInt  closureSize;
986fe1cc32dSStefano Zampini 
9879566063dSJacob Faibussowitsch           PetscCall(DMLabelGetValue(lbl, c, &val));
988fe1cc32dSStefano Zampini           if (val == defval) continue;
989fe1cc32dSStefano Zampini 
9909566063dSJacob Faibussowitsch           PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
991fe1cc32dSStefano Zampini           for (p = 0; p < closureSize*2; p += 2) {
9929566063dSJacob Faibussowitsch             PetscCall(PetscBTSet(wp, closure[p] - pStart));
993fe1cc32dSStefano Zampini           }
9949566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
995fe1cc32dSStefano Zampini         }
996fe1cc32dSStefano Zampini       }
997fe1cc32dSStefano Zampini     }
998fe1cc32dSStefano Zampini 
9999566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
10009566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
10019566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject) dm, &name));
10029566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\
10030588280cSMatthew G. Knepley \\documentclass[tikz]{standalone}\n\n\
1004552f7358SJed Brown \\usepackage{pgflibraryshapes}\n\
1005552f7358SJed Brown \\usetikzlibrary{backgrounds}\n\
1006552f7358SJed Brown \\usetikzlibrary{arrows}\n\
10075f80ce2aSJacob Faibussowitsch \\begin{document}\n"));
10080588280cSMatthew G. Knepley     if (size > 1) {
10099566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s for process ", name));
1010770b213bSMatthew G Knepley       for (p = 0; p < size; ++p) {
101163a3b9bcSJacob Faibussowitsch         if (p) PetscCall(PetscViewerASCIIPrintf(viewer, (p == size-1) ? ", and " :  ", "));
101263a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%" PetscInt_FMT "}", colors[p%numColors], p));
1013770b213bSMatthew G Knepley       }
10149566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, ".\n\n\n"));
10150588280cSMatthew G. Knepley     }
1016b7f6ffafSMatthew G. Knepley     if (drawHasse) {
1017b7f6ffafSMatthew G. Knepley       PetscInt maxStratum = PetscMax(vEnd-vStart, PetscMax(eEnd-eStart, cEnd-cStart));
1018b7f6ffafSMatthew G. Knepley 
101963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vStart}{%" PetscInt_FMT "}\n", vStart));
102063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vEnd}{%" PetscInt_FMT "}\n", vEnd-1));
102163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numVertices}{%" PetscInt_FMT "}\n", vEnd-vStart));
10229566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vShift}{%.2f}\n", 3 + (maxStratum-(vEnd-vStart))/2.));
102363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eStart}{%" PetscInt_FMT "}\n", eStart));
102463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eEnd}{%" PetscInt_FMT "}\n", eEnd-1));
10259566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eShift}{%.2f}\n", 3 + (maxStratum-(eEnd-eStart))/2.));
102663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numEdges}{%" PetscInt_FMT "}\n", eEnd-eStart));
102763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cStart}{%" PetscInt_FMT "}\n", cStart));
102863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cEnd}{%" PetscInt_FMT "}\n", cEnd-1));
102963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numCells}{%" PetscInt_FMT "}\n", cEnd-cStart));
10309566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cShift}{%.2f}\n", 3 + (maxStratum-(cEnd-cStart))/2.));
1031b7f6ffafSMatthew G. Knepley     }
10329566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double) tikzscale));
1033fe1cc32dSStefano Zampini 
1034552f7358SJed Brown     /* Plot vertices */
10359566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
10369566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
1037552f7358SJed Brown     for (v = vStart; v < vEnd; ++v) {
1038552f7358SJed Brown       PetscInt  off, dof, d;
10390588280cSMatthew G. Knepley       PetscBool isLabeled = PETSC_FALSE;
1040552f7358SJed Brown 
1041fe1cc32dSStefano Zampini       if (wp && !PetscBTLookup(wp,v - pStart)) continue;
10429566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(coordSection, v, &dof));
10439566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, v, &off));
10449566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path ("));
104563a3b9bcSJacob Faibussowitsch       PetscCheck(dof <= 3,PETSC_COMM_SELF,PETSC_ERR_PLIB,"coordSection vertex %" PetscInt_FMT " has dof %" PetscInt_FMT " > 3",v,dof);
10460588280cSMatthew G. Knepley       for (d = 0; d < dof; ++d) {
10470588280cSMatthew G. Knepley         tcoords[d] = (double) (scale*PetscRealPart(coords[off+d]));
1048c068d9bbSLisandro Dalcin         tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
10490588280cSMatthew G. Knepley       }
10500588280cSMatthew G. Knepley       /* Rotate coordinates since PGF makes z point out of the page instead of up */
10510588280cSMatthew G. Knepley       if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;}
1052552f7358SJed Brown       for (d = 0; d < dof; ++d) {
10539566063dSJacob Faibussowitsch         if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
10549566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) tcoords[d]));
1055552f7358SJed Brown       }
1056b7f6ffafSMatthew G. Knepley       if (drawHasse) color = colors[0%numColors];
1057b7f6ffafSMatthew G. Knepley       else           color = colors[rank%numColors];
10580588280cSMatthew G. Knepley       for (l = 0; l < numLabels; ++l) {
10590588280cSMatthew G. Knepley         PetscInt val;
10609566063dSJacob Faibussowitsch         PetscCall(DMGetLabelValue(dm, names[l], v, &val));
10610588280cSMatthew G. Knepley         if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;}
10620588280cSMatthew G. Knepley       }
1063b7f6ffafSMatthew G. Knepley       if (drawNumbers[0]) {
106463a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", v, rank, color, v));
1065b7f6ffafSMatthew G. Knepley       } else if (drawColors[0]) {
106663a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color));
10671baa6e33SBarry Smith       } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", v, rank));
1068552f7358SJed Brown     }
10699566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
10709566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
1071b7f6ffafSMatthew G. Knepley     /* Plot edges */
1072b7f6ffafSMatthew G. Knepley     if (plotEdges) {
10739566063dSJacob Faibussowitsch       PetscCall(VecGetArray(coordinates, &coords));
10749566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\path\n"));
1075b7f6ffafSMatthew G. Knepley       for (e = eStart; e < eEnd; ++e) {
1076b7f6ffafSMatthew G. Knepley         const PetscInt *cone;
1077b7f6ffafSMatthew G. Knepley         PetscInt        coneSize, offA, offB, dof, d;
1078b7f6ffafSMatthew G. Knepley 
1079b7f6ffafSMatthew G. Knepley         if (wp && !PetscBTLookup(wp,e - pStart)) continue;
10809566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, e, &coneSize));
108163a3b9bcSJacob Faibussowitsch         PetscCheck(coneSize == 2,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %" PetscInt_FMT " cone should have two vertices, not %" PetscInt_FMT, e, coneSize);
10829566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, e, &cone));
10839566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(coordSection, cone[0], &dof));
10849566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(coordSection, cone[0], &offA));
10859566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(coordSection, cone[1], &offB));
10869566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "("));
1087b7f6ffafSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
1088b7f6ffafSMatthew G. Knepley           tcoords[d] = (double) (0.5*scale*PetscRealPart(coords[offA+d]+coords[offB+d]));
1089b7f6ffafSMatthew G. Knepley           tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
1090b7f6ffafSMatthew G. Knepley         }
1091b7f6ffafSMatthew G. Knepley         /* Rotate coordinates since PGF makes z point out of the page instead of up */
1092b7f6ffafSMatthew G. Knepley         if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;}
1093b7f6ffafSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
10949566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
10959566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d]));
1096b7f6ffafSMatthew G. Knepley         }
1097b7f6ffafSMatthew G. Knepley         if (drawHasse) color = colors[1%numColors];
1098b7f6ffafSMatthew G. Knepley         else           color = colors[rank%numColors];
1099b7f6ffafSMatthew G. Knepley         for (l = 0; l < numLabels; ++l) {
1100b7f6ffafSMatthew G. Knepley           PetscInt val;
11019566063dSJacob Faibussowitsch           PetscCall(DMGetLabelValue(dm, names[l], v, &val));
1102b7f6ffafSMatthew G. Knepley           if (val >= 0) {color = lcolors[l%numLColors]; break;}
1103b7f6ffafSMatthew G. Knepley         }
110463a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "} --\n", e, rank, color, e));
1105b7f6ffafSMatthew G. Knepley       }
11069566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(coordinates, &coords));
11079566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
11089566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "(0,0);\n"));
1109b7f6ffafSMatthew G. Knepley     }
1110846a3e8bSMatthew G. Knepley     /* Plot cells */
1111b7f6ffafSMatthew G. Knepley     if (dim == 3 || !drawNumbers[1]) {
1112846a3e8bSMatthew G. Knepley       for (e = eStart; e < eEnd; ++e) {
1113846a3e8bSMatthew G. Knepley         const PetscInt *cone;
1114846a3e8bSMatthew G. Knepley 
1115fe1cc32dSStefano Zampini         if (wp && !PetscBTLookup(wp,e - pStart)) continue;
1116846a3e8bSMatthew G. Knepley         color = colors[rank%numColors];
1117846a3e8bSMatthew G. Knepley         for (l = 0; l < numLabels; ++l) {
1118846a3e8bSMatthew G. Knepley           PetscInt val;
11199566063dSJacob Faibussowitsch           PetscCall(DMGetLabelValue(dm, names[l], e, &val));
1120846a3e8bSMatthew G. Knepley           if (val >= 0) {color = lcolors[l%numLColors]; break;}
1121846a3e8bSMatthew G. Knepley         }
11229566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, e, &cone));
112363a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", color, cone[0], rank, cone[1], rank));
1124846a3e8bSMatthew G. Knepley       }
1125846a3e8bSMatthew G. Knepley     } else {
1126b7f6ffafSMatthew G. Knepley        DMPolytopeType ct;
1127846a3e8bSMatthew G. Knepley 
1128b7f6ffafSMatthew G. Knepley       /* Drawing a 2D polygon */
1129b7f6ffafSMatthew G. Knepley       for (c = cStart; c < cEnd; ++c) {
1130fe1cc32dSStefano Zampini         if (wp && !PetscBTLookup(wp, c - pStart)) continue;
11319566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, c, &ct));
1132b7f6ffafSMatthew G. Knepley         if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR ||
1133b7f6ffafSMatthew G. Knepley             ct == DM_POLYTOPE_TRI_PRISM_TENSOR ||
1134b7f6ffafSMatthew G. Knepley             ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) {
1135b7f6ffafSMatthew G. Knepley           const PetscInt *cone;
1136b7f6ffafSMatthew G. Knepley           PetscInt        coneSize, e;
1137b7f6ffafSMatthew G. Knepley 
11389566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCone(dm, c, &cone));
11399566063dSJacob Faibussowitsch           PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
1140b7f6ffafSMatthew G. Knepley           for (e = 0; e < coneSize; ++e) {
1141b7f6ffafSMatthew G. Knepley             const PetscInt *econe;
1142b7f6ffafSMatthew G. Knepley 
11439566063dSJacob Faibussowitsch             PetscCall(DMPlexGetCone(dm, cone[e], &econe));
114463a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", colors[rank%numColors], econe[0], rank, cone[e], rank, econe[1], rank));
1145b7f6ffafSMatthew G. Knepley           }
1146b7f6ffafSMatthew G. Knepley         } else {
1147b7f6ffafSMatthew G. Knepley           PetscInt *closure = NULL;
1148b7f6ffafSMatthew G. Knepley           PetscInt  closureSize, Nv = 0, v;
1149b7f6ffafSMatthew G. Knepley 
11509566063dSJacob Faibussowitsch           PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1151846a3e8bSMatthew G. Knepley           for (p = 0; p < closureSize*2; p += 2) {
1152846a3e8bSMatthew G. Knepley             const PetscInt point = closure[p];
1153846a3e8bSMatthew G. Knepley 
1154b7f6ffafSMatthew G. Knepley             if ((point >= vStart) && (point < vEnd)) closure[Nv++] = point;
1155846a3e8bSMatthew G. Knepley           }
11569566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]));
1157b7f6ffafSMatthew G. Knepley           for (v = 0; v <= Nv; ++v) {
1158b7f6ffafSMatthew G. Knepley             const PetscInt vertex = closure[v%Nv];
1159b7f6ffafSMatthew G. Knepley 
1160b7f6ffafSMatthew G. Knepley             if (v > 0) {
1161b7f6ffafSMatthew G. Knepley               if (plotEdges) {
1162b7f6ffafSMatthew G. Knepley                 const PetscInt *edge;
1163b7f6ffafSMatthew G. Knepley                 PetscInt        endpoints[2], ne;
1164b7f6ffafSMatthew G. Knepley 
1165b7f6ffafSMatthew G. Knepley                 endpoints[0] = closure[v-1]; endpoints[1] = vertex;
11669566063dSJacob Faibussowitsch                 PetscCall(DMPlexGetJoin(dm, 2, endpoints, &ne, &edge));
116763a3b9bcSJacob Faibussowitsch                 PetscCheck(ne == 1,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find edge for vertices %" PetscInt_FMT ", %" PetscInt_FMT, endpoints[0], endpoints[1]);
116863a3b9bcSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- (%" PetscInt_FMT "_%d) -- ", edge[0], rank));
11699566063dSJacob Faibussowitsch                 PetscCall(DMPlexRestoreJoin(dm, 2, endpoints, &ne, &edge));
11701baa6e33SBarry Smith               } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- "));
1171b7f6ffafSMatthew G. Knepley             }
117263a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(%" PetscInt_FMT "_%d)", vertex, rank));
1173b7f6ffafSMatthew G. Knepley           }
11749566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ";\n"));
11759566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1176846a3e8bSMatthew G. Knepley         }
1177846a3e8bSMatthew G. Knepley       }
1178b7f6ffafSMatthew G. Knepley     }
11799566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
1180846a3e8bSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
1181846a3e8bSMatthew G. Knepley       double    ccoords[3] = {0.0, 0.0, 0.0};
1182846a3e8bSMatthew G. Knepley       PetscBool isLabeled  = PETSC_FALSE;
1183846a3e8bSMatthew G. Knepley       PetscInt *closure    = NULL;
1184846a3e8bSMatthew G. Knepley       PetscInt  closureSize, dof, d, n = 0;
1185846a3e8bSMatthew G. Knepley 
1186fe1cc32dSStefano Zampini       if (wp && !PetscBTLookup(wp,c - pStart)) continue;
11879566063dSJacob Faibussowitsch       PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
11889566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path ("));
1189846a3e8bSMatthew G. Knepley       for (p = 0; p < closureSize*2; p += 2) {
1190846a3e8bSMatthew G. Knepley         const PetscInt point = closure[p];
1191846a3e8bSMatthew G. Knepley         PetscInt       off;
1192846a3e8bSMatthew G. Knepley 
1193846a3e8bSMatthew G. Knepley         if ((point < vStart) || (point >= vEnd)) continue;
11949566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(coordSection, point, &dof));
11959566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(coordSection, point, &off));
1196846a3e8bSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
1197846a3e8bSMatthew G. Knepley           tcoords[d] = (double) (scale*PetscRealPart(coords[off+d]));
1198846a3e8bSMatthew G. Knepley           tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
1199846a3e8bSMatthew G. Knepley         }
1200846a3e8bSMatthew G. Knepley         /* Rotate coordinates since PGF makes z point out of the page instead of up */
1201846a3e8bSMatthew G. Knepley         if (dof == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;}
1202846a3e8bSMatthew G. Knepley         for (d = 0; d < dof; ++d) {ccoords[d] += tcoords[d];}
1203846a3e8bSMatthew G. Knepley         ++n;
1204846a3e8bSMatthew G. Knepley       }
1205846a3e8bSMatthew G. Knepley       for (d = 0; d < dof; ++d) {ccoords[d] /= n;}
12069566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1207846a3e8bSMatthew G. Knepley       for (d = 0; d < dof; ++d) {
12089566063dSJacob Faibussowitsch         if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
12099566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) ccoords[d]));
1210846a3e8bSMatthew G. Knepley       }
1211b7f6ffafSMatthew G. Knepley       if (drawHasse) color = colors[depth%numColors];
1212b7f6ffafSMatthew G. Knepley       else           color = colors[rank%numColors];
1213846a3e8bSMatthew G. Knepley       for (l = 0; l < numLabels; ++l) {
1214846a3e8bSMatthew G. Knepley         PetscInt val;
12159566063dSJacob Faibussowitsch         PetscCall(DMGetLabelValue(dm, names[l], c, &val));
1216846a3e8bSMatthew G. Knepley         if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;}
1217846a3e8bSMatthew G. Knepley       }
1218b7f6ffafSMatthew G. Knepley       if (drawNumbers[dim]) {
121963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", c, rank, color, c));
1220b7f6ffafSMatthew G. Knepley       } else if (drawColors[dim]) {
122163a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color));
12221baa6e33SBarry Smith       } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", c, rank));
1223846a3e8bSMatthew G. Knepley     }
12249566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
1225b7f6ffafSMatthew G. Knepley     if (drawHasse) {
1226b7f6ffafSMatthew G. Knepley       color = colors[depth%numColors];
12279566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Cells\n"));
12289566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\c in {\\cStart,...,\\cEnd}\n"));
12299566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
12309566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\c_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\cShift+\\c-\\cStart,0) {\\c};\n", rank, color));
12319566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1232552f7358SJed Brown 
1233b7f6ffafSMatthew G. Knepley       color = colors[1%numColors];
12349566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Edges\n"));
12359566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\e in {\\eStart,...,\\eEnd}\n"));
12369566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
12379566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\e_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\eShift+\\e-\\eStart,1) {\\e};\n", rank, color));
12389566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1239b7f6ffafSMatthew G. Knepley 
1240b7f6ffafSMatthew G. Knepley       color = colors[0%numColors];
12419566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Vertices\n"));
12429566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\v in {\\vStart,...,\\vEnd}\n"));
12439566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
12449566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\v_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\vShift+\\v-\\vStart,2) {\\v};\n", rank, color));
12459566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1246b7f6ffafSMatthew G. Knepley 
1247b7f6ffafSMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
1248b7f6ffafSMatthew G. Knepley         const PetscInt *cone;
1249b7f6ffafSMatthew G. Knepley         PetscInt        coneSize, cp;
1250b7f6ffafSMatthew G. Knepley 
12519566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, p, &cone));
12529566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
1253b7f6ffafSMatthew G. Knepley         for (cp = 0; cp < coneSize; ++cp) {
125463a3b9bcSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "\\draw[->, shorten >=1pt] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", cone[cp], rank, p, rank));
1255552f7358SJed Brown         }
12560588280cSMatthew G. Knepley       }
12570588280cSMatthew G. Knepley     }
12589566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
12599566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
12609566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n"));
126163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{document}\n"));
12629566063dSJacob Faibussowitsch     for (l = 0; l < numLabels;  ++l) PetscCall(PetscFree(names[l]));
12639566063dSJacob Faibussowitsch     for (c = 0; c < numColors;  ++c) PetscCall(PetscFree(colors[c]));
12649566063dSJacob Faibussowitsch     for (c = 0; c < numLColors; ++c) PetscCall(PetscFree(lcolors[c]));
12659566063dSJacob Faibussowitsch     PetscCall(PetscFree3(names, colors, lcolors));
12669566063dSJacob Faibussowitsch     PetscCall(PetscBTDestroy(&wp));
12670f7d6e4aSStefano Zampini   } else if (format == PETSC_VIEWER_LOAD_BALANCE) {
12680f7d6e4aSStefano Zampini     Vec                    cown,acown;
12690f7d6e4aSStefano Zampini     VecScatter             sct;
12700f7d6e4aSStefano Zampini     ISLocalToGlobalMapping g2l;
12710f7d6e4aSStefano Zampini     IS                     gid,acis;
12720f7d6e4aSStefano Zampini     MPI_Comm               comm,ncomm = MPI_COMM_NULL;
12730f7d6e4aSStefano Zampini     MPI_Group              ggroup,ngroup;
12740f7d6e4aSStefano Zampini     PetscScalar            *array,nid;
12750f7d6e4aSStefano Zampini     const PetscInt         *idxs;
12760f7d6e4aSStefano Zampini     PetscInt               *idxs2,*start,*adjacency,*work;
12770f7d6e4aSStefano Zampini     PetscInt64             lm[3],gm[3];
12780f7d6e4aSStefano Zampini     PetscInt               i,c,cStart,cEnd,cum,numVertices,ect,ectn,cellHeight;
12790f7d6e4aSStefano Zampini     PetscMPIInt            d1,d2,rank;
12800f7d6e4aSStefano Zampini 
12819566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)dm,&comm));
12829566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm,&rank));
1283b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
12849566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_split_type(comm,MPI_COMM_TYPE_SHARED,rank,MPI_INFO_NULL,&ncomm));
12850f7d6e4aSStefano Zampini #endif
12860f7d6e4aSStefano Zampini     if (ncomm != MPI_COMM_NULL) {
12879566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_group(comm,&ggroup));
12889566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_group(ncomm,&ngroup));
12890f7d6e4aSStefano Zampini       d1   = 0;
12909566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_translate_ranks(ngroup,1,&d1,ggroup,&d2));
12910f7d6e4aSStefano Zampini       nid  = d2;
12929566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_free(&ggroup));
12939566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_free(&ngroup));
12949566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_free(&ncomm));
12950f7d6e4aSStefano Zampini     } else nid = 0.0;
12960f7d6e4aSStefano Zampini 
12970f7d6e4aSStefano Zampini     /* Get connectivity */
12989566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm,&cellHeight));
12999566063dSJacob Faibussowitsch     PetscCall(DMPlexCreatePartitionerGraph(dm,cellHeight,&numVertices,&start,&adjacency,&gid));
13000f7d6e4aSStefano Zampini 
13010f7d6e4aSStefano Zampini     /* filter overlapped local cells */
13029566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm,cellHeight,&cStart,&cEnd));
13039566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(gid,&idxs));
13049566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(gid,&cum));
13059566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(cum,&idxs2));
13060f7d6e4aSStefano Zampini     for (c = cStart, cum = 0; c < cEnd; c++) {
13070f7d6e4aSStefano Zampini       if (idxs[c-cStart] < 0) continue;
13080f7d6e4aSStefano Zampini       idxs2[cum++] = idxs[c-cStart];
13090f7d6e4aSStefano Zampini     }
13109566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(gid,&idxs));
131163a3b9bcSJacob Faibussowitsch     PetscCheck(numVertices == cum,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected %" PetscInt_FMT " != %" PetscInt_FMT,numVertices,cum);
13129566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&gid));
13139566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm,numVertices,idxs2,PETSC_OWN_POINTER,&gid));
13140f7d6e4aSStefano Zampini 
13150f7d6e4aSStefano Zampini     /* support for node-aware cell locality */
13169566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm,start[numVertices],adjacency,PETSC_USE_POINTER,&acis));
13179566063dSJacob Faibussowitsch     PetscCall(VecCreateSeq(PETSC_COMM_SELF,start[numVertices],&acown));
13189566063dSJacob Faibussowitsch     PetscCall(VecCreateMPI(comm,numVertices,PETSC_DECIDE,&cown));
13199566063dSJacob Faibussowitsch     PetscCall(VecGetArray(cown,&array));
13200f7d6e4aSStefano Zampini     for (c = 0; c < numVertices; c++) array[c] = nid;
13219566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(cown,&array));
13229566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(cown,acis,acown,NULL,&sct));
13239566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD));
13249566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD));
13259566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&acis));
13269566063dSJacob Faibussowitsch     PetscCall(VecScatterDestroy(&sct));
13279566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&cown));
13280f7d6e4aSStefano Zampini 
13290f7d6e4aSStefano Zampini     /* compute edgeCut */
13300f7d6e4aSStefano Zampini     for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum,start[c+1]-start[c]);
13319566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(cum,&work));
13329566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(gid,&g2l));
13339566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingSetType(g2l,ISLOCALTOGLOBALMAPPINGHASH));
13349566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&gid));
13359566063dSJacob Faibussowitsch     PetscCall(VecGetArray(acown,&array));
13360f7d6e4aSStefano Zampini     for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) {
13370f7d6e4aSStefano Zampini       PetscInt totl;
13380f7d6e4aSStefano Zampini 
13390f7d6e4aSStefano Zampini       totl = start[c+1]-start[c];
13409566063dSJacob Faibussowitsch       PetscCall(ISGlobalToLocalMappingApply(g2l,IS_GTOLM_MASK,totl,adjacency+start[c],NULL,work));
13410f7d6e4aSStefano Zampini       for (i = 0; i < totl; i++) {
13420f7d6e4aSStefano Zampini         if (work[i] < 0) {
13430f7d6e4aSStefano Zampini           ect  += 1;
13440f7d6e4aSStefano Zampini           ectn += (array[i + start[c]] != nid) ? 0 : 1;
13450f7d6e4aSStefano Zampini         }
13460f7d6e4aSStefano Zampini       }
13470f7d6e4aSStefano Zampini     }
13489566063dSJacob Faibussowitsch     PetscCall(PetscFree(work));
13499566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(acown,&array));
13500f7d6e4aSStefano Zampini     lm[0] = numVertices > 0 ?  numVertices : PETSC_MAX_INT;
13510f7d6e4aSStefano Zampini     lm[1] = -numVertices;
13521c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(lm,gm,2,MPIU_INT64,MPI_MIN,comm));
135363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Cell balance: %.2f (max %" PetscInt_FMT ", min %" PetscInt_FMT,-((double)gm[1])/((double)gm[0]),-(PetscInt)gm[1],(PetscInt)gm[0]));
13540f7d6e4aSStefano Zampini     lm[0] = ect; /* edgeCut */
13550f7d6e4aSStefano Zampini     lm[1] = ectn; /* node-aware edgeCut */
13560f7d6e4aSStefano Zampini     lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */
13571c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(lm,gm,3,MPIU_INT64,MPI_SUM,comm));
135863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,", empty %" PetscInt_FMT ")\n",(PetscInt)gm[2]));
1359b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
136063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Edge Cut: %" PetscInt_FMT " (on node %.3f)\n",(PetscInt)(gm[0]/2),gm[0] ? ((double)(gm[1]))/((double)gm[0]) : 1.));
13610f7d6e4aSStefano Zampini #else
136263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Edge Cut: %" PetscInt_FMT " (on node %.3f)\n",(PetscInt)(gm[0]/2),0.0));
13630f7d6e4aSStefano Zampini #endif
13649566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&g2l));
13659566063dSJacob Faibussowitsch     PetscCall(PetscFree(start));
13669566063dSJacob Faibussowitsch     PetscCall(PetscFree(adjacency));
13679566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&acown));
1368552f7358SJed Brown   } else {
1369412e9a14SMatthew G. Knepley     const char    *name;
1370d80ece95SMatthew G. Knepley     PetscInt      *sizes, *hybsizes, *ghostsizes;
1371412e9a14SMatthew G. Knepley     PetscInt       locDepth, depth, cellHeight, dim, d;
1372d80ece95SMatthew G. Knepley     PetscInt       pStart, pEnd, p, gcStart, gcEnd, gcNum;
1373ca7bf7eeSMatthew G. Knepley     PetscInt       numLabels, l, maxSize = 17;
13749318fe57SMatthew G. Knepley     DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN;
1375412e9a14SMatthew G. Knepley     MPI_Comm       comm;
1376412e9a14SMatthew G. Knepley     PetscMPIInt    size, rank;
1377552f7358SJed Brown 
13789566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject) dm, &comm));
13799566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(comm, &size));
13809566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
13819566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
13829566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
13839566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject) dm, &name));
138463a3b9bcSJacob Faibussowitsch     if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s"));
138563a3b9bcSJacob Faibussowitsch     else      PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s"));
138663a3b9bcSJacob Faibussowitsch     if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, "  Cells are at height %" PetscInt_FMT "\n", cellHeight));
13879566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dm, &locDepth));
13881c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm));
13899566063dSJacob Faibussowitsch     PetscCall(DMPlexGetGhostCellStratum(dm, &gcStart, &gcEnd));
1390d80ece95SMatthew G. Knepley     gcNum = gcEnd - gcStart;
13919566063dSJacob Faibussowitsch     if (size < maxSize) PetscCall(PetscCalloc3(size, &sizes, size, &hybsizes, size, &ghostsizes));
13929566063dSJacob Faibussowitsch     else                PetscCall(PetscCalloc3(3,    &sizes, 3,    &hybsizes, 3,    &ghostsizes));
1393412e9a14SMatthew G. Knepley     for (d = 0; d <= depth; d++) {
1394412e9a14SMatthew G. Knepley       PetscInt Nc[2] = {0, 0}, ict;
1395412e9a14SMatthew G. Knepley 
13969566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
13979566063dSJacob Faibussowitsch       if (pStart < pEnd) PetscCall(DMPlexGetCellType(dm, pStart, &ct0));
1398412e9a14SMatthew G. Knepley       ict  = ct0;
13999566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Bcast(&ict, 1, MPIU_INT, 0, comm));
1400412e9a14SMatthew G. Knepley       ct0  = (DMPolytopeType) ict;
1401412e9a14SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
1402412e9a14SMatthew G. Knepley         DMPolytopeType ct;
1403412e9a14SMatthew G. Knepley 
14049566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, p, &ct));
1405412e9a14SMatthew G. Knepley         if (ct == ct0) ++Nc[0];
1406412e9a14SMatthew G. Knepley         else           ++Nc[1];
1407412e9a14SMatthew G. Knepley       }
1408ca7bf7eeSMatthew G. Knepley       if (size < maxSize) {
14099566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Gather(&Nc[0], 1, MPIU_INT, sizes,    1, MPIU_INT, 0, comm));
14109566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm));
14119566063dSJacob Faibussowitsch         if (d == depth) PetscCallMPI(MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm));
141263a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Number of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d));
1413834065abSMatthew G. Knepley         for (p = 0; p < size; ++p) {
1414dd400576SPatrick Sanan           if (rank == 0) {
141563a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sizes[p]+hybsizes[p]));
141663a3b9bcSJacob Faibussowitsch             if (hybsizes[p]   > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ")", hybsizes[p]));
141763a3b9bcSJacob Faibussowitsch             if (ghostsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "]", ghostsizes[p]));
1418834065abSMatthew G. Knepley           }
1419cbb7f117SMark Adams         }
1420ca7bf7eeSMatthew G. Knepley       } else {
1421ca7bf7eeSMatthew G. Knepley         PetscInt locMinMax[2];
1422ca7bf7eeSMatthew G. Knepley 
1423ca7bf7eeSMatthew G. Knepley         locMinMax[0] = Nc[0]+Nc[1]; locMinMax[1] = Nc[0]+Nc[1];
14249566063dSJacob Faibussowitsch         PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, sizes));
1425ca7bf7eeSMatthew G. Knepley         locMinMax[0] = Nc[1]; locMinMax[1] = Nc[1];
14269566063dSJacob Faibussowitsch         PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, hybsizes));
1427ca7bf7eeSMatthew G. Knepley         if (d == depth) {
1428ca7bf7eeSMatthew G. Knepley           locMinMax[0] = gcNum; locMinMax[1] = gcNum;
14299566063dSJacob Faibussowitsch           PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, ghostsizes));
1430ca7bf7eeSMatthew G. Knepley         }
143163a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Min/Max of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d));
14329566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1]));
14339566063dSJacob Faibussowitsch         if (hybsizes[0]   > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT "/%" PetscInt_FMT ")", hybsizes[0], hybsizes[1]));
14349566063dSJacob Faibussowitsch         if (ghostsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "/%" PetscInt_FMT "]", ghostsizes[0], ghostsizes[1]));
1435ca7bf7eeSMatthew G. Knepley       }
14369566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
1437552f7358SJed Brown     }
14389566063dSJacob Faibussowitsch     PetscCall(PetscFree3(sizes, hybsizes, ghostsizes));
14399318fe57SMatthew G. Knepley     {
14409318fe57SMatthew G. Knepley       const PetscReal *maxCell;
14419318fe57SMatthew G. Knepley       const PetscReal *L;
14426858538eSMatthew G. Knepley       PetscBool        localized;
14439318fe57SMatthew G. Knepley 
14444fb89dddSMatthew G. Knepley       PetscCall(DMGetPeriodicity(dm, &maxCell, NULL, &L));
14459566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocalized(dm, &localized));
14466858538eSMatthew G. Knepley       if (L || localized) {
14476858538eSMatthew G. Knepley         PetscCall(PetscViewerASCIIPrintf(viewer, "Periodic mesh"));
14489566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
14496858538eSMatthew G. Knepley         if (L) {
14506858538eSMatthew G. Knepley           PetscCall(PetscViewerASCIIPrintf(viewer, " ("));
14519318fe57SMatthew G. Knepley           for (d = 0; d < dim; ++d) {
14526858538eSMatthew G. Knepley             if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
14536858538eSMatthew G. Knepley             PetscCall(PetscViewerASCIIPrintf(viewer, "%s", L[d] > 0.0 ? "PERIODIC" : "NONE"));
14549318fe57SMatthew G. Knepley           }
14556858538eSMatthew G. Knepley           PetscCall(PetscViewerASCIIPrintf(viewer, ")"));
14566858538eSMatthew G. Knepley         }
14576858538eSMatthew G. Knepley         PetscCall(PetscViewerASCIIPrintf(viewer, " coordinates %s\n", localized ? "localized" : "not localized"));
14589566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
14599318fe57SMatthew G. Knepley       }
14609318fe57SMatthew G. Knepley     }
14619566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
14629566063dSJacob Faibussowitsch     if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n"));
1463a57dd577SMatthew G Knepley     for (l = 0; l < numLabels; ++l) {
1464a57dd577SMatthew G Knepley       DMLabel         label;
1465a57dd577SMatthew G Knepley       const char     *name;
1466a57dd577SMatthew G Knepley       IS              valueIS;
1467a57dd577SMatthew G Knepley       const PetscInt *values;
1468a57dd577SMatthew G Knepley       PetscInt        numValues, v;
1469a57dd577SMatthew G Knepley 
14709566063dSJacob Faibussowitsch       PetscCall(DMGetLabelName(dm, l, &name));
14719566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, name, &label));
14729566063dSJacob Faibussowitsch       PetscCall(DMLabelGetNumValues(label, &numValues));
147363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  %s: %" PetscInt_FMT " strata with value/size (", name, numValues));
14749566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValueIS(label, &valueIS));
14759566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(valueIS, &values));
14769566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
1477a57dd577SMatthew G Knepley       for (v = 0; v < numValues; ++v) {
1478a57dd577SMatthew G Knepley         PetscInt size;
1479a57dd577SMatthew G Knepley 
14809566063dSJacob Faibussowitsch         PetscCall(DMLabelGetStratumSize(label, values[v], &size));
14819566063dSJacob Faibussowitsch         if (v > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
148263a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " (%" PetscInt_FMT ")", values[v], size));
1483a57dd577SMatthew G Knepley       }
14849566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, ")\n"));
14859566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
14869566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(valueIS, &values));
14879566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&valueIS));
1488a57dd577SMatthew G Knepley     }
1489c1cad2e7SMatthew G. Knepley     {
1490c1cad2e7SMatthew G. Knepley       char    **labelNames;
1491c1cad2e7SMatthew G. Knepley       PetscInt  Nl = numLabels;
1492c1cad2e7SMatthew G. Knepley       PetscBool flg;
1493c1cad2e7SMatthew G. Knepley 
14949566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Nl, &labelNames));
14959566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetStringArray(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_plex_view_labels", labelNames, &Nl, &flg));
1496c1cad2e7SMatthew G. Knepley       for (l = 0; l < Nl; ++l) {
1497c1cad2e7SMatthew G. Knepley         DMLabel label;
1498c1cad2e7SMatthew G. Knepley 
14999566063dSJacob Faibussowitsch         PetscCall(DMHasLabel(dm, labelNames[l], &flg));
1500c1cad2e7SMatthew G. Knepley         if (flg) {
15019566063dSJacob Faibussowitsch           PetscCall(DMGetLabel(dm, labelNames[l], &label));
15029566063dSJacob Faibussowitsch           PetscCall(DMLabelView(label, viewer));
1503c1cad2e7SMatthew G. Knepley         }
15049566063dSJacob Faibussowitsch         PetscCall(PetscFree(labelNames[l]));
1505c1cad2e7SMatthew G. Knepley       }
15069566063dSJacob Faibussowitsch       PetscCall(PetscFree(labelNames));
1507c1cad2e7SMatthew G. Knepley     }
150834aa8a36SMatthew G. Knepley     /* If no fields are specified, people do not want to see adjacency */
150934aa8a36SMatthew G. Knepley     if (dm->Nf) {
151034aa8a36SMatthew G. Knepley       PetscInt f;
151134aa8a36SMatthew G. Knepley 
151234aa8a36SMatthew G. Knepley       for (f = 0; f < dm->Nf; ++f) {
151334aa8a36SMatthew G. Knepley         const char *name;
151434aa8a36SMatthew G. Knepley 
15159566063dSJacob Faibussowitsch         PetscCall(PetscObjectGetName(dm->fields[f].disc, &name));
15169566063dSJacob Faibussowitsch         if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Field %s:\n", name));
15179566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
15189566063dSJacob Faibussowitsch         if (dm->fields[f].label) PetscCall(DMLabelView(dm->fields[f].label, viewer));
151934aa8a36SMatthew G. Knepley         if (dm->fields[f].adjacency[0]) {
15209566063dSJacob Faibussowitsch           if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n"));
15219566063dSJacob Faibussowitsch           else                            PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM\n"));
152234aa8a36SMatthew G. Knepley         } else {
15239566063dSJacob Faibussowitsch           if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FEM\n"));
15249566063dSJacob Faibussowitsch           else                            PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n"));
152534aa8a36SMatthew G. Knepley         }
15269566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
152734aa8a36SMatthew G. Knepley       }
152834aa8a36SMatthew G. Knepley     }
15299566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dm, &cdm));
15308e7ff633SMatthew G. Knepley     if (cdm) {
15319566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(viewer));
15329566063dSJacob Faibussowitsch       PetscCall(DMPlexView_Ascii(cdm, viewer));
15339566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(viewer));
15348e7ff633SMatthew G. Knepley     }
1535552f7358SJed Brown   }
1536552f7358SJed Brown   PetscFunctionReturn(0);
1537552f7358SJed Brown }
1538552f7358SJed Brown 
1539e5c487bfSMatthew G. Knepley static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[])
1540e5c487bfSMatthew G. Knepley {
1541e5c487bfSMatthew G. Knepley   DMPolytopeType ct;
1542e5c487bfSMatthew G. Knepley   PetscMPIInt    rank;
1543a12d352dSMatthew G. Knepley   PetscInt       cdim;
1544e5c487bfSMatthew G. Knepley 
1545e5c487bfSMatthew G. Knepley   PetscFunctionBegin;
15469566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank));
15479566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cell, &ct));
15489566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
1549e5c487bfSMatthew G. Knepley   switch (ct) {
1550a12d352dSMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
1551a12d352dSMatthew G. Knepley   case DM_POLYTOPE_POINT_PRISM_TENSOR:
1552a12d352dSMatthew G. Knepley     switch (cdim) {
1553a12d352dSMatthew G. Knepley     case 1:
1554a12d352dSMatthew G. Knepley     {
1555a12d352dSMatthew G. Knepley       const PetscReal y  = 0.5;  /* TODO Put it in the middle of the viewport */
1556a12d352dSMatthew G. Knepley       const PetscReal dy = 0.05; /* TODO Make it a fraction of the total length */
1557a12d352dSMatthew G. Knepley 
15589566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y,    PetscRealPart(coords[1]), y,    PETSC_DRAW_BLACK));
15599566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y+dy, PetscRealPart(coords[0]), y-dy, PETSC_DRAW_BLACK));
15609566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[1]), y+dy, PetscRealPart(coords[1]), y-dy, PETSC_DRAW_BLACK));
1561a12d352dSMatthew G. Knepley     }
1562a12d352dSMatthew G. Knepley     break;
1563a12d352dSMatthew G. Knepley     case 2:
1564a12d352dSMatthew G. Knepley     {
1565a12d352dSMatthew G. Knepley       const PetscReal dx = (PetscRealPart(coords[3]) - PetscRealPart(coords[1]));
1566a12d352dSMatthew G. Knepley       const PetscReal dy = (PetscRealPart(coords[2]) - PetscRealPart(coords[0]));
1567a12d352dSMatthew G. Knepley       const PetscReal l  = 0.1/PetscSqrtReal(dx*dx + dy*dy);
1568a12d352dSMatthew G. Knepley 
15699566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
15709566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0])+l*dx, PetscRealPart(coords[1])+l*dy, PetscRealPart(coords[0])-l*dx, PetscRealPart(coords[1])-l*dy, PETSC_DRAW_BLACK));
15719566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2])+l*dx, PetscRealPart(coords[3])+l*dy, PetscRealPart(coords[2])-l*dx, PetscRealPart(coords[3])-l*dy, PETSC_DRAW_BLACK));
1572a12d352dSMatthew G. Knepley     }
1573a12d352dSMatthew G. Knepley     break;
157463a3b9bcSJacob Faibussowitsch     default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of dimension %" PetscInt_FMT, cdim);
1575a12d352dSMatthew G. Knepley     }
1576a12d352dSMatthew G. Knepley     break;
1577e5c487bfSMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
15789566063dSJacob Faibussowitsch     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]),
1579e5c487bfSMatthew G. Knepley                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2,
1580e5c487bfSMatthew G. Knepley                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2,
15815f80ce2aSJacob Faibussowitsch                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2));
15829566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
15839566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK));
15849566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK));
1585e5c487bfSMatthew G. Knepley     break;
1586e5c487bfSMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
15879566063dSJacob Faibussowitsch     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]),
1588e5c487bfSMatthew G. Knepley                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2,
1589e5c487bfSMatthew G. Knepley                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2,
15905f80ce2aSJacob Faibussowitsch                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2));
15919566063dSJacob Faibussowitsch     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]),
1592e5c487bfSMatthew G. Knepley                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2,
1593e5c487bfSMatthew G. Knepley                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2,
15945f80ce2aSJacob Faibussowitsch                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2));
15959566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
15969566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK));
15979566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK));
15989566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK));
1599e5c487bfSMatthew G. Knepley     break;
160098921bdaSJacob Faibussowitsch   default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]);
1601e5c487bfSMatthew G. Knepley   }
1602e5c487bfSMatthew G. Knepley   PetscFunctionReturn(0);
1603e5c487bfSMatthew G. Knepley }
1604e5c487bfSMatthew G. Knepley 
1605e5c487bfSMatthew G. Knepley static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[])
1606e5c487bfSMatthew G. Knepley {
1607e5c487bfSMatthew G. Knepley   DMPolytopeType ct;
1608e5c487bfSMatthew G. Knepley   PetscReal      centroid[2] = {0., 0.};
1609e5c487bfSMatthew G. Knepley   PetscMPIInt    rank;
1610e5c487bfSMatthew G. Knepley   PetscInt       fillColor, v, e, d;
1611e5c487bfSMatthew G. Knepley 
1612e5c487bfSMatthew G. Knepley   PetscFunctionBegin;
16139566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank));
16149566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cell, &ct));
1615e5c487bfSMatthew G. Knepley   fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2;
1616e5c487bfSMatthew G. Knepley   switch (ct) {
1617e5c487bfSMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
1618e5c487bfSMatthew G. Knepley     {
1619e5c487bfSMatthew G. Knepley       PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.};
1620e5c487bfSMatthew G. Knepley 
1621e5c487bfSMatthew G. Knepley       for (v = 0; v < 3; ++v) {centroid[0] += PetscRealPart(coords[v*2+0])/3.;centroid[1] += PetscRealPart(coords[v*2+1])/3.;}
1622e5c487bfSMatthew G. Knepley       for (e = 0; e < 3; ++e) {
1623e5c487bfSMatthew G. Knepley         refCoords[0] = refVertices[e*2+0];
1624e5c487bfSMatthew G. Knepley         refCoords[1] = refVertices[e*2+1];
1625e5c487bfSMatthew G. Knepley         for (d = 1; d <= edgeDiv; ++d) {
1626e5c487bfSMatthew G. Knepley           refCoords[d*2+0] = refCoords[0] + (refVertices[(e+1)%3 * 2 + 0] - refCoords[0])*d/edgeDiv;
1627e5c487bfSMatthew G. Knepley           refCoords[d*2+1] = refCoords[1] + (refVertices[(e+1)%3 * 2 + 1] - refCoords[1])*d/edgeDiv;
1628e5c487bfSMatthew G. Knepley         }
16299566063dSJacob Faibussowitsch         PetscCall(DMPlexReferenceToCoordinates(dm, cell, edgeDiv+1, refCoords, edgeCoords));
1630e5c487bfSMatthew G. Knepley         for (d = 0; d < edgeDiv; ++d) {
16319566063dSJacob Faibussowitsch           PetscCall(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));
16329566063dSJacob Faibussowitsch           PetscCall(PetscDrawLine(draw, edgeCoords[d*2+0], edgeCoords[d*2+1], edgeCoords[(d+1)*2+0], edgeCoords[(d+1)*2+1], PETSC_DRAW_BLACK));
1633e5c487bfSMatthew G. Knepley         }
1634e5c487bfSMatthew G. Knepley       }
1635e5c487bfSMatthew G. Knepley     }
1636e5c487bfSMatthew G. Knepley     break;
163798921bdaSJacob Faibussowitsch   default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]);
1638e5c487bfSMatthew G. Knepley   }
1639e5c487bfSMatthew G. Knepley   PetscFunctionReturn(0);
1640e5c487bfSMatthew G. Knepley }
1641e5c487bfSMatthew G. Knepley 
16427cd05799SMatthew G. Knepley static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer)
1643e412dcbdSMatthew G. Knepley {
1644e412dcbdSMatthew G. Knepley   PetscDraw          draw;
1645e412dcbdSMatthew G. Knepley   DM                 cdm;
1646e412dcbdSMatthew G. Knepley   PetscSection       coordSection;
1647e412dcbdSMatthew G. Knepley   Vec                coordinates;
1648e412dcbdSMatthew G. Knepley   const PetscScalar *coords;
164929494db1SLisandro Dalcin   PetscReal          xyl[2],xyr[2],bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL};
1650e5c487bfSMatthew G. Knepley   PetscReal         *refCoords, *edgeCoords;
1651e5c487bfSMatthew G. Knepley   PetscBool          isnull, drawAffine = PETSC_TRUE;
1652e5c487bfSMatthew G. Knepley   PetscInt           dim, vStart, vEnd, cStart, cEnd, c, N, edgeDiv = 4;
1653e412dcbdSMatthew G. Knepley 
1654e412dcbdSMatthew G. Knepley   PetscFunctionBegin;
16559566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dim));
165663a3b9bcSJacob Faibussowitsch   PetscCheck(dim <= 2,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT, dim);
16579566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL));
16589566063dSJacob Faibussowitsch   if (!drawAffine) PetscCall(PetscMalloc2((edgeDiv+1)*dim, &refCoords, (edgeDiv+1)*dim, &edgeCoords));
16599566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
16609566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(cdm, &coordSection));
16619566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
16629566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
16639566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
1664e412dcbdSMatthew G. Knepley 
16659566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
16669566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
1667e412dcbdSMatthew G. Knepley   if (isnull) PetscFunctionReturn(0);
16689566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "Mesh"));
1669e412dcbdSMatthew G. Knepley 
16709566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(coordinates, &N));
16719566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(coordinates, &coords));
1672e412dcbdSMatthew G. Knepley   for (c = 0; c < N; c += dim) {
16730c81f2a8SMatthew G. Knepley     bound[0] = PetscMin(bound[0], PetscRealPart(coords[c]));   bound[2] = PetscMax(bound[2], PetscRealPart(coords[c]));
16740c81f2a8SMatthew G. Knepley     bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1]));
1675e412dcbdSMatthew G. Knepley   }
16769566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(coordinates, &coords));
16771c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&bound[0],xyl,2,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)dm)));
16781c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&bound[2],xyr,2,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)dm)));
16799566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1]));
16809566063dSJacob Faibussowitsch   PetscCall(PetscDrawClear(draw));
1681e412dcbdSMatthew G. Knepley 
1682cf3064d3SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1683cf3064d3SMatthew G. Knepley     PetscScalar *coords = NULL;
1684ba2698f1SMatthew G. Knepley     PetscInt     numCoords;
1685cf3064d3SMatthew G. Knepley 
16869566063dSJacob Faibussowitsch     PetscCall(DMPlexVecGetClosureAtDepth_Internal(dm, coordSection, coordinates, c, 0, &numCoords, &coords));
16871baa6e33SBarry Smith     if (drawAffine) PetscCall(DMPlexDrawCell(dm, draw, c, coords));
16881baa6e33SBarry Smith     else PetscCall(DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords));
16899566063dSJacob Faibussowitsch     PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords));
1690cf3064d3SMatthew G. Knepley   }
16919566063dSJacob Faibussowitsch   if (!drawAffine) PetscCall(PetscFree2(refCoords, edgeCoords));
16929566063dSJacob Faibussowitsch   PetscCall(PetscDrawFlush(draw));
16939566063dSJacob Faibussowitsch   PetscCall(PetscDrawPause(draw));
16949566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave(draw));
1695e412dcbdSMatthew G. Knepley   PetscFunctionReturn(0);
1696e412dcbdSMatthew G. Knepley }
1697e412dcbdSMatthew G. Knepley 
16981e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII)
16991e50132fSMatthew G. Knepley #include <exodusII.h>
17006823f3c5SBlaise Bourdin #include <petscviewerexodusii.h>
17011e50132fSMatthew G. Knepley #endif
17021e50132fSMatthew G. Knepley 
1703552f7358SJed Brown PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer)
1704552f7358SJed Brown {
17051e50132fSMatthew G. Knepley   PetscBool      iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus;
1706002a2709SMatthew G. Knepley   char           name[PETSC_MAX_PATH_LEN];
1707552f7358SJed Brown 
1708552f7358SJed Brown   PetscFunctionBegin;
1709552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1710552f7358SJed Brown   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
17119566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII,    &iascii));
17129566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK,      &isvtk));
17139566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,     &ishdf5));
17149566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW,     &isdraw));
17159566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS,    &isglvis));
17169566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodus));
1717552f7358SJed Brown   if (iascii) {
17188135c375SStefano Zampini     PetscViewerFormat format;
17199566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
17201baa6e33SBarry Smith     if (format == PETSC_VIEWER_ASCII_GLVIS) PetscCall(DMPlexView_GLVis(dm, viewer));
17211baa6e33SBarry Smith     else PetscCall(DMPlexView_Ascii(dm, viewer));
1722c6ccd67eSMatthew G. Knepley   } else if (ishdf5) {
1723c6ccd67eSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
17249566063dSJacob Faibussowitsch     PetscCall(DMPlexView_HDF5_Internal(dm, viewer));
1725c6ccd67eSMatthew G. Knepley #else
1726c6ccd67eSMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1727552f7358SJed Brown #endif
1728e412dcbdSMatthew G. Knepley   } else if (isvtk) {
17299566063dSJacob Faibussowitsch     PetscCall(DMPlexVTKWriteAll((PetscObject) dm,viewer));
1730e412dcbdSMatthew G. Knepley   } else if (isdraw) {
17319566063dSJacob Faibussowitsch     PetscCall(DMPlexView_Draw(dm, viewer));
17328135c375SStefano Zampini   } else if (isglvis) {
17339566063dSJacob Faibussowitsch     PetscCall(DMPlexView_GLVis(dm, viewer));
17341e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII)
17351e50132fSMatthew G. Knepley   } else if (isexodus) {
17366823f3c5SBlaise Bourdin /*
17376823f3c5SBlaise Bourdin       exodusII requires that all sets be part of exactly one cell set.
17386823f3c5SBlaise Bourdin       If the dm does not have a "Cell Sets" label defined, we create one
17396823f3c5SBlaise Bourdin       with ID 1, containig all cells.
17406823f3c5SBlaise Bourdin       Note that if the Cell Sets label is defined but does not cover all cells,
17416823f3c5SBlaise Bourdin       we may still have a problem. This should probably be checked here or in the viewer;
17426823f3c5SBlaise Bourdin     */
17436823f3c5SBlaise Bourdin     PetscInt numCS;
17449566063dSJacob Faibussowitsch     PetscCall(DMGetLabelSize(dm,"Cell Sets",&numCS));
17456823f3c5SBlaise Bourdin     if (!numCS) {
17461e50132fSMatthew G. Knepley       PetscInt cStart, cEnd, c;
17479566063dSJacob Faibussowitsch       PetscCall(DMCreateLabel(dm, "Cell Sets"));
17489566063dSJacob Faibussowitsch       PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
17499566063dSJacob Faibussowitsch       for (c = cStart; c < cEnd; ++c) PetscCall(DMSetLabelValue(dm, "Cell Sets", c, 1));
17506823f3c5SBlaise Bourdin     }
17519566063dSJacob Faibussowitsch     PetscCall(DMView_PlexExodusII(dm, viewer));
17521e50132fSMatthew G. Knepley #endif
17531baa6e33SBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name);
17541baa6e33SBarry Smith 
1755cb3ba0daSMatthew G. Knepley   /* Optionally view the partition */
17569566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_partition_view", &flg));
1757cb3ba0daSMatthew G. Knepley   if (flg) {
1758cb3ba0daSMatthew G. Knepley     Vec ranks;
17599566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateRankField(dm, &ranks));
17609566063dSJacob Faibussowitsch     PetscCall(VecView(ranks, viewer));
17619566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&ranks));
1762cb3ba0daSMatthew G. Knepley   }
1763002a2709SMatthew G. Knepley   /* Optionally view a label */
17649566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetString(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_label_view", name, sizeof(name), &flg));
1765002a2709SMatthew G. Knepley   if (flg) {
1766002a2709SMatthew G. Knepley     DMLabel label;
1767002a2709SMatthew G. Knepley     Vec     val;
1768002a2709SMatthew G. Knepley 
17699566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, name, &label));
177028b400f6SJacob Faibussowitsch     PetscCheck(label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name);
17719566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateLabelField(dm, label, &val));
17729566063dSJacob Faibussowitsch     PetscCall(VecView(val, viewer));
17739566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&val));
1774002a2709SMatthew G. Knepley   }
1775552f7358SJed Brown   PetscFunctionReturn(0);
1776552f7358SJed Brown }
1777552f7358SJed Brown 
17787f96f51bSksagiyam /*@
17797f96f51bSksagiyam   DMPlexTopologyView - Saves a DMPlex topology into a file
17807f96f51bSksagiyam 
17817f96f51bSksagiyam   Collective on DM
17827f96f51bSksagiyam 
17837f96f51bSksagiyam   Input Parameters:
17847f96f51bSksagiyam + dm     - The DM whose topology is to be saved
17857f96f51bSksagiyam - viewer - The PetscViewer for saving
17867f96f51bSksagiyam 
17877f96f51bSksagiyam   Level: advanced
17887f96f51bSksagiyam 
1789db781477SPatrick Sanan .seealso: `DMView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexTopologyLoad()`
17907f96f51bSksagiyam @*/
17917f96f51bSksagiyam PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer)
17927f96f51bSksagiyam {
17937f96f51bSksagiyam   PetscBool      ishdf5;
17947f96f51bSksagiyam 
17957f96f51bSksagiyam   PetscFunctionBegin;
17967f96f51bSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
17977f96f51bSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
17989566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
17999566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_TopologyView,viewer,0,0,0));
18007f96f51bSksagiyam   if (ishdf5) {
18017f96f51bSksagiyam #if defined(PETSC_HAVE_HDF5)
18027f96f51bSksagiyam     PetscViewerFormat format;
18039566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
18047f96f51bSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
18057f96f51bSksagiyam       IS globalPointNumbering;
18067f96f51bSksagiyam 
18079566063dSJacob Faibussowitsch       PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering));
18089566063dSJacob Faibussowitsch       PetscCall(DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer));
18099566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&globalPointNumbering));
181098921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]);
18117f96f51bSksagiyam #else
18127f96f51bSksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
18137f96f51bSksagiyam #endif
18147f96f51bSksagiyam   }
18159566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_TopologyView,viewer,0,0,0));
18167f96f51bSksagiyam   PetscFunctionReturn(0);
18177f96f51bSksagiyam }
18187f96f51bSksagiyam 
181977b8e257Sksagiyam /*@
182077b8e257Sksagiyam   DMPlexCoordinatesView - Saves DMPlex coordinates into a file
182177b8e257Sksagiyam 
182277b8e257Sksagiyam   Collective on DM
182377b8e257Sksagiyam 
182477b8e257Sksagiyam   Input Parameters:
182577b8e257Sksagiyam + dm     - The DM whose coordinates are to be saved
182677b8e257Sksagiyam - viewer - The PetscViewer for saving
182777b8e257Sksagiyam 
182877b8e257Sksagiyam   Level: advanced
182977b8e257Sksagiyam 
1830db781477SPatrick Sanan .seealso: `DMView()`, `DMPlexTopologyView()`, `DMPlexLabelsView()`, `DMPlexCoordinatesLoad()`
183177b8e257Sksagiyam @*/
183277b8e257Sksagiyam PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer)
183377b8e257Sksagiyam {
183477b8e257Sksagiyam   PetscBool      ishdf5;
183577b8e257Sksagiyam 
183677b8e257Sksagiyam   PetscFunctionBegin;
183777b8e257Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
183877b8e257Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
18399566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
18409566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesView,viewer,0,0,0));
184177b8e257Sksagiyam   if (ishdf5) {
184277b8e257Sksagiyam #if defined(PETSC_HAVE_HDF5)
184377b8e257Sksagiyam     PetscViewerFormat format;
18449566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
184577b8e257Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
18469566063dSJacob Faibussowitsch       PetscCall(DMPlexCoordinatesView_HDF5_Internal(dm, viewer));
184798921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
184877b8e257Sksagiyam #else
184977b8e257Sksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
185077b8e257Sksagiyam #endif
185177b8e257Sksagiyam   }
18529566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesView,viewer,0,0,0));
185377b8e257Sksagiyam   PetscFunctionReturn(0);
185477b8e257Sksagiyam }
185577b8e257Sksagiyam 
1856bd6565f1Sksagiyam /*@
1857bd6565f1Sksagiyam   DMPlexLabelsView - Saves DMPlex labels into a file
1858bd6565f1Sksagiyam 
1859bd6565f1Sksagiyam   Collective on DM
1860bd6565f1Sksagiyam 
1861bd6565f1Sksagiyam   Input Parameters:
1862bd6565f1Sksagiyam + dm     - The DM whose labels are to be saved
1863bd6565f1Sksagiyam - viewer - The PetscViewer for saving
1864bd6565f1Sksagiyam 
1865bd6565f1Sksagiyam   Level: advanced
1866bd6565f1Sksagiyam 
1867db781477SPatrick Sanan .seealso: `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsLoad()`
1868bd6565f1Sksagiyam @*/
1869bd6565f1Sksagiyam PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer)
1870bd6565f1Sksagiyam {
1871bd6565f1Sksagiyam   PetscBool      ishdf5;
1872bd6565f1Sksagiyam 
1873bd6565f1Sksagiyam   PetscFunctionBegin;
1874bd6565f1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1875bd6565f1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
18769566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
18779566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LabelsView,viewer,0,0,0));
1878bd6565f1Sksagiyam   if (ishdf5) {
1879bd6565f1Sksagiyam #if defined(PETSC_HAVE_HDF5)
1880bd6565f1Sksagiyam     IS                globalPointNumbering;
1881bd6565f1Sksagiyam     PetscViewerFormat format;
1882bd6565f1Sksagiyam 
18839566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
1884bd6565f1Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
18859566063dSJacob Faibussowitsch       PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering));
18869566063dSJacob Faibussowitsch       PetscCall(DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer));
18879566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&globalPointNumbering));
188898921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
1889bd6565f1Sksagiyam #else
1890bd6565f1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1891bd6565f1Sksagiyam #endif
1892bd6565f1Sksagiyam   }
18939566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LabelsView,viewer,0,0,0));
1894bd6565f1Sksagiyam   PetscFunctionReturn(0);
1895bd6565f1Sksagiyam }
1896bd6565f1Sksagiyam 
1897021affd3Sksagiyam /*@
1898021affd3Sksagiyam   DMPlexSectionView - Saves a section associated with a DMPlex
1899021affd3Sksagiyam 
1900021affd3Sksagiyam   Collective on DM
1901021affd3Sksagiyam 
1902021affd3Sksagiyam   Input Parameters:
1903021affd3Sksagiyam + dm         - The DM that contains the topology on which the section to be saved is defined
1904021affd3Sksagiyam . viewer     - The PetscViewer for saving
1905021affd3Sksagiyam - sectiondm  - The DM that contains the section to be saved
1906021affd3Sksagiyam 
1907021affd3Sksagiyam   Level: advanced
1908021affd3Sksagiyam 
1909021affd3Sksagiyam   Notes:
1910021affd3Sksagiyam   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.
1911021affd3Sksagiyam 
1912021affd3Sksagiyam   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.
1913021affd3Sksagiyam 
1914db781477SPatrick Sanan .seealso: `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, `PetscSectionView()`, `DMPlexSectionLoad()`
1915021affd3Sksagiyam @*/
1916021affd3Sksagiyam PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm)
1917021affd3Sksagiyam {
1918021affd3Sksagiyam   PetscBool      ishdf5;
1919021affd3Sksagiyam 
1920021affd3Sksagiyam   PetscFunctionBegin;
1921021affd3Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1922021affd3Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1923021affd3Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
19249566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5));
19259566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_SectionView,viewer,0,0,0));
1926021affd3Sksagiyam   if (ishdf5) {
1927021affd3Sksagiyam #if defined(PETSC_HAVE_HDF5)
19289566063dSJacob Faibussowitsch     PetscCall(DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm));
1929021affd3Sksagiyam #else
1930021affd3Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1931021affd3Sksagiyam #endif
1932021affd3Sksagiyam   }
19339566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_SectionView,viewer,0,0,0));
1934021affd3Sksagiyam   PetscFunctionReturn(0);
1935021affd3Sksagiyam }
1936021affd3Sksagiyam 
19373e97647fSksagiyam /*@
19383e97647fSksagiyam   DMPlexGlobalVectorView - Saves a global vector
19393e97647fSksagiyam 
19403e97647fSksagiyam   Collective on DM
19413e97647fSksagiyam 
19423e97647fSksagiyam   Input Parameters:
19433e97647fSksagiyam + dm        - The DM that represents the topology
19443e97647fSksagiyam . viewer    - The PetscViewer to save data with
19453e97647fSksagiyam . sectiondm - The DM that contains the global section on which vec is defined
19463e97647fSksagiyam - vec       - The global vector to be saved
19473e97647fSksagiyam 
19483e97647fSksagiyam   Level: advanced
19493e97647fSksagiyam 
19503e97647fSksagiyam   Notes:
19513e97647fSksagiyam   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.
19523e97647fSksagiyam 
19533e97647fSksagiyam   Typical calling sequence
19543e97647fSksagiyam $       DMCreate(PETSC_COMM_WORLD, &dm);
19553e97647fSksagiyam $       DMSetType(dm, DMPLEX);
19563e97647fSksagiyam $       PetscObjectSetName((PetscObject)dm, "topologydm_name");
19573e97647fSksagiyam $       DMClone(dm, &sectiondm);
19583e97647fSksagiyam $       PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
19593e97647fSksagiyam $       PetscSectionCreate(PETSC_COMM_WORLD, &section);
19603e97647fSksagiyam $       DMPlexGetChart(sectiondm, &pStart, &pEnd);
19613e97647fSksagiyam $       PetscSectionSetChart(section, pStart, pEnd);
19623e97647fSksagiyam $       PetscSectionSetUp(section);
19633e97647fSksagiyam $       DMSetLocalSection(sectiondm, section);
19643e97647fSksagiyam $       PetscSectionDestroy(&section);
19653e97647fSksagiyam $       DMGetGlobalVector(sectiondm, &vec);
19663e97647fSksagiyam $       PetscObjectSetName((PetscObject)vec, "vec_name");
19673e97647fSksagiyam $       DMPlexTopologyView(dm, viewer);
19683e97647fSksagiyam $       DMPlexSectionView(dm, viewer, sectiondm);
19693e97647fSksagiyam $       DMPlexGlobalVectorView(dm, viewer, sectiondm, vec);
19703e97647fSksagiyam $       DMRestoreGlobalVector(sectiondm, &vec);
19713e97647fSksagiyam $       DMDestroy(&sectiondm);
19723e97647fSksagiyam $       DMDestroy(&dm);
19733e97647fSksagiyam 
1974db781477SPatrick Sanan .seealso: `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexLocalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`
19753e97647fSksagiyam @*/
19763e97647fSksagiyam PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec)
19773e97647fSksagiyam {
19783e97647fSksagiyam   PetscBool       ishdf5;
19793e97647fSksagiyam 
19803e97647fSksagiyam   PetscFunctionBegin;
19813e97647fSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
19823e97647fSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
19833e97647fSksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
19843e97647fSksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 4);
19853e97647fSksagiyam   /* Check consistency */
19863e97647fSksagiyam   {
19873e97647fSksagiyam     PetscSection  section;
19883e97647fSksagiyam     PetscBool     includesConstraints;
19893e97647fSksagiyam     PetscInt      m, m1;
19903e97647fSksagiyam 
19919566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
19929566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(sectiondm, &section));
19939566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
19949566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
19959566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
199663a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m);
19973e97647fSksagiyam   }
19989566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
19999566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorView,viewer,0,0,0));
20003e97647fSksagiyam   if (ishdf5) {
20013e97647fSksagiyam #if defined(PETSC_HAVE_HDF5)
20029566063dSJacob Faibussowitsch     PetscCall(DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec));
20033e97647fSksagiyam #else
20043e97647fSksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
20053e97647fSksagiyam #endif
20063e97647fSksagiyam   }
20079566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorView,viewer,0,0,0));
20083e97647fSksagiyam   PetscFunctionReturn(0);
20093e97647fSksagiyam }
20103e97647fSksagiyam 
20113e97647fSksagiyam /*@
20123e97647fSksagiyam   DMPlexLocalVectorView - Saves a local vector
20133e97647fSksagiyam 
20143e97647fSksagiyam   Collective on DM
20153e97647fSksagiyam 
20163e97647fSksagiyam   Input Parameters:
20173e97647fSksagiyam + dm        - The DM that represents the topology
20183e97647fSksagiyam . viewer    - The PetscViewer to save data with
20193e97647fSksagiyam . sectiondm - The DM that contains the local section on which vec is defined; may be the same as dm
20203e97647fSksagiyam - vec       - The local vector to be saved
20213e97647fSksagiyam 
20223e97647fSksagiyam   Level: advanced
20233e97647fSksagiyam 
20243e97647fSksagiyam   Notes:
20253e97647fSksagiyam   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.
20263e97647fSksagiyam 
20273e97647fSksagiyam   Typical calling sequence
20283e97647fSksagiyam $       DMCreate(PETSC_COMM_WORLD, &dm);
20293e97647fSksagiyam $       DMSetType(dm, DMPLEX);
20303e97647fSksagiyam $       PetscObjectSetName((PetscObject)dm, "topologydm_name");
20313e97647fSksagiyam $       DMClone(dm, &sectiondm);
20323e97647fSksagiyam $       PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
20333e97647fSksagiyam $       PetscSectionCreate(PETSC_COMM_WORLD, &section);
20343e97647fSksagiyam $       DMPlexGetChart(sectiondm, &pStart, &pEnd);
20353e97647fSksagiyam $       PetscSectionSetChart(section, pStart, pEnd);
20363e97647fSksagiyam $       PetscSectionSetUp(section);
20373e97647fSksagiyam $       DMSetLocalSection(sectiondm, section);
20383e97647fSksagiyam $       DMGetLocalVector(sectiondm, &vec);
20393e97647fSksagiyam $       PetscObjectSetName((PetscObject)vec, "vec_name");
20403e97647fSksagiyam $       DMPlexTopologyView(dm, viewer);
20413e97647fSksagiyam $       DMPlexSectionView(dm, viewer, sectiondm);
20423e97647fSksagiyam $       DMPlexLocalVectorView(dm, viewer, sectiondm, vec);
20433e97647fSksagiyam $       DMRestoreLocalVector(sectiondm, &vec);
20443e97647fSksagiyam $       DMDestroy(&sectiondm);
20453e97647fSksagiyam $       DMDestroy(&dm);
20463e97647fSksagiyam 
2047db781477SPatrick Sanan .seealso: `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexGlobalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`
20483e97647fSksagiyam @*/
20493e97647fSksagiyam PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec)
20503e97647fSksagiyam {
20513e97647fSksagiyam   PetscBool       ishdf5;
20523e97647fSksagiyam 
20533e97647fSksagiyam   PetscFunctionBegin;
20543e97647fSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
20553e97647fSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
20563e97647fSksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
20573e97647fSksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 4);
20583e97647fSksagiyam   /* Check consistency */
20593e97647fSksagiyam   {
20603e97647fSksagiyam     PetscSection  section;
20613e97647fSksagiyam     PetscBool     includesConstraints;
20623e97647fSksagiyam     PetscInt      m, m1;
20633e97647fSksagiyam 
20649566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
20659566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(sectiondm, &section));
20669566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
20679566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
20689566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
206963a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m);
20703e97647fSksagiyam   }
20719566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
20729566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorView,viewer,0,0,0));
20733e97647fSksagiyam   if (ishdf5) {
20743e97647fSksagiyam #if defined(PETSC_HAVE_HDF5)
20759566063dSJacob Faibussowitsch     PetscCall(DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec));
20763e97647fSksagiyam #else
20773e97647fSksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
20783e97647fSksagiyam #endif
20793e97647fSksagiyam   }
20809566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorView,viewer,0,0,0));
20813e97647fSksagiyam   PetscFunctionReturn(0);
20823e97647fSksagiyam }
20833e97647fSksagiyam 
20842c40f234SMatthew G. Knepley PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer)
20852c40f234SMatthew G. Knepley {
2086d4f5a9a0SVaclav Hapla   PetscBool      ishdf5;
20872c40f234SMatthew G. Knepley 
20882c40f234SMatthew G. Knepley   PetscFunctionBegin;
20892c40f234SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
20902c40f234SMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
20919566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,   &ishdf5));
2092d4f5a9a0SVaclav Hapla   if (ishdf5) {
20932c40f234SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
20949c48423bSVaclav Hapla     PetscViewerFormat format;
20959566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
20969c48423bSVaclav Hapla     if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) {
20979566063dSJacob Faibussowitsch       PetscCall(DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer));
2098509517efSVaclav Hapla     } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
20999566063dSJacob Faibussowitsch       PetscCall(DMPlexLoad_HDF5_Internal(dm, viewer));
210098921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2101b458e8f1SJose E. Roman     PetscFunctionReturn(0);
21022c40f234SMatthew G. Knepley #else
21032c40f234SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2104552f7358SJed Brown #endif
210598921bdaSJacob Faibussowitsch   } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name);
2106552f7358SJed Brown }
2107552f7358SJed Brown 
2108ea8e1828Sksagiyam /*@
2109ea8e1828Sksagiyam   DMPlexTopologyLoad - Loads a topology into a DMPlex
2110ea8e1828Sksagiyam 
2111ea8e1828Sksagiyam   Collective on DM
2112ea8e1828Sksagiyam 
2113ea8e1828Sksagiyam   Input Parameters:
2114ea8e1828Sksagiyam + dm     - The DM into which the topology is loaded
2115ea8e1828Sksagiyam - viewer - The PetscViewer for the saved topology
2116ea8e1828Sksagiyam 
2117dec9e869Sksagiyam   Output Parameters:
2118f84dd6b4Sksagiyam . 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
2119dec9e869Sksagiyam 
2120ea8e1828Sksagiyam   Level: advanced
2121ea8e1828Sksagiyam 
2122db781477SPatrick Sanan .seealso: `DMLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`
2123ea8e1828Sksagiyam @*/
2124f84dd6b4Sksagiyam PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF)
2125ea8e1828Sksagiyam {
2126ea8e1828Sksagiyam   PetscBool      ishdf5;
2127ea8e1828Sksagiyam 
2128ea8e1828Sksagiyam   PetscFunctionBegin;
2129ea8e1828Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2130ea8e1828Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2131f84dd6b4Sksagiyam   if (globalToLocalPointSF) PetscValidPointer(globalToLocalPointSF, 3);
21329566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
21339566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_TopologyLoad,viewer,0,0,0));
2134ea8e1828Sksagiyam   if (ishdf5) {
2135ea8e1828Sksagiyam #if defined(PETSC_HAVE_HDF5)
2136ea8e1828Sksagiyam     PetscViewerFormat format;
21379566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
2138ea8e1828Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
21399566063dSJacob Faibussowitsch       PetscCall(DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
214098921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2141ea8e1828Sksagiyam #else
2142ea8e1828Sksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2143ea8e1828Sksagiyam #endif
2144ea8e1828Sksagiyam   }
21459566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_TopologyLoad,viewer,0,0,0));
2146ea8e1828Sksagiyam   PetscFunctionReturn(0);
2147ea8e1828Sksagiyam }
2148ea8e1828Sksagiyam 
21493e701f1cSksagiyam /*@
21503e701f1cSksagiyam   DMPlexCoordinatesLoad - Loads coordinates into a DMPlex
21513e701f1cSksagiyam 
21523e701f1cSksagiyam   Collective on DM
21533e701f1cSksagiyam 
21543e701f1cSksagiyam   Input Parameters:
21553e701f1cSksagiyam + dm     - The DM into which the coordinates are loaded
2156c9ad657eSksagiyam . viewer - The PetscViewer for the saved coordinates
2157c9ad657eSksagiyam - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer
21583e701f1cSksagiyam 
21593e701f1cSksagiyam   Level: advanced
21603e701f1cSksagiyam 
2161db781477SPatrick Sanan .seealso: `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`
21623e701f1cSksagiyam @*/
2163c9ad657eSksagiyam PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF)
21643e701f1cSksagiyam {
21653e701f1cSksagiyam   PetscBool      ishdf5;
21663e701f1cSksagiyam 
21673e701f1cSksagiyam   PetscFunctionBegin;
21683e701f1cSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
21693e701f1cSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2170c9ad657eSksagiyam   PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3);
21719566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
21729566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesLoad,viewer,0,0,0));
21733e701f1cSksagiyam   if (ishdf5) {
21743e701f1cSksagiyam #if defined(PETSC_HAVE_HDF5)
21753e701f1cSksagiyam     PetscViewerFormat format;
21769566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
21773e701f1cSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
21789566063dSJacob Faibussowitsch       PetscCall(DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
217998921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
21803e701f1cSksagiyam #else
21813e701f1cSksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
21823e701f1cSksagiyam #endif
21833e701f1cSksagiyam   }
21849566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesLoad,viewer,0,0,0));
21853e701f1cSksagiyam   PetscFunctionReturn(0);
21863e701f1cSksagiyam }
21873e701f1cSksagiyam 
2188b08ad5deSksagiyam /*@
2189b08ad5deSksagiyam   DMPlexLabelsLoad - Loads labels into a DMPlex
2190b08ad5deSksagiyam 
2191b08ad5deSksagiyam   Collective on DM
2192b08ad5deSksagiyam 
2193b08ad5deSksagiyam   Input Parameters:
2194b08ad5deSksagiyam + dm     - The DM into which the labels are loaded
2195e6368b79SVaclav Hapla . viewer - The PetscViewer for the saved labels
2196e6368b79SVaclav Hapla - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer
2197b08ad5deSksagiyam 
2198b08ad5deSksagiyam   Level: advanced
2199b08ad5deSksagiyam 
2200e6368b79SVaclav Hapla   Notes:
2201e6368b79SVaclav Hapla   The PetscSF argument must not be NULL if the DM is distributed, otherwise an error occurs.
2202e6368b79SVaclav Hapla 
2203db781477SPatrick Sanan .seealso: `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`
2204b08ad5deSksagiyam @*/
2205e6368b79SVaclav Hapla PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF)
2206b08ad5deSksagiyam {
2207b08ad5deSksagiyam   PetscBool      ishdf5;
2208b08ad5deSksagiyam 
2209b08ad5deSksagiyam   PetscFunctionBegin;
2210b08ad5deSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2211b08ad5deSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2212e6368b79SVaclav Hapla   if (globalToLocalPointSF) PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3);
22139566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
22149566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LabelsLoad,viewer,0,0,0));
2215b08ad5deSksagiyam   if (ishdf5) {
2216b08ad5deSksagiyam #if defined(PETSC_HAVE_HDF5)
2217b08ad5deSksagiyam     PetscViewerFormat format;
2218b08ad5deSksagiyam 
22199566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
2220b08ad5deSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
22219566063dSJacob Faibussowitsch       PetscCall(DMPlexLabelsLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
222298921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2223b08ad5deSksagiyam #else
2224b08ad5deSksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2225b08ad5deSksagiyam #endif
2226b08ad5deSksagiyam   }
22279566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LabelsLoad,viewer,0,0,0));
2228b08ad5deSksagiyam   PetscFunctionReturn(0);
2229b08ad5deSksagiyam }
2230b08ad5deSksagiyam 
2231f84dd6b4Sksagiyam /*@
2232f84dd6b4Sksagiyam   DMPlexSectionLoad - Loads section into a DMPlex
2233f84dd6b4Sksagiyam 
2234f84dd6b4Sksagiyam   Collective on DM
2235f84dd6b4Sksagiyam 
2236f84dd6b4Sksagiyam   Input Parameters:
2237f84dd6b4Sksagiyam + dm          - The DM that represents the topology
2238f84dd6b4Sksagiyam . viewer      - The PetscViewer that represents the on-disk section (sectionA)
2239f84dd6b4Sksagiyam . sectiondm   - The DM into which the on-disk section (sectionA) is migrated
2240f84dd6b4Sksagiyam - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer
2241f84dd6b4Sksagiyam 
2242f84dd6b4Sksagiyam   Output Parameters
2243f84dd6b4Sksagiyam + 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)
2244f84dd6b4Sksagiyam - 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)
2245f84dd6b4Sksagiyam 
2246f84dd6b4Sksagiyam   Level: advanced
2247f84dd6b4Sksagiyam 
2248f84dd6b4Sksagiyam   Notes:
2249f84dd6b4Sksagiyam   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.
2250f84dd6b4Sksagiyam 
2251f84dd6b4Sksagiyam   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.
2252f84dd6b4Sksagiyam 
2253f84dd6b4Sksagiyam   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.
2254f84dd6b4Sksagiyam 
2255f84dd6b4Sksagiyam   Example using 2 processes:
2256f84dd6b4Sksagiyam $  NX (number of points on dm): 4
2257f84dd6b4Sksagiyam $  sectionA                   : the on-disk section
2258f84dd6b4Sksagiyam $  vecA                       : a vector associated with sectionA
2259f84dd6b4Sksagiyam $  sectionB                   : sectiondm's local section constructed in this function
2260f84dd6b4Sksagiyam $  vecB (local)               : a vector associated with sectiondm's local section
2261f84dd6b4Sksagiyam $  vecB (global)              : a vector associated with sectiondm's global section
2262f84dd6b4Sksagiyam $
2263f84dd6b4Sksagiyam $                                     rank 0    rank 1
2264f84dd6b4Sksagiyam $  vecA (global)                  : [.0 .4 .1 | .2 .3]        <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad()
2265f84dd6b4Sksagiyam $  sectionA->atlasOff             :       0 2 | 1             <- loaded in PetscSectionLoad()
2266f84dd6b4Sksagiyam $  sectionA->atlasDof             :       1 3 | 1             <- loaded in PetscSectionLoad()
2267f84dd6b4Sksagiyam $  sectionA's global point numbers:       0 2 | 3             <- loaded in DMPlexSectionLoad()
2268f84dd6b4Sksagiyam $  [0, NX)                        :       0 1 | 2 3           <- conceptual partition used in globalToLocalPointSF
2269f84dd6b4Sksagiyam $  sectionB's global point numbers:     0 1 3 | 3 2           <- associated with [0, NX) by globalToLocalPointSF
2270f84dd6b4Sksagiyam $  sectionB->atlasDof             :     1 0 1 | 1 3
2271f84dd6b4Sksagiyam $  sectionB->atlasOff (no perm)   :     0 1 1 | 0 1
2272f84dd6b4Sksagiyam $  vecB (local)                   :   [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF
2273f84dd6b4Sksagiyam $  vecB (global)                  :    [.0 .4 | .1 .2 .3]     <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF
2274f84dd6b4Sksagiyam $
2275f84dd6b4Sksagiyam $  where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0.
2276f84dd6b4Sksagiyam 
2277db781477SPatrick Sanan .seealso: `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`, `PetscSectionLoad()`, `DMPlexSectionView()`
2278f84dd6b4Sksagiyam @*/
2279f84dd6b4Sksagiyam PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF globalToLocalPointSF, PetscSF *globalDofSF, PetscSF *localDofSF)
2280f84dd6b4Sksagiyam {
2281f84dd6b4Sksagiyam   PetscBool      ishdf5;
2282f84dd6b4Sksagiyam 
2283f84dd6b4Sksagiyam   PetscFunctionBegin;
2284f84dd6b4Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2285f84dd6b4Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2286f84dd6b4Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
2287f84dd6b4Sksagiyam   PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4);
2288f84dd6b4Sksagiyam   if (globalDofSF) PetscValidPointer(globalDofSF, 5);
2289f84dd6b4Sksagiyam   if (localDofSF) PetscValidPointer(localDofSF, 6);
22909566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5));
22919566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_SectionLoad,viewer,0,0,0));
2292f84dd6b4Sksagiyam   if (ishdf5) {
2293f84dd6b4Sksagiyam #if defined(PETSC_HAVE_HDF5)
22949566063dSJacob Faibussowitsch     PetscCall(DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF));
2295f84dd6b4Sksagiyam #else
2296f84dd6b4Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2297f84dd6b4Sksagiyam #endif
2298f84dd6b4Sksagiyam   }
22999566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_SectionLoad,viewer,0,0,0));
2300f84dd6b4Sksagiyam   PetscFunctionReturn(0);
2301f84dd6b4Sksagiyam }
2302f84dd6b4Sksagiyam 
23038be3dfe1Sksagiyam /*@
23048be3dfe1Sksagiyam   DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector
23058be3dfe1Sksagiyam 
23068be3dfe1Sksagiyam   Collective on DM
23078be3dfe1Sksagiyam 
23088be3dfe1Sksagiyam   Input Parameters:
23098be3dfe1Sksagiyam + dm        - The DM that represents the topology
23108be3dfe1Sksagiyam . viewer    - The PetscViewer that represents the on-disk vector data
23118be3dfe1Sksagiyam . sectiondm - The DM that contains the global section on which vec is defined
23128be3dfe1Sksagiyam . sf        - The SF that migrates the on-disk vector data into vec
23138be3dfe1Sksagiyam - vec       - The global vector to set values of
23148be3dfe1Sksagiyam 
23158be3dfe1Sksagiyam   Level: advanced
23168be3dfe1Sksagiyam 
23178be3dfe1Sksagiyam   Notes:
23188be3dfe1Sksagiyam   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.
23198be3dfe1Sksagiyam 
23208be3dfe1Sksagiyam   Typical calling sequence
23218be3dfe1Sksagiyam $       DMCreate(PETSC_COMM_WORLD, &dm);
23228be3dfe1Sksagiyam $       DMSetType(dm, DMPLEX);
23238be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)dm, "topologydm_name");
23248be3dfe1Sksagiyam $       DMPlexTopologyLoad(dm, viewer, &sfX);
23258be3dfe1Sksagiyam $       DMClone(dm, &sectiondm);
23268be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
23278be3dfe1Sksagiyam $       DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL);
23288be3dfe1Sksagiyam $       DMGetGlobalVector(sectiondm, &vec);
23298be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)vec, "vec_name");
23308be3dfe1Sksagiyam $       DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec);
23318be3dfe1Sksagiyam $       DMRestoreGlobalVector(sectiondm, &vec);
23328be3dfe1Sksagiyam $       PetscSFDestroy(&gsf);
23338be3dfe1Sksagiyam $       PetscSFDestroy(&sfX);
23348be3dfe1Sksagiyam $       DMDestroy(&sectiondm);
23358be3dfe1Sksagiyam $       DMDestroy(&dm);
23368be3dfe1Sksagiyam 
2337db781477SPatrick Sanan .seealso: `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexLocalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`
23388be3dfe1Sksagiyam @*/
23398be3dfe1Sksagiyam PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec)
23408be3dfe1Sksagiyam {
23418be3dfe1Sksagiyam   PetscBool       ishdf5;
23428be3dfe1Sksagiyam 
23438be3dfe1Sksagiyam   PetscFunctionBegin;
23448be3dfe1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
23458be3dfe1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
23468be3dfe1Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
23478be3dfe1Sksagiyam   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4);
23488be3dfe1Sksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 5);
23498be3dfe1Sksagiyam   /* Check consistency */
23508be3dfe1Sksagiyam   {
23518be3dfe1Sksagiyam     PetscSection  section;
23528be3dfe1Sksagiyam     PetscBool     includesConstraints;
23538be3dfe1Sksagiyam     PetscInt      m, m1;
23548be3dfe1Sksagiyam 
23559566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
23569566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(sectiondm, &section));
23579566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
23589566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
23599566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
236063a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m);
23618be3dfe1Sksagiyam   }
23629566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5));
23639566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorLoad,viewer,0,0,0));
23648be3dfe1Sksagiyam   if (ishdf5) {
23658be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5)
23669566063dSJacob Faibussowitsch     PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec));
23678be3dfe1Sksagiyam #else
23688be3dfe1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
23698be3dfe1Sksagiyam #endif
23708be3dfe1Sksagiyam   }
23719566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorLoad,viewer,0,0,0));
23728be3dfe1Sksagiyam   PetscFunctionReturn(0);
23738be3dfe1Sksagiyam }
23748be3dfe1Sksagiyam 
23758be3dfe1Sksagiyam /*@
23768be3dfe1Sksagiyam   DMPlexLocalVectorLoad - Loads on-disk vector data into a local vector
23778be3dfe1Sksagiyam 
23788be3dfe1Sksagiyam   Collective on DM
23798be3dfe1Sksagiyam 
23808be3dfe1Sksagiyam   Input Parameters:
23818be3dfe1Sksagiyam + dm        - The DM that represents the topology
23828be3dfe1Sksagiyam . viewer    - The PetscViewer that represents the on-disk vector data
23838be3dfe1Sksagiyam . sectiondm - The DM that contains the local section on which vec is defined
23848be3dfe1Sksagiyam . sf        - The SF that migrates the on-disk vector data into vec
23858be3dfe1Sksagiyam - vec       - The local vector to set values of
23868be3dfe1Sksagiyam 
23878be3dfe1Sksagiyam   Level: advanced
23888be3dfe1Sksagiyam 
23898be3dfe1Sksagiyam   Notes:
23908be3dfe1Sksagiyam   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.
23918be3dfe1Sksagiyam 
23928be3dfe1Sksagiyam   Typical calling sequence
23938be3dfe1Sksagiyam $       DMCreate(PETSC_COMM_WORLD, &dm);
23948be3dfe1Sksagiyam $       DMSetType(dm, DMPLEX);
23958be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)dm, "topologydm_name");
23968be3dfe1Sksagiyam $       DMPlexTopologyLoad(dm, viewer, &sfX);
23978be3dfe1Sksagiyam $       DMClone(dm, &sectiondm);
23988be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
23998be3dfe1Sksagiyam $       DMPlexSectionLoad(dm, viewer, sectiondm, sfX, NULL, &lsf);
24008be3dfe1Sksagiyam $       DMGetLocalVector(sectiondm, &vec);
24018be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)vec, "vec_name");
24028be3dfe1Sksagiyam $       DMPlexLocalVectorLoad(dm, viewer, sectiondm, lsf, vec);
24038be3dfe1Sksagiyam $       DMRestoreLocalVector(sectiondm, &vec);
24048be3dfe1Sksagiyam $       PetscSFDestroy(&lsf);
24058be3dfe1Sksagiyam $       PetscSFDestroy(&sfX);
24068be3dfe1Sksagiyam $       DMDestroy(&sectiondm);
24078be3dfe1Sksagiyam $       DMDestroy(&dm);
24088be3dfe1Sksagiyam 
2409db781477SPatrick Sanan .seealso: `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`
24108be3dfe1Sksagiyam @*/
24118be3dfe1Sksagiyam PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec)
24128be3dfe1Sksagiyam {
24138be3dfe1Sksagiyam   PetscBool       ishdf5;
24148be3dfe1Sksagiyam 
24158be3dfe1Sksagiyam   PetscFunctionBegin;
24168be3dfe1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
24178be3dfe1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
24188be3dfe1Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
24198be3dfe1Sksagiyam   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4);
24208be3dfe1Sksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 5);
24218be3dfe1Sksagiyam   /* Check consistency */
24228be3dfe1Sksagiyam   {
24238be3dfe1Sksagiyam     PetscSection  section;
24248be3dfe1Sksagiyam     PetscBool     includesConstraints;
24258be3dfe1Sksagiyam     PetscInt      m, m1;
24268be3dfe1Sksagiyam 
24279566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
24289566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(sectiondm, &section));
24299566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
24309566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
24319566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
243263a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m);
24338be3dfe1Sksagiyam   }
24349566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5));
24359566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorLoad,viewer,0,0,0));
24368be3dfe1Sksagiyam   if (ishdf5) {
24378be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5)
24389566063dSJacob Faibussowitsch     PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec));
24398be3dfe1Sksagiyam #else
24408be3dfe1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
24418be3dfe1Sksagiyam #endif
24428be3dfe1Sksagiyam   }
24439566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorLoad,viewer,0,0,0));
24448be3dfe1Sksagiyam   PetscFunctionReturn(0);
24458be3dfe1Sksagiyam }
24468be3dfe1Sksagiyam 
2447552f7358SJed Brown PetscErrorCode DMDestroy_Plex(DM dm)
2448552f7358SJed Brown {
2449552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2450552f7358SJed Brown 
2451552f7358SJed Brown   PetscFunctionBegin;
24529566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMSetUpGLVisViewer_C",NULL));
24539566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertBoundaryValues_C", NULL));
24549566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMCreateNeumannOverlap_C", NULL));
24559566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMInterpolateSolution_C", NULL));
24562e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertTimeDerviativeBoundaryValues_C", NULL));
24572e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexGetOverlap_C", NULL));
24582e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexDistributeGetDefault_C", NULL));
24592e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexDistributeSetDefault_C", NULL));
24602e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"MatComputeNeumannOverlap_C",NULL));
24616bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexReorderGetDefault_C", NULL));
24626bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexReorderSetDefault_C", NULL));
2463c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexGetOverlap_C",NULL));
2464c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexSetOverlap_C",NULL));
24650d644c17SKarl Rupp   if (--mesh->refct > 0) PetscFunctionReturn(0);
24669566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->coneSection));
24679566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->cones));
24689566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->coneOrientations));
24699566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->supportSection));
24709566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->subdomainSection));
24719566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->supports));
24729566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->facesTmp));
24739566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->tetgenOpts));
24749566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->triangleOpts));
24759566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->transformType));
24769566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerDestroy(&mesh->partitioner));
24779566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&mesh->subpointMap));
24789566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->subpointIS));
24799566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->globalVertexNumbers));
24809566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->globalCellNumbers));
24819566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->anchorSection));
24829566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->anchorIS));
24839566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->parentSection));
24849566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->parents));
24859566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->childIDs));
24869566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->childSection));
24879566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->children));
24889566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&mesh->referenceTree));
24899566063dSJacob Faibussowitsch   PetscCall(PetscGridHashDestroy(&mesh->lbox));
24909566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->neighbors));
24919566063dSJacob Faibussowitsch   if (mesh->metricCtx) PetscCall(PetscFree(mesh->metricCtx));
2492552f7358SJed Brown   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
24939566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh));
2494552f7358SJed Brown   PetscFunctionReturn(0);
2495552f7358SJed Brown }
2496552f7358SJed Brown 
2497b412c318SBarry Smith PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J)
2498552f7358SJed Brown {
24998d1174e4SMatthew G. Knepley   PetscSection           sectionGlobal;
2500acd755d7SMatthew G. Knepley   PetscInt               bs = -1, mbs;
25019fca9976SJed Brown   PetscInt               localSize, localStart = 0;
2502837628f4SStefano Zampini   PetscBool              isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS;
2503b412c318SBarry Smith   MatType                mtype;
25041428887cSShri Abhyankar   ISLocalToGlobalMapping ltog;
2505552f7358SJed Brown 
2506552f7358SJed Brown   PetscFunctionBegin;
25079566063dSJacob Faibussowitsch   PetscCall(MatInitializePackage());
2508b412c318SBarry Smith   mtype = dm->mattype;
25099566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dm, &sectionGlobal));
25109566063dSJacob Faibussowitsch   /* PetscCall(PetscSectionGetStorageSize(sectionGlobal, &localSize)); */
25119566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize));
25129fca9976SJed Brown   PetscCallMPI(MPI_Exscan(&localSize, &localStart, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) dm)));
25139566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), J));
25149566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE));
25159566063dSJacob Faibussowitsch   PetscCall(MatSetType(*J, mtype));
25169566063dSJacob Faibussowitsch   PetscCall(MatSetFromOptions(*J));
25179566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(*J, &mbs));
2518acd755d7SMatthew G. Knepley   if (mbs > 1) bs = mbs;
25199566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSHELL, &isShell));
25209566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATBAIJ, &isBlock));
25219566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock));
25229566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock));
25239566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSBAIJ, &isSymBlock));
25249566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock));
25259566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock));
25269566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATIS, &isMatIS));
2527552f7358SJed Brown   if (!isShell) {
2528837628f4SStefano Zampini     PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS);
25299fca9976SJed Brown     PetscInt  *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *pblocks;
2530fad22124SMatthew G Knepley     PetscInt  pStart, pEnd, p, dof, cdof;
2531552f7358SJed Brown 
25329566063dSJacob Faibussowitsch     PetscCall(DMGetLocalToGlobalMapping(dm,&ltog));
25339fca9976SJed Brown 
25349fca9976SJed Brown     PetscCall(PetscCalloc1(localSize, &pblocks));
25359566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(sectionGlobal, &pStart, &pEnd));
2536e432b41dSStefano Zampini     for (p = pStart; p < pEnd; ++p) {
25379fca9976SJed Brown       PetscInt bdof, offset;
2538a9d99c84SMatthew G. Knepley 
25399566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sectionGlobal, p, &dof));
25409fca9976SJed Brown       PetscCall(PetscSectionGetOffset(sectionGlobal, p, &offset));
25419566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetConstraintDof(sectionGlobal, p, &cdof));
25429fca9976SJed Brown       for (PetscInt i=0; i < dof - cdof; i++)
25439fca9976SJed Brown         pblocks[offset - localStart + i] = dof - cdof;
25441d17a0a3SMatthew G. Knepley       dof  = dof < 0 ? -(dof+1) : dof;
25451d17a0a3SMatthew G. Knepley       bdof = cdof && (dof-cdof) ? 1 : dof;
25461d17a0a3SMatthew G. Knepley       if (dof) {
25471d17a0a3SMatthew G. Knepley         if (bs < 0)          {bs = bdof;}
25489fca9976SJed Brown         else if (bs != bdof) {bs = 1;}
2549552f7358SJed Brown       }
25502a28c762SMatthew G Knepley     }
25512a28c762SMatthew G Knepley     /* Must have same blocksize on all procs (some might have no points) */
2552e432b41dSStefano Zampini     bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs;
2553e432b41dSStefano Zampini     bsLocal[1] = bs;
25549566063dSJacob Faibussowitsch     PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax));
2555e432b41dSStefano Zampini     if (bsMinMax[0] != bsMinMax[1]) bs = 1;
2556e432b41dSStefano Zampini     else bs = bsMinMax[0];
25576fd5c86aSStefano Zampini     bs = PetscMax(1,bs);
25589566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(*J,ltog,ltog));
25590682b8bbSJed Brown     if (dm->prealloc_skip) { // User will likely use MatSetPreallocationCOO(), but still set structural parameters
25609566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSize(*J, bs));
25619566063dSJacob Faibussowitsch       PetscCall(MatSetUp(*J));
25620682b8bbSJed Brown     } else {
25639566063dSJacob Faibussowitsch       PetscCall(PetscCalloc4(localSize/bs, &dnz, localSize/bs, &onz, localSize/bs, &dnzu, localSize/bs, &onzu));
25649566063dSJacob Faibussowitsch       PetscCall(DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix));
25659566063dSJacob Faibussowitsch       PetscCall(PetscFree4(dnz, onz, dnzu, onzu));
2566552f7358SJed Brown     }
25679fca9976SJed Brown     { // Consolidate blocks
25689fca9976SJed Brown       PetscInt nblocks = 0;
25699fca9976SJed Brown       for (PetscInt i=0; i<localSize; i += PetscMax(1, pblocks[i])) {
25709fca9976SJed Brown         if (pblocks[i] == 0) continue;
25719fca9976SJed Brown         pblocks[nblocks++] = pblocks[i]; // nblocks always <= i
25729fca9976SJed Brown         for (PetscInt j=1; j<pblocks[i]; j++) {
25739fca9976SJed Brown            PetscCheck(pblocks[i+j] == pblocks[i], PETSC_COMM_SELF, PETSC_ERR_PLIB, "Block of size %" PetscInt_FMT " mismatches entry %" PetscInt_FMT, pblocks[i], pblocks[i+j]);
25749fca9976SJed Brown         }
25759fca9976SJed Brown       }
25769fca9976SJed Brown       PetscCall(MatSetVariableBlockSizes(*J, nblocks, pblocks));
25779fca9976SJed Brown     }
25789fca9976SJed Brown     PetscCall(PetscFree(pblocks));
2579aa0f6e3cSJed Brown   }
25809566063dSJacob Faibussowitsch   PetscCall(MatSetDM(*J, dm));
2581552f7358SJed Brown   PetscFunctionReturn(0);
2582552f7358SJed Brown }
2583552f7358SJed Brown 
25847cd05799SMatthew G. Knepley /*@
2585a8f00d21SMatthew G. Knepley   DMPlexGetSubdomainSection - Returns the section associated with the subdomain
2586be36d101SStefano Zampini 
2587be36d101SStefano Zampini   Not collective
2588be36d101SStefano Zampini 
2589be36d101SStefano Zampini   Input Parameter:
2590be36d101SStefano Zampini . mesh - The DMPlex
2591be36d101SStefano Zampini 
2592be36d101SStefano Zampini   Output Parameters:
2593be36d101SStefano Zampini . subsection - The subdomain section
2594be36d101SStefano Zampini 
2595be36d101SStefano Zampini   Level: developer
2596be36d101SStefano Zampini 
2597be36d101SStefano Zampini .seealso:
25987cd05799SMatthew G. Knepley @*/
2599be36d101SStefano Zampini PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection)
2600be36d101SStefano Zampini {
2601be36d101SStefano Zampini   DM_Plex       *mesh = (DM_Plex*) dm->data;
2602be36d101SStefano Zampini 
2603be36d101SStefano Zampini   PetscFunctionBegin;
2604be36d101SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2605be36d101SStefano Zampini   if (!mesh->subdomainSection) {
2606be36d101SStefano Zampini     PetscSection section;
2607be36d101SStefano Zampini     PetscSF      sf;
2608be36d101SStefano Zampini 
26099566063dSJacob Faibussowitsch     PetscCall(PetscSFCreate(PETSC_COMM_SELF,&sf));
26109566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm,&section));
26119566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreateGlobalSection(section,sf,PETSC_FALSE,PETSC_TRUE,&mesh->subdomainSection));
26129566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sf));
2613be36d101SStefano Zampini   }
2614be36d101SStefano Zampini   *subsection = mesh->subdomainSection;
2615be36d101SStefano Zampini   PetscFunctionReturn(0);
2616be36d101SStefano Zampini }
2617be36d101SStefano Zampini 
2618552f7358SJed Brown /*@
2619552f7358SJed Brown   DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd)
2620552f7358SJed Brown 
2621552f7358SJed Brown   Not collective
2622552f7358SJed Brown 
2623552f7358SJed Brown   Input Parameter:
2624552f7358SJed Brown . mesh - The DMPlex
2625552f7358SJed Brown 
2626552f7358SJed Brown   Output Parameters:
2627552f7358SJed Brown + pStart - The first mesh point
2628552f7358SJed Brown - pEnd   - The upper bound for mesh points
2629552f7358SJed Brown 
2630552f7358SJed Brown   Level: beginner
2631552f7358SJed Brown 
2632db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetChart()`
2633552f7358SJed Brown @*/
2634552f7358SJed Brown PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd)
2635552f7358SJed Brown {
2636552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2637552f7358SJed Brown 
2638552f7358SJed Brown   PetscFunctionBegin;
2639552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
26409566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->coneSection, pStart, pEnd));
2641552f7358SJed Brown   PetscFunctionReturn(0);
2642552f7358SJed Brown }
2643552f7358SJed Brown 
2644552f7358SJed Brown /*@
2645552f7358SJed Brown   DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd)
2646552f7358SJed Brown 
2647552f7358SJed Brown   Not collective
2648552f7358SJed Brown 
2649552f7358SJed Brown   Input Parameters:
2650552f7358SJed Brown + mesh - The DMPlex
2651552f7358SJed Brown . pStart - The first mesh point
2652552f7358SJed Brown - pEnd   - The upper bound for mesh points
2653552f7358SJed Brown 
2654552f7358SJed Brown   Output Parameters:
2655552f7358SJed Brown 
2656552f7358SJed Brown   Level: beginner
2657552f7358SJed Brown 
2658db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetChart()`
2659552f7358SJed Brown @*/
2660552f7358SJed Brown PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd)
2661552f7358SJed Brown {
2662552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2663552f7358SJed Brown 
2664552f7358SJed Brown   PetscFunctionBegin;
2665552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
26669566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(mesh->coneSection, pStart, pEnd));
26679566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(mesh->supportSection, pStart, pEnd));
2668552f7358SJed Brown   PetscFunctionReturn(0);
2669552f7358SJed Brown }
2670552f7358SJed Brown 
2671552f7358SJed Brown /*@
2672eaf898f9SPatrick Sanan   DMPlexGetConeSize - Return the number of in-edges for this point in the DAG
2673552f7358SJed Brown 
2674552f7358SJed Brown   Not collective
2675552f7358SJed Brown 
2676552f7358SJed Brown   Input Parameters:
2677552f7358SJed Brown + mesh - The DMPlex
2678eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
2679552f7358SJed Brown 
2680552f7358SJed Brown   Output Parameter:
2681552f7358SJed Brown . size - The cone size for point p
2682552f7358SJed Brown 
2683552f7358SJed Brown   Level: beginner
2684552f7358SJed Brown 
2685db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`
2686552f7358SJed Brown @*/
2687552f7358SJed Brown PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size)
2688552f7358SJed Brown {
2689552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2690552f7358SJed Brown 
2691552f7358SJed Brown   PetscFunctionBegin;
2692552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2693dadcf809SJacob Faibussowitsch   PetscValidIntPointer(size, 3);
26949566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, size));
2695552f7358SJed Brown   PetscFunctionReturn(0);
2696552f7358SJed Brown }
2697552f7358SJed Brown 
2698552f7358SJed Brown /*@
2699eaf898f9SPatrick Sanan   DMPlexSetConeSize - Set the number of in-edges for this point in the DAG
2700552f7358SJed Brown 
2701552f7358SJed Brown   Not collective
2702552f7358SJed Brown 
2703552f7358SJed Brown   Input Parameters:
2704552f7358SJed Brown + mesh - The DMPlex
2705eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
2706552f7358SJed Brown - size - The cone size for point p
2707552f7358SJed Brown 
2708552f7358SJed Brown   Output Parameter:
2709552f7358SJed Brown 
2710552f7358SJed Brown   Note:
2711552f7358SJed Brown   This should be called after DMPlexSetChart().
2712552f7358SJed Brown 
2713552f7358SJed Brown   Level: beginner
2714552f7358SJed Brown 
2715db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetConeSize()`, `DMPlexSetChart()`
2716552f7358SJed Brown @*/
2717552f7358SJed Brown PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size)
2718552f7358SJed Brown {
2719552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2720552f7358SJed Brown 
2721552f7358SJed Brown   PetscFunctionBegin;
2722552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
27239566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetDof(mesh->coneSection, p, size));
2724552f7358SJed Brown   PetscFunctionReturn(0);
2725552f7358SJed Brown }
2726552f7358SJed Brown 
2727f5a469b9SMatthew G. Knepley /*@
2728eaf898f9SPatrick Sanan   DMPlexAddConeSize - Add the given number of in-edges to this point in the DAG
2729f5a469b9SMatthew G. Knepley 
2730f5a469b9SMatthew G. Knepley   Not collective
2731f5a469b9SMatthew G. Knepley 
2732f5a469b9SMatthew G. Knepley   Input Parameters:
2733f5a469b9SMatthew G. Knepley + mesh - The DMPlex
2734eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
2735f5a469b9SMatthew G. Knepley - size - The additional cone size for point p
2736f5a469b9SMatthew G. Knepley 
2737f5a469b9SMatthew G. Knepley   Output Parameter:
2738f5a469b9SMatthew G. Knepley 
2739f5a469b9SMatthew G. Knepley   Note:
2740f5a469b9SMatthew G. Knepley   This should be called after DMPlexSetChart().
2741f5a469b9SMatthew G. Knepley 
2742f5a469b9SMatthew G. Knepley   Level: beginner
2743f5a469b9SMatthew G. Knepley 
2744db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexGetConeSize()`, `DMPlexSetChart()`
2745f5a469b9SMatthew G. Knepley @*/
2746f5a469b9SMatthew G. Knepley PetscErrorCode DMPlexAddConeSize(DM dm, PetscInt p, PetscInt size)
2747f5a469b9SMatthew G. Knepley {
2748f5a469b9SMatthew G. Knepley   DM_Plex       *mesh = (DM_Plex*) dm->data;
2749f5a469b9SMatthew G. Knepley   PetscFunctionBegin;
2750f5a469b9SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
27519566063dSJacob Faibussowitsch   PetscCall(PetscSectionAddDof(mesh->coneSection, p, size));
2752f5a469b9SMatthew G. Knepley   PetscFunctionReturn(0);
2753f5a469b9SMatthew G. Knepley }
2754f5a469b9SMatthew G. Knepley 
2755552f7358SJed Brown /*@C
2756eaf898f9SPatrick Sanan   DMPlexGetCone - Return the points on the in-edges for this point in the DAG
2757552f7358SJed Brown 
2758552f7358SJed Brown   Not collective
2759552f7358SJed Brown 
2760552f7358SJed Brown   Input Parameters:
2761833c876bSVaclav Hapla + dm - The DMPlex
2762eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
2763552f7358SJed Brown 
2764552f7358SJed Brown   Output Parameter:
2765552f7358SJed Brown . cone - An array of points which are on the in-edges for point p
2766552f7358SJed Brown 
2767552f7358SJed Brown   Level: beginner
2768552f7358SJed Brown 
27693813dfbdSMatthew G Knepley   Fortran Notes:
27703813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
27713813dfbdSMatthew G Knepley   include petsc.h90 in your code.
2772922102d1SVaclav Hapla   You must also call DMPlexRestoreCone() after you finish using the returned array.
2773922102d1SVaclav Hapla   DMPlexRestoreCone() is not needed/available in C.
27743813dfbdSMatthew G Knepley 
2775db781477SPatrick Sanan .seealso: `DMPlexGetConeSize()`, `DMPlexSetCone()`, `DMPlexGetConeTuple()`, `DMPlexSetChart()`
2776552f7358SJed Brown @*/
2777552f7358SJed Brown PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[])
2778552f7358SJed Brown {
2779552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2780552f7358SJed Brown   PetscInt       off;
2781552f7358SJed Brown 
2782552f7358SJed Brown   PetscFunctionBegin;
2783552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2784552f7358SJed Brown   PetscValidPointer(cone, 3);
27859566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
2786552f7358SJed Brown   *cone = &mesh->cones[off];
2787552f7358SJed Brown   PetscFunctionReturn(0);
2788552f7358SJed Brown }
2789552f7358SJed Brown 
27900ce7577fSVaclav Hapla /*@C
27910ce7577fSVaclav Hapla   DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG
27920ce7577fSVaclav Hapla 
27930ce7577fSVaclav Hapla   Not collective
27940ce7577fSVaclav Hapla 
27950ce7577fSVaclav Hapla   Input Parameters:
27960ce7577fSVaclav Hapla + dm - The DMPlex
27970ce7577fSVaclav Hapla - p - The IS of points, which must lie in the chart set with DMPlexSetChart()
27980ce7577fSVaclav Hapla 
2799d8d19677SJose E. Roman   Output Parameters:
28000ce7577fSVaclav Hapla + pConesSection - PetscSection describing the layout of pCones
28010ce7577fSVaclav Hapla - pCones - An array of points which are on the in-edges for the point set p
28020ce7577fSVaclav Hapla 
28030ce7577fSVaclav Hapla   Level: intermediate
28040ce7577fSVaclav Hapla 
2805db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeRecursive()`, `DMPlexSetChart()`
28060ce7577fSVaclav Hapla @*/
28070ce7577fSVaclav Hapla PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones)
28080ce7577fSVaclav Hapla {
28090ce7577fSVaclav Hapla   PetscSection        cs, newcs;
28100ce7577fSVaclav Hapla   PetscInt            *cones;
28110ce7577fSVaclav Hapla   PetscInt            *newarr=NULL;
28120ce7577fSVaclav Hapla   PetscInt            n;
28130ce7577fSVaclav Hapla 
28140ce7577fSVaclav Hapla   PetscFunctionBegin;
28159566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCones(dm, &cones));
28169566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSection(dm, &cs));
28179566063dSJacob Faibussowitsch   PetscCall(PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void**)&newarr) : NULL));
28180ce7577fSVaclav Hapla   if (pConesSection) *pConesSection = newcs;
28190ce7577fSVaclav Hapla   if (pCones) {
28209566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(newcs, &n));
28219566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones));
28220ce7577fSVaclav Hapla   }
28230ce7577fSVaclav Hapla   PetscFunctionReturn(0);
28240ce7577fSVaclav Hapla }
28250ce7577fSVaclav Hapla 
2826af9eab45SVaclav Hapla /*@
2827af9eab45SVaclav Hapla   DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices.
2828d4636a37SVaclav Hapla 
2829d4636a37SVaclav Hapla   Not collective
2830d4636a37SVaclav Hapla 
2831d4636a37SVaclav Hapla   Input Parameters:
2832d4636a37SVaclav Hapla + dm - The DMPlex
2833af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart()
2834d4636a37SVaclav Hapla 
2835d4636a37SVaclav Hapla   Output Parameter:
2836af9eab45SVaclav Hapla . expandedPoints - An array of vertices recursively expanded from input points
2837d4636a37SVaclav Hapla 
2838d4636a37SVaclav Hapla   Level: advanced
2839d4636a37SVaclav Hapla 
2840af9eab45SVaclav Hapla   Notes:
2841af9eab45SVaclav Hapla   Like DMPlexGetConeRecursive but returns only the 0-depth IS (i.e. vertices only) and no sections.
2842af9eab45SVaclav Hapla   There is no corresponding Restore function, just call ISDestroy() on the returned IS to deallocate.
2843af9eab45SVaclav Hapla 
2844db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetDepth()`
2845d4636a37SVaclav Hapla @*/
2846af9eab45SVaclav Hapla PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints)
2847d4636a37SVaclav Hapla {
2848af9eab45SVaclav Hapla   IS                  *expandedPointsAll;
2849af9eab45SVaclav Hapla   PetscInt            depth;
2850d4636a37SVaclav Hapla 
2851d4636a37SVaclav Hapla   PetscFunctionBegin;
2852af9eab45SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2853af9eab45SVaclav Hapla   PetscValidHeaderSpecific(points, IS_CLASSID, 2);
2854af9eab45SVaclav Hapla   PetscValidPointer(expandedPoints, 3);
28559566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL));
2856af9eab45SVaclav Hapla   *expandedPoints = expandedPointsAll[0];
28579566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)expandedPointsAll[0]));
28589566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL));
2859af9eab45SVaclav Hapla   PetscFunctionReturn(0);
2860af9eab45SVaclav Hapla }
2861af9eab45SVaclav Hapla 
2862af9eab45SVaclav Hapla /*@
2863af9eab45SVaclav 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).
2864af9eab45SVaclav Hapla 
2865af9eab45SVaclav Hapla   Not collective
2866af9eab45SVaclav Hapla 
2867af9eab45SVaclav Hapla   Input Parameters:
2868af9eab45SVaclav Hapla + dm - The DMPlex
2869af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart()
2870af9eab45SVaclav Hapla 
2871d8d19677SJose E. Roman   Output Parameters:
2872af9eab45SVaclav Hapla + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth()
2873af9eab45SVaclav Hapla . expandedPoints - (optional) An array of index sets with recursively expanded cones
2874af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points
2875af9eab45SVaclav Hapla 
2876af9eab45SVaclav Hapla   Level: advanced
2877af9eab45SVaclav Hapla 
2878af9eab45SVaclav Hapla   Notes:
2879af9eab45SVaclav Hapla   Like DMPlexGetConeTuple() but recursive.
2880af9eab45SVaclav Hapla 
2881af9eab45SVaclav 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.
2882af9eab45SVaclav Hapla   For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc.
2883af9eab45SVaclav Hapla 
2884af9eab45SVaclav 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:
2885af9eab45SVaclav Hapla   (1) DAG points in expandedPoints[d+1] with depth d+1 to their cone points in expandedPoints[d];
2886af9eab45SVaclav Hapla   (2) DAG points in expandedPoints[d+1] with depth in [0,d] to the same points in expandedPoints[d].
2887af9eab45SVaclav Hapla 
2888db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, `DMPlexGetDepth()`
2889af9eab45SVaclav Hapla @*/
2890af9eab45SVaclav Hapla PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[])
2891af9eab45SVaclav Hapla {
2892af9eab45SVaclav Hapla   const PetscInt      *arr0=NULL, *cone=NULL;
2893af9eab45SVaclav Hapla   PetscInt            *arr=NULL, *newarr=NULL;
2894af9eab45SVaclav Hapla   PetscInt            d, depth_, i, n, newn, cn, co, start, end;
2895af9eab45SVaclav Hapla   IS                  *expandedPoints_;
2896af9eab45SVaclav Hapla   PetscSection        *sections_;
2897af9eab45SVaclav Hapla 
2898af9eab45SVaclav Hapla   PetscFunctionBegin;
2899af9eab45SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2900af9eab45SVaclav Hapla   PetscValidHeaderSpecific(points, IS_CLASSID, 2);
2901af9eab45SVaclav Hapla   if (depth) PetscValidIntPointer(depth, 3);
2902af9eab45SVaclav Hapla   if (expandedPoints) PetscValidPointer(expandedPoints, 4);
2903af9eab45SVaclav Hapla   if (sections) PetscValidPointer(sections, 5);
29049566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(points, &n));
29059566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(points, &arr0));
29069566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth_));
29079566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(depth_, &expandedPoints_));
29089566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(depth_, &sections_));
2909af9eab45SVaclav Hapla   arr = (PetscInt*) arr0; /* this is ok because first generation of arr is not modified */
2910af9eab45SVaclav Hapla   for (d=depth_-1; d>=0; d--) {
29119566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &sections_[d]));
29129566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(sections_[d], 0, n));
2913af9eab45SVaclav Hapla     for (i=0; i<n; i++) {
29149566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d+1, &start, &end));
2915af9eab45SVaclav Hapla       if (arr[i] >= start && arr[i] < end) {
29169566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, arr[i], &cn));
29179566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetDof(sections_[d], i, cn));
2918af9eab45SVaclav Hapla       } else {
29199566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetDof(sections_[d], i, 1));
2920af9eab45SVaclav Hapla       }
2921af9eab45SVaclav Hapla     }
29229566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(sections_[d]));
29239566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(sections_[d], &newn));
29249566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(newn, &newarr));
2925af9eab45SVaclav Hapla     for (i=0; i<n; i++) {
29269566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sections_[d], i, &cn));
29279566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(sections_[d], i, &co));
2928af9eab45SVaclav Hapla       if (cn > 1) {
29299566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, arr[i], &cone));
29309566063dSJacob Faibussowitsch         PetscCall(PetscMemcpy(&newarr[co], cone, cn*sizeof(PetscInt)));
2931af9eab45SVaclav Hapla       } else {
2932af9eab45SVaclav Hapla         newarr[co] = arr[i];
2933af9eab45SVaclav Hapla       }
2934af9eab45SVaclav Hapla     }
29359566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d]));
2936af9eab45SVaclav Hapla     arr = newarr;
2937af9eab45SVaclav Hapla     n = newn;
2938af9eab45SVaclav Hapla   }
29399566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(points, &arr0));
2940af9eab45SVaclav Hapla   *depth = depth_;
2941af9eab45SVaclav Hapla   if (expandedPoints) *expandedPoints = expandedPoints_;
2942af9eab45SVaclav Hapla   else {
29439566063dSJacob Faibussowitsch     for (d=0; d<depth_; d++) PetscCall(ISDestroy(&expandedPoints_[d]));
29449566063dSJacob Faibussowitsch     PetscCall(PetscFree(expandedPoints_));
2945af9eab45SVaclav Hapla   }
2946af9eab45SVaclav Hapla   if (sections) *sections = sections_;
2947af9eab45SVaclav Hapla   else {
29489566063dSJacob Faibussowitsch     for (d=0; d<depth_; d++) PetscCall(PetscSectionDestroy(&sections_[d]));
29499566063dSJacob Faibussowitsch     PetscCall(PetscFree(sections_));
2950af9eab45SVaclav Hapla   }
2951af9eab45SVaclav Hapla   PetscFunctionReturn(0);
2952af9eab45SVaclav Hapla }
2953af9eab45SVaclav Hapla 
2954af9eab45SVaclav Hapla /*@
2955af9eab45SVaclav Hapla   DMPlexRestoreConeRecursive - Deallocates arrays created by DMPlexGetConeRecursive
2956af9eab45SVaclav Hapla 
2957af9eab45SVaclav Hapla   Not collective
2958af9eab45SVaclav Hapla 
2959af9eab45SVaclav Hapla   Input Parameters:
2960af9eab45SVaclav Hapla + dm - The DMPlex
2961af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart()
2962af9eab45SVaclav Hapla 
2963d8d19677SJose E. Roman   Output Parameters:
2964af9eab45SVaclav Hapla + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth()
2965af9eab45SVaclav Hapla . expandedPoints - (optional) An array of recursively expanded cones
2966af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points
2967af9eab45SVaclav Hapla 
2968af9eab45SVaclav Hapla   Level: advanced
2969af9eab45SVaclav Hapla 
2970af9eab45SVaclav Hapla   Notes:
2971af9eab45SVaclav Hapla   See DMPlexGetConeRecursive() for details.
2972af9eab45SVaclav Hapla 
2973db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, `DMPlexGetDepth()`
2974af9eab45SVaclav Hapla @*/
2975af9eab45SVaclav Hapla PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[])
2976af9eab45SVaclav Hapla {
2977af9eab45SVaclav Hapla   PetscInt            d, depth_;
2978af9eab45SVaclav Hapla 
2979af9eab45SVaclav Hapla   PetscFunctionBegin;
29809566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth_));
29811dca8a05SBarry Smith   PetscCheck(!depth || *depth == depth_,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive");
2982af9eab45SVaclav Hapla   if (depth) *depth = 0;
2983af9eab45SVaclav Hapla   if (expandedPoints) {
29849566063dSJacob Faibussowitsch     for (d=0; d<depth_; d++) PetscCall(ISDestroy(&((*expandedPoints)[d])));
29859566063dSJacob Faibussowitsch     PetscCall(PetscFree(*expandedPoints));
2986af9eab45SVaclav Hapla   }
2987af9eab45SVaclav Hapla   if (sections)  {
29889566063dSJacob Faibussowitsch     for (d=0; d<depth_; d++) PetscCall(PetscSectionDestroy(&((*sections)[d])));
29899566063dSJacob Faibussowitsch     PetscCall(PetscFree(*sections));
2990af9eab45SVaclav Hapla   }
2991d4636a37SVaclav Hapla   PetscFunctionReturn(0);
2992d4636a37SVaclav Hapla }
2993d4636a37SVaclav Hapla 
2994552f7358SJed Brown /*@
299592371b87SBarry 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
2996552f7358SJed Brown 
2997552f7358SJed Brown   Not collective
2998552f7358SJed Brown 
2999552f7358SJed Brown   Input Parameters:
3000552f7358SJed Brown + mesh - The DMPlex
3001eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
3002552f7358SJed Brown - cone - An array of points which are on the in-edges for point p
3003552f7358SJed Brown 
3004552f7358SJed Brown   Output Parameter:
3005552f7358SJed Brown 
3006552f7358SJed Brown   Note:
3007552f7358SJed Brown   This should be called after all calls to DMPlexSetConeSize() and DMSetUp().
3008552f7358SJed Brown 
3009552f7358SJed Brown   Level: beginner
3010552f7358SJed Brown 
3011db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`, `DMPlexSetSupport()`, `DMPlexSetSupportSize()`
3012552f7358SJed Brown @*/
3013552f7358SJed Brown PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[])
3014552f7358SJed Brown {
3015552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3016552f7358SJed Brown   PetscInt       pStart, pEnd;
3017552f7358SJed Brown   PetscInt       dof, off, c;
3018552f7358SJed Brown 
3019552f7358SJed Brown   PetscFunctionBegin;
3020552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
30219566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
30229566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
3023dadcf809SJacob Faibussowitsch   if (dof) PetscValidIntPointer(cone, 3);
30249566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
302563a3b9bcSJacob Faibussowitsch   PetscCheck(!(p < pStart) && !(p >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd);
3026552f7358SJed Brown   for (c = 0; c < dof; ++c) {
302763a3b9bcSJacob Faibussowitsch     PetscCheck(!(cone[c] < pStart) && !(cone[c] >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", cone[c], pStart, pEnd);
3028552f7358SJed Brown     mesh->cones[off+c] = cone[c];
3029552f7358SJed Brown   }
3030552f7358SJed Brown   PetscFunctionReturn(0);
3031552f7358SJed Brown }
3032552f7358SJed Brown 
3033552f7358SJed Brown /*@C
3034eaf898f9SPatrick Sanan   DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG
3035552f7358SJed Brown 
3036552f7358SJed Brown   Not collective
3037552f7358SJed Brown 
3038552f7358SJed Brown   Input Parameters:
3039552f7358SJed Brown + mesh - The DMPlex
3040eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
3041552f7358SJed Brown 
3042552f7358SJed Brown   Output Parameter:
3043552f7358SJed Brown . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an
3044b5a892a1SMatthew G. Knepley                     integer giving the prescription for cone traversal.
3045552f7358SJed Brown 
3046552f7358SJed Brown   Level: beginner
3047552f7358SJed Brown 
3048b5a892a1SMatthew G. Knepley   Notes:
3049b5a892a1SMatthew G. Knepley   The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always
3050b5a892a1SMatthew G. Knepley   the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection
3051b5a892a1SMatthew G. Knepley   of o, however it is not necessarily the inverse. To get the inverse, use DMPolytopeTypeComposeOrientationInv()
3052b5a892a1SMatthew G. Knepley   with the identity.
3053b5a892a1SMatthew G. Knepley 
30543813dfbdSMatthew G Knepley   Fortran Notes:
30553813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
30563813dfbdSMatthew G Knepley   include petsc.h90 in your code.
30573b12b3d8SVaclav Hapla   You must also call DMPlexRestoreConeOrientation() after you finish using the returned array.
3058922102d1SVaclav Hapla   DMPlexRestoreConeOrientation() is not needed/available in C.
30593813dfbdSMatthew G Knepley 
3060db781477SPatrick Sanan .seealso: `DMPolytopeTypeComposeOrientation()`, `DMPolytopeTypeComposeOrientationInv()`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetCone()`, `DMPlexSetChart()`
3061552f7358SJed Brown @*/
3062552f7358SJed Brown PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[])
3063552f7358SJed Brown {
3064552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3065552f7358SJed Brown   PetscInt       off;
3066552f7358SJed Brown 
3067552f7358SJed Brown   PetscFunctionBegin;
3068552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
306976bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
3070552f7358SJed Brown     PetscInt dof;
30719566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
3072552f7358SJed Brown     if (dof) PetscValidPointer(coneOrientation, 3);
3073552f7358SJed Brown   }
30749566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
30750d644c17SKarl Rupp 
3076552f7358SJed Brown   *coneOrientation = &mesh->coneOrientations[off];
3077552f7358SJed Brown   PetscFunctionReturn(0);
3078552f7358SJed Brown }
3079552f7358SJed Brown 
3080552f7358SJed Brown /*@
3081eaf898f9SPatrick Sanan   DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG
3082552f7358SJed Brown 
3083552f7358SJed Brown   Not collective
3084552f7358SJed Brown 
3085552f7358SJed Brown   Input Parameters:
3086552f7358SJed Brown + mesh - The DMPlex
3087eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
3088b5a892a1SMatthew G. Knepley - coneOrientation - An array of orientations
3089552f7358SJed Brown   Output Parameter:
3090552f7358SJed Brown 
3091b5a892a1SMatthew G. Knepley   Notes:
3092552f7358SJed Brown   This should be called after all calls to DMPlexSetConeSize() and DMSetUp().
3093552f7358SJed Brown 
3094b5a892a1SMatthew G. Knepley   The meaning of coneOrientation is detailed in DMPlexGetConeOrientation().
3095b5a892a1SMatthew G. Knepley 
3096552f7358SJed Brown   Level: beginner
3097552f7358SJed Brown 
3098db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetConeOrientation()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
3099552f7358SJed Brown @*/
3100552f7358SJed Brown PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[])
3101552f7358SJed Brown {
3102552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3103552f7358SJed Brown   PetscInt       pStart, pEnd;
3104552f7358SJed Brown   PetscInt       dof, off, c;
3105552f7358SJed Brown 
3106552f7358SJed Brown   PetscFunctionBegin;
3107552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
31089566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
31099566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
3110dadcf809SJacob Faibussowitsch   if (dof) PetscValidIntPointer(coneOrientation, 3);
31119566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
311263a3b9bcSJacob Faibussowitsch   PetscCheck(!(p < pStart) && !(p >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd);
3113552f7358SJed Brown   for (c = 0; c < dof; ++c) {
3114552f7358SJed Brown     PetscInt cdof, o = coneOrientation[c];
3115552f7358SJed Brown 
31169566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof));
31171dca8a05SBarry Smith     PetscCheck(!o || (o >= -(cdof+1) && o < cdof),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone orientation %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ". %" PetscInt_FMT ")", o, -(cdof+1), cdof);
3118552f7358SJed Brown     mesh->coneOrientations[off+c] = o;
3119552f7358SJed Brown   }
3120552f7358SJed Brown   PetscFunctionReturn(0);
3121552f7358SJed Brown }
3122552f7358SJed Brown 
31237cd05799SMatthew G. Knepley /*@
3124eaf898f9SPatrick Sanan   DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG
31257cd05799SMatthew G. Knepley 
31267cd05799SMatthew G. Knepley   Not collective
31277cd05799SMatthew G. Knepley 
31287cd05799SMatthew G. Knepley   Input Parameters:
31297cd05799SMatthew G. Knepley + mesh - The DMPlex
3130eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
31317cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put
31327cd05799SMatthew G. Knepley - conePoint - The mesh point to insert
31337cd05799SMatthew G. Knepley 
31347cd05799SMatthew G. Knepley   Level: beginner
31357cd05799SMatthew G. Knepley 
3136db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
31377cd05799SMatthew G. Knepley @*/
3138552f7358SJed Brown PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint)
3139552f7358SJed Brown {
3140552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3141552f7358SJed Brown   PetscInt       pStart, pEnd;
3142552f7358SJed Brown   PetscInt       dof, off;
3143552f7358SJed Brown 
3144552f7358SJed Brown   PetscFunctionBegin;
3145552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
31469566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
314763a3b9bcSJacob Faibussowitsch   PetscCheck(!(p < pStart) && !(p >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd);
314863a3b9bcSJacob Faibussowitsch   PetscCheck(!(conePoint < pStart) && !(conePoint >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", conePoint, pStart, pEnd);
31499566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
31509566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
315163a3b9bcSJacob Faibussowitsch   PetscCheck(!(conePos < 0) && !(conePos >= dof),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %" PetscInt_FMT " of point %" PetscInt_FMT " is not in the valid range [0, %" PetscInt_FMT ")", conePos, p, dof);
3152552f7358SJed Brown   mesh->cones[off+conePos] = conePoint;
3153552f7358SJed Brown   PetscFunctionReturn(0);
3154552f7358SJed Brown }
3155552f7358SJed Brown 
31567cd05799SMatthew G. Knepley /*@
3157eaf898f9SPatrick Sanan   DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG
31587cd05799SMatthew G. Knepley 
31597cd05799SMatthew G. Knepley   Not collective
31607cd05799SMatthew G. Knepley 
31617cd05799SMatthew G. Knepley   Input Parameters:
31627cd05799SMatthew G. Knepley + mesh - The DMPlex
3163eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
31647cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put
31657cd05799SMatthew G. Knepley - coneOrientation - The point orientation to insert
31667cd05799SMatthew G. Knepley 
31677cd05799SMatthew G. Knepley   Level: beginner
31687cd05799SMatthew G. Knepley 
3169b5a892a1SMatthew G. Knepley   Notes:
3170b5a892a1SMatthew G. Knepley   The meaning of coneOrientation values is detailed in DMPlexGetConeOrientation().
3171b5a892a1SMatthew G. Knepley 
3172db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
31737cd05799SMatthew G. Knepley @*/
317477c88f5bSMatthew G Knepley PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation)
317577c88f5bSMatthew G Knepley {
317677c88f5bSMatthew G Knepley   DM_Plex       *mesh = (DM_Plex*) dm->data;
317777c88f5bSMatthew G Knepley   PetscInt       pStart, pEnd;
317877c88f5bSMatthew G Knepley   PetscInt       dof, off;
317977c88f5bSMatthew G Knepley 
318077c88f5bSMatthew G Knepley   PetscFunctionBegin;
318177c88f5bSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
31829566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
318363a3b9bcSJacob Faibussowitsch   PetscCheck(!(p < pStart) && !(p >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd);
31849566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
31859566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
318663a3b9bcSJacob Faibussowitsch   PetscCheck(!(conePos < 0) && !(conePos >= dof),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %" PetscInt_FMT " of point %" PetscInt_FMT " is not in the valid range [0, %" PetscInt_FMT ")", conePos, p, dof);
318777c88f5bSMatthew G Knepley   mesh->coneOrientations[off+conePos] = coneOrientation;
318877c88f5bSMatthew G Knepley   PetscFunctionReturn(0);
318977c88f5bSMatthew G Knepley }
319077c88f5bSMatthew G Knepley 
3191552f7358SJed Brown /*@
3192eaf898f9SPatrick Sanan   DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG
3193552f7358SJed Brown 
3194552f7358SJed Brown   Not collective
3195552f7358SJed Brown 
3196552f7358SJed Brown   Input Parameters:
3197552f7358SJed Brown + mesh - The DMPlex
3198eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
3199552f7358SJed Brown 
3200552f7358SJed Brown   Output Parameter:
3201552f7358SJed Brown . size - The support size for point p
3202552f7358SJed Brown 
3203552f7358SJed Brown   Level: beginner
3204552f7358SJed Brown 
3205db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`, `DMPlexGetConeSize()`
3206552f7358SJed Brown @*/
3207552f7358SJed Brown PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size)
3208552f7358SJed Brown {
3209552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3210552f7358SJed Brown 
3211552f7358SJed Brown   PetscFunctionBegin;
3212552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3213dadcf809SJacob Faibussowitsch   PetscValidIntPointer(size, 3);
32149566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, size));
3215552f7358SJed Brown   PetscFunctionReturn(0);
3216552f7358SJed Brown }
3217552f7358SJed Brown 
3218552f7358SJed Brown /*@
3219eaf898f9SPatrick Sanan   DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG
3220552f7358SJed Brown 
3221552f7358SJed Brown   Not collective
3222552f7358SJed Brown 
3223552f7358SJed Brown   Input Parameters:
3224552f7358SJed Brown + mesh - The DMPlex
3225eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
3226552f7358SJed Brown - size - The support size for point p
3227552f7358SJed Brown 
3228552f7358SJed Brown   Output Parameter:
3229552f7358SJed Brown 
3230552f7358SJed Brown   Note:
3231552f7358SJed Brown   This should be called after DMPlexSetChart().
3232552f7358SJed Brown 
3233552f7358SJed Brown   Level: beginner
3234552f7358SJed Brown 
3235db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetSupportSize()`, `DMPlexSetChart()`
3236552f7358SJed Brown @*/
3237552f7358SJed Brown PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size)
3238552f7358SJed Brown {
3239552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3240552f7358SJed Brown 
3241552f7358SJed Brown   PetscFunctionBegin;
3242552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
32439566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetDof(mesh->supportSection, p, size));
3244552f7358SJed Brown   PetscFunctionReturn(0);
3245552f7358SJed Brown }
3246552f7358SJed Brown 
3247552f7358SJed Brown /*@C
3248eaf898f9SPatrick Sanan   DMPlexGetSupport - Return the points on the out-edges for this point in the DAG
3249552f7358SJed Brown 
3250552f7358SJed Brown   Not collective
3251552f7358SJed Brown 
3252552f7358SJed Brown   Input Parameters:
3253552f7358SJed Brown + mesh - The DMPlex
3254eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
3255552f7358SJed Brown 
3256552f7358SJed Brown   Output Parameter:
3257552f7358SJed Brown . support - An array of points which are on the out-edges for point p
3258552f7358SJed Brown 
3259552f7358SJed Brown   Level: beginner
3260552f7358SJed Brown 
32613813dfbdSMatthew G Knepley   Fortran Notes:
32623813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
32633813dfbdSMatthew G Knepley   include petsc.h90 in your code.
32643b12b3d8SVaclav Hapla   You must also call DMPlexRestoreSupport() after you finish using the returned array.
3265922102d1SVaclav Hapla   DMPlexRestoreSupport() is not needed/available in C.
32663813dfbdSMatthew G Knepley 
3267db781477SPatrick Sanan .seealso: `DMPlexGetSupportSize()`, `DMPlexSetSupport()`, `DMPlexGetCone()`, `DMPlexSetChart()`
3268552f7358SJed Brown @*/
3269552f7358SJed Brown PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[])
3270552f7358SJed Brown {
3271552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3272552f7358SJed Brown   PetscInt       off;
3273552f7358SJed Brown 
3274552f7358SJed Brown   PetscFunctionBegin;
3275552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3276552f7358SJed Brown   PetscValidPointer(support, 3);
32779566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
3278552f7358SJed Brown   *support = &mesh->supports[off];
3279552f7358SJed Brown   PetscFunctionReturn(0);
3280552f7358SJed Brown }
3281552f7358SJed Brown 
3282552f7358SJed Brown /*@
328392371b87SBarry 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
3284552f7358SJed Brown 
3285552f7358SJed Brown   Not collective
3286552f7358SJed Brown 
3287552f7358SJed Brown   Input Parameters:
3288552f7358SJed Brown + mesh - The DMPlex
3289eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
329092371b87SBarry Smith - support - An array of points which are on the out-edges for point p
3291552f7358SJed Brown 
3292552f7358SJed Brown   Output Parameter:
3293552f7358SJed Brown 
3294552f7358SJed Brown   Note:
3295552f7358SJed Brown   This should be called after all calls to DMPlexSetSupportSize() and DMSetUp().
3296552f7358SJed Brown 
3297552f7358SJed Brown   Level: beginner
3298552f7358SJed Brown 
3299db781477SPatrick Sanan .seealso: `DMPlexSetCone()`, `DMPlexSetConeSize()`, `DMPlexCreate()`, `DMPlexGetSupport()`, `DMPlexSetChart()`, `DMPlexSetSupportSize()`, `DMSetUp()`
3300552f7358SJed Brown @*/
3301552f7358SJed Brown PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[])
3302552f7358SJed Brown {
3303552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3304552f7358SJed Brown   PetscInt       pStart, pEnd;
3305552f7358SJed Brown   PetscInt       dof, off, c;
3306552f7358SJed Brown 
3307552f7358SJed Brown   PetscFunctionBegin;
3308552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
33099566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd));
33109566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
3311dadcf809SJacob Faibussowitsch   if (dof) PetscValidIntPointer(support, 3);
33129566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
331363a3b9bcSJacob Faibussowitsch   PetscCheck(!(p < pStart) && !(p >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd);
3314552f7358SJed Brown   for (c = 0; c < dof; ++c) {
331563a3b9bcSJacob Faibussowitsch     PetscCheck(!(support[c] < pStart) && !(support[c] >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", support[c], pStart, pEnd);
3316552f7358SJed Brown     mesh->supports[off+c] = support[c];
3317552f7358SJed Brown   }
3318552f7358SJed Brown   PetscFunctionReturn(0);
3319552f7358SJed Brown }
3320552f7358SJed Brown 
33217cd05799SMatthew G. Knepley /*@
3322eaf898f9SPatrick Sanan   DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG
33237cd05799SMatthew G. Knepley 
33247cd05799SMatthew G. Knepley   Not collective
33257cd05799SMatthew G. Knepley 
33267cd05799SMatthew G. Knepley   Input Parameters:
33277cd05799SMatthew G. Knepley + mesh - The DMPlex
3328eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
33297cd05799SMatthew G. Knepley . supportPos - The local index in the cone where the point should be put
33307cd05799SMatthew G. Knepley - supportPoint - The mesh point to insert
33317cd05799SMatthew G. Knepley 
33327cd05799SMatthew G. Knepley   Level: beginner
33337cd05799SMatthew G. Knepley 
3334db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
33357cd05799SMatthew G. Knepley @*/
3336552f7358SJed Brown PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint)
3337552f7358SJed Brown {
3338552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3339552f7358SJed Brown   PetscInt       pStart, pEnd;
3340552f7358SJed Brown   PetscInt       dof, off;
3341552f7358SJed Brown 
3342552f7358SJed Brown   PetscFunctionBegin;
3343552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
33449566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd));
33459566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
33469566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
334763a3b9bcSJacob Faibussowitsch   PetscCheck(!(p < pStart) && !(p >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd);
334863a3b9bcSJacob Faibussowitsch   PetscCheck(!(supportPoint < pStart) && !(supportPoint >= pEnd),PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", supportPoint, pStart, pEnd);
334963a3b9bcSJacob Faibussowitsch   PetscCheck(supportPos < dof,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support position %" PetscInt_FMT " of point %" PetscInt_FMT " is not in the valid range [0, %" PetscInt_FMT ")", supportPos, p, dof);
3350552f7358SJed Brown   mesh->supports[off+supportPos] = supportPoint;
3351552f7358SJed Brown   PetscFunctionReturn(0);
3352552f7358SJed Brown }
3353552f7358SJed Brown 
3354b5a892a1SMatthew G. Knepley /* Converts an orientation o in the current numbering to the previous scheme used in Plex */
3355b5a892a1SMatthew G. Knepley PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o)
3356b5a892a1SMatthew G. Knepley {
3357b5a892a1SMatthew G. Knepley   switch (ct) {
3358b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:
3359b5a892a1SMatthew G. Knepley       if (o == -1) return -2;
3360b5a892a1SMatthew G. Knepley       break;
3361b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:
3362b5a892a1SMatthew G. Knepley       if (o == -3) return -1;
3363b5a892a1SMatthew G. Knepley       if (o == -2) return -3;
3364b5a892a1SMatthew G. Knepley       if (o == -1) return -2;
3365b5a892a1SMatthew G. Knepley       break;
3366b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:
3367b5a892a1SMatthew G. Knepley       if (o == -4) return -2;
3368b5a892a1SMatthew G. Knepley       if (o == -3) return -1;
3369b5a892a1SMatthew G. Knepley       if (o == -2) return -4;
3370b5a892a1SMatthew G. Knepley       if (o == -1) return -3;
3371b5a892a1SMatthew G. Knepley       break;
3372b5a892a1SMatthew G. Knepley     default: return o;
3373b5a892a1SMatthew G. Knepley   }
3374b5a892a1SMatthew G. Knepley   return o;
3375b5a892a1SMatthew G. Knepley }
3376b5a892a1SMatthew G. Knepley 
3377b5a892a1SMatthew G. Knepley /* Converts an orientation o in the previous scheme used in Plex to the current numbering */
3378b5a892a1SMatthew G. Knepley PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o)
3379b5a892a1SMatthew G. Knepley {
3380b5a892a1SMatthew G. Knepley   switch (ct) {
3381b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:
3382b5a892a1SMatthew G. Knepley       if ((o == -2) || (o == 1)) return -1;
3383b5a892a1SMatthew G. Knepley       if (o == -1) return 0;
3384b5a892a1SMatthew G. Knepley       break;
3385b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:
3386b5a892a1SMatthew G. Knepley       if (o == -3) return -2;
3387b5a892a1SMatthew G. Knepley       if (o == -2) return -1;
3388b5a892a1SMatthew G. Knepley       if (o == -1) return -3;
3389b5a892a1SMatthew G. Knepley       break;
3390b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:
3391b5a892a1SMatthew G. Knepley       if (o == -4) return -2;
3392b5a892a1SMatthew G. Knepley       if (o == -3) return -1;
3393b5a892a1SMatthew G. Knepley       if (o == -2) return -4;
3394b5a892a1SMatthew G. Knepley       if (o == -1) return -3;
3395b5a892a1SMatthew G. Knepley       break;
3396b5a892a1SMatthew G. Knepley     default: return o;
3397b5a892a1SMatthew G. Knepley   }
3398b5a892a1SMatthew G. Knepley   return o;
3399b5a892a1SMatthew G. Knepley }
3400b5a892a1SMatthew G. Knepley 
3401b5a892a1SMatthew G. Knepley /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */
3402b5a892a1SMatthew G. Knepley PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm)
3403b5a892a1SMatthew G. Knepley {
3404b5a892a1SMatthew G. Knepley   PetscInt       pStart, pEnd, p;
3405b5a892a1SMatthew G. Knepley 
3406b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
34079566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
3408b5a892a1SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
3409b5a892a1SMatthew G. Knepley     const PetscInt *cone, *ornt;
3410b5a892a1SMatthew G. Knepley     PetscInt        coneSize, c;
3411b5a892a1SMatthew G. Knepley 
34129566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
34139566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
34149566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dm, p, &ornt));
3415b5a892a1SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
3416b5a892a1SMatthew G. Knepley       DMPolytopeType ct;
3417b5a892a1SMatthew G. Knepley       const PetscInt o = ornt[c];
3418b5a892a1SMatthew G. Knepley 
34199566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, cone[c], &ct));
3420b5a892a1SMatthew G. Knepley       switch (ct) {
3421b5a892a1SMatthew G. Knepley         case DM_POLYTOPE_SEGMENT:
34229566063dSJacob Faibussowitsch           if ((o == -2) || (o == 1)) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
34239566063dSJacob Faibussowitsch           if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, 0));
3424b5a892a1SMatthew G. Knepley           break;
3425b5a892a1SMatthew G. Knepley         case DM_POLYTOPE_TRIANGLE:
34269566063dSJacob Faibussowitsch           if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2));
34279566063dSJacob Faibussowitsch           if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
34289566063dSJacob Faibussowitsch           if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3));
3429b5a892a1SMatthew G. Knepley           break;
3430b5a892a1SMatthew G. Knepley         case DM_POLYTOPE_QUADRILATERAL:
34319566063dSJacob Faibussowitsch           if (o == -4) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2));
34329566063dSJacob Faibussowitsch           if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
34339566063dSJacob Faibussowitsch           if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -4));
34349566063dSJacob Faibussowitsch           if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3));
3435b5a892a1SMatthew G. Knepley           break;
3436b5a892a1SMatthew G. Knepley         default: break;
3437b5a892a1SMatthew G. Knepley       }
3438b5a892a1SMatthew G. Knepley     }
3439b5a892a1SMatthew G. Knepley   }
3440b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
3441b5a892a1SMatthew G. Knepley }
3442b5a892a1SMatthew G. Knepley 
3443012bc364SMatthew G. Knepley static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3444b5a892a1SMatthew G. Knepley {
3445b5a892a1SMatthew G. Knepley   DMPolytopeType  ct = DM_POLYTOPE_UNKNOWN;
3446b5a892a1SMatthew G. Knepley   PetscInt       *closure;
3447b5a892a1SMatthew G. Knepley   const PetscInt *tmp = NULL, *tmpO = NULL;
3448b5a892a1SMatthew G. Knepley   PetscInt        off = 0, tmpSize, t;
3449b5a892a1SMatthew G. Knepley 
3450b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3451b5a892a1SMatthew G. Knepley   if (ornt) {
34529566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, p, &ct));
3453b5a892a1SMatthew G. Knepley     if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN;
3454b5a892a1SMatthew G. Knepley   }
3455b5a892a1SMatthew G. Knepley   if (*points) {
3456b5a892a1SMatthew G. Knepley     closure = *points;
3457b5a892a1SMatthew G. Knepley   } else {
3458b5a892a1SMatthew G. Knepley     PetscInt maxConeSize, maxSupportSize;
34599566063dSJacob Faibussowitsch     PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
34609566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, 2*(PetscMax(maxConeSize, maxSupportSize)+1), MPIU_INT, &closure));
3461b5a892a1SMatthew G. Knepley   }
3462b5a892a1SMatthew G. Knepley   if (useCone) {
34639566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &tmpSize));
34649566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &tmp));
34659566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dm, p, &tmpO));
3466b5a892a1SMatthew G. Knepley   } else {
34679566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dm, p, &tmpSize));
34689566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dm, p, &tmp));
3469b5a892a1SMatthew G. Knepley   }
3470b5a892a1SMatthew G. Knepley   if (ct == DM_POLYTOPE_UNKNOWN) {
3471b5a892a1SMatthew G. Knepley     closure[off++] = p;
3472b5a892a1SMatthew G. Knepley     closure[off++] = 0;
3473b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3474b5a892a1SMatthew G. Knepley       closure[off++] = tmp[t];
3475b5a892a1SMatthew G. Knepley       closure[off++] = tmpO ? tmpO[t] : 0;
3476b5a892a1SMatthew G. Knepley     }
3477b5a892a1SMatthew G. Knepley   } else {
34785f80ce2aSJacob Faibussowitsch     const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, ornt);
3479b5a892a1SMatthew G. Knepley 
3480b5a892a1SMatthew G. Knepley     /* We assume that cells with a valid type have faces with a valid type */
3481b5a892a1SMatthew G. Knepley     closure[off++] = p;
3482b5a892a1SMatthew G. Knepley     closure[off++] = ornt;
3483b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3484b5a892a1SMatthew G. Knepley       DMPolytopeType ft;
3485b5a892a1SMatthew G. Knepley 
34869566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, tmp[t], &ft));
3487b5a892a1SMatthew G. Knepley       closure[off++] = tmp[arr[t]];
3488b5a892a1SMatthew G. Knepley       closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0;
3489b5a892a1SMatthew G. Knepley     }
3490b5a892a1SMatthew G. Knepley   }
3491b5a892a1SMatthew G. Knepley   if (numPoints) *numPoints = tmpSize+1;
3492b5a892a1SMatthew G. Knepley   if (points)    *points    = closure;
3493b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
3494b5a892a1SMatthew G. Knepley }
3495b5a892a1SMatthew G. Knepley 
3496b5a892a1SMatthew G. Knepley /* We need a special tensor verison becasue we want to allow duplicate points in the endcaps for hybrid cells */
3497b5a892a1SMatthew G. Knepley static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points)
3498b5a892a1SMatthew G. Knepley {
3499b5a892a1SMatthew G. Knepley   const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, o);
3500b5a892a1SMatthew G. Knepley   const PetscInt *cone, *ornt;
3501b5a892a1SMatthew G. Knepley   PetscInt       *pts,  *closure = NULL;
3502b5a892a1SMatthew G. Knepley   DMPolytopeType  ft;
3503b5a892a1SMatthew G. Knepley   PetscInt        maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize;
3504b5a892a1SMatthew G. Knepley   PetscInt        dim, coneSize, c, d, clSize, cl;
3505b5a892a1SMatthew G. Knepley 
3506b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
35079566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
35089566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, point, &coneSize));
35099566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, point, &cone));
35109566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeOrientation(dm, point, &ornt));
35119566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
3512b5a892a1SMatthew G. Knepley   coneSeries    = (maxConeSize    > 1) ? ((PetscPowInt(maxConeSize,    dim+1)-1)/(maxConeSize-1))    : dim+1;
3513b5a892a1SMatthew G. Knepley   supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim+1)-1)/(maxSupportSize-1)) : dim+1;
3514b5a892a1SMatthew G. Knepley   maxSize       = PetscMax(coneSeries, supportSeries);
3515b5a892a1SMatthew G. Knepley   if (*points) {pts  = *points;}
35169566063dSJacob Faibussowitsch   else         PetscCall(DMGetWorkArray(dm, 2*maxSize, MPIU_INT, &pts));
3517b5a892a1SMatthew G. Knepley   c    = 0;
3518b5a892a1SMatthew G. Knepley   pts[c++] = point;
3519b5a892a1SMatthew G. Knepley   pts[c++] = o;
35209566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cone[arr[0*2+0]], &ft));
35219566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0*2+0]], DMPolytopeTypeComposeOrientation(ft, arr[0*2+1], ornt[0]), useCone, &clSize, &closure));
3522b5a892a1SMatthew G. Knepley   for (cl = 0; cl < clSize*2; cl += 2) {pts[c++] = closure[cl]; pts[c++] = closure[cl+1];}
35239566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1*2+0]], DMPolytopeTypeComposeOrientation(ft, arr[1*2+1], ornt[1]), useCone, &clSize, &closure));
3524b5a892a1SMatthew G. Knepley   for (cl = 0; cl < clSize*2; cl += 2) {pts[c++] = closure[cl]; pts[c++] = closure[cl+1];}
35259566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure));
3526b5a892a1SMatthew G. Knepley   for (d = 2; d < coneSize; ++d) {
35279566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, cone[arr[d*2+0]], &ft));
3528b5a892a1SMatthew G. Knepley     pts[c++] = cone[arr[d*2+0]];
3529b5a892a1SMatthew G. Knepley     pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d*2+1], ornt[d]);
3530b5a892a1SMatthew G. Knepley   }
3531b5a892a1SMatthew G. Knepley   if (dim >= 3) {
3532b5a892a1SMatthew G. Knepley     for (d = 2; d < coneSize; ++d) {
3533b5a892a1SMatthew G. Knepley       const PetscInt  fpoint = cone[arr[d*2+0]];
3534b5a892a1SMatthew G. Knepley       const PetscInt *fcone, *fornt;
3535b5a892a1SMatthew G. Knepley       PetscInt        fconeSize, fc, i;
3536b5a892a1SMatthew G. Knepley 
35379566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, fpoint, &ft));
3538b5a892a1SMatthew G. Knepley       const PetscInt *farr = DMPolytopeTypeGetArrangment(ft, DMPolytopeTypeComposeOrientation(ft, arr[d*2+1], ornt[d]));
35399566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, fpoint, &fconeSize));
35409566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, fpoint, &fcone));
35419566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeOrientation(dm, fpoint, &fornt));
3542b5a892a1SMatthew G. Knepley       for (fc = 0; fc < fconeSize; ++fc) {
3543b5a892a1SMatthew G. Knepley         const PetscInt cp = fcone[farr[fc*2+0]];
3544b5a892a1SMatthew G. Knepley         const PetscInt co = farr[fc*2+1];
3545b5a892a1SMatthew G. Knepley 
3546b5a892a1SMatthew G. Knepley         for (i = 0; i < c; i += 2) if (pts[i] == cp) break;
3547b5a892a1SMatthew G. Knepley         if (i == c) {
35489566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCellType(dm, cp, &ft));
3549b5a892a1SMatthew G. Knepley           pts[c++] = cp;
3550b5a892a1SMatthew G. Knepley           pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc*2+0]]);
3551b5a892a1SMatthew G. Knepley         }
3552b5a892a1SMatthew G. Knepley       }
3553b5a892a1SMatthew G. Knepley     }
3554b5a892a1SMatthew G. Knepley   }
3555b5a892a1SMatthew G. Knepley   *numPoints = c/2;
3556b5a892a1SMatthew G. Knepley   *points    = pts;
3557b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
3558b5a892a1SMatthew G. Knepley }
3559b5a892a1SMatthew G. Knepley 
3560b5a892a1SMatthew G. Knepley PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3561b5a892a1SMatthew G. Knepley {
3562b5a892a1SMatthew G. Knepley   DMPolytopeType ct;
3563b5a892a1SMatthew G. Knepley   PetscInt      *closure, *fifo;
3564b5a892a1SMatthew G. Knepley   PetscInt       closureSize = 0, fifoStart = 0, fifoSize = 0;
3565b5a892a1SMatthew G. Knepley   PetscInt       maxConeSize, maxSupportSize, coneSeries, supportSeries;
3566b5a892a1SMatthew G. Knepley   PetscInt       depth, maxSize;
3567b5a892a1SMatthew G. Knepley 
3568b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
35699566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
3570b5a892a1SMatthew G. Knepley   if (depth == 1) {
35719566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points));
3572b5a892a1SMatthew G. Knepley     PetscFunctionReturn(0);
3573b5a892a1SMatthew G. Knepley   }
35749566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, p, &ct));
3575b5a892a1SMatthew G. Knepley   if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN;
3576b5a892a1SMatthew G. Knepley   if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || ct == DM_POLYTOPE_TRI_PRISM_TENSOR || ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) {
35779566063dSJacob Faibussowitsch     PetscCall(DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points));
3578b5a892a1SMatthew G. Knepley     PetscFunctionReturn(0);
3579b5a892a1SMatthew G. Knepley   }
35809566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
3581b5a892a1SMatthew G. Knepley   coneSeries    = (maxConeSize    > 1) ? ((PetscPowInt(maxConeSize,    depth+1)-1)/(maxConeSize-1))    : depth+1;
3582b5a892a1SMatthew G. Knepley   supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth+1)-1)/(maxSupportSize-1)) : depth+1;
3583b5a892a1SMatthew G. Knepley   maxSize       = PetscMax(coneSeries, supportSeries);
35849566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, 3*maxSize, MPIU_INT, &fifo));
3585b5a892a1SMatthew G. Knepley   if (*points) {closure = *points;}
35869566063dSJacob Faibussowitsch   else         PetscCall(DMGetWorkArray(dm, 2*maxSize, MPIU_INT, &closure));
3587b5a892a1SMatthew G. Knepley   closure[closureSize++] = p;
3588b5a892a1SMatthew G. Knepley   closure[closureSize++] = ornt;
3589b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = p;
3590b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = ornt;
3591b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = ct;
3592b5a892a1SMatthew G. Knepley   /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */
3593b5a892a1SMatthew G. Knepley   while (fifoSize - fifoStart) {
3594b5a892a1SMatthew G. Knepley     const PetscInt       q    = fifo[fifoStart++];
3595b5a892a1SMatthew G. Knepley     const PetscInt       o    = fifo[fifoStart++];
3596b5a892a1SMatthew G. Knepley     const DMPolytopeType qt   = (DMPolytopeType) fifo[fifoStart++];
3597b5a892a1SMatthew G. Knepley     const PetscInt      *qarr = DMPolytopeTypeGetArrangment(qt, o);
3598b5a892a1SMatthew G. Knepley     const PetscInt      *tmp, *tmpO;
3599b5a892a1SMatthew G. Knepley     PetscInt             tmpSize, t;
3600b5a892a1SMatthew G. Knepley 
3601b5a892a1SMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) {
3602b5a892a1SMatthew G. Knepley       PetscInt nO = DMPolytopeTypeGetNumArrangments(qt)/2;
360363a3b9bcSJacob Faibussowitsch       PetscCheck(!o || !(o >= nO || o < -nO),PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid orientation %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ") for %s %" PetscInt_FMT, o, -nO, nO, DMPolytopeTypes[qt], q);
3604b5a892a1SMatthew G. Knepley     }
3605b5a892a1SMatthew G. Knepley     if (useCone) {
36069566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, q, &tmpSize));
36079566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, q, &tmp));
36089566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeOrientation(dm, q, &tmpO));
3609b5a892a1SMatthew G. Knepley     } else {
36109566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, q, &tmpSize));
36119566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupport(dm, q, &tmp));
3612b5a892a1SMatthew G. Knepley       tmpO = NULL;
3613b5a892a1SMatthew G. Knepley     }
3614b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3615b5a892a1SMatthew G. Knepley       const PetscInt ip = useCone && qarr ? qarr[t*2]   : t;
3616b5a892a1SMatthew G. Knepley       const PetscInt io = useCone && qarr ? qarr[t*2+1] : 0;
3617b5a892a1SMatthew G. Knepley       const PetscInt cp = tmp[ip];
36189566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, cp, &ct));
3619b5a892a1SMatthew G. Knepley       const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0;
3620b5a892a1SMatthew G. Knepley       PetscInt       c;
3621b5a892a1SMatthew G. Knepley 
3622b5a892a1SMatthew G. Knepley       /* Check for duplicate */
3623b5a892a1SMatthew G. Knepley       for (c = 0; c < closureSize; c += 2) {
3624b5a892a1SMatthew G. Knepley         if (closure[c] == cp) break;
3625b5a892a1SMatthew G. Knepley       }
3626b5a892a1SMatthew G. Knepley       if (c == closureSize) {
3627b5a892a1SMatthew G. Knepley         closure[closureSize++] = cp;
3628b5a892a1SMatthew G. Knepley         closure[closureSize++] = co;
3629b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = cp;
3630b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = co;
3631b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = ct;
3632b5a892a1SMatthew G. Knepley       }
3633b5a892a1SMatthew G. Knepley     }
3634b5a892a1SMatthew G. Knepley   }
36359566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 3*maxSize, MPIU_INT, &fifo));
3636b5a892a1SMatthew G. Knepley   if (numPoints) *numPoints = closureSize/2;
3637b5a892a1SMatthew G. Knepley   if (points)    *points    = closure;
3638b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
3639b5a892a1SMatthew G. Knepley }
3640b5a892a1SMatthew G. Knepley 
3641552f7358SJed Brown /*@C
3642eaf898f9SPatrick Sanan   DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG
3643552f7358SJed Brown 
3644552f7358SJed Brown   Not collective
3645552f7358SJed Brown 
3646552f7358SJed Brown   Input Parameters:
3647b5a892a1SMatthew G. Knepley + dm      - The DMPlex
3648b5a892a1SMatthew G. Knepley . p       - The mesh point
36496b867d5aSJose E. Roman - useCone - PETSC_TRUE for the closure, otherwise return the star
3650552f7358SJed Brown 
36516b867d5aSJose E. Roman   Input/Output Parameter:
36526b867d5aSJose E. Roman . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...];
36536b867d5aSJose E. Roman            if NULL on input, internal storage will be returned, otherwise the provided array is used
36546b867d5aSJose E. Roman 
36556b867d5aSJose E. Roman   Output Parameter:
36566b867d5aSJose E. Roman . numPoints - The number of points in the closure, so points[] is of size 2*numPoints
3657552f7358SJed Brown 
3658552f7358SJed Brown   Note:
36590298fd71SBarry Smith   If using internal storage (points is NULL on input), each call overwrites the last output.
3660552f7358SJed Brown 
36613813dfbdSMatthew G Knepley   Fortran Notes:
3662b5a892a1SMatthew G. Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must include petsc.h90 in your code.
36633813dfbdSMatthew G Knepley 
36643813dfbdSMatthew G Knepley   The numPoints argument is not present in the Fortran 90 binding since it is internal to the array.
36653813dfbdSMatthew G Knepley 
3666552f7358SJed Brown   Level: beginner
3667552f7358SJed Brown 
3668db781477SPatrick Sanan .seealso: `DMPlexRestoreTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()`
3669552f7358SJed Brown @*/
3670552f7358SJed Brown PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3671552f7358SJed Brown {
3672b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3673552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3674b5a892a1SMatthew G. Knepley   if (numPoints) PetscValidIntPointer(numPoints, 4);
3675b5a892a1SMatthew G. Knepley   if (points)    PetscValidPointer(points, 5);
36769566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points));
36779bf0dad6SMatthew G. Knepley   PetscFunctionReturn(0);
36789bf0dad6SMatthew G. Knepley }
36799bf0dad6SMatthew G. Knepley 
3680552f7358SJed Brown /*@C
3681eaf898f9SPatrick Sanan   DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG
3682552f7358SJed Brown 
3683552f7358SJed Brown   Not collective
3684552f7358SJed Brown 
3685552f7358SJed Brown   Input Parameters:
3686b5a892a1SMatthew G. Knepley + dm        - The DMPlex
3687b5a892a1SMatthew G. Knepley . p         - The mesh point
3688b5a892a1SMatthew G. Knepley . useCone   - PETSC_TRUE for the closure, otherwise return the star
3689b5a892a1SMatthew G. Knepley . numPoints - The number of points in the closure, so points[] is of size 2*numPoints
3690b5a892a1SMatthew G. Knepley - points    - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]
3691552f7358SJed Brown 
3692552f7358SJed Brown   Note:
36930298fd71SBarry Smith   If not using internal storage (points is not NULL on input), this call is unnecessary
3694552f7358SJed Brown 
36953813dfbdSMatthew G Knepley   Fortran Notes:
3696b5a892a1SMatthew G. Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must include petsc.h90 in your code.
36973813dfbdSMatthew G Knepley 
36983813dfbdSMatthew G Knepley   The numPoints argument is not present in the Fortran 90 binding since it is internal to the array.
36993813dfbdSMatthew G Knepley 
3700552f7358SJed Brown   Level: beginner
3701552f7358SJed Brown 
3702db781477SPatrick Sanan .seealso: `DMPlexGetTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()`
3703552f7358SJed Brown @*/
3704552f7358SJed Brown PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3705552f7358SJed Brown {
3706b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3707552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
37084ff43b2cSJed Brown   if (numPoints) *numPoints = 0;
37099566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, points));
3710552f7358SJed Brown   PetscFunctionReturn(0);
3711552f7358SJed Brown }
3712552f7358SJed Brown 
3713552f7358SJed Brown /*@
3714eaf898f9SPatrick Sanan   DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG
3715552f7358SJed Brown 
3716552f7358SJed Brown   Not collective
3717552f7358SJed Brown 
3718552f7358SJed Brown   Input Parameter:
3719552f7358SJed Brown . mesh - The DMPlex
3720552f7358SJed Brown 
3721552f7358SJed Brown   Output Parameters:
3722552f7358SJed Brown + maxConeSize - The maximum number of in-edges
3723552f7358SJed Brown - maxSupportSize - The maximum number of out-edges
3724552f7358SJed Brown 
3725552f7358SJed Brown   Level: beginner
3726552f7358SJed Brown 
3727db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`
3728552f7358SJed Brown @*/
3729552f7358SJed Brown PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize)
3730552f7358SJed Brown {
3731552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
3732552f7358SJed Brown 
3733552f7358SJed Brown   PetscFunctionBegin;
3734552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
37351baa6e33SBarry Smith   if (maxConeSize) PetscCall(PetscSectionGetMaxDof(mesh->coneSection, maxConeSize));
37361baa6e33SBarry Smith   if (maxSupportSize) PetscCall(PetscSectionGetMaxDof(mesh->supportSection, maxSupportSize));
3737552f7358SJed Brown   PetscFunctionReturn(0);
3738552f7358SJed Brown }
3739552f7358SJed Brown 
3740552f7358SJed Brown PetscErrorCode DMSetUp_Plex(DM dm)
3741552f7358SJed Brown {
3742552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
37436302a7fbSVaclav Hapla   PetscInt       size, maxSupportSize;
3744552f7358SJed Brown 
3745552f7358SJed Brown   PetscFunctionBegin;
3746552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
37479566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(mesh->coneSection));
37489566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(mesh->coneSection, &size));
37499566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, &mesh->cones));
37509566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(size, &mesh->coneOrientations));
37519566063dSJacob Faibussowitsch   PetscCall(PetscLogObjectMemory((PetscObject) dm, size*2*sizeof(PetscInt)));
37526302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize));
37536302a7fbSVaclav Hapla   if (maxSupportSize) {
37549566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(mesh->supportSection));
37559566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &size));
37569566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(size, &mesh->supports));
37579566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectMemory((PetscObject) dm, size*sizeof(PetscInt)));
3758552f7358SJed Brown   }
3759552f7358SJed Brown   PetscFunctionReturn(0);
3760552f7358SJed Brown }
3761552f7358SJed Brown 
3762276c5506SMatthew G. Knepley PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm)
3763552f7358SJed Brown {
3764552f7358SJed Brown   PetscFunctionBegin;
37659566063dSJacob Faibussowitsch   if (subdm) PetscCall(DMClone(dm, subdm));
37669566063dSJacob Faibussowitsch   PetscCall(DMCreateSectionSubDM(dm, numFields, fields, is, subdm));
3767c2939958SSatish Balay   if (subdm) {(*subdm)->useNatural = dm->useNatural;}
3768736995cdSBlaise Bourdin   if (dm->useNatural && dm->sfMigration) {
3769f94b4a02SBlaise Bourdin     PetscSF        sfMigrationInv,sfNatural;
3770f94b4a02SBlaise Bourdin     PetscSection   section, sectionSeq;
3771f94b4a02SBlaise Bourdin 
37723dcd263cSBlaise Bourdin     (*subdm)->sfMigration = dm->sfMigration;
37739566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject) dm->sfMigration));
37749566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection((*subdm), &section));
37759566063dSJacob Faibussowitsch     PetscCall(PetscSFCreateInverseSF((*subdm)->sfMigration, &sfMigrationInv));
37769566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject) (*subdm)), &sectionSeq));
37779566063dSJacob Faibussowitsch     PetscCall(PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq));
3778f94b4a02SBlaise Bourdin 
37799566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateGlobalToNaturalSF(*subdm, sectionSeq, (*subdm)->sfMigration, &sfNatural));
3780c40e9495SBlaise Bourdin     (*subdm)->sfNatural = sfNatural;
37819566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&sectionSeq));
37829566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfMigrationInv));
3783f94b4a02SBlaise Bourdin   }
3784552f7358SJed Brown   PetscFunctionReturn(0);
3785552f7358SJed Brown }
3786552f7358SJed Brown 
37872adcc780SMatthew G. Knepley PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm)
37882adcc780SMatthew G. Knepley {
37893dcd263cSBlaise Bourdin   PetscInt       i = 0;
37902adcc780SMatthew G. Knepley 
37912adcc780SMatthew G. Knepley   PetscFunctionBegin;
37929566063dSJacob Faibussowitsch   PetscCall(DMClone(dms[0], superdm));
37939566063dSJacob Faibussowitsch   PetscCall(DMCreateSectionSuperDM(dms, len, is, superdm));
3794c40e9495SBlaise Bourdin   (*superdm)->useNatural = PETSC_FALSE;
37953dcd263cSBlaise Bourdin   for (i = 0; i < len; i++) {
37963dcd263cSBlaise Bourdin     if (dms[i]->useNatural && dms[i]->sfMigration) {
37973dcd263cSBlaise Bourdin       PetscSF        sfMigrationInv,sfNatural;
37983dcd263cSBlaise Bourdin       PetscSection   section, sectionSeq;
37993dcd263cSBlaise Bourdin 
38003dcd263cSBlaise Bourdin       (*superdm)->sfMigration = dms[i]->sfMigration;
38019566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject) dms[i]->sfMigration));
3802c40e9495SBlaise Bourdin       (*superdm)->useNatural = PETSC_TRUE;
38039566063dSJacob Faibussowitsch       PetscCall(DMGetLocalSection((*superdm), &section));
38049566063dSJacob Faibussowitsch       PetscCall(PetscSFCreateInverseSF((*superdm)->sfMigration, &sfMigrationInv));
38059566063dSJacob Faibussowitsch       PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject) (*superdm)), &sectionSeq));
38069566063dSJacob Faibussowitsch       PetscCall(PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq));
38073dcd263cSBlaise Bourdin 
38089566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateGlobalToNaturalSF(*superdm, sectionSeq, (*superdm)->sfMigration, &sfNatural));
3809c40e9495SBlaise Bourdin       (*superdm)->sfNatural = sfNatural;
38109566063dSJacob Faibussowitsch       PetscCall(PetscSectionDestroy(&sectionSeq));
38119566063dSJacob Faibussowitsch       PetscCall(PetscSFDestroy(&sfMigrationInv));
38123dcd263cSBlaise Bourdin       break;
38133dcd263cSBlaise Bourdin     }
38143dcd263cSBlaise Bourdin   }
38152adcc780SMatthew G. Knepley   PetscFunctionReturn(0);
38162adcc780SMatthew G. Knepley }
38172adcc780SMatthew G. Knepley 
3818552f7358SJed Brown /*@
3819eaf898f9SPatrick Sanan   DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information
3820552f7358SJed Brown 
3821552f7358SJed Brown   Not collective
3822552f7358SJed Brown 
3823552f7358SJed Brown   Input Parameter:
3824552f7358SJed Brown . mesh - The DMPlex
3825552f7358SJed Brown 
3826552f7358SJed Brown   Output Parameter:
3827552f7358SJed Brown 
3828552f7358SJed Brown   Note:
3829552f7358SJed Brown   This should be called after all calls to DMPlexSetCone()
3830552f7358SJed Brown 
3831552f7358SJed Brown   Level: beginner
3832552f7358SJed Brown 
3833db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMPlexSetCone()`
3834552f7358SJed Brown @*/
3835552f7358SJed Brown PetscErrorCode DMPlexSymmetrize(DM dm)
3836552f7358SJed Brown {
3837552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3838552f7358SJed Brown   PetscInt      *offsets;
3839552f7358SJed Brown   PetscInt       supportSize;
3840552f7358SJed Brown   PetscInt       pStart, pEnd, p;
3841552f7358SJed Brown 
3842552f7358SJed Brown   PetscFunctionBegin;
3843552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
384428b400f6SJacob Faibussowitsch   PetscCheck(!mesh->supports,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex");
38459566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_Symmetrize,dm,0,0,0));
3846552f7358SJed Brown   /* Calculate support sizes */
38479566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
3848552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
3849552f7358SJed Brown     PetscInt dof, off, c;
3850552f7358SJed Brown 
38519566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
38529566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
3853552f7358SJed Brown     for (c = off; c < off+dof; ++c) {
38549566063dSJacob Faibussowitsch       PetscCall(PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1));
3855552f7358SJed Brown     }
3856552f7358SJed Brown   }
38579566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(mesh->supportSection));
3858552f7358SJed Brown   /* Calculate supports */
38599566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &supportSize));
38609566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(supportSize, &mesh->supports));
38619566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(pEnd - pStart, &offsets));
3862552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
3863552f7358SJed Brown     PetscInt dof, off, c;
3864552f7358SJed Brown 
38659566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
38669566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
3867552f7358SJed Brown     for (c = off; c < off+dof; ++c) {
3868552f7358SJed Brown       const PetscInt q = mesh->cones[c];
3869552f7358SJed Brown       PetscInt       offS;
3870552f7358SJed Brown 
38719566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->supportSection, q, &offS));
38720d644c17SKarl Rupp 
3873552f7358SJed Brown       mesh->supports[offS+offsets[q]] = p;
3874552f7358SJed Brown       ++offsets[q];
3875552f7358SJed Brown     }
3876552f7358SJed Brown   }
38779566063dSJacob Faibussowitsch   PetscCall(PetscFree(offsets));
38789566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_Symmetrize,dm,0,0,0));
3879552f7358SJed Brown   PetscFunctionReturn(0);
3880552f7358SJed Brown }
3881552f7358SJed Brown 
3882277ea44aSLisandro Dalcin static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd)
3883277ea44aSLisandro Dalcin {
3884277ea44aSLisandro Dalcin   IS             stratumIS;
3885277ea44aSLisandro Dalcin 
3886277ea44aSLisandro Dalcin   PetscFunctionBegin;
3887277ea44aSLisandro Dalcin   if (pStart >= pEnd) PetscFunctionReturn(0);
388876bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
3889277ea44aSLisandro Dalcin     PetscInt  qStart, qEnd, numLevels, level;
3890277ea44aSLisandro Dalcin     PetscBool overlap = PETSC_FALSE;
38919566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &numLevels));
3892277ea44aSLisandro Dalcin     for (level = 0; level < numLevels; level++) {
38939566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
3894277ea44aSLisandro Dalcin       if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) {overlap = PETSC_TRUE; break;}
3895277ea44aSLisandro Dalcin     }
389663a3b9bcSJacob Faibussowitsch     PetscCheck(!overlap,PETSC_COMM_SELF, PETSC_ERR_PLIB, "New depth %" PetscInt_FMT " range [%" PetscInt_FMT ",%" PetscInt_FMT ") overlaps with depth %" PetscInt_FMT " range [%" PetscInt_FMT ",%" PetscInt_FMT ")", depth, pStart, pEnd, level, qStart, qEnd);
3897277ea44aSLisandro Dalcin   }
38989566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd-pStart, pStart, 1, &stratumIS));
38999566063dSJacob Faibussowitsch   PetscCall(DMLabelSetStratumIS(label, depth, stratumIS));
39009566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&stratumIS));
3901277ea44aSLisandro Dalcin   PetscFunctionReturn(0);
3902277ea44aSLisandro Dalcin }
3903277ea44aSLisandro Dalcin 
3904552f7358SJed Brown /*@
3905a8d69d7bSBarry Smith   DMPlexStratify - The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and
39066dd80730SBarry Smith   can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the
3907552f7358SJed Brown   same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in
3908552f7358SJed Brown   the DAG.
3909552f7358SJed Brown 
3910bf4602e4SToby Isaac   Collective on dm
3911552f7358SJed Brown 
3912552f7358SJed Brown   Input Parameter:
3913552f7358SJed Brown . mesh - The DMPlex
3914552f7358SJed Brown 
3915552f7358SJed Brown   Output Parameter:
3916552f7358SJed Brown 
3917552f7358SJed Brown   Notes:
3918b1bb481bSMatthew Knepley   Concretely, DMPlexStratify() creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex
3919b1bb481bSMatthew 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
3920b1bb481bSMatthew Knepley   until cells have depth equal to the dimension of the mesh. The depth label can be accessed through DMPlexGetDepthLabel() or DMPlexGetDepthStratum(), or
3921c58f1c22SToby Isaac   manually via DMGetLabel().  The height is defined implicitly by height = maxDimension - depth, and can be accessed
3922150b719bSJed Brown   via DMPlexGetHeightStratum().  For example, cells have height 0 and faces have height 1.
3923552f7358SJed Brown 
3924b1bb481bSMatthew Knepley   The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results
3925b1bb481bSMatthew Knepley   if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that
3926b1bb481bSMatthew 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
3927b1bb481bSMatthew Knepley   to interpolate only that one (e0), so that
3928b1bb481bSMatthew Knepley $  cone(c0) = {e0, v2}
3929b1bb481bSMatthew Knepley $  cone(e0) = {v0, v1}
3930b1bb481bSMatthew Knepley   If DMPlexStratify() is run on this mesh, it will give depths
3931b1bb481bSMatthew Knepley $  depth 0 = {v0, v1, v2}
3932b1bb481bSMatthew Knepley $  depth 1 = {e0, c0}
3933b1bb481bSMatthew Knepley   where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2.
3934b1bb481bSMatthew Knepley 
3935150b719bSJed Brown   DMPlexStratify() should be called after all calls to DMPlexSymmetrize()
3936552f7358SJed Brown 
3937552f7358SJed Brown   Level: beginner
3938552f7358SJed Brown 
3939db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexComputeCellTypes()`
3940552f7358SJed Brown @*/
3941552f7358SJed Brown PetscErrorCode DMPlexStratify(DM dm)
3942552f7358SJed Brown {
3943df0420ecSMatthew G. Knepley   DM_Plex       *mesh = (DM_Plex*) dm->data;
3944aa50250dSMatthew G. Knepley   DMLabel        label;
3945552f7358SJed Brown   PetscInt       pStart, pEnd, p;
3946552f7358SJed Brown   PetscInt       numRoots = 0, numLeaves = 0;
3947552f7358SJed Brown 
3948552f7358SJed Brown   PetscFunctionBegin;
3949552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
39509566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0));
3951277ea44aSLisandro Dalcin 
3952277ea44aSLisandro Dalcin   /* Create depth label */
39539566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
39549566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "depth"));
39559566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
3956277ea44aSLisandro Dalcin 
3957277ea44aSLisandro Dalcin   {
3958552f7358SJed Brown     /* Initialize roots and count leaves */
3959277ea44aSLisandro Dalcin     PetscInt sMin = PETSC_MAX_INT;
3960277ea44aSLisandro Dalcin     PetscInt sMax = PETSC_MIN_INT;
3961552f7358SJed Brown     PetscInt coneSize, supportSize;
3962552f7358SJed Brown 
3963277ea44aSLisandro Dalcin     for (p = pStart; p < pEnd; ++p) {
39649566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
39659566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
3966552f7358SJed Brown       if (!coneSize && supportSize) {
3967277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
3968277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
3969552f7358SJed Brown         ++numRoots;
3970552f7358SJed Brown       } else if (!supportSize && coneSize) {
3971552f7358SJed Brown         ++numLeaves;
3972552f7358SJed Brown       } else if (!supportSize && !coneSize) {
3973552f7358SJed Brown         /* Isolated points */
3974277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
3975277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
3976552f7358SJed Brown       }
3977552f7358SJed Brown     }
39789566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax+1));
3979277ea44aSLisandro Dalcin   }
3980277ea44aSLisandro Dalcin 
3981552f7358SJed Brown   if (numRoots + numLeaves == (pEnd - pStart)) {
3982277ea44aSLisandro Dalcin     PetscInt sMin = PETSC_MAX_INT;
3983277ea44aSLisandro Dalcin     PetscInt sMax = PETSC_MIN_INT;
3984552f7358SJed Brown     PetscInt coneSize, supportSize;
3985552f7358SJed Brown 
3986277ea44aSLisandro Dalcin     for (p = pStart; p < pEnd; ++p) {
39879566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
39889566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
3989552f7358SJed Brown       if (!supportSize && coneSize) {
3990277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
3991277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
3992552f7358SJed Brown       }
3993552f7358SJed Brown     }
39949566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax+1));
3995552f7358SJed Brown   } else {
3996277ea44aSLisandro Dalcin     PetscInt level = 0;
3997277ea44aSLisandro Dalcin     PetscInt qStart, qEnd, q;
3998552f7358SJed Brown 
39999566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
4000277ea44aSLisandro Dalcin     while (qEnd > qStart) {
4001277ea44aSLisandro Dalcin       PetscInt sMin = PETSC_MAX_INT;
4002277ea44aSLisandro Dalcin       PetscInt sMax = PETSC_MIN_INT;
400374ef644bSMatthew G. Knepley 
4004277ea44aSLisandro Dalcin       for (q = qStart; q < qEnd; ++q) {
400574ef644bSMatthew G. Knepley         const PetscInt *support;
400674ef644bSMatthew G. Knepley         PetscInt        supportSize, s;
400774ef644bSMatthew G. Knepley 
40089566063dSJacob Faibussowitsch         PetscCall(DMPlexGetSupportSize(dm, q, &supportSize));
40099566063dSJacob Faibussowitsch         PetscCall(DMPlexGetSupport(dm, q, &support));
401074ef644bSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
4011277ea44aSLisandro Dalcin           sMin = PetscMin(support[s], sMin);
4012277ea44aSLisandro Dalcin           sMax = PetscMax(support[s], sMax);
4013552f7358SJed Brown         }
4014552f7358SJed Brown       }
40159566063dSJacob Faibussowitsch       PetscCall(DMLabelGetNumValues(label, &level));
40169566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateDepthStratum(dm, label, level, sMin, sMax+1));
40179566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
401874ef644bSMatthew G. Knepley     }
401974ef644bSMatthew G. Knepley   }
4020bf4602e4SToby Isaac   { /* just in case there is an empty process */
4021bf4602e4SToby Isaac     PetscInt numValues, maxValues = 0, v;
4022bf4602e4SToby Isaac 
40239566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &numValues));
40249566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(&numValues,&maxValues,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm)));
4025bf4602e4SToby Isaac     for (v = numValues; v < maxValues; v++) {
40269566063dSJacob Faibussowitsch       PetscCall(DMLabelAddStratum(label, v));
4027bf4602e4SToby Isaac     }
4028bf4602e4SToby Isaac   }
40299566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateGet((PetscObject) label, &mesh->depthState));
40309566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0));
4031552f7358SJed Brown   PetscFunctionReturn(0);
4032552f7358SJed Brown }
4033552f7358SJed Brown 
4034412e9a14SMatthew G. Knepley PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt)
4035ba2698f1SMatthew G. Knepley {
4036412e9a14SMatthew G. Knepley   DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
4037412e9a14SMatthew G. Knepley   PetscInt       dim, depth, pheight, coneSize;
4038ba2698f1SMatthew G. Knepley 
4039412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
40409566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
40419566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
40429566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
4043ba2698f1SMatthew G. Knepley   pheight = depth - pdepth;
4044ba2698f1SMatthew G. Knepley   if (depth <= 1) {
4045ba2698f1SMatthew G. Knepley     switch (pdepth) {
4046ba2698f1SMatthew G. Knepley       case 0: ct = DM_POLYTOPE_POINT;break;
4047ba2698f1SMatthew G. Knepley       case 1:
4048ba2698f1SMatthew G. Knepley         switch (coneSize) {
4049ba2698f1SMatthew G. Knepley           case 2: ct = DM_POLYTOPE_SEGMENT;break;
4050ba2698f1SMatthew G. Knepley           case 3: ct = DM_POLYTOPE_TRIANGLE;break;
4051ba2698f1SMatthew G. Knepley           case 4:
4052ba2698f1SMatthew G. Knepley           switch (dim) {
4053ba2698f1SMatthew G. Knepley             case 2: ct = DM_POLYTOPE_QUADRILATERAL;break;
4054ba2698f1SMatthew G. Knepley             case 3: ct = DM_POLYTOPE_TETRAHEDRON;break;
4055ba2698f1SMatthew G. Knepley             default: break;
4056ba2698f1SMatthew G. Knepley           }
4057ba2698f1SMatthew G. Knepley           break;
4058da9060c4SMatthew G. Knepley         case 5: ct = DM_POLYTOPE_PYRAMID;break;
4059ba2698f1SMatthew G. Knepley         case 6: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break;
4060ba2698f1SMatthew G. Knepley         case 8: ct = DM_POLYTOPE_HEXAHEDRON;break;
4061ba2698f1SMatthew G. Knepley         default: break;
4062ba2698f1SMatthew G. Knepley       }
4063ba2698f1SMatthew G. Knepley     }
4064ba2698f1SMatthew G. Knepley   } else {
4065ba2698f1SMatthew G. Knepley     if (pdepth == 0) {
4066ba2698f1SMatthew G. Knepley       ct = DM_POLYTOPE_POINT;
4067ba2698f1SMatthew G. Knepley     } else if (pheight == 0) {
4068ba2698f1SMatthew G. Knepley       switch (dim) {
4069ba2698f1SMatthew G. Knepley         case 1:
4070ba2698f1SMatthew G. Knepley           switch (coneSize) {
4071ba2698f1SMatthew G. Knepley             case 2: ct = DM_POLYTOPE_SEGMENT;break;
4072ba2698f1SMatthew G. Knepley             default: break;
4073ba2698f1SMatthew G. Knepley           }
4074ba2698f1SMatthew G. Knepley           break;
4075ba2698f1SMatthew G. Knepley         case 2:
4076ba2698f1SMatthew G. Knepley           switch (coneSize) {
4077ba2698f1SMatthew G. Knepley             case 3: ct = DM_POLYTOPE_TRIANGLE;break;
4078ba2698f1SMatthew G. Knepley             case 4: ct = DM_POLYTOPE_QUADRILATERAL;break;
4079ba2698f1SMatthew G. Knepley             default: break;
4080ba2698f1SMatthew G. Knepley           }
4081ba2698f1SMatthew G. Knepley           break;
4082ba2698f1SMatthew G. Knepley         case 3:
4083ba2698f1SMatthew G. Knepley           switch (coneSize) {
4084ba2698f1SMatthew G. Knepley             case 4: ct = DM_POLYTOPE_TETRAHEDRON;break;
4085da9060c4SMatthew G. Knepley             case 5:
4086da9060c4SMatthew G. Knepley             {
4087da9060c4SMatthew G. Knepley               const PetscInt *cone;
4088da9060c4SMatthew G. Knepley               PetscInt        faceConeSize;
4089da9060c4SMatthew G. Knepley 
40909566063dSJacob Faibussowitsch               PetscCall(DMPlexGetCone(dm, p, &cone));
40919566063dSJacob Faibussowitsch               PetscCall(DMPlexGetConeSize(dm, cone[0], &faceConeSize));
4092da9060c4SMatthew G. Knepley               switch (faceConeSize) {
4093da9060c4SMatthew G. Knepley                 case 3: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break;
4094da9060c4SMatthew G. Knepley                 case 4: ct = DM_POLYTOPE_PYRAMID;break;
4095da9060c4SMatthew G. Knepley               }
4096da9060c4SMatthew G. Knepley             }
4097da9060c4SMatthew G. Knepley             break;
4098ba2698f1SMatthew G. Knepley             case 6: ct = DM_POLYTOPE_HEXAHEDRON;break;
4099ba2698f1SMatthew G. Knepley             default: break;
4100ba2698f1SMatthew G. Knepley           }
4101ba2698f1SMatthew G. Knepley           break;
4102ba2698f1SMatthew G. Knepley         default: break;
4103ba2698f1SMatthew G. Knepley       }
4104ba2698f1SMatthew G. Knepley     } else if (pheight > 0) {
4105ba2698f1SMatthew G. Knepley       switch (coneSize) {
4106ba2698f1SMatthew G. Knepley         case 2: ct = DM_POLYTOPE_SEGMENT;break;
4107ba2698f1SMatthew G. Knepley         case 3: ct = DM_POLYTOPE_TRIANGLE;break;
4108ba2698f1SMatthew G. Knepley         case 4: ct = DM_POLYTOPE_QUADRILATERAL;break;
4109ba2698f1SMatthew G. Knepley         default: break;
4110ba2698f1SMatthew G. Knepley       }
4111ba2698f1SMatthew G. Knepley     }
4112ba2698f1SMatthew G. Knepley   }
4113412e9a14SMatthew G. Knepley   *pt = ct;
4114412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
4115ba2698f1SMatthew G. Knepley }
4116412e9a14SMatthew G. Knepley 
4117412e9a14SMatthew G. Knepley /*@
4118412e9a14SMatthew G. Knepley   DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size.
4119412e9a14SMatthew G. Knepley 
4120412e9a14SMatthew G. Knepley   Collective on dm
4121412e9a14SMatthew G. Knepley 
4122412e9a14SMatthew G. Knepley   Input Parameter:
4123412e9a14SMatthew G. Knepley . mesh - The DMPlex
4124412e9a14SMatthew G. Knepley 
4125412e9a14SMatthew G. Knepley   DMPlexComputeCellTypes() should be called after all calls to DMPlexSymmetrize() and DMPlexStratify()
4126412e9a14SMatthew G. Knepley 
4127412e9a14SMatthew G. Knepley   Level: developer
4128412e9a14SMatthew G. Knepley 
4129412e9a14SMatthew G. Knepley   Note: This function is normally called automatically by Plex when a cell type is requested. It creates an
4130412e9a14SMatthew G. Knepley   internal DMLabel named "celltype" which can be directly accessed using DMGetLabel(). A user may disable
4131412e9a14SMatthew G. Knepley   automatic creation by creating the label manually, using DMCreateLabel(dm, "celltype").
4132412e9a14SMatthew G. Knepley 
4133db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexStratify()`, `DMGetLabel()`, `DMCreateLabel()`
4134412e9a14SMatthew G. Knepley @*/
4135412e9a14SMatthew G. Knepley PetscErrorCode DMPlexComputeCellTypes(DM dm)
4136412e9a14SMatthew G. Knepley {
4137412e9a14SMatthew G. Knepley   DM_Plex       *mesh;
4138412e9a14SMatthew G. Knepley   DMLabel        ctLabel;
4139412e9a14SMatthew G. Knepley   PetscInt       pStart, pEnd, p;
4140412e9a14SMatthew G. Knepley 
4141412e9a14SMatthew G. Knepley   PetscFunctionBegin;
4142412e9a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4143412e9a14SMatthew G. Knepley   mesh = (DM_Plex *) dm->data;
41449566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "celltype"));
41459566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel));
41469566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
4147412e9a14SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
4148327c2912SStefano Zampini     DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
4149412e9a14SMatthew G. Knepley     PetscInt       pdepth;
4150412e9a14SMatthew G. Knepley 
41519566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPointDepth(dm, p, &pdepth));
41529566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellType_Internal(dm, p, pdepth, &ct));
415363a3b9bcSJacob Faibussowitsch     PetscCheck(ct != DM_POLYTOPE_UNKNOWN,PETSC_COMM_SELF, PETSC_ERR_SUP, "Point %" PetscInt_FMT " is screwed up", p);
41549566063dSJacob Faibussowitsch     PetscCall(DMLabelSetValue(ctLabel, p, ct));
4155412e9a14SMatthew G. Knepley   }
41569566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateGet((PetscObject) ctLabel, &mesh->celltypeState));
41579566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject) ctLabel, NULL, "-dm_plex_celltypes_view"));
4158ba2698f1SMatthew G. Knepley   PetscFunctionReturn(0);
4159ba2698f1SMatthew G. Knepley }
4160ba2698f1SMatthew G. Knepley 
4161552f7358SJed Brown /*@C
4162552f7358SJed Brown   DMPlexGetJoin - Get an array for the join of the set of points
4163552f7358SJed Brown 
4164552f7358SJed Brown   Not Collective
4165552f7358SJed Brown 
4166552f7358SJed Brown   Input Parameters:
4167552f7358SJed Brown + dm - The DMPlex object
4168552f7358SJed Brown . numPoints - The number of input points for the join
4169552f7358SJed Brown - points - The input points
4170552f7358SJed Brown 
4171552f7358SJed Brown   Output Parameters:
4172552f7358SJed Brown + numCoveredPoints - The number of points in the join
4173552f7358SJed Brown - coveredPoints - The points in the join
4174552f7358SJed Brown 
4175552f7358SJed Brown   Level: intermediate
4176552f7358SJed Brown 
4177552f7358SJed Brown   Note: Currently, this is restricted to a single level join
4178552f7358SJed Brown 
41793813dfbdSMatthew G Knepley   Fortran Notes:
41803813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
41813813dfbdSMatthew G Knepley   include petsc.h90 in your code.
41823813dfbdSMatthew G Knepley 
41833813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
41843813dfbdSMatthew G Knepley 
4185db781477SPatrick Sanan .seealso: `DMPlexRestoreJoin()`, `DMPlexGetMeet()`
4186552f7358SJed Brown @*/
4187552f7358SJed Brown PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4188552f7358SJed Brown {
4189552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
4190552f7358SJed Brown   PetscInt      *join[2];
4191552f7358SJed Brown   PetscInt       joinSize, i = 0;
4192552f7358SJed Brown   PetscInt       dof, off, p, c, m;
41936302a7fbSVaclav Hapla   PetscInt       maxSupportSize;
4194552f7358SJed Brown 
4195552f7358SJed Brown   PetscFunctionBegin;
4196552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
419748bb261cSVaclav Hapla   PetscValidIntPointer(points, 3);
419848bb261cSVaclav Hapla   PetscValidIntPointer(numCoveredPoints, 4);
419948bb261cSVaclav Hapla   PetscValidPointer(coveredPoints, 5);
42006302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize));
42016302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[0]));
42026302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[1]));
4203552f7358SJed Brown   /* Copy in support of first point */
42049566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, points[0], &dof));
42059566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, points[0], &off));
4206552f7358SJed Brown   for (joinSize = 0; joinSize < dof; ++joinSize) {
4207552f7358SJed Brown     join[i][joinSize] = mesh->supports[off+joinSize];
4208552f7358SJed Brown   }
4209552f7358SJed Brown   /* Check each successive support */
4210552f7358SJed Brown   for (p = 1; p < numPoints; ++p) {
4211552f7358SJed Brown     PetscInt newJoinSize = 0;
4212552f7358SJed Brown 
42139566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->supportSection, points[p], &dof));
42149566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->supportSection, points[p], &off));
4215552f7358SJed Brown     for (c = 0; c < dof; ++c) {
4216552f7358SJed Brown       const PetscInt point = mesh->supports[off+c];
4217552f7358SJed Brown 
4218552f7358SJed Brown       for (m = 0; m < joinSize; ++m) {
4219552f7358SJed Brown         if (point == join[i][m]) {
4220552f7358SJed Brown           join[1-i][newJoinSize++] = point;
4221552f7358SJed Brown           break;
4222552f7358SJed Brown         }
4223552f7358SJed Brown       }
4224552f7358SJed Brown     }
4225552f7358SJed Brown     joinSize = newJoinSize;
4226552f7358SJed Brown     i        = 1-i;
4227552f7358SJed Brown   }
4228552f7358SJed Brown   *numCoveredPoints = joinSize;
4229552f7358SJed Brown   *coveredPoints    = join[i];
42306302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, maxSupportSize, MPIU_INT, &join[1-i]));
4231552f7358SJed Brown   PetscFunctionReturn(0);
4232552f7358SJed Brown }
4233552f7358SJed Brown 
4234552f7358SJed Brown /*@C
4235552f7358SJed Brown   DMPlexRestoreJoin - Restore an array for the join of the set of points
4236552f7358SJed Brown 
4237552f7358SJed Brown   Not Collective
4238552f7358SJed Brown 
4239552f7358SJed Brown   Input Parameters:
4240552f7358SJed Brown + dm - The DMPlex object
4241552f7358SJed Brown . numPoints - The number of input points for the join
4242552f7358SJed Brown - points - The input points
4243552f7358SJed Brown 
4244552f7358SJed Brown   Output Parameters:
4245552f7358SJed Brown + numCoveredPoints - The number of points in the join
4246552f7358SJed Brown - coveredPoints - The points in the join
4247552f7358SJed Brown 
42483813dfbdSMatthew G Knepley   Fortran Notes:
42493813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
42503813dfbdSMatthew G Knepley   include petsc.h90 in your code.
42513813dfbdSMatthew G Knepley 
42523813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
42533813dfbdSMatthew G Knepley 
4254552f7358SJed Brown   Level: intermediate
4255552f7358SJed Brown 
4256db781477SPatrick Sanan .seealso: `DMPlexGetJoin()`, `DMPlexGetFullJoin()`, `DMPlexGetMeet()`
4257552f7358SJed Brown @*/
4258552f7358SJed Brown PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4259552f7358SJed Brown {
4260552f7358SJed Brown   PetscFunctionBegin;
4261552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4262d7902bd2SMatthew G. Knepley   if (points) PetscValidIntPointer(points,3);
4263d7902bd2SMatthew G. Knepley   if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4);
4264d7902bd2SMatthew G. Knepley   PetscValidPointer(coveredPoints, 5);
42659566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints));
4266d7902bd2SMatthew G. Knepley   if (numCoveredPoints) *numCoveredPoints = 0;
4267552f7358SJed Brown   PetscFunctionReturn(0);
4268552f7358SJed Brown }
4269552f7358SJed Brown 
4270552f7358SJed Brown /*@C
4271552f7358SJed Brown   DMPlexGetFullJoin - Get an array for the join of the set of points
4272552f7358SJed Brown 
4273552f7358SJed Brown   Not Collective
4274552f7358SJed Brown 
4275552f7358SJed Brown   Input Parameters:
4276552f7358SJed Brown + dm - The DMPlex object
4277552f7358SJed Brown . numPoints - The number of input points for the join
4278552f7358SJed Brown - points - The input points
4279552f7358SJed Brown 
4280552f7358SJed Brown   Output Parameters:
4281552f7358SJed Brown + numCoveredPoints - The number of points in the join
4282552f7358SJed Brown - coveredPoints - The points in the join
4283552f7358SJed Brown 
42843813dfbdSMatthew G Knepley   Fortran Notes:
42853813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
42863813dfbdSMatthew G Knepley   include petsc.h90 in your code.
42873813dfbdSMatthew G Knepley 
42883813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
42893813dfbdSMatthew G Knepley 
4290552f7358SJed Brown   Level: intermediate
4291552f7358SJed Brown 
4292db781477SPatrick Sanan .seealso: `DMPlexGetJoin()`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()`
4293552f7358SJed Brown @*/
4294552f7358SJed Brown PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4295552f7358SJed Brown {
4296552f7358SJed Brown   PetscInt      *offsets, **closures;
4297552f7358SJed Brown   PetscInt      *join[2];
4298552f7358SJed Brown   PetscInt       depth = 0, maxSize, joinSize = 0, i = 0;
429924c766afSToby Isaac   PetscInt       p, d, c, m, ms;
4300552f7358SJed Brown 
4301552f7358SJed Brown   PetscFunctionBegin;
4302552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
430348bb261cSVaclav Hapla   PetscValidIntPointer(points, 3);
430448bb261cSVaclav Hapla   PetscValidIntPointer(numCoveredPoints, 4);
430548bb261cSVaclav Hapla   PetscValidPointer(coveredPoints, 5);
4306552f7358SJed Brown 
43079566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
43089566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(numPoints, &closures));
43099566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets));
43106302a7fbSVaclav Hapla   PetscCall(DMPlexGetMaxSizes(dm, NULL, &ms));
431124c766afSToby Isaac   maxSize = (ms > 1) ? ((PetscPowInt(ms,depth+1)-1)/(ms-1)) : depth + 1;
43129566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0]));
43139566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1]));
4314552f7358SJed Brown 
4315552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
4316552f7358SJed Brown     PetscInt closureSize;
4317552f7358SJed Brown 
43189566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]));
43190d644c17SKarl Rupp 
4320552f7358SJed Brown     offsets[p*(depth+2)+0] = 0;
4321552f7358SJed Brown     for (d = 0; d < depth+1; ++d) {
4322552f7358SJed Brown       PetscInt pStart, pEnd, i;
4323552f7358SJed Brown 
43249566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
4325552f7358SJed Brown       for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) {
4326552f7358SJed Brown         if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) {
4327552f7358SJed Brown           offsets[p*(depth+2)+d+1] = i;
4328552f7358SJed Brown           break;
4329552f7358SJed Brown         }
4330552f7358SJed Brown       }
4331552f7358SJed Brown       if (i == closureSize) offsets[p*(depth+2)+d+1] = i;
4332552f7358SJed Brown     }
433363a3b9bcSJacob Faibussowitsch     PetscCheck(offsets[p*(depth+2)+depth+1] == closureSize,PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Total size of closure %" PetscInt_FMT " should be %" PetscInt_FMT, offsets[p*(depth+2)+depth+1], closureSize);
4334552f7358SJed Brown   }
4335552f7358SJed Brown   for (d = 0; d < depth+1; ++d) {
4336552f7358SJed Brown     PetscInt dof;
4337552f7358SJed Brown 
4338552f7358SJed Brown     /* Copy in support of first point */
4339552f7358SJed Brown     dof = offsets[d+1] - offsets[d];
4340552f7358SJed Brown     for (joinSize = 0; joinSize < dof; ++joinSize) {
4341552f7358SJed Brown       join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2];
4342552f7358SJed Brown     }
4343552f7358SJed Brown     /* Check each successive cone */
4344552f7358SJed Brown     for (p = 1; p < numPoints && joinSize; ++p) {
4345552f7358SJed Brown       PetscInt newJoinSize = 0;
4346552f7358SJed Brown 
4347552f7358SJed Brown       dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d];
4348552f7358SJed Brown       for (c = 0; c < dof; ++c) {
4349552f7358SJed Brown         const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2];
4350552f7358SJed Brown 
4351552f7358SJed Brown         for (m = 0; m < joinSize; ++m) {
4352552f7358SJed Brown           if (point == join[i][m]) {
4353552f7358SJed Brown             join[1-i][newJoinSize++] = point;
4354552f7358SJed Brown             break;
4355552f7358SJed Brown           }
4356552f7358SJed Brown         }
4357552f7358SJed Brown       }
4358552f7358SJed Brown       joinSize = newJoinSize;
4359552f7358SJed Brown       i        = 1-i;
4360552f7358SJed Brown     }
4361552f7358SJed Brown     if (joinSize) break;
4362552f7358SJed Brown   }
4363552f7358SJed Brown   *numCoveredPoints = joinSize;
4364552f7358SJed Brown   *coveredPoints    = join[i];
4365552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
43669566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]));
4367552f7358SJed Brown   }
43689566063dSJacob Faibussowitsch   PetscCall(PetscFree(closures));
43699566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets));
43706302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, ms, MPIU_INT, &join[1-i]));
4371552f7358SJed Brown   PetscFunctionReturn(0);
4372552f7358SJed Brown }
4373552f7358SJed Brown 
4374552f7358SJed Brown /*@C
4375552f7358SJed Brown   DMPlexGetMeet - Get an array for the meet of the set of points
4376552f7358SJed Brown 
4377552f7358SJed Brown   Not Collective
4378552f7358SJed Brown 
4379552f7358SJed Brown   Input Parameters:
4380552f7358SJed Brown + dm - The DMPlex object
4381552f7358SJed Brown . numPoints - The number of input points for the meet
4382552f7358SJed Brown - points - The input points
4383552f7358SJed Brown 
4384552f7358SJed Brown   Output Parameters:
4385552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4386552f7358SJed Brown - coveredPoints - The points in the meet
4387552f7358SJed Brown 
4388552f7358SJed Brown   Level: intermediate
4389552f7358SJed Brown 
4390552f7358SJed Brown   Note: Currently, this is restricted to a single level meet
4391552f7358SJed Brown 
43923813dfbdSMatthew G Knepley   Fortran Notes:
43933813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
43943813dfbdSMatthew G Knepley   include petsc.h90 in your code.
43953813dfbdSMatthew G Knepley 
43963813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
43973813dfbdSMatthew G Knepley 
4398db781477SPatrick Sanan .seealso: `DMPlexRestoreMeet()`, `DMPlexGetJoin()`
4399552f7358SJed Brown @*/
4400552f7358SJed Brown PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints)
4401552f7358SJed Brown {
4402552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
4403552f7358SJed Brown   PetscInt      *meet[2];
4404552f7358SJed Brown   PetscInt       meetSize, i = 0;
4405552f7358SJed Brown   PetscInt       dof, off, p, c, m;
44066302a7fbSVaclav Hapla   PetscInt       maxConeSize;
4407552f7358SJed Brown 
4408552f7358SJed Brown   PetscFunctionBegin;
4409552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4410dadcf809SJacob Faibussowitsch   PetscValidIntPointer(points, 3);
4411dadcf809SJacob Faibussowitsch   PetscValidIntPointer(numCoveringPoints, 4);
4412064a246eSJacob Faibussowitsch   PetscValidPointer(coveringPoints, 5);
44136302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->coneSection, &maxConeSize));
44146302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[0]));
44156302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[1]));
4416552f7358SJed Brown   /* Copy in cone of first point */
44179566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, points[0], &dof));
44189566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, points[0], &off));
4419552f7358SJed Brown   for (meetSize = 0; meetSize < dof; ++meetSize) {
4420552f7358SJed Brown     meet[i][meetSize] = mesh->cones[off+meetSize];
4421552f7358SJed Brown   }
4422552f7358SJed Brown   /* Check each successive cone */
4423552f7358SJed Brown   for (p = 1; p < numPoints; ++p) {
4424552f7358SJed Brown     PetscInt newMeetSize = 0;
4425552f7358SJed Brown 
44269566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, points[p], &dof));
44279566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, points[p], &off));
4428552f7358SJed Brown     for (c = 0; c < dof; ++c) {
4429552f7358SJed Brown       const PetscInt point = mesh->cones[off+c];
4430552f7358SJed Brown 
4431552f7358SJed Brown       for (m = 0; m < meetSize; ++m) {
4432552f7358SJed Brown         if (point == meet[i][m]) {
4433552f7358SJed Brown           meet[1-i][newMeetSize++] = point;
4434552f7358SJed Brown           break;
4435552f7358SJed Brown         }
4436552f7358SJed Brown       }
4437552f7358SJed Brown     }
4438552f7358SJed Brown     meetSize = newMeetSize;
4439552f7358SJed Brown     i        = 1-i;
4440552f7358SJed Brown   }
4441552f7358SJed Brown   *numCoveringPoints = meetSize;
4442552f7358SJed Brown   *coveringPoints    = meet[i];
44436302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, maxConeSize, MPIU_INT, &meet[1-i]));
4444552f7358SJed Brown   PetscFunctionReturn(0);
4445552f7358SJed Brown }
4446552f7358SJed Brown 
4447552f7358SJed Brown /*@C
4448552f7358SJed Brown   DMPlexRestoreMeet - Restore an array for the meet of the set of points
4449552f7358SJed Brown 
4450552f7358SJed Brown   Not Collective
4451552f7358SJed Brown 
4452552f7358SJed Brown   Input Parameters:
4453552f7358SJed Brown + dm - The DMPlex object
4454552f7358SJed Brown . numPoints - The number of input points for the meet
4455552f7358SJed Brown - points - The input points
4456552f7358SJed Brown 
4457552f7358SJed Brown   Output Parameters:
4458552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4459552f7358SJed Brown - coveredPoints - The points in the meet
4460552f7358SJed Brown 
4461552f7358SJed Brown   Level: intermediate
4462552f7358SJed Brown 
44633813dfbdSMatthew G Knepley   Fortran Notes:
44643813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
44653813dfbdSMatthew G Knepley   include petsc.h90 in your code.
44663813dfbdSMatthew G Knepley 
44673813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
44683813dfbdSMatthew G Knepley 
4469db781477SPatrick Sanan .seealso: `DMPlexGetMeet()`, `DMPlexGetFullMeet()`, `DMPlexGetJoin()`
4470552f7358SJed Brown @*/
4471552f7358SJed Brown PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4472552f7358SJed Brown {
4473552f7358SJed Brown   PetscFunctionBegin;
4474552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4475d7902bd2SMatthew G. Knepley   if (points) PetscValidIntPointer(points,3);
4476d7902bd2SMatthew G. Knepley   if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4);
4477d7902bd2SMatthew G. Knepley   PetscValidPointer(coveredPoints,5);
44789566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints));
4479d7902bd2SMatthew G. Knepley   if (numCoveredPoints) *numCoveredPoints = 0;
4480552f7358SJed Brown   PetscFunctionReturn(0);
4481552f7358SJed Brown }
4482552f7358SJed Brown 
4483552f7358SJed Brown /*@C
4484552f7358SJed Brown   DMPlexGetFullMeet - Get an array for the meet of the set of points
4485552f7358SJed Brown 
4486552f7358SJed Brown   Not Collective
4487552f7358SJed Brown 
4488552f7358SJed Brown   Input Parameters:
4489552f7358SJed Brown + dm - The DMPlex object
4490552f7358SJed Brown . numPoints - The number of input points for the meet
4491552f7358SJed Brown - points - The input points
4492552f7358SJed Brown 
4493552f7358SJed Brown   Output Parameters:
4494552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4495552f7358SJed Brown - coveredPoints - The points in the meet
4496552f7358SJed Brown 
4497552f7358SJed Brown   Level: intermediate
4498552f7358SJed Brown 
44993813dfbdSMatthew G Knepley   Fortran Notes:
45003813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
45013813dfbdSMatthew G Knepley   include petsc.h90 in your code.
45023813dfbdSMatthew G Knepley 
45033813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
45043813dfbdSMatthew G Knepley 
4505db781477SPatrick Sanan .seealso: `DMPlexGetMeet()`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()`
4506552f7358SJed Brown @*/
4507552f7358SJed Brown PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4508552f7358SJed Brown {
4509552f7358SJed Brown   PetscInt      *offsets, **closures;
4510552f7358SJed Brown   PetscInt      *meet[2];
4511552f7358SJed Brown   PetscInt       height = 0, maxSize, meetSize = 0, i = 0;
451224c766afSToby Isaac   PetscInt       p, h, c, m, mc;
4513552f7358SJed Brown 
4514552f7358SJed Brown   PetscFunctionBegin;
4515552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4516dadcf809SJacob Faibussowitsch   PetscValidIntPointer(points, 3);
4517dadcf809SJacob Faibussowitsch   PetscValidIntPointer(numCoveredPoints, 4);
4518064a246eSJacob Faibussowitsch   PetscValidPointer(coveredPoints, 5);
4519552f7358SJed Brown 
45209566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &height));
45219566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(numPoints, &closures));
45229566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets));
45236302a7fbSVaclav Hapla   PetscCall(DMPlexGetMaxSizes(dm, &mc, NULL));
452424c766afSToby Isaac   maxSize = (mc > 1) ? ((PetscPowInt(mc,height+1)-1)/(mc-1)) : height + 1;
45259566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0]));
45269566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1]));
4527552f7358SJed Brown 
4528552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
4529552f7358SJed Brown     PetscInt closureSize;
4530552f7358SJed Brown 
45319566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]));
45320d644c17SKarl Rupp 
4533552f7358SJed Brown     offsets[p*(height+2)+0] = 0;
4534552f7358SJed Brown     for (h = 0; h < height+1; ++h) {
4535552f7358SJed Brown       PetscInt pStart, pEnd, i;
4536552f7358SJed Brown 
45379566063dSJacob Faibussowitsch       PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd));
4538552f7358SJed Brown       for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) {
4539552f7358SJed Brown         if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) {
4540552f7358SJed Brown           offsets[p*(height+2)+h+1] = i;
4541552f7358SJed Brown           break;
4542552f7358SJed Brown         }
4543552f7358SJed Brown       }
4544552f7358SJed Brown       if (i == closureSize) offsets[p*(height+2)+h+1] = i;
4545552f7358SJed Brown     }
454663a3b9bcSJacob Faibussowitsch     PetscCheck(offsets[p*(height+2)+height+1] == closureSize,PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Total size of closure %" PetscInt_FMT " should be %" PetscInt_FMT, offsets[p*(height+2)+height+1], closureSize);
4547552f7358SJed Brown   }
4548552f7358SJed Brown   for (h = 0; h < height+1; ++h) {
4549552f7358SJed Brown     PetscInt dof;
4550552f7358SJed Brown 
4551552f7358SJed Brown     /* Copy in cone of first point */
4552552f7358SJed Brown     dof = offsets[h+1] - offsets[h];
4553552f7358SJed Brown     for (meetSize = 0; meetSize < dof; ++meetSize) {
4554552f7358SJed Brown       meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2];
4555552f7358SJed Brown     }
4556552f7358SJed Brown     /* Check each successive cone */
4557552f7358SJed Brown     for (p = 1; p < numPoints && meetSize; ++p) {
4558552f7358SJed Brown       PetscInt newMeetSize = 0;
4559552f7358SJed Brown 
4560552f7358SJed Brown       dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h];
4561552f7358SJed Brown       for (c = 0; c < dof; ++c) {
4562552f7358SJed Brown         const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2];
4563552f7358SJed Brown 
4564552f7358SJed Brown         for (m = 0; m < meetSize; ++m) {
4565552f7358SJed Brown           if (point == meet[i][m]) {
4566552f7358SJed Brown             meet[1-i][newMeetSize++] = point;
4567552f7358SJed Brown             break;
4568552f7358SJed Brown           }
4569552f7358SJed Brown         }
4570552f7358SJed Brown       }
4571552f7358SJed Brown       meetSize = newMeetSize;
4572552f7358SJed Brown       i        = 1-i;
4573552f7358SJed Brown     }
4574552f7358SJed Brown     if (meetSize) break;
4575552f7358SJed Brown   }
4576552f7358SJed Brown   *numCoveredPoints = meetSize;
4577552f7358SJed Brown   *coveredPoints    = meet[i];
4578552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
45799566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]));
4580552f7358SJed Brown   }
45819566063dSJacob Faibussowitsch   PetscCall(PetscFree(closures));
45829566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets));
45836302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, mc, MPIU_INT, &meet[1-i]));
4584552f7358SJed Brown   PetscFunctionReturn(0);
4585552f7358SJed Brown }
4586552f7358SJed Brown 
45874e3744c5SMatthew G. Knepley /*@C
45884e3744c5SMatthew G. Knepley   DMPlexEqual - Determine if two DMs have the same topology
45894e3744c5SMatthew G. Knepley 
45904e3744c5SMatthew G. Knepley   Not Collective
45914e3744c5SMatthew G. Knepley 
45924e3744c5SMatthew G. Knepley   Input Parameters:
45934e3744c5SMatthew G. Knepley + dmA - A DMPlex object
45944e3744c5SMatthew G. Knepley - dmB - A DMPlex object
45954e3744c5SMatthew G. Knepley 
45964e3744c5SMatthew G. Knepley   Output Parameters:
45974e3744c5SMatthew G. Knepley . equal - PETSC_TRUE if the topologies are identical
45984e3744c5SMatthew G. Knepley 
45994e3744c5SMatthew G. Knepley   Level: intermediate
46004e3744c5SMatthew G. Knepley 
46014e3744c5SMatthew G. Knepley   Notes:
46024e3744c5SMatthew G. Knepley   We are not solving graph isomorphism, so we do not permutation.
46034e3744c5SMatthew G. Knepley 
4604db781477SPatrick Sanan .seealso: `DMPlexGetCone()`
46054e3744c5SMatthew G. Knepley @*/
46064e3744c5SMatthew G. Knepley PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal)
46074e3744c5SMatthew G. Knepley {
46084e3744c5SMatthew G. Knepley   PetscInt       depth, depthB, pStart, pEnd, pStartB, pEndB, p;
46094e3744c5SMatthew G. Knepley 
46104e3744c5SMatthew G. Knepley   PetscFunctionBegin;
46114e3744c5SMatthew G. Knepley   PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
46124e3744c5SMatthew G. Knepley   PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
4613dadcf809SJacob Faibussowitsch   PetscValidBoolPointer(equal, 3);
46144e3744c5SMatthew G. Knepley 
46154e3744c5SMatthew G. Knepley   *equal = PETSC_FALSE;
46169566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmA, &depth));
46179566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmB, &depthB));
46184e3744c5SMatthew G. Knepley   if (depth != depthB) PetscFunctionReturn(0);
46199566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dmA, &pStart,  &pEnd));
46209566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dmB, &pStartB, &pEndB));
46214e3744c5SMatthew G. Knepley   if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(0);
46224e3744c5SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
46234e3744c5SMatthew G. Knepley     const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB;
46244e3744c5SMatthew G. Knepley     PetscInt        coneSize, coneSizeB, c, supportSize, supportSizeB, s;
46254e3744c5SMatthew G. Knepley 
46269566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dmA, p, &coneSize));
46279566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dmA, p, &cone));
46289566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dmA, p, &ornt));
46299566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dmB, p, &coneSizeB));
46309566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dmB, p, &coneB));
46319566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dmB, p, &orntB));
46324e3744c5SMatthew G. Knepley     if (coneSize != coneSizeB) PetscFunctionReturn(0);
46334e3744c5SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
46344e3744c5SMatthew G. Knepley       if (cone[c] != coneB[c]) PetscFunctionReturn(0);
46354e3744c5SMatthew G. Knepley       if (ornt[c] != orntB[c]) PetscFunctionReturn(0);
46364e3744c5SMatthew G. Knepley     }
46379566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dmA, p, &supportSize));
46389566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dmA, p, &support));
46399566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dmB, p, &supportSizeB));
46409566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dmB, p, &supportB));
46414e3744c5SMatthew G. Knepley     if (supportSize != supportSizeB) PetscFunctionReturn(0);
46424e3744c5SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
46434e3744c5SMatthew G. Knepley       if (support[s] != supportB[s]) PetscFunctionReturn(0);
46444e3744c5SMatthew G. Knepley     }
46454e3744c5SMatthew G. Knepley   }
46464e3744c5SMatthew G. Knepley   *equal = PETSC_TRUE;
46474e3744c5SMatthew G. Knepley   PetscFunctionReturn(0);
46484e3744c5SMatthew G. Knepley }
46494e3744c5SMatthew G. Knepley 
46507cd05799SMatthew G. Knepley /*@C
46517cd05799SMatthew G. Knepley   DMPlexGetNumFaceVertices - Returns the number of vertices on a face
46527cd05799SMatthew G. Knepley 
46537cd05799SMatthew G. Knepley   Not Collective
46547cd05799SMatthew G. Knepley 
46557cd05799SMatthew G. Knepley   Input Parameters:
46567cd05799SMatthew G. Knepley + dm         - The DMPlex
46577cd05799SMatthew G. Knepley . cellDim    - The cell dimension
46587cd05799SMatthew G. Knepley - numCorners - The number of vertices on a cell
46597cd05799SMatthew G. Knepley 
46607cd05799SMatthew G. Knepley   Output Parameters:
46617cd05799SMatthew G. Knepley . numFaceVertices - The number of vertices on a face
46627cd05799SMatthew G. Knepley 
46637cd05799SMatthew G. Knepley   Level: developer
46647cd05799SMatthew G. Knepley 
46657cd05799SMatthew G. Knepley   Notes:
46667cd05799SMatthew G. Knepley   Of course this can only work for a restricted set of symmetric shapes
46677cd05799SMatthew G. Knepley 
4668db781477SPatrick Sanan .seealso: `DMPlexGetCone()`
46697cd05799SMatthew G. Knepley @*/
467018ad9376SMatthew G. Knepley PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices)
4671a6dfd86eSKarl Rupp {
467282f516ccSBarry Smith   MPI_Comm       comm;
4673552f7358SJed Brown 
4674552f7358SJed Brown   PetscFunctionBegin;
46759566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm,&comm));
4676dadcf809SJacob Faibussowitsch   PetscValidIntPointer(numFaceVertices,4);
4677552f7358SJed Brown   switch (cellDim) {
4678552f7358SJed Brown   case 0:
4679552f7358SJed Brown     *numFaceVertices = 0;
4680552f7358SJed Brown     break;
4681552f7358SJed Brown   case 1:
4682552f7358SJed Brown     *numFaceVertices = 1;
4683552f7358SJed Brown     break;
4684552f7358SJed Brown   case 2:
4685552f7358SJed Brown     switch (numCorners) {
468619436ca2SJed Brown     case 3: /* triangle */
468719436ca2SJed Brown       *numFaceVertices = 2; /* Edge has 2 vertices */
4688552f7358SJed Brown       break;
468919436ca2SJed Brown     case 4: /* quadrilateral */
469019436ca2SJed Brown       *numFaceVertices = 2; /* Edge has 2 vertices */
4691552f7358SJed Brown       break;
469219436ca2SJed Brown     case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */
469319436ca2SJed Brown       *numFaceVertices = 3; /* Edge has 3 vertices */
4694552f7358SJed Brown       break;
469519436ca2SJed Brown     case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */
469619436ca2SJed Brown       *numFaceVertices = 3; /* Edge has 3 vertices */
4697552f7358SJed Brown       break;
4698552f7358SJed Brown     default:
469963a3b9bcSJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim);
4700552f7358SJed Brown     }
4701552f7358SJed Brown     break;
4702552f7358SJed Brown   case 3:
4703552f7358SJed Brown     switch (numCorners) {
470419436ca2SJed Brown     case 4: /* tetradehdron */
470519436ca2SJed Brown       *numFaceVertices = 3; /* Face has 3 vertices */
4706552f7358SJed Brown       break;
470719436ca2SJed Brown     case 6: /* tet cohesive cells */
470819436ca2SJed Brown       *numFaceVertices = 4; /* Face has 4 vertices */
4709552f7358SJed Brown       break;
471019436ca2SJed Brown     case 8: /* hexahedron */
471119436ca2SJed Brown       *numFaceVertices = 4; /* Face has 4 vertices */
4712552f7358SJed Brown       break;
471319436ca2SJed Brown     case 9: /* tet cohesive Lagrange cells */
471419436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4715552f7358SJed Brown       break;
471619436ca2SJed Brown     case 10: /* quadratic tetrahedron */
471719436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4718552f7358SJed Brown       break;
471919436ca2SJed Brown     case 12: /* hex cohesive Lagrange cells */
472019436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4721552f7358SJed Brown       break;
472219436ca2SJed Brown     case 18: /* quadratic tet cohesive Lagrange cells */
472319436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4724552f7358SJed Brown       break;
472519436ca2SJed Brown     case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */
472619436ca2SJed Brown       *numFaceVertices = 9; /* Face has 9 vertices */
4727552f7358SJed Brown       break;
4728552f7358SJed Brown     default:
472963a3b9bcSJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim);
4730552f7358SJed Brown     }
4731552f7358SJed Brown     break;
4732552f7358SJed Brown   default:
473363a3b9bcSJacob Faibussowitsch     SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %" PetscInt_FMT, cellDim);
4734552f7358SJed Brown   }
4735552f7358SJed Brown   PetscFunctionReturn(0);
4736552f7358SJed Brown }
4737552f7358SJed Brown 
4738552f7358SJed Brown /*@
4739aa50250dSMatthew G. Knepley   DMPlexGetDepthLabel - Get the DMLabel recording the depth of each point
4740552f7358SJed Brown 
4741552f7358SJed Brown   Not Collective
4742552f7358SJed Brown 
4743aa50250dSMatthew G. Knepley   Input Parameter:
4744552f7358SJed Brown . dm    - The DMPlex object
4745552f7358SJed Brown 
4746aa50250dSMatthew G. Knepley   Output Parameter:
4747aa50250dSMatthew G. Knepley . depthLabel - The DMLabel recording point depth
4748552f7358SJed Brown 
4749552f7358SJed Brown   Level: developer
4750552f7358SJed Brown 
4751db781477SPatrick Sanan .seealso: `DMPlexGetDepth()`, `DMPlexGetHeightStratum()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`,
4752aa50250dSMatthew G. Knepley @*/
4753aa50250dSMatthew G. Knepley PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel)
4754aa50250dSMatthew G. Knepley {
4755aa50250dSMatthew G. Knepley   PetscFunctionBegin;
4756aa50250dSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4757aa50250dSMatthew G. Knepley   PetscValidPointer(depthLabel, 2);
4758c58f1c22SToby Isaac   *depthLabel = dm->depthLabel;
4759aa50250dSMatthew G. Knepley   PetscFunctionReturn(0);
4760aa50250dSMatthew G. Knepley }
4761aa50250dSMatthew G. Knepley 
4762aa50250dSMatthew G. Knepley /*@
4763aa50250dSMatthew G. Knepley   DMPlexGetDepth - Get the depth of the DAG representing this mesh
4764aa50250dSMatthew G. Knepley 
4765aa50250dSMatthew G. Knepley   Not Collective
4766aa50250dSMatthew G. Knepley 
4767aa50250dSMatthew G. Knepley   Input Parameter:
4768aa50250dSMatthew G. Knepley . dm    - The DMPlex object
4769aa50250dSMatthew G. Knepley 
4770aa50250dSMatthew G. Knepley   Output Parameter:
4771aa50250dSMatthew G. Knepley . depth - The number of strata (breadth first levels) in the DAG
4772aa50250dSMatthew G. Knepley 
4773aa50250dSMatthew G. Knepley   Level: developer
4774552f7358SJed Brown 
4775b1bb481bSMatthew Knepley   Notes:
4776b1bb481bSMatthew Knepley   This returns maximum of point depths over all points, i.e. maximum value of the label returned by DMPlexGetDepthLabel().
4777dc287ab2SVaclav Hapla   The point depth is described more in detail in DMPlexGetDepthStratum().
4778dc287ab2SVaclav Hapla   An empty mesh gives -1.
4779b1bb481bSMatthew Knepley 
4780db781477SPatrick Sanan .seealso: `DMPlexGetDepthLabel()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`
4781552f7358SJed Brown @*/
4782552f7358SJed Brown PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth)
4783552f7358SJed Brown {
4784aa50250dSMatthew G. Knepley   DMLabel        label;
4785aa50250dSMatthew G. Knepley   PetscInt       d = 0;
4786552f7358SJed Brown 
4787552f7358SJed Brown   PetscFunctionBegin;
4788552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4789dadcf809SJacob Faibussowitsch   PetscValidIntPointer(depth, 2);
47909566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
47919566063dSJacob Faibussowitsch   if (label) PetscCall(DMLabelGetNumValues(label, &d));
4792552f7358SJed Brown   *depth = d-1;
4793552f7358SJed Brown   PetscFunctionReturn(0);
4794552f7358SJed Brown }
4795552f7358SJed Brown 
4796552f7358SJed Brown /*@
4797552f7358SJed Brown   DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth.
4798552f7358SJed Brown 
4799552f7358SJed Brown   Not Collective
4800552f7358SJed Brown 
4801552f7358SJed Brown   Input Parameters:
4802552f7358SJed Brown + dm    - The DMPlex object
4803570fa34dSVaclav Hapla - depth - The requested depth
4804552f7358SJed Brown 
4805552f7358SJed Brown   Output Parameters:
4806552f7358SJed Brown + start - The first point at this depth
4807552f7358SJed Brown - end   - One beyond the last point at this depth
4808552f7358SJed Brown 
4809647867b2SJed Brown   Notes:
4810647867b2SJed Brown   Depth indexing is related to topological dimension.  Depth stratum 0 contains the lowest topological dimension points,
4811647867b2SJed Brown   often "vertices".  If the mesh is "interpolated" (see DMPlexInterpolate()), then depth stratum 1 contains the next
4812647867b2SJed Brown   higher dimension, e.g., "edges".
4813647867b2SJed Brown 
4814552f7358SJed Brown   Level: developer
4815552f7358SJed Brown 
4816db781477SPatrick Sanan .seealso: `DMPlexGetHeightStratum()`, `DMPlexGetDepth()`, `DMPlexGetDepthLabel()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`, `DMPlexInterpolate()`
4817552f7358SJed Brown @*/
4818570fa34dSVaclav Hapla PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt depth, PetscInt *start, PetscInt *end)
48190adebc6cSBarry Smith {
4820aa50250dSMatthew G. Knepley   DMLabel        label;
482163d1a920SMatthew G. Knepley   PetscInt       pStart, pEnd;
4822552f7358SJed Brown 
4823552f7358SJed Brown   PetscFunctionBegin;
4824552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4825dadcf809SJacob Faibussowitsch   if (start) {PetscValidIntPointer(start, 3); *start = 0;}
4826dadcf809SJacob Faibussowitsch   if (end)   {PetscValidIntPointer(end,   4); *end   = 0;}
48279566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
48280d644c17SKarl Rupp   if (pStart == pEnd) PetscFunctionReturn(0);
4829570fa34dSVaclav Hapla   if (depth < 0) {
483063d1a920SMatthew G. Knepley     if (start) *start = pStart;
483163d1a920SMatthew G. Knepley     if (end)   *end   = pEnd;
483263d1a920SMatthew G. Knepley     PetscFunctionReturn(0);
4833552f7358SJed Brown   }
48349566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
483528b400f6SJacob Faibussowitsch   PetscCheck(label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");
4836570fa34dSVaclav Hapla   PetscCall(DMLabelGetStratumBounds(label, depth, start, end));
4837552f7358SJed Brown   PetscFunctionReturn(0);
4838552f7358SJed Brown }
4839552f7358SJed Brown 
4840552f7358SJed Brown /*@
4841552f7358SJed Brown   DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height.
4842552f7358SJed Brown 
4843552f7358SJed Brown   Not Collective
4844552f7358SJed Brown 
4845552f7358SJed Brown   Input Parameters:
4846552f7358SJed Brown + dm     - The DMPlex object
4847570fa34dSVaclav Hapla - height - The requested height
4848552f7358SJed Brown 
4849552f7358SJed Brown   Output Parameters:
4850552f7358SJed Brown + start - The first point at this height
4851552f7358SJed Brown - end   - One beyond the last point at this height
4852552f7358SJed Brown 
4853647867b2SJed Brown   Notes:
4854647867b2SJed Brown   Height indexing is related to topological codimension.  Height stratum 0 contains the highest topological dimension
4855647867b2SJed Brown   points, often called "cells" or "elements".  If the mesh is "interpolated" (see DMPlexInterpolate()), then height
4856647867b2SJed Brown   stratum 1 contains the boundary of these "cells", often called "faces" or "facets".
4857647867b2SJed Brown 
4858552f7358SJed Brown   Level: developer
4859552f7358SJed Brown 
4860db781477SPatrick Sanan .seealso: `DMPlexGetDepthStratum()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()`
4861552f7358SJed Brown @*/
4862570fa34dSVaclav Hapla PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt height, PetscInt *start, PetscInt *end)
48630adebc6cSBarry Smith {
4864aa50250dSMatthew G. Knepley   DMLabel        label;
486563d1a920SMatthew G. Knepley   PetscInt       depth, pStart, pEnd;
4866552f7358SJed Brown 
4867552f7358SJed Brown   PetscFunctionBegin;
4868552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4869dadcf809SJacob Faibussowitsch   if (start) {PetscValidIntPointer(start, 3); *start = 0;}
4870dadcf809SJacob Faibussowitsch   if (end)   {PetscValidIntPointer(end,   4); *end   = 0;}
48719566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
48720d644c17SKarl Rupp   if (pStart == pEnd) PetscFunctionReturn(0);
4873570fa34dSVaclav Hapla   if (height < 0) {
487463d1a920SMatthew G. Knepley     if (start) *start = pStart;
487563d1a920SMatthew G. Knepley     if (end)   *end   = pEnd;
487663d1a920SMatthew G. Knepley     PetscFunctionReturn(0);
4877552f7358SJed Brown   }
48789566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
487928b400f6SJacob Faibussowitsch   PetscCheck(label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");
48809566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(label, &depth));
4881570fa34dSVaclav Hapla   PetscCall(DMLabelGetStratumBounds(label, depth-1-height, start, end));
4882552f7358SJed Brown   PetscFunctionReturn(0);
4883552f7358SJed Brown }
4884552f7358SJed Brown 
4885ba2698f1SMatthew G. Knepley /*@
4886ba2698f1SMatthew G. Knepley   DMPlexGetPointDepth - Get the depth of a given point
4887ba2698f1SMatthew G. Knepley 
4888ba2698f1SMatthew G. Knepley   Not Collective
4889ba2698f1SMatthew G. Knepley 
4890d8d19677SJose E. Roman   Input Parameters:
4891ba2698f1SMatthew G. Knepley + dm    - The DMPlex object
4892ba2698f1SMatthew G. Knepley - point - The point
4893ba2698f1SMatthew G. Knepley 
4894ba2698f1SMatthew G. Knepley   Output Parameter:
4895ba2698f1SMatthew G. Knepley . depth - The depth of the point
4896ba2698f1SMatthew G. Knepley 
4897ba2698f1SMatthew G. Knepley   Level: intermediate
4898ba2698f1SMatthew G. Knepley 
4899db781477SPatrick Sanan .seealso: `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()`
4900ba2698f1SMatthew G. Knepley @*/
4901ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth)
4902ba2698f1SMatthew G. Knepley {
4903ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
4904ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
490540a2aa30SMatthew G. Knepley   PetscValidIntPointer(depth, 3);
49069566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(dm->depthLabel, point, depth));
4907ba2698f1SMatthew G. Knepley   PetscFunctionReturn(0);
4908ba2698f1SMatthew G. Knepley }
4909ba2698f1SMatthew G. Knepley 
4910ba2698f1SMatthew G. Knepley /*@
49110c0a32dcSVaclav Hapla   DMPlexGetPointHeight - Get the height of a given point
49120c0a32dcSVaclav Hapla 
49130c0a32dcSVaclav Hapla   Not Collective
49140c0a32dcSVaclav Hapla 
4915d8d19677SJose E. Roman   Input Parameters:
49160c0a32dcSVaclav Hapla + dm    - The DMPlex object
49170c0a32dcSVaclav Hapla - point - The point
49180c0a32dcSVaclav Hapla 
49190c0a32dcSVaclav Hapla   Output Parameter:
49200c0a32dcSVaclav Hapla . height - The height of the point
49210c0a32dcSVaclav Hapla 
49220c0a32dcSVaclav Hapla   Level: intermediate
49230c0a32dcSVaclav Hapla 
4924db781477SPatrick Sanan .seealso: `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointDepth()`
49250c0a32dcSVaclav Hapla @*/
49260c0a32dcSVaclav Hapla PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height)
49270c0a32dcSVaclav Hapla {
49280c0a32dcSVaclav Hapla   PetscInt       n, pDepth;
49290c0a32dcSVaclav Hapla 
49300c0a32dcSVaclav Hapla   PetscFunctionBegin;
49310c0a32dcSVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
49320c0a32dcSVaclav Hapla   PetscValidIntPointer(height, 3);
49339566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(dm->depthLabel, &n));
49349566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(dm->depthLabel, point, &pDepth));
49350c0a32dcSVaclav Hapla   *height = n - 1 - pDepth;  /* DAG depth is n-1 */
49360c0a32dcSVaclav Hapla   PetscFunctionReturn(0);
49370c0a32dcSVaclav Hapla }
49380c0a32dcSVaclav Hapla 
49390c0a32dcSVaclav Hapla /*@
4940ba2698f1SMatthew G. Knepley   DMPlexGetCellTypeLabel - Get the DMLabel recording the polytope type of each cell
4941ba2698f1SMatthew G. Knepley 
4942ba2698f1SMatthew G. Knepley   Not Collective
4943ba2698f1SMatthew G. Knepley 
4944ba2698f1SMatthew G. Knepley   Input Parameter:
4945ba2698f1SMatthew G. Knepley . dm - The DMPlex object
4946ba2698f1SMatthew G. Knepley 
4947ba2698f1SMatthew G. Knepley   Output Parameter:
4948ba2698f1SMatthew G. Knepley . celltypeLabel - The DMLabel recording cell polytope type
4949ba2698f1SMatthew G. Knepley 
4950412e9a14SMatthew G. Knepley   Note: This function will trigger automatica computation of cell types. This can be disabled by calling
4951412e9a14SMatthew G. Knepley   DMCreateLabel(dm, "celltype") beforehand.
4952412e9a14SMatthew G. Knepley 
4953ba2698f1SMatthew G. Knepley   Level: developer
4954ba2698f1SMatthew G. Knepley 
4955db781477SPatrick Sanan .seealso: `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMCreateLabel()`
4956ba2698f1SMatthew G. Knepley @*/
4957ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel)
4958ba2698f1SMatthew G. Knepley {
4959ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
4960ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4961ba2698f1SMatthew G. Knepley   PetscValidPointer(celltypeLabel, 2);
49629566063dSJacob Faibussowitsch   if (!dm->celltypeLabel) PetscCall(DMPlexComputeCellTypes(dm));
4963ba2698f1SMatthew G. Knepley   *celltypeLabel = dm->celltypeLabel;
4964ba2698f1SMatthew G. Knepley   PetscFunctionReturn(0);
4965ba2698f1SMatthew G. Knepley }
4966ba2698f1SMatthew G. Knepley 
4967ba2698f1SMatthew G. Knepley /*@
4968ba2698f1SMatthew G. Knepley   DMPlexGetCellType - Get the polytope type of a given cell
4969ba2698f1SMatthew G. Knepley 
4970ba2698f1SMatthew G. Knepley   Not Collective
4971ba2698f1SMatthew G. Knepley 
4972d8d19677SJose E. Roman   Input Parameters:
4973ba2698f1SMatthew G. Knepley + dm   - The DMPlex object
4974ba2698f1SMatthew G. Knepley - cell - The cell
4975ba2698f1SMatthew G. Knepley 
4976ba2698f1SMatthew G. Knepley   Output Parameter:
4977ba2698f1SMatthew G. Knepley . celltype - The polytope type of the cell
4978ba2698f1SMatthew G. Knepley 
4979ba2698f1SMatthew G. Knepley   Level: intermediate
4980ba2698f1SMatthew G. Knepley 
4981db781477SPatrick Sanan .seealso: `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`
4982ba2698f1SMatthew G. Knepley @*/
4983ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype)
4984ba2698f1SMatthew G. Knepley {
4985ba2698f1SMatthew G. Knepley   DMLabel        label;
4986ba2698f1SMatthew G. Knepley   PetscInt       ct;
4987ba2698f1SMatthew G. Knepley 
4988ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
4989ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4990ba2698f1SMatthew G. Knepley   PetscValidPointer(celltype, 3);
49919566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &label));
49929566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(label, cell, &ct));
499363a3b9bcSJacob Faibussowitsch   PetscCheck(ct >= 0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %" PetscInt_FMT " has not been assigned a cell type", cell);
4994ba2698f1SMatthew G. Knepley   *celltype = (DMPolytopeType) ct;
4995ba2698f1SMatthew G. Knepley   PetscFunctionReturn(0);
4996ba2698f1SMatthew G. Knepley }
4997ba2698f1SMatthew G. Knepley 
4998412e9a14SMatthew G. Knepley /*@
4999412e9a14SMatthew G. Knepley   DMPlexSetCellType - Set the polytope type of a given cell
5000412e9a14SMatthew G. Knepley 
5001412e9a14SMatthew G. Knepley   Not Collective
5002412e9a14SMatthew G. Knepley 
5003412e9a14SMatthew G. Knepley   Input Parameters:
5004412e9a14SMatthew G. Knepley + dm   - The DMPlex object
5005412e9a14SMatthew G. Knepley . cell - The cell
5006412e9a14SMatthew G. Knepley - celltype - The polytope type of the cell
5007412e9a14SMatthew G. Knepley 
5008412e9a14SMatthew G. Knepley   Note: By default, cell types will be automatically computed using DMPlexComputeCellTypes() before this function
5009412e9a14SMatthew G. Knepley   is executed. This function will override the computed type. However, if automatic classification will not succeed
5010412e9a14SMatthew G. Knepley   and a user wants to manually specify all types, the classification must be disabled by calling
5011412e9a14SMatthew G. Knepley   DMCreaateLabel(dm, "celltype") before getting or setting any cell types.
5012412e9a14SMatthew G. Knepley 
5013412e9a14SMatthew G. Knepley   Level: advanced
5014412e9a14SMatthew G. Knepley 
5015db781477SPatrick Sanan .seealso: `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexComputeCellTypes()`, `DMCreateLabel()`
5016412e9a14SMatthew G. Knepley @*/
5017412e9a14SMatthew G. Knepley PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype)
5018412e9a14SMatthew G. Knepley {
5019412e9a14SMatthew G. Knepley   DMLabel        label;
5020412e9a14SMatthew G. Knepley 
5021412e9a14SMatthew G. Knepley   PetscFunctionBegin;
5022412e9a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
50239566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &label));
50249566063dSJacob Faibussowitsch   PetscCall(DMLabelSetValue(label, cell, celltype));
5025412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
5026412e9a14SMatthew G. Knepley }
5027412e9a14SMatthew G. Knepley 
50280adebc6cSBarry Smith PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm)
50290adebc6cSBarry Smith {
5030efe440bfSMatthew G. Knepley   PetscSection   section, s;
5031efe440bfSMatthew G. Knepley   Mat            m;
50323e922f36SToby Isaac   PetscInt       maxHeight;
5033552f7358SJed Brown 
5034552f7358SJed Brown   PetscFunctionBegin;
50359566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, cdm));
50369566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxProjectionHeight(dm, &maxHeight));
50379566063dSJacob Faibussowitsch   PetscCall(DMPlexSetMaxProjectionHeight(*cdm, maxHeight));
50389566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section));
50399566063dSJacob Faibussowitsch   PetscCall(DMSetLocalSection(*cdm, section));
50409566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&section));
50419566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &s));
50429566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_SELF, &m));
50439566063dSJacob Faibussowitsch   PetscCall(DMSetDefaultConstraints(*cdm, s, m, NULL));
50449566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&s));
50459566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&m));
50468f4c458bSMatthew G. Knepley 
50479566063dSJacob Faibussowitsch   PetscCall(DMSetNumFields(*cdm, 1));
50489566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(*cdm));
5049552f7358SJed Brown   PetscFunctionReturn(0);
5050552f7358SJed Brown }
5051552f7358SJed Brown 
5052f19dbd58SToby Isaac PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field)
5053f19dbd58SToby Isaac {
50546858538eSMatthew G. Knepley   Vec coordsLocal, cellCoordsLocal;
50556858538eSMatthew G. Knepley   DM  coordsDM,    cellCoordsDM;
5056f19dbd58SToby Isaac 
5057f19dbd58SToby Isaac   PetscFunctionBegin;
5058f19dbd58SToby Isaac   *field = NULL;
50599566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal));
50609566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &coordsDM));
50616858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dm, &cellCoordsLocal));
50626858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dm, &cellCoordsDM));
5063f19dbd58SToby Isaac   if (coordsLocal && coordsDM) {
50646858538eSMatthew G. Knepley     if (cellCoordsLocal && cellCoordsDM) PetscCall(DMFieldCreateDSWithDG(coordsDM, cellCoordsDM, 0, coordsLocal, cellCoordsLocal, field));
50656858538eSMatthew G. Knepley     else                                 PetscCall(DMFieldCreateDS(coordsDM, 0, coordsLocal, field));
5066f19dbd58SToby Isaac   }
5067f19dbd58SToby Isaac   PetscFunctionReturn(0);
5068f19dbd58SToby Isaac }
5069f19dbd58SToby Isaac 
50707cd05799SMatthew G. Knepley /*@C
50717cd05799SMatthew G. Knepley   DMPlexGetConeSection - Return a section which describes the layout of cone data
50727cd05799SMatthew G. Knepley 
50737cd05799SMatthew G. Knepley   Not Collective
50747cd05799SMatthew G. Knepley 
50757cd05799SMatthew G. Knepley   Input Parameters:
50767cd05799SMatthew G. Knepley . dm        - The DMPlex object
50777cd05799SMatthew G. Knepley 
50787cd05799SMatthew G. Knepley   Output Parameter:
50797cd05799SMatthew G. Knepley . section - The PetscSection object
50807cd05799SMatthew G. Knepley 
50817cd05799SMatthew G. Knepley   Level: developer
50827cd05799SMatthew G. Knepley 
5083db781477SPatrick Sanan .seealso: `DMPlexGetSupportSection()`, `DMPlexGetCones()`, `DMPlexGetConeOrientations()`
50847cd05799SMatthew G. Knepley @*/
50850adebc6cSBarry Smith PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section)
50860adebc6cSBarry Smith {
5087552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
5088552f7358SJed Brown 
5089552f7358SJed Brown   PetscFunctionBegin;
5090552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5091552f7358SJed Brown   if (section) *section = mesh->coneSection;
5092552f7358SJed Brown   PetscFunctionReturn(0);
5093552f7358SJed Brown }
5094552f7358SJed Brown 
50957cd05799SMatthew G. Knepley /*@C
50967cd05799SMatthew G. Knepley   DMPlexGetSupportSection - Return a section which describes the layout of support data
50977cd05799SMatthew G. Knepley 
50987cd05799SMatthew G. Knepley   Not Collective
50997cd05799SMatthew G. Knepley 
51007cd05799SMatthew G. Knepley   Input Parameters:
51017cd05799SMatthew G. Knepley . dm        - The DMPlex object
51027cd05799SMatthew G. Knepley 
51037cd05799SMatthew G. Knepley   Output Parameter:
51047cd05799SMatthew G. Knepley . section - The PetscSection object
51057cd05799SMatthew G. Knepley 
51067cd05799SMatthew G. Knepley   Level: developer
51077cd05799SMatthew G. Knepley 
5108db781477SPatrick Sanan .seealso: `DMPlexGetConeSection()`
51097cd05799SMatthew G. Knepley @*/
51108cb4d582SMatthew G. Knepley PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section)
51118cb4d582SMatthew G. Knepley {
51128cb4d582SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
51138cb4d582SMatthew G. Knepley 
51148cb4d582SMatthew G. Knepley   PetscFunctionBegin;
51158cb4d582SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
51168cb4d582SMatthew G. Knepley   if (section) *section = mesh->supportSection;
51178cb4d582SMatthew G. Knepley   PetscFunctionReturn(0);
51188cb4d582SMatthew G. Knepley }
51198cb4d582SMatthew G. Knepley 
51207cd05799SMatthew G. Knepley /*@C
51217cd05799SMatthew G. Knepley   DMPlexGetCones - Return cone data
51227cd05799SMatthew G. Knepley 
51237cd05799SMatthew G. Knepley   Not Collective
51247cd05799SMatthew G. Knepley 
51257cd05799SMatthew G. Knepley   Input Parameters:
51267cd05799SMatthew G. Knepley . dm        - The DMPlex object
51277cd05799SMatthew G. Knepley 
51287cd05799SMatthew G. Knepley   Output Parameter:
51297cd05799SMatthew G. Knepley . cones - The cone for each point
51307cd05799SMatthew G. Knepley 
51317cd05799SMatthew G. Knepley   Level: developer
51327cd05799SMatthew G. Knepley 
5133db781477SPatrick Sanan .seealso: `DMPlexGetConeSection()`
51347cd05799SMatthew G. Knepley @*/
5135a6dfd86eSKarl Rupp PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[])
5136a6dfd86eSKarl Rupp {
5137552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
5138552f7358SJed Brown 
5139552f7358SJed Brown   PetscFunctionBegin;
5140552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5141552f7358SJed Brown   if (cones) *cones = mesh->cones;
5142552f7358SJed Brown   PetscFunctionReturn(0);
5143552f7358SJed Brown }
5144552f7358SJed Brown 
51457cd05799SMatthew G. Knepley /*@C
51467cd05799SMatthew G. Knepley   DMPlexGetConeOrientations - Return cone orientation data
51477cd05799SMatthew G. Knepley 
51487cd05799SMatthew G. Knepley   Not Collective
51497cd05799SMatthew G. Knepley 
51507cd05799SMatthew G. Knepley   Input Parameters:
51517cd05799SMatthew G. Knepley . dm        - The DMPlex object
51527cd05799SMatthew G. Knepley 
51537cd05799SMatthew G. Knepley   Output Parameter:
5154b5a892a1SMatthew G. Knepley . coneOrientations - The array of cone orientations for all points
51557cd05799SMatthew G. Knepley 
51567cd05799SMatthew G. Knepley   Level: developer
51577cd05799SMatthew G. Knepley 
5158b5a892a1SMatthew G. Knepley   Notes:
5159b5a892a1SMatthew G. Knepley   The PetscSection returned by DMPlexGetConeSection() partitions coneOrientations into cone orientations of particular points as returned by DMPlexGetConeOrientation().
5160b5a892a1SMatthew G. Knepley 
5161b5a892a1SMatthew G. Knepley   The meaning of coneOrientations values is detailed in DMPlexGetConeOrientation().
5162b5a892a1SMatthew G. Knepley 
5163db781477SPatrick Sanan .seealso: `DMPlexGetConeSection()`, `DMPlexGetConeOrientation()`
51647cd05799SMatthew G. Knepley @*/
5165a6dfd86eSKarl Rupp PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[])
5166a6dfd86eSKarl Rupp {
5167552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
5168552f7358SJed Brown 
5169552f7358SJed Brown   PetscFunctionBegin;
5170552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5171552f7358SJed Brown   if (coneOrientations) *coneOrientations = mesh->coneOrientations;
5172552f7358SJed Brown   PetscFunctionReturn(0);
5173552f7358SJed Brown }
5174552f7358SJed Brown 
5175552f7358SJed Brown /******************************** FEM Support **********************************/
5176552f7358SJed Brown 
51779e8305c2SJed Brown /*
51789e8305c2SJed Brown  Returns number of components and tensor degree for the field.  For interpolated meshes, line should be a point
51799e8305c2SJed Brown  representing a line in the section.
51809e8305c2SJed Brown */
51819e8305c2SJed Brown static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(PetscSection section,PetscInt field,PetscInt line,PetscBool vertexchart,PetscInt *Nc,PetscInt *k)
51829e8305c2SJed Brown {
51839e8305c2SJed Brown   PetscFunctionBeginHot;
51849566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldComponents(section, field, Nc));
5185a433471fSStefano Zampini   if (line < 0) {
5186a433471fSStefano Zampini     *k = 0;
5187a433471fSStefano Zampini     *Nc = 0;
5188a433471fSStefano Zampini   } else if (vertexchart) {            /* If we only have a vertex chart, we must have degree k=1 */
51899e8305c2SJed Brown     *k = 1;
51909e8305c2SJed Brown   } else {                      /* Assume the full interpolated mesh is in the chart; lines in particular */
51919e8305c2SJed Brown     /* An order k SEM disc has k-1 dofs on an edge */
51929566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, line, field, k));
51939e8305c2SJed Brown     *k = *k / *Nc + 1;
51949e8305c2SJed Brown   }
51959e8305c2SJed Brown   PetscFunctionReturn(0);
51969e8305c2SJed Brown }
51979e8305c2SJed Brown 
5198a4355906SMatthew Knepley /*@
5199bc1eb3faSJed Brown 
5200bc1eb3faSJed Brown   DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a
5201bc1eb3faSJed Brown   lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the
52021bb6d2a8SBarry Smith   section provided (or the section of the DM).
5203a4355906SMatthew Knepley 
5204a4355906SMatthew Knepley   Input Parameters:
5205a4355906SMatthew Knepley + dm      - The DM
5206a4355906SMatthew Knepley . point   - Either a cell (highest dim point) or an edge (dim 1 point), or PETSC_DETERMINE
5207a4355906SMatthew Knepley - section - The PetscSection to reorder, or NULL for the default section
5208a4355906SMatthew Knepley 
5209a4355906SMatthew Knepley   Note: The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial
5210a4355906SMatthew Knepley   degree of the basis.
5211a4355906SMatthew Knepley 
5212bc1eb3faSJed Brown   Example:
5213bc1eb3faSJed Brown   A typical interpolated single-quad mesh might order points as
5214bc1eb3faSJed Brown .vb
5215bc1eb3faSJed Brown   [c0, v1, v2, v3, v4, e5, e6, e7, e8]
5216bc1eb3faSJed Brown 
5217bc1eb3faSJed Brown   v4 -- e6 -- v3
5218bc1eb3faSJed Brown   |           |
5219bc1eb3faSJed Brown   e7    c0    e8
5220bc1eb3faSJed Brown   |           |
5221bc1eb3faSJed Brown   v1 -- e5 -- v2
5222bc1eb3faSJed Brown .ve
5223bc1eb3faSJed Brown 
5224bc1eb3faSJed Brown   (There is no significance to the ordering described here.)  The default section for a Q3 quad might typically assign
5225bc1eb3faSJed Brown   dofs in the order of points, e.g.,
5226bc1eb3faSJed Brown .vb
5227bc1eb3faSJed Brown     c0 -> [0,1,2,3]
5228bc1eb3faSJed Brown     v1 -> [4]
5229bc1eb3faSJed Brown     ...
5230bc1eb3faSJed Brown     e5 -> [8, 9]
5231bc1eb3faSJed Brown .ve
5232bc1eb3faSJed Brown 
5233bc1eb3faSJed Brown   which corresponds to the dofs
5234bc1eb3faSJed Brown .vb
5235bc1eb3faSJed Brown     6   10  11  7
5236bc1eb3faSJed Brown     13  2   3   15
5237bc1eb3faSJed Brown     12  0   1   14
5238bc1eb3faSJed Brown     4   8   9   5
5239bc1eb3faSJed Brown .ve
5240bc1eb3faSJed Brown 
5241bc1eb3faSJed Brown   The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering
5242bc1eb3faSJed Brown .vb
5243bc1eb3faSJed Brown   0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6
5244bc1eb3faSJed Brown .ve
5245bc1eb3faSJed Brown 
5246bc1eb3faSJed Brown   After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically,
5247bc1eb3faSJed Brown .vb
5248bc1eb3faSJed Brown    4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7
5249bc1eb3faSJed Brown .ve
5250bc1eb3faSJed Brown 
5251a4355906SMatthew Knepley   Level: developer
5252a4355906SMatthew Knepley 
5253db781477SPatrick Sanan .seealso: `DMGetLocalSection()`, `PetscSectionSetClosurePermutation()`, `DMSetGlobalSection()`
5254a4355906SMatthew Knepley @*/
5255bc1eb3faSJed Brown PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section)
52563194fc30SMatthew G. Knepley {
52577391a63aSMatthew G. Knepley   DMLabel        label;
5258bb197d40SJed Brown   PetscInt       dim, depth = -1, eStart = -1, Nf;
52599e8305c2SJed Brown   PetscBool      vertexchart;
52603194fc30SMatthew G. Knepley 
52613194fc30SMatthew G. Knepley   PetscFunctionBegin;
52629566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
5263a433471fSStefano Zampini   if (dim < 1) PetscFunctionReturn(0);
5264a433471fSStefano Zampini   if (point < 0) {
5265a433471fSStefano Zampini     PetscInt sStart,sEnd;
5266a433471fSStefano Zampini 
52679566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd));
5268a433471fSStefano Zampini     point = sEnd-sStart ? sStart : point;
5269a433471fSStefano Zampini   }
52709566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
52719566063dSJacob Faibussowitsch   if (point >= 0) PetscCall(DMLabelGetValue(label, point, &depth));
52729566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
52737391a63aSMatthew G. Knepley   if (depth == 1) {eStart = point;}
52747391a63aSMatthew G. Knepley   else if  (depth == dim) {
52757391a63aSMatthew G. Knepley     const PetscInt *cone;
52767391a63aSMatthew G. Knepley 
52779566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, point, &cone));
5278d4e6627bSStefano Zampini     if (dim == 2) eStart = cone[0];
5279d4e6627bSStefano Zampini     else if (dim == 3) {
5280d4e6627bSStefano Zampini       const PetscInt *cone2;
52819566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, cone[0], &cone2));
5282d4e6627bSStefano Zampini       eStart = cone2[0];
528363a3b9bcSJacob Faibussowitsch     } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Point %" PetscInt_FMT " of depth %" PetscInt_FMT " cannot be used to bootstrap spectral ordering for dim %" PetscInt_FMT, point, depth, dim);
528463a3b9bcSJacob Faibussowitsch   } else PetscCheck(depth < 0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Point %" PetscInt_FMT " of depth %" PetscInt_FMT " cannot be used to bootstrap spectral ordering for dim %" PetscInt_FMT, point, depth, dim);
52859e8305c2SJed Brown   {                             /* Determine whether the chart covers all points or just vertices. */
52869e8305c2SJed Brown     PetscInt pStart,pEnd,cStart,cEnd;
52879566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm,0,&pStart,&pEnd));
52889566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(section,&cStart,&cEnd));
5289796d0a68SJed Brown     if (pStart == cStart && pEnd == cEnd) vertexchart = PETSC_TRUE;      /* Only vertices are in the chart */
5290796d0a68SJed Brown     else if (cStart <= point && point < cEnd) vertexchart = PETSC_FALSE; /* Some interpolated points exist in the chart */
5291796d0a68SJed Brown     else vertexchart = PETSC_TRUE;                                       /* Some interpolated points are not in chart; assume dofs only at cells and vertices */
52929e8305c2SJed Brown   }
52939566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &Nf));
5294bb197d40SJed Brown   for (PetscInt d=1; d<=dim; d++) {
5295bb197d40SJed Brown     PetscInt k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0;
5296bb197d40SJed Brown     PetscInt *perm;
5297bb197d40SJed Brown 
52983194fc30SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
52999566063dSJacob Faibussowitsch       PetscCall(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k));
5300bb197d40SJed Brown       size += PetscPowInt(k+1, d)*Nc;
53013194fc30SMatthew G. Knepley     }
53029566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(size, &perm));
53033194fc30SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
5304bb197d40SJed Brown       switch (d) {
5305babf31e0SJed Brown       case 1:
53069566063dSJacob Faibussowitsch         PetscCall(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k));
5307babf31e0SJed Brown         /*
5308babf31e0SJed Brown          Original ordering is [ edge of length k-1; vtx0; vtx1 ]
5309babf31e0SJed Brown          We want              [ vtx0; edge of length k-1; vtx1 ]
5310babf31e0SJed Brown          */
5311babf31e0SJed Brown         for (c=0; c<Nc; c++,offset++) perm[offset] = (k-1)*Nc + c + foffset;
5312babf31e0SJed Brown         for (i=0; i<k-1; i++) for (c=0; c<Nc; c++,offset++) perm[offset] = i*Nc + c + foffset;
5313babf31e0SJed Brown         for (c=0; c<Nc; c++,offset++) perm[offset] = k*Nc + c + foffset;
5314babf31e0SJed Brown         foffset = offset;
5315babf31e0SJed Brown         break;
531689eabcffSMatthew G. Knepley       case 2:
53173194fc30SMatthew 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} */
53189566063dSJacob Faibussowitsch         PetscCall(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k));
53193194fc30SMatthew G. Knepley         /* The SEM order is
53203194fc30SMatthew G. Knepley 
53213194fc30SMatthew G. Knepley          v_lb, {e_b}, v_rb,
532289eabcffSMatthew G. Knepley          e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r,
53233194fc30SMatthew G. Knepley          v_lt, reverse {e_t}, v_rt
53243194fc30SMatthew G. Knepley          */
53253194fc30SMatthew G. Knepley         {
53263194fc30SMatthew G. Knepley           const PetscInt of   = 0;
53273194fc30SMatthew G. Knepley           const PetscInt oeb  = of   + PetscSqr(k-1);
53283194fc30SMatthew G. Knepley           const PetscInt oer  = oeb  + (k-1);
53293194fc30SMatthew G. Knepley           const PetscInt oet  = oer  + (k-1);
53303194fc30SMatthew G. Knepley           const PetscInt oel  = oet  + (k-1);
53313194fc30SMatthew G. Knepley           const PetscInt ovlb = oel  + (k-1);
53323194fc30SMatthew G. Knepley           const PetscInt ovrb = ovlb + 1;
53333194fc30SMatthew G. Knepley           const PetscInt ovrt = ovrb + 1;
53343194fc30SMatthew G. Knepley           const PetscInt ovlt = ovrt + 1;
53353194fc30SMatthew G. Knepley           PetscInt       o;
53363194fc30SMatthew G. Knepley 
53373194fc30SMatthew G. Knepley           /* bottom */
53383194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb*Nc + c + foffset;
53393194fc30SMatthew G. Knepley           for (o = oeb; o < oer; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
53403194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb*Nc + c + foffset;
53413194fc30SMatthew G. Knepley           /* middle */
53423194fc30SMatthew G. Knepley           for (i = 0; i < k-1; ++i) {
53433194fc30SMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel+(k-2)-i)*Nc + c + foffset;
53443194fc30SMatthew 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;
53453194fc30SMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer+i)*Nc + c + foffset;
53463194fc30SMatthew G. Knepley           }
53473194fc30SMatthew G. Knepley           /* top */
53483194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt*Nc + c + foffset;
53493194fc30SMatthew G. Knepley           for (o = oel-1; o >= oet; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
53503194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt*Nc + c + foffset;
53513194fc30SMatthew G. Knepley           foffset = offset;
53523194fc30SMatthew G. Knepley         }
535389eabcffSMatthew G. Knepley         break;
535489eabcffSMatthew G. Knepley       case 3:
535589eabcffSMatthew G. Knepley         /* The original hex closure is
535689eabcffSMatthew G. Knepley 
535789eabcffSMatthew G. Knepley          {c,
535889eabcffSMatthew G. Knepley          f_b, f_t, f_f, f_b, f_r, f_l,
535989eabcffSMatthew 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,
536089eabcffSMatthew G. Knepley          v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb}
536189eabcffSMatthew G. Knepley          */
53629566063dSJacob Faibussowitsch         PetscCall(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k));
536389eabcffSMatthew G. Knepley         /* The SEM order is
536489eabcffSMatthew G. Knepley          Bottom Slice
536589eabcffSMatthew G. Knepley          v_blf, {e^{(k-1)-n}_bf}, v_brf,
536689eabcffSMatthew G. Knepley          e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br,
536789eabcffSMatthew G. Knepley          v_blb, {e_bb}, v_brb,
536889eabcffSMatthew G. Knepley 
536989eabcffSMatthew G. Knepley          Middle Slice (j)
537089eabcffSMatthew G. Knepley          {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf,
537189eabcffSMatthew G. Knepley          f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r,
537289eabcffSMatthew G. Knepley          e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb,
537389eabcffSMatthew G. Knepley 
537489eabcffSMatthew G. Knepley          Top Slice
537589eabcffSMatthew G. Knepley          v_tlf, {e_tf}, v_trf,
537689eabcffSMatthew G. Knepley          e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr,
537789eabcffSMatthew G. Knepley          v_tlb, {e^{(k-1)-n}_tb}, v_trb,
537889eabcffSMatthew G. Knepley          */
537989eabcffSMatthew G. Knepley         {
538089eabcffSMatthew G. Knepley           const PetscInt oc    = 0;
538189eabcffSMatthew G. Knepley           const PetscInt ofb   = oc    + PetscSqr(k-1)*(k-1);
538289eabcffSMatthew G. Knepley           const PetscInt oft   = ofb   + PetscSqr(k-1);
538389eabcffSMatthew G. Knepley           const PetscInt off   = oft   + PetscSqr(k-1);
538489eabcffSMatthew G. Knepley           const PetscInt ofk   = off   + PetscSqr(k-1);
538589eabcffSMatthew G. Knepley           const PetscInt ofr   = ofk   + PetscSqr(k-1);
538689eabcffSMatthew G. Knepley           const PetscInt ofl   = ofr   + PetscSqr(k-1);
538789eabcffSMatthew G. Knepley           const PetscInt oebl  = ofl   + PetscSqr(k-1);
538889eabcffSMatthew G. Knepley           const PetscInt oebb  = oebl  + (k-1);
538989eabcffSMatthew G. Knepley           const PetscInt oebr  = oebb  + (k-1);
539089eabcffSMatthew G. Knepley           const PetscInt oebf  = oebr  + (k-1);
539189eabcffSMatthew G. Knepley           const PetscInt oetf  = oebf  + (k-1);
539289eabcffSMatthew G. Knepley           const PetscInt oetr  = oetf  + (k-1);
539389eabcffSMatthew G. Knepley           const PetscInt oetb  = oetr  + (k-1);
539489eabcffSMatthew G. Knepley           const PetscInt oetl  = oetb  + (k-1);
539589eabcffSMatthew G. Knepley           const PetscInt oerf  = oetl  + (k-1);
539689eabcffSMatthew G. Knepley           const PetscInt oelf  = oerf  + (k-1);
539789eabcffSMatthew G. Knepley           const PetscInt oelb  = oelf  + (k-1);
539889eabcffSMatthew G. Knepley           const PetscInt oerb  = oelb  + (k-1);
539989eabcffSMatthew G. Knepley           const PetscInt ovblf = oerb  + (k-1);
540089eabcffSMatthew G. Knepley           const PetscInt ovblb = ovblf + 1;
540189eabcffSMatthew G. Knepley           const PetscInt ovbrb = ovblb + 1;
540289eabcffSMatthew G. Knepley           const PetscInt ovbrf = ovbrb + 1;
540389eabcffSMatthew G. Knepley           const PetscInt ovtlf = ovbrf + 1;
540489eabcffSMatthew G. Knepley           const PetscInt ovtrf = ovtlf + 1;
540589eabcffSMatthew G. Knepley           const PetscInt ovtrb = ovtrf + 1;
540689eabcffSMatthew G. Knepley           const PetscInt ovtlb = ovtrb + 1;
540789eabcffSMatthew G. Knepley           PetscInt       o, n;
540889eabcffSMatthew G. Knepley 
540989eabcffSMatthew G. Knepley           /* Bottom Slice */
541089eabcffSMatthew G. Knepley           /*   bottom */
541189eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf*Nc + c + foffset;
541289eabcffSMatthew G. Knepley           for (o = oetf-1; o >= oebf; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
541389eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf*Nc + c + foffset;
541489eabcffSMatthew G. Knepley           /*   middle */
541589eabcffSMatthew G. Knepley           for (i = 0; i < k-1; ++i) {
541689eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl+i)*Nc + c + foffset;
5417316b7f87SMax 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;}
541889eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr+(k-2)-i)*Nc + c + foffset;
54193194fc30SMatthew G. Knepley           }
542089eabcffSMatthew G. Knepley           /*   top */
542189eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb*Nc + c + foffset;
542289eabcffSMatthew G. Knepley           for (o = oebb; o < oebr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
542389eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb*Nc + c + foffset;
542489eabcffSMatthew G. Knepley 
542589eabcffSMatthew G. Knepley           /* Middle Slice */
542689eabcffSMatthew G. Knepley           for (j = 0; j < k-1; ++j) {
542789eabcffSMatthew G. Knepley             /*   bottom */
542889eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf+(k-2)-j)*Nc + c + foffset;
542989eabcffSMatthew 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;
543089eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf+j)*Nc + c + foffset;
543189eabcffSMatthew G. Knepley             /*   middle */
543289eabcffSMatthew G. Knepley             for (i = 0; i < k-1; ++i) {
543389eabcffSMatthew G. Knepley               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl+i*(k-1)+j)*Nc + c + foffset;
543489eabcffSMatthew 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;
543589eabcffSMatthew G. Knepley               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr+j*(k-1)+i)*Nc + c + foffset;
543689eabcffSMatthew G. Knepley             }
543789eabcffSMatthew G. Knepley             /*   top */
543889eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb+j)*Nc + c + foffset;
543989eabcffSMatthew 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;
544089eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb+(k-2)-j)*Nc + c + foffset;
544189eabcffSMatthew G. Knepley           }
544289eabcffSMatthew G. Knepley 
544389eabcffSMatthew G. Knepley           /* Top Slice */
544489eabcffSMatthew G. Knepley           /*   bottom */
544589eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf*Nc + c + foffset;
544689eabcffSMatthew G. Knepley           for (o = oetf; o < oetr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
544789eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf*Nc + c + foffset;
544889eabcffSMatthew G. Knepley           /*   middle */
544989eabcffSMatthew G. Knepley           for (i = 0; i < k-1; ++i) {
545089eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl+(k-2)-i)*Nc + c + foffset;
545189eabcffSMatthew 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;
545289eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr+i)*Nc + c + foffset;
545389eabcffSMatthew G. Knepley           }
545489eabcffSMatthew G. Knepley           /*   top */
545589eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb*Nc + c + foffset;
545689eabcffSMatthew G. Knepley           for (o = oetl-1; o >= oetb; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
545789eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb*Nc + c + foffset;
545889eabcffSMatthew G. Knepley 
545989eabcffSMatthew G. Knepley           foffset = offset;
546089eabcffSMatthew G. Knepley         }
546189eabcffSMatthew G. Knepley         break;
546263a3b9bcSJacob Faibussowitsch       default: SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %" PetscInt_FMT, d);
546389eabcffSMatthew G. Knepley       }
546489eabcffSMatthew G. Knepley     }
546563a3b9bcSJacob Faibussowitsch     PetscCheck(offset == size,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Number of permutation entries %" PetscInt_FMT " != %" PetscInt_FMT, offset, size);
54663194fc30SMatthew G. Knepley     /* Check permutation */
54673194fc30SMatthew G. Knepley     {
54683194fc30SMatthew G. Knepley       PetscInt *check;
54693194fc30SMatthew G. Knepley 
54709566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(size, &check));
54711dca8a05SBarry Smith       for (i = 0; i < size; ++i) {
54721dca8a05SBarry Smith         check[i] = -1;
54731dca8a05SBarry Smith         PetscCheck(perm[i] >= 0 && perm[i] < size,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid permutation index p[%" PetscInt_FMT "] = %" PetscInt_FMT, i, perm[i]);
54741dca8a05SBarry Smith       }
54753194fc30SMatthew G. Knepley       for (i = 0; i < size; ++i) check[perm[i]] = i;
54761dca8a05SBarry Smith       for (i = 0; i < size; ++i) PetscCheck(check[i] >= 0,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Missing permutation index %" PetscInt_FMT, i);
54779566063dSJacob Faibussowitsch       PetscCall(PetscFree(check));
54783194fc30SMatthew G. Knepley     }
54799566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size, PETSC_OWN_POINTER, perm));
5480a05c9aa3SJed Brown     if (d == dim) { // Add permutation for localized (in case this is a coordinate DM)
5481a05c9aa3SJed Brown       PetscInt *loc_perm;
54829566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(size*2, &loc_perm));
5483a05c9aa3SJed Brown       for (PetscInt i=0; i<size; i++) {
5484a05c9aa3SJed Brown         loc_perm[i] = perm[i];
5485a05c9aa3SJed Brown         loc_perm[size+i] = size + perm[i];
5486a05c9aa3SJed Brown       }
54879566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size*2, PETSC_OWN_POINTER, loc_perm));
5488a05c9aa3SJed Brown     }
5489bb197d40SJed Brown   }
54903194fc30SMatthew G. Knepley   PetscFunctionReturn(0);
54913194fc30SMatthew G. Knepley }
54923194fc30SMatthew G. Knepley 
5493e071409bSToby Isaac PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace)
5494e071409bSToby Isaac {
5495e071409bSToby Isaac   PetscDS        prob;
5496e071409bSToby Isaac   PetscInt       depth, Nf, h;
5497e071409bSToby Isaac   DMLabel        label;
5498e071409bSToby Isaac 
5499e071409bSToby Isaac   PetscFunctionBeginHot;
55009566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &prob));
5501e071409bSToby Isaac   Nf      = prob->Nf;
5502e071409bSToby Isaac   label   = dm->depthLabel;
5503e071409bSToby Isaac   *dspace = NULL;
5504e071409bSToby Isaac   if (field < Nf) {
5505e071409bSToby Isaac     PetscObject disc = prob->disc[field];
5506e071409bSToby Isaac 
5507e071409bSToby Isaac     if (disc->classid == PETSCFE_CLASSID) {
5508e071409bSToby Isaac       PetscDualSpace dsp;
5509e071409bSToby Isaac 
55109566063dSJacob Faibussowitsch       PetscCall(PetscFEGetDualSpace((PetscFE)disc,&dsp));
55119566063dSJacob Faibussowitsch       PetscCall(DMLabelGetNumValues(label,&depth));
55129566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(label,point,&h));
5513e071409bSToby Isaac       h    = depth - 1 - h;
5514e071409bSToby Isaac       if (h) {
55159566063dSJacob Faibussowitsch         PetscCall(PetscDualSpaceGetHeightSubspace(dsp,h,dspace));
5516e071409bSToby Isaac       } else {
5517e071409bSToby Isaac         *dspace = dsp;
5518e071409bSToby Isaac       }
5519e071409bSToby Isaac     }
5520e071409bSToby Isaac   }
5521e071409bSToby Isaac   PetscFunctionReturn(0);
5522e071409bSToby Isaac }
5523e071409bSToby Isaac 
55249fbee547SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
5525a6dfd86eSKarl Rupp {
5526552f7358SJed Brown   PetscScalar    *array, *vArray;
5527d9917b9dSMatthew G. Knepley   const PetscInt *cone, *coneO;
55281a271a75SMatthew G. Knepley   PetscInt        pStart, pEnd, p, numPoints, size = 0, offset = 0;
5529552f7358SJed Brown 
55301b406b76SMatthew G. Knepley   PetscFunctionBeginHot;
55319566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
55329566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, point, &numPoints));
55339566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, point, &cone));
55349566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeOrientation(dm, point, &coneO));
55353f7cbbe7SMatthew G. Knepley   if (!values || !*values) {
55369df71ca4SMatthew G. Knepley     if ((point >= pStart) && (point < pEnd)) {
55379df71ca4SMatthew G. Knepley       PetscInt dof;
5538d9917b9dSMatthew G. Knepley 
55399566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, point, &dof));
55409df71ca4SMatthew G. Knepley       size += dof;
55419df71ca4SMatthew G. Knepley     }
55429df71ca4SMatthew G. Knepley     for (p = 0; p < numPoints; ++p) {
55439df71ca4SMatthew G. Knepley       const PetscInt cp = cone[p];
55442a3aaacfSMatthew G. Knepley       PetscInt       dof;
55455a1bb5cfSMatthew G. Knepley 
55465a1bb5cfSMatthew G. Knepley       if ((cp < pStart) || (cp >= pEnd)) continue;
55479566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, cp, &dof));
55485a1bb5cfSMatthew G. Knepley       size += dof;
55495a1bb5cfSMatthew G. Knepley     }
55503f7cbbe7SMatthew G. Knepley     if (!values) {
55513f7cbbe7SMatthew G. Knepley       if (csize) *csize = size;
55523f7cbbe7SMatthew G. Knepley       PetscFunctionReturn(0);
55533f7cbbe7SMatthew G. Knepley     }
55549566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, size, MPIU_SCALAR, &array));
5555982e9ed1SMatthew G. Knepley   } else {
5556982e9ed1SMatthew G. Knepley     array = *values;
5557982e9ed1SMatthew G. Knepley   }
55589df71ca4SMatthew G. Knepley   size = 0;
55599566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &vArray));
55609df71ca4SMatthew G. Knepley   if ((point >= pStart) && (point < pEnd)) {
55619df71ca4SMatthew G. Knepley     PetscInt     dof, off, d;
55629df71ca4SMatthew G. Knepley     PetscScalar *varr;
5563d9917b9dSMatthew G. Knepley 
55649566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, point, &dof));
55659566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, point, &off));
55669df71ca4SMatthew G. Knepley     varr = &vArray[off];
55671a271a75SMatthew G. Knepley     for (d = 0; d < dof; ++d, ++offset) {
55681a271a75SMatthew G. Knepley       array[offset] = varr[d];
55699df71ca4SMatthew G. Knepley     }
55709df71ca4SMatthew G. Knepley     size += dof;
55719df71ca4SMatthew G. Knepley   }
55729df71ca4SMatthew G. Knepley   for (p = 0; p < numPoints; ++p) {
55739df71ca4SMatthew G. Knepley     const PetscInt cp = cone[p];
55749df71ca4SMatthew G. Knepley     PetscInt       o  = coneO[p];
55755a1bb5cfSMatthew G. Knepley     PetscInt       dof, off, d;
55765a1bb5cfSMatthew G. Knepley     PetscScalar   *varr;
55775a1bb5cfSMatthew G. Knepley 
557852ed52e8SMatthew G. Knepley     if ((cp < pStart) || (cp >= pEnd)) continue;
55799566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, cp, &dof));
55809566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, cp, &off));
55815a1bb5cfSMatthew G. Knepley     varr = &vArray[off];
55825a1bb5cfSMatthew G. Knepley     if (o >= 0) {
55831a271a75SMatthew G. Knepley       for (d = 0; d < dof; ++d, ++offset) {
55841a271a75SMatthew G. Knepley         array[offset] = varr[d];
55855a1bb5cfSMatthew G. Knepley       }
55865a1bb5cfSMatthew G. Knepley     } else {
55871a271a75SMatthew G. Knepley       for (d = dof-1; d >= 0; --d, ++offset) {
55881a271a75SMatthew G. Knepley         array[offset] = varr[d];
55895a1bb5cfSMatthew G. Knepley       }
55905a1bb5cfSMatthew G. Knepley     }
55919df71ca4SMatthew G. Knepley     size += dof;
55925a1bb5cfSMatthew G. Knepley   }
55939566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &vArray));
55949df71ca4SMatthew G. Knepley   if (!*values) {
55955a1bb5cfSMatthew G. Knepley     if (csize) *csize = size;
55965a1bb5cfSMatthew G. Knepley     *values = array;
55979df71ca4SMatthew G. Knepley   } else {
559863a3b9bcSJacob Faibussowitsch     PetscCheck(size <= *csize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size);
55998c312ff3SMatthew G. Knepley     *csize = size;
56009df71ca4SMatthew G. Knepley   }
56015a1bb5cfSMatthew G. Knepley   PetscFunctionReturn(0);
56025a1bb5cfSMatthew G. Knepley }
5603d9917b9dSMatthew G. Knepley 
560427f02ce8SMatthew G. Knepley /* Compress out points not in the section */
56059fbee547SJacob Faibussowitsch static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[])
560627f02ce8SMatthew G. Knepley {
560727f02ce8SMatthew G. Knepley   const PetscInt np = *numPoints;
560827f02ce8SMatthew G. Knepley   PetscInt       pStart, pEnd, p, q;
560927f02ce8SMatthew G. Knepley 
56109566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
561127f02ce8SMatthew G. Knepley   for (p = 0, q = 0; p < np; ++p) {
561227f02ce8SMatthew G. Knepley     const PetscInt r = points[p*2];
561327f02ce8SMatthew G. Knepley     if ((r >= pStart) && (r < pEnd)) {
561427f02ce8SMatthew G. Knepley       points[q*2]   = r;
561527f02ce8SMatthew G. Knepley       points[q*2+1] = points[p*2+1];
561627f02ce8SMatthew G. Knepley       ++q;
561727f02ce8SMatthew G. Knepley     }
561827f02ce8SMatthew G. Knepley   }
561927f02ce8SMatthew G. Knepley   *numPoints = q;
562027f02ce8SMatthew G. Knepley   return 0;
562127f02ce8SMatthew G. Knepley }
562227f02ce8SMatthew G. Knepley 
562397529cf3SJed Brown /* Compressed closure does not apply closure permutation */
56241dc59d61SMatthew G. Knepley PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp)
5625923c78e0SToby Isaac {
562627f02ce8SMatthew G. Knepley   const PetscInt *cla = NULL;
5627923c78e0SToby Isaac   PetscInt       np, *pts = NULL;
5628923c78e0SToby Isaac 
5629923c78e0SToby Isaac   PetscFunctionBeginHot;
56309566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureIndex(section, (PetscObject) dm, clSec, clPoints));
563127f02ce8SMatthew G. Knepley   if (*clPoints) {
5632923c78e0SToby Isaac     PetscInt dof, off;
5633923c78e0SToby Isaac 
56349566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(*clSec, point, &dof));
56359566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(*clSec, point, &off));
56369566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(*clPoints, &cla));
5637923c78e0SToby Isaac     np   = dof/2;
5638923c78e0SToby Isaac     pts  = (PetscInt *) &cla[off];
563927f02ce8SMatthew G. Knepley   } else {
56409566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &np, &pts));
56419566063dSJacob Faibussowitsch     PetscCall(CompressPoints_Private(section, &np, pts));
5642923c78e0SToby Isaac   }
5643923c78e0SToby Isaac   *numPoints = np;
5644923c78e0SToby Isaac   *points    = pts;
5645923c78e0SToby Isaac   *clp       = cla;
5646923c78e0SToby Isaac   PetscFunctionReturn(0);
5647923c78e0SToby Isaac }
5648923c78e0SToby Isaac 
56491dc59d61SMatthew G. Knepley PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp)
5650923c78e0SToby Isaac {
5651923c78e0SToby Isaac   PetscFunctionBeginHot;
5652923c78e0SToby Isaac   if (!*clPoints) {
56539566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points));
5654923c78e0SToby Isaac   } else {
56559566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(*clPoints, clp));
5656923c78e0SToby Isaac   }
5657923c78e0SToby Isaac   *numPoints = 0;
5658923c78e0SToby Isaac   *points    = NULL;
5659923c78e0SToby Isaac   *clSec     = NULL;
5660923c78e0SToby Isaac   *clPoints  = NULL;
5661923c78e0SToby Isaac   *clp       = NULL;
5662923c78e0SToby Isaac   PetscFunctionReturn(0);
5663923c78e0SToby Isaac }
5664923c78e0SToby Isaac 
56659fbee547SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Static(DM dm, PetscSection section, PetscInt numPoints, const PetscInt points[], const PetscInt clperm[], const PetscScalar vArray[], PetscInt *size, PetscScalar array[])
56661a271a75SMatthew G. Knepley {
56671a271a75SMatthew G. Knepley   PetscInt          offset = 0, p;
566897e99dd9SToby Isaac   const PetscInt    **perms = NULL;
566997e99dd9SToby Isaac   const PetscScalar **flips = NULL;
56701a271a75SMatthew G. Knepley 
56711a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
5672fe02ba77SJed Brown   *size = 0;
56739566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips));
567497e99dd9SToby Isaac   for (p = 0; p < numPoints; p++) {
567597e99dd9SToby Isaac     const PetscInt    point = points[2*p];
567697e99dd9SToby Isaac     const PetscInt    *perm = perms ? perms[p] : NULL;
567797e99dd9SToby Isaac     const PetscScalar *flip = flips ? flips[p] : NULL;
56781a271a75SMatthew G. Knepley     PetscInt          dof, off, d;
56791a271a75SMatthew G. Knepley     const PetscScalar *varr;
56801a271a75SMatthew G. Knepley 
56819566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, point, &dof));
56829566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, point, &off));
56831a271a75SMatthew G. Knepley     varr = &vArray[off];
568497e99dd9SToby Isaac     if (clperm) {
568597e99dd9SToby Isaac       if (perm) {
568697e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]]  = varr[d];
56871a271a75SMatthew G. Knepley       } else {
568897e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset +      d ]]  = varr[d];
568997e99dd9SToby Isaac       }
569097e99dd9SToby Isaac       if (flip) {
569197e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset +      d ]] *= flip[d];
569297e99dd9SToby Isaac       }
569397e99dd9SToby Isaac     } else {
569497e99dd9SToby Isaac       if (perm) {
569597e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset + perm[d]]  = varr[d];
569697e99dd9SToby Isaac       } else {
569797e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset +      d ]  = varr[d];
569897e99dd9SToby Isaac       }
569997e99dd9SToby Isaac       if (flip) {
570097e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset +      d ] *= flip[d];
57011a271a75SMatthew G. Knepley       }
57021a271a75SMatthew G. Knepley     }
570397e99dd9SToby Isaac     offset += dof;
570497e99dd9SToby Isaac   }
57059566063dSJacob Faibussowitsch   PetscCall(PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips));
57061a271a75SMatthew G. Knepley   *size = offset;
57071a271a75SMatthew G. Knepley   PetscFunctionReturn(0);
57081a271a75SMatthew G. Knepley }
57091a271a75SMatthew G. Knepley 
57109fbee547SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Fields_Static(DM dm, PetscSection section, PetscInt numPoints, const PetscInt points[], PetscInt numFields, const PetscInt clperm[], const PetscScalar vArray[], PetscInt *size, PetscScalar array[])
57111a271a75SMatthew G. Knepley {
57121a271a75SMatthew G. Knepley   PetscInt          offset = 0, f;
57131a271a75SMatthew G. Knepley 
57141a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
5715fe02ba77SJed Brown   *size = 0;
57161a271a75SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
571797e99dd9SToby Isaac     PetscInt          p;
571897e99dd9SToby Isaac     const PetscInt    **perms = NULL;
571997e99dd9SToby Isaac     const PetscScalar **flips = NULL;
57201a271a75SMatthew G. Knepley 
57219566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips));
572297e99dd9SToby Isaac     for (p = 0; p < numPoints; p++) {
572397e99dd9SToby Isaac       const PetscInt    point = points[2*p];
572497e99dd9SToby Isaac       PetscInt          fdof, foff, b;
57251a271a75SMatthew G. Knepley       const PetscScalar *varr;
572697e99dd9SToby Isaac       const PetscInt    *perm = perms ? perms[p] : NULL;
572797e99dd9SToby Isaac       const PetscScalar *flip = flips ? flips[p] : NULL;
57281a271a75SMatthew G. Knepley 
57299566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
57309566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
57311a271a75SMatthew G. Knepley       varr = &vArray[foff];
573297e99dd9SToby Isaac       if (clperm) {
573397e99dd9SToby Isaac         if (perm) {for (b = 0; b < fdof; b++) {array[clperm[offset + perm[b]]]  = varr[b];}}
573497e99dd9SToby Isaac         else      {for (b = 0; b < fdof; b++) {array[clperm[offset +      b ]]  = varr[b];}}
573597e99dd9SToby Isaac         if (flip) {for (b = 0; b < fdof; b++) {array[clperm[offset +      b ]] *= flip[b];}}
57361a271a75SMatthew G. Knepley       } else {
573797e99dd9SToby Isaac         if (perm) {for (b = 0; b < fdof; b++) {array[offset + perm[b]]  = varr[b];}}
573897e99dd9SToby Isaac         else      {for (b = 0; b < fdof; b++) {array[offset +      b ]  = varr[b];}}
573997e99dd9SToby Isaac         if (flip) {for (b = 0; b < fdof; b++) {array[offset +      b ] *= flip[b];}}
57401a271a75SMatthew G. Knepley       }
574197e99dd9SToby Isaac       offset += fdof;
57421a271a75SMatthew G. Knepley     }
57439566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips));
57441a271a75SMatthew G. Knepley   }
57451a271a75SMatthew G. Knepley   *size = offset;
57461a271a75SMatthew G. Knepley   PetscFunctionReturn(0);
57471a271a75SMatthew G. Knepley }
57481a271a75SMatthew G. Knepley 
5749552f7358SJed Brown /*@C
5750552f7358SJed Brown   DMPlexVecGetClosure - Get an array of the values on the closure of 'point'
5751552f7358SJed Brown 
5752552f7358SJed Brown   Not collective
5753552f7358SJed Brown 
5754552f7358SJed Brown   Input Parameters:
5755552f7358SJed Brown + dm - The DM
5756552f7358SJed Brown . section - The section describing the layout in v, or NULL to use the default section
5757552f7358SJed Brown . v - The local vector
57586b867d5aSJose E. Roman - point - The point in the DM
5759552f7358SJed Brown 
57606b867d5aSJose E. Roman   Input/Output Parameters:
57616b867d5aSJose E. Roman + csize  - The size of the input values array, or NULL; on output the number of values in the closure
57626b867d5aSJose E. Roman - values - An array to use for the values, or NULL to have it allocated automatically;
57636b867d5aSJose E. Roman            if the user provided NULL, it is a borrowed array and should not be freed
576422c1ee49SMatthew G. Knepley 
576522c1ee49SMatthew G. Knepley $ Note that DMPlexVecGetClosure/DMPlexVecRestoreClosure only allocates the values array if it set to NULL in the
576622c1ee49SMatthew G. Knepley $ calling function. This is because DMPlexVecGetClosure() is typically called in the inner loop of a Vec or Mat
576722c1ee49SMatthew G. Knepley $ assembly function, and a user may already have allocated storage for this operation.
576822c1ee49SMatthew G. Knepley $
576922c1ee49SMatthew G. Knepley $ A typical use could be
577022c1ee49SMatthew G. Knepley $
577122c1ee49SMatthew G. Knepley $  values = NULL;
57729566063dSJacob Faibussowitsch $  PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values));
577322c1ee49SMatthew G. Knepley $  for (cl = 0; cl < clSize; ++cl) {
577422c1ee49SMatthew G. Knepley $    <Compute on closure>
577522c1ee49SMatthew G. Knepley $  }
57769566063dSJacob Faibussowitsch $  PetscCall(DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values));
577722c1ee49SMatthew G. Knepley $
577822c1ee49SMatthew G. Knepley $ or
577922c1ee49SMatthew G. Knepley $
578022c1ee49SMatthew G. Knepley $  PetscMalloc1(clMaxSize, &values);
578122c1ee49SMatthew G. Knepley $  for (p = pStart; p < pEnd; ++p) {
578222c1ee49SMatthew G. Knepley $    clSize = clMaxSize;
57839566063dSJacob Faibussowitsch $    PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values));
578422c1ee49SMatthew G. Knepley $    for (cl = 0; cl < clSize; ++cl) {
578522c1ee49SMatthew G. Knepley $      <Compute on closure>
578622c1ee49SMatthew G. Knepley $    }
578722c1ee49SMatthew G. Knepley $  }
578822c1ee49SMatthew G. Knepley $  PetscFree(values);
5789552f7358SJed Brown 
5790552f7358SJed Brown   Fortran Notes:
5791552f7358SJed Brown   Since it returns an array, this routine is only available in Fortran 90, and you must
5792552f7358SJed Brown   include petsc.h90 in your code.
5793552f7358SJed Brown 
5794552f7358SJed Brown   The csize argument is not present in the Fortran 90 binding since it is internal to the array.
5795552f7358SJed Brown 
5796552f7358SJed Brown   Level: intermediate
5797552f7358SJed Brown 
5798db781477SPatrick Sanan .seealso `DMPlexVecRestoreClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()`
5799552f7358SJed Brown @*/
5800552f7358SJed Brown PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
5801552f7358SJed Brown {
5802552f7358SJed Brown   PetscSection       clSection;
5803d9917b9dSMatthew G. Knepley   IS                 clPoints;
5804552f7358SJed Brown   PetscInt          *points = NULL;
5805c459fbc1SJed Brown   const PetscInt    *clp, *perm;
5806c459fbc1SJed Brown   PetscInt           depth, numFields, numPoints, asize;
5807552f7358SJed Brown 
5808d9917b9dSMatthew G. Knepley   PetscFunctionBeginHot;
5809552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
58109566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
58111a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
58121a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
58139566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
58149566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
5815552f7358SJed Brown   if (depth == 1 && numFields < 2) {
58169566063dSJacob Faibussowitsch     PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values));
5817552f7358SJed Brown     PetscFunctionReturn(0);
5818552f7358SJed Brown   }
58191a271a75SMatthew G. Knepley   /* Get points */
58209566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
5821c459fbc1SJed Brown   /* Get sizes */
5822c459fbc1SJed Brown   asize = 0;
5823c459fbc1SJed Brown   for (PetscInt p = 0; p < numPoints*2; p += 2) {
5824c459fbc1SJed Brown     PetscInt dof;
58259566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[p], &dof));
58261a271a75SMatthew G. Knepley     asize += dof;
5827552f7358SJed Brown   }
5828c459fbc1SJed Brown   if (values) {
5829c459fbc1SJed Brown     const PetscScalar *vArray;
5830c459fbc1SJed Brown     PetscInt          size;
5831c459fbc1SJed Brown 
5832c459fbc1SJed Brown     if (*values) {
583363a3b9bcSJacob Faibussowitsch       PetscCheck(*csize >= asize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Provided array size %" PetscInt_FMT " not sufficient to hold closure size %" PetscInt_FMT, *csize, asize);
58349566063dSJacob Faibussowitsch     } else PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, values));
58359566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, asize, &perm));
58369566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(v, &vArray));
58371a271a75SMatthew G. Knepley     /* Get values */
58389566063dSJacob Faibussowitsch     if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values));
58399566063dSJacob Faibussowitsch     else               PetscCall(DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values));
584063a3b9bcSJacob Faibussowitsch     PetscCheck(asize == size,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Section size %" PetscInt_FMT " does not match Vec closure size %" PetscInt_FMT, asize, size);
58411a271a75SMatthew G. Knepley     /* Cleanup array */
58429566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(v, &vArray));
5843d0f6b257SMatthew G. Knepley   }
5844c459fbc1SJed Brown   if (csize) *csize = asize;
5845c459fbc1SJed Brown   /* Cleanup points */
58469566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
5847552f7358SJed Brown   PetscFunctionReturn(0);
5848552f7358SJed Brown }
5849552f7358SJed Brown 
5850e5c487bfSMatthew G. Knepley PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[])
5851e5c487bfSMatthew G. Knepley {
5852e5c487bfSMatthew G. Knepley   DMLabel            depthLabel;
5853e5c487bfSMatthew G. Knepley   PetscSection       clSection;
5854e5c487bfSMatthew G. Knepley   IS                 clPoints;
5855e5c487bfSMatthew G. Knepley   PetscScalar       *array;
5856e5c487bfSMatthew G. Knepley   const PetscScalar *vArray;
5857e5c487bfSMatthew G. Knepley   PetscInt          *points = NULL;
5858c459fbc1SJed Brown   const PetscInt    *clp, *perm = NULL;
5859c459fbc1SJed Brown   PetscInt           mdepth, numFields, numPoints, Np = 0, p, clsize, size;
5860e5c487bfSMatthew G. Knepley 
5861e5c487bfSMatthew G. Knepley   PetscFunctionBeginHot;
5862e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
58639566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
5864e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
5865e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
58669566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &mdepth));
58679566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
58689566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
5869e5c487bfSMatthew G. Knepley   if (mdepth == 1 && numFields < 2) {
58709566063dSJacob Faibussowitsch     PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values));
5871e5c487bfSMatthew G. Knepley     PetscFunctionReturn(0);
5872e5c487bfSMatthew G. Knepley   }
5873e5c487bfSMatthew G. Knepley   /* Get points */
58749566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
5875c459fbc1SJed Brown   for (clsize=0,p=0; p<Np; p++) {
5876c459fbc1SJed Brown     PetscInt dof;
58779566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[2*p], &dof));
5878c459fbc1SJed Brown     clsize += dof;
5879c459fbc1SJed Brown   }
58809566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &perm));
5881e5c487bfSMatthew G. Knepley   /* Filter points */
5882e5c487bfSMatthew G. Knepley   for (p = 0; p < numPoints*2; p += 2) {
5883e5c487bfSMatthew G. Knepley     PetscInt dep;
5884e5c487bfSMatthew G. Knepley 
58859566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(depthLabel, points[p], &dep));
5886e5c487bfSMatthew G. Knepley     if (dep != depth) continue;
5887e5c487bfSMatthew G. Knepley     points[Np*2+0] = points[p];
5888e5c487bfSMatthew G. Knepley     points[Np*2+1] = points[p+1];
5889e5c487bfSMatthew G. Knepley     ++Np;
5890e5c487bfSMatthew G. Knepley   }
5891e5c487bfSMatthew G. Knepley   /* Get array */
5892e5c487bfSMatthew G. Knepley   if (!values || !*values) {
5893e5c487bfSMatthew G. Knepley     PetscInt asize = 0, dof;
5894e5c487bfSMatthew G. Knepley 
5895e5c487bfSMatthew G. Knepley     for (p = 0; p < Np*2; p += 2) {
58969566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, points[p], &dof));
5897e5c487bfSMatthew G. Knepley       asize += dof;
5898e5c487bfSMatthew G. Knepley     }
5899e5c487bfSMatthew G. Knepley     if (!values) {
59009566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
5901e5c487bfSMatthew G. Knepley       if (csize) *csize = asize;
5902e5c487bfSMatthew G. Knepley       PetscFunctionReturn(0);
5903e5c487bfSMatthew G. Knepley     }
59049566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, &array));
5905e5c487bfSMatthew G. Knepley   } else {
5906e5c487bfSMatthew G. Knepley     array = *values;
5907e5c487bfSMatthew G. Knepley   }
59089566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(v, &vArray));
5909e5c487bfSMatthew G. Knepley   /* Get values */
59109566063dSJacob Faibussowitsch   if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array));
59119566063dSJacob Faibussowitsch   else               PetscCall(DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array));
5912e5c487bfSMatthew G. Knepley   /* Cleanup points */
59139566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
5914e5c487bfSMatthew G. Knepley   /* Cleanup array */
59159566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(v, &vArray));
5916e5c487bfSMatthew G. Knepley   if (!*values) {
5917e5c487bfSMatthew G. Knepley     if (csize) *csize = size;
5918e5c487bfSMatthew G. Knepley     *values = array;
5919e5c487bfSMatthew G. Knepley   } else {
592063a3b9bcSJacob Faibussowitsch     PetscCheck(size <= *csize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size);
5921e5c487bfSMatthew G. Knepley     *csize = size;
5922e5c487bfSMatthew G. Knepley   }
5923e5c487bfSMatthew G. Knepley   PetscFunctionReturn(0);
5924e5c487bfSMatthew G. Knepley }
5925e5c487bfSMatthew G. Knepley 
5926552f7358SJed Brown /*@C
5927552f7358SJed Brown   DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point'
5928552f7358SJed Brown 
5929552f7358SJed Brown   Not collective
5930552f7358SJed Brown 
5931552f7358SJed Brown   Input Parameters:
5932552f7358SJed Brown + dm - The DM
59330298fd71SBarry Smith . section - The section describing the layout in v, or NULL to use the default section
5934552f7358SJed Brown . v - The local vector
5935eaf898f9SPatrick Sanan . point - The point in the DM
59360298fd71SBarry Smith . csize - The number of values in the closure, or NULL
5937552f7358SJed Brown - values - The array of values, which is a borrowed array and should not be freed
5938552f7358SJed Brown 
593922c1ee49SMatthew 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()
594022c1ee49SMatthew G. Knepley 
59413813dfbdSMatthew G Knepley   Fortran Notes:
59423813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
59433813dfbdSMatthew G Knepley   include petsc.h90 in your code.
59443813dfbdSMatthew G Knepley 
59453813dfbdSMatthew G Knepley   The csize argument is not present in the Fortran 90 binding since it is internal to the array.
59463813dfbdSMatthew G Knepley 
5947552f7358SJed Brown   Level: intermediate
5948552f7358SJed Brown 
5949db781477SPatrick Sanan .seealso `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()`
5950552f7358SJed Brown @*/
59517c1f9639SMatthew G Knepley PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
5952a6dfd86eSKarl Rupp {
5953552f7358SJed Brown   PetscInt       size = 0;
5954552f7358SJed Brown 
5955552f7358SJed Brown   PetscFunctionBegin;
5956552f7358SJed Brown   /* Should work without recalculating size */
59579566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void*) values));
5958c9fdaa05SMatthew G. Knepley   *values = NULL;
5959552f7358SJed Brown   PetscFunctionReturn(0);
5960552f7358SJed Brown }
5961552f7358SJed Brown 
59629fbee547SJacob Faibussowitsch static inline void add   (PetscScalar *x, PetscScalar y) {*x += y;}
59639fbee547SJacob Faibussowitsch static inline void insert(PetscScalar *x, PetscScalar y) {*x  = y;}
5964552f7358SJed Brown 
59659fbee547SJacob Faibussowitsch static inline PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, const PetscInt perm[], const PetscScalar flip[], const PetscInt clperm[], const PetscScalar values[], PetscInt offset, PetscScalar array[])
5966552f7358SJed Brown {
5967552f7358SJed Brown   PetscInt        cdof;   /* The number of constraints on this point */
5968552f7358SJed Brown   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
5969552f7358SJed Brown   PetscScalar    *a;
5970552f7358SJed Brown   PetscInt        off, cind = 0, k;
5971552f7358SJed Brown 
5972552f7358SJed Brown   PetscFunctionBegin;
59739566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
59749566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(section, point, &off));
5975552f7358SJed Brown   a    = &array[off];
5976552f7358SJed Brown   if (!cdof || setBC) {
597797e99dd9SToby Isaac     if (clperm) {
597897e99dd9SToby Isaac       if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));}}
597997e99dd9SToby Isaac       else      {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+     k ]] * (flip ? flip[     k ] : 1.));}}
5980552f7358SJed Brown     } else {
598197e99dd9SToby Isaac       if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));}}
598297e99dd9SToby Isaac       else      {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+     k ] * (flip ? flip[     k ] : 1.));}}
5983552f7358SJed Brown     }
5984552f7358SJed Brown   } else {
59859566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
598697e99dd9SToby Isaac     if (clperm) {
598797e99dd9SToby Isaac       if (perm) {for (k = 0; k < dof; ++k) {
5988552f7358SJed Brown           if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
598997e99dd9SToby Isaac           fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));
5990552f7358SJed Brown         }
5991552f7358SJed Brown       } else {
5992552f7358SJed Brown         for (k = 0; k < dof; ++k) {
5993552f7358SJed Brown           if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
599497e99dd9SToby Isaac           fuse(&a[k], values[clperm[offset+     k ]] * (flip ? flip[     k ] : 1.));
599597e99dd9SToby Isaac         }
599697e99dd9SToby Isaac       }
599797e99dd9SToby Isaac     } else {
599897e99dd9SToby Isaac       if (perm) {
599997e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
600097e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
600197e99dd9SToby Isaac           fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));
600297e99dd9SToby Isaac         }
600397e99dd9SToby Isaac       } else {
600497e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
600597e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
600697e99dd9SToby Isaac           fuse(&a[k], values[offset+     k ] * (flip ? flip[     k ] : 1.));
600797e99dd9SToby Isaac         }
6008552f7358SJed Brown       }
6009552f7358SJed Brown     }
6010552f7358SJed Brown   }
6011552f7358SJed Brown   PetscFunctionReturn(0);
6012552f7358SJed Brown }
6013552f7358SJed Brown 
60149fbee547SJacob Faibussowitsch static inline PetscErrorCode updatePointBC_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), const PetscInt perm[], const PetscScalar flip[], const PetscInt clperm[], const PetscScalar values[], PetscInt offset, PetscScalar array[])
6015a5e93ea8SMatthew G. Knepley {
6016a5e93ea8SMatthew G. Knepley   PetscInt        cdof;   /* The number of constraints on this point */
6017a5e93ea8SMatthew G. Knepley   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6018a5e93ea8SMatthew G. Knepley   PetscScalar    *a;
6019a5e93ea8SMatthew G. Knepley   PetscInt        off, cind = 0, k;
6020a5e93ea8SMatthew G. Knepley 
6021a5e93ea8SMatthew G. Knepley   PetscFunctionBegin;
60229566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
60239566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(section, point, &off));
6024a5e93ea8SMatthew G. Knepley   a    = &array[off];
6025a5e93ea8SMatthew G. Knepley   if (cdof) {
60269566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
602797e99dd9SToby Isaac     if (clperm) {
602897e99dd9SToby Isaac       if (perm) {
6029a5e93ea8SMatthew G. Knepley         for (k = 0; k < dof; ++k) {
6030a5e93ea8SMatthew G. Knepley           if ((cind < cdof) && (k == cdofs[cind])) {
603197e99dd9SToby Isaac             fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));
603297e99dd9SToby Isaac             cind++;
6033a5e93ea8SMatthew G. Knepley           }
6034a5e93ea8SMatthew G. Knepley         }
6035a5e93ea8SMatthew G. Knepley       } else {
6036a5e93ea8SMatthew G. Knepley         for (k = 0; k < dof; ++k) {
6037a5e93ea8SMatthew G. Knepley           if ((cind < cdof) && (k == cdofs[cind])) {
603897e99dd9SToby Isaac             fuse(&a[k], values[clperm[offset+     k ]] * (flip ? flip[     k ] : 1.));
603997e99dd9SToby Isaac             cind++;
604097e99dd9SToby Isaac           }
604197e99dd9SToby Isaac         }
604297e99dd9SToby Isaac       }
604397e99dd9SToby Isaac     } else {
604497e99dd9SToby Isaac       if (perm) {
604597e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
604697e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {
604797e99dd9SToby Isaac             fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));
604897e99dd9SToby Isaac             cind++;
604997e99dd9SToby Isaac           }
605097e99dd9SToby Isaac         }
605197e99dd9SToby Isaac       } else {
605297e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
605397e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {
605497e99dd9SToby Isaac             fuse(&a[k], values[offset+     k ] * (flip ? flip[     k ] : 1.));
605597e99dd9SToby Isaac             cind++;
605697e99dd9SToby Isaac           }
6057a5e93ea8SMatthew G. Knepley         }
6058a5e93ea8SMatthew G. Knepley       }
6059a5e93ea8SMatthew G. Knepley     }
6060a5e93ea8SMatthew G. Knepley   }
6061a5e93ea8SMatthew G. Knepley   PetscFunctionReturn(0);
6062a5e93ea8SMatthew G. Knepley }
6063a5e93ea8SMatthew G. Knepley 
60649fbee547SJacob Faibussowitsch static inline PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, const PetscInt *perm, const PetscScalar *flip, PetscInt f, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, const PetscInt clperm[], const PetscScalar values[], PetscInt *offset, PetscScalar array[])
6065a6dfd86eSKarl Rupp {
6066552f7358SJed Brown   PetscScalar    *a;
60671a271a75SMatthew G. Knepley   PetscInt        fdof, foff, fcdof, foffset = *offset;
60681a271a75SMatthew G. Knepley   const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
606997e99dd9SToby Isaac   PetscInt        cind = 0, b;
6070552f7358SJed Brown 
6071552f7358SJed Brown   PetscFunctionBegin;
60729566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
60739566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof));
60749566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
60751a271a75SMatthew G. Knepley   a    = &array[foff];
6076552f7358SJed Brown   if (!fcdof || setBC) {
607797e99dd9SToby Isaac     if (clperm) {
607897e99dd9SToby Isaac       if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));}}
607997e99dd9SToby Isaac       else      {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+     b ]] * (flip ? flip[     b ] : 1.));}}
6080552f7358SJed Brown     } else {
608197e99dd9SToby Isaac       if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));}}
608297e99dd9SToby Isaac       else      {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+     b ] * (flip ? flip[     b ] : 1.));}}
6083552f7358SJed Brown     }
6084552f7358SJed Brown   } else {
60859566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
608697e99dd9SToby Isaac     if (clperm) {
608797e99dd9SToby Isaac       if (perm) {
608897e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
608997e99dd9SToby Isaac           if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;}
609097e99dd9SToby Isaac           fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));
6091552f7358SJed Brown         }
6092552f7358SJed Brown       } else {
609397e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
609497e99dd9SToby Isaac           if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;}
609597e99dd9SToby Isaac           fuse(&a[b], values[clperm[foffset+     b ]] * (flip ? flip[     b ] : 1.));
609697e99dd9SToby Isaac         }
609797e99dd9SToby Isaac       }
609897e99dd9SToby Isaac     } else {
609997e99dd9SToby Isaac       if (perm) {
610097e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
610197e99dd9SToby Isaac           if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;}
610297e99dd9SToby Isaac           fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));
610397e99dd9SToby Isaac         }
610497e99dd9SToby Isaac       } else {
610597e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
610697e99dd9SToby Isaac           if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;}
610797e99dd9SToby Isaac           fuse(&a[b], values[foffset+     b ] * (flip ? flip[     b ] : 1.));
6108552f7358SJed Brown         }
6109552f7358SJed Brown       }
6110552f7358SJed Brown     }
6111552f7358SJed Brown   }
61121a271a75SMatthew G. Knepley   *offset += fdof;
6113552f7358SJed Brown   PetscFunctionReturn(0);
6114552f7358SJed Brown }
6115552f7358SJed Brown 
61169fbee547SJacob Faibussowitsch static inline PetscErrorCode updatePointFieldsBC_private(PetscSection section, PetscInt point, const PetscInt perm[], const PetscScalar flip[], PetscInt f, PetscInt Ncc, const PetscInt comps[], void (*fuse)(PetscScalar*, PetscScalar), const PetscInt clperm[], const PetscScalar values[], PetscInt *offset, PetscScalar array[])
6117a5e93ea8SMatthew G. Knepley {
6118a5e93ea8SMatthew G. Knepley   PetscScalar    *a;
61191a271a75SMatthew G. Knepley   PetscInt        fdof, foff, fcdof, foffset = *offset;
61201a271a75SMatthew G. Knepley   const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
61215da9d227SMatthew G. Knepley   PetscInt        Nc, cind = 0, ncind = 0, b;
6122ba322698SMatthew G. Knepley   PetscBool       ncSet, fcSet;
6123a5e93ea8SMatthew G. Knepley 
6124a5e93ea8SMatthew G. Knepley   PetscFunctionBegin;
61259566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldComponents(section, f, &Nc));
61269566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
61279566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof));
61289566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
61291a271a75SMatthew G. Knepley   a    = &array[foff];
6130a5e93ea8SMatthew G. Knepley   if (fcdof) {
6131ba322698SMatthew G. Knepley     /* We just override fcdof and fcdofs with Ncc and comps */
61329566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
613397e99dd9SToby Isaac     if (clperm) {
613497e99dd9SToby Isaac       if (perm) {
6135ba322698SMatthew G. Knepley         if (comps) {
6136ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6137ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
61385da9d227SMatthew G. Knepley             if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;}
6139ba322698SMatthew G. Knepley             if ((cind < fcdof) && (b == fcdofs[cind])) {++cind;  fcSet = PETSC_TRUE;}
6140ba322698SMatthew G. Knepley             if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));}
6141ba322698SMatthew G. Knepley           }
6142ba322698SMatthew G. Knepley         } else {
614397e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
614497e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
614597e99dd9SToby Isaac               fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));
6146a5e93ea8SMatthew G. Knepley               ++cind;
6147a5e93ea8SMatthew G. Knepley             }
6148a5e93ea8SMatthew G. Knepley           }
6149ba322698SMatthew G. Knepley         }
6150ba322698SMatthew G. Knepley       } else {
6151ba322698SMatthew G. Knepley         if (comps) {
6152ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6153ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
61545da9d227SMatthew G. Knepley             if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;}
6155ba322698SMatthew G. Knepley             if ((cind < fcdof) && (b == fcdofs[cind])) {++cind;  fcSet = PETSC_TRUE;}
6156ba322698SMatthew G. Knepley             if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+     b ]] * (flip ? flip[     b ] : 1.));}
6157ba322698SMatthew G. Knepley           }
6158a5e93ea8SMatthew G. Knepley         } else {
615997e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
616097e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
616197e99dd9SToby Isaac               fuse(&a[b], values[clperm[foffset+     b ]] * (flip ? flip[     b ] : 1.));
616297e99dd9SToby Isaac               ++cind;
616397e99dd9SToby Isaac             }
616497e99dd9SToby Isaac           }
616597e99dd9SToby Isaac         }
6166ba322698SMatthew G. Knepley       }
616797e99dd9SToby Isaac     } else {
616897e99dd9SToby Isaac       if (perm) {
6169ba322698SMatthew G. Knepley         if (comps) {
6170ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6171ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
61725da9d227SMatthew G. Knepley             if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;}
6173ba322698SMatthew G. Knepley             if ((cind < fcdof) && (b == fcdofs[cind])) {++cind;  fcSet = PETSC_TRUE;}
6174ba322698SMatthew G. Knepley             if (ncSet && fcSet) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));}
6175ba322698SMatthew G. Knepley           }
6176ba322698SMatthew G. Knepley         } else {
617797e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
617897e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
617997e99dd9SToby Isaac               fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));
618097e99dd9SToby Isaac               ++cind;
618197e99dd9SToby Isaac             }
618297e99dd9SToby Isaac           }
6183ba322698SMatthew G. Knepley         }
6184ba322698SMatthew G. Knepley       } else {
6185ba322698SMatthew G. Knepley         if (comps) {
6186ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6187ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
61885da9d227SMatthew G. Knepley             if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;}
6189ba322698SMatthew G. Knepley             if ((cind < fcdof) && (b == fcdofs[cind])) {++cind;  fcSet = PETSC_TRUE;}
6190ba322698SMatthew G. Knepley             if (ncSet && fcSet) {fuse(&a[b], values[foffset+     b ] * (flip ? flip[     b ] : 1.));}
6191ba322698SMatthew G. Knepley           }
619297e99dd9SToby Isaac         } else {
619397e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
619497e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
619597e99dd9SToby Isaac               fuse(&a[b], values[foffset+     b ] * (flip ? flip[     b ] : 1.));
6196a5e93ea8SMatthew G. Knepley               ++cind;
6197a5e93ea8SMatthew G. Knepley             }
6198a5e93ea8SMatthew G. Knepley           }
6199a5e93ea8SMatthew G. Knepley         }
6200a5e93ea8SMatthew G. Knepley       }
6201a5e93ea8SMatthew G. Knepley     }
6202ba322698SMatthew G. Knepley   }
62031a271a75SMatthew G. Knepley   *offset += fdof;
6204a5e93ea8SMatthew G. Knepley   PetscFunctionReturn(0);
6205a5e93ea8SMatthew G. Knepley }
6206a5e93ea8SMatthew G. Knepley 
62079fbee547SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode)
6208a6dfd86eSKarl Rupp {
6209552f7358SJed Brown   PetscScalar    *array;
62101b406b76SMatthew G. Knepley   const PetscInt *cone, *coneO;
62111b406b76SMatthew G. Knepley   PetscInt        pStart, pEnd, p, numPoints, off, dof;
6212552f7358SJed Brown 
62131b406b76SMatthew G. Knepley   PetscFunctionBeginHot;
62149566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
62159566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, point, &numPoints));
62169566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, point, &cone));
62179566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeOrientation(dm, point, &coneO));
62189566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
6219b6ebb6e6SMatthew G. Knepley   for (p = 0, off = 0; p <= numPoints; ++p, off += dof) {
6220b6ebb6e6SMatthew G. Knepley     const PetscInt cp = !p ? point : cone[p-1];
6221b6ebb6e6SMatthew G. Knepley     const PetscInt o  = !p ? 0     : coneO[p-1];
6222b6ebb6e6SMatthew G. Knepley 
6223b6ebb6e6SMatthew G. Knepley     if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;}
62249566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, cp, &dof));
6225b6ebb6e6SMatthew G. Knepley     /* ADD_VALUES */
6226b6ebb6e6SMatthew G. Knepley     {
6227b6ebb6e6SMatthew G. Knepley       const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6228b6ebb6e6SMatthew G. Knepley       PetscScalar    *a;
6229b6ebb6e6SMatthew G. Knepley       PetscInt        cdof, coff, cind = 0, k;
6230b6ebb6e6SMatthew G. Knepley 
62319566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetConstraintDof(section, cp, &cdof));
62329566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(section, cp, &coff));
6233b6ebb6e6SMatthew G. Knepley       a    = &array[coff];
6234b6ebb6e6SMatthew G. Knepley       if (!cdof) {
6235b6ebb6e6SMatthew G. Knepley         if (o >= 0) {
6236b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
6237b6ebb6e6SMatthew G. Knepley             a[k] += values[off+k];
6238b6ebb6e6SMatthew G. Knepley           }
6239b6ebb6e6SMatthew G. Knepley         } else {
6240b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
6241b6ebb6e6SMatthew G. Knepley             a[k] += values[off+dof-k-1];
6242b6ebb6e6SMatthew G. Knepley           }
6243b6ebb6e6SMatthew G. Knepley         }
6244b6ebb6e6SMatthew G. Knepley       } else {
62459566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintIndices(section, cp, &cdofs));
6246b6ebb6e6SMatthew G. Knepley         if (o >= 0) {
6247b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
6248b6ebb6e6SMatthew G. Knepley             if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
6249b6ebb6e6SMatthew G. Knepley             a[k] += values[off+k];
6250b6ebb6e6SMatthew G. Knepley           }
6251b6ebb6e6SMatthew G. Knepley         } else {
6252b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
6253b6ebb6e6SMatthew G. Knepley             if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
6254b6ebb6e6SMatthew G. Knepley             a[k] += values[off+dof-k-1];
6255b6ebb6e6SMatthew G. Knepley           }
6256b6ebb6e6SMatthew G. Knepley         }
6257b6ebb6e6SMatthew G. Knepley       }
6258b6ebb6e6SMatthew G. Knepley     }
6259b6ebb6e6SMatthew G. Knepley   }
62609566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
6261b6ebb6e6SMatthew G. Knepley   PetscFunctionReturn(0);
6262b6ebb6e6SMatthew G. Knepley }
62631b406b76SMatthew G. Knepley 
62641b406b76SMatthew G. Knepley /*@C
62651b406b76SMatthew G. Knepley   DMPlexVecSetClosure - Set an array of the values on the closure of 'point'
62661b406b76SMatthew G. Knepley 
62671b406b76SMatthew G. Knepley   Not collective
62681b406b76SMatthew G. Knepley 
62691b406b76SMatthew G. Knepley   Input Parameters:
62701b406b76SMatthew G. Knepley + dm - The DM
62711b406b76SMatthew G. Knepley . section - The section describing the layout in v, or NULL to use the default section
62721b406b76SMatthew G. Knepley . v - The local vector
6273eaf898f9SPatrick Sanan . point - The point in the DM
62741b406b76SMatthew G. Knepley . values - The array of values
627522c1ee49SMatthew 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,
627622c1ee49SMatthew G. Knepley          where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions.
62771b406b76SMatthew G. Knepley 
62781b406b76SMatthew G. Knepley   Fortran Notes:
62791b406b76SMatthew G. Knepley   This routine is only available in Fortran 90, and you must include petsc.h90 in your code.
62801b406b76SMatthew G. Knepley 
62811b406b76SMatthew G. Knepley   Level: intermediate
62821b406b76SMatthew G. Knepley 
6283db781477SPatrick Sanan .seealso `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`
62841b406b76SMatthew G. Knepley @*/
62851b406b76SMatthew G. Knepley PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode)
62861b406b76SMatthew G. Knepley {
62871b406b76SMatthew G. Knepley   PetscSection    clSection;
62881b406b76SMatthew G. Knepley   IS              clPoints;
62891b406b76SMatthew G. Knepley   PetscScalar    *array;
62901b406b76SMatthew G. Knepley   PetscInt       *points = NULL;
629127f02ce8SMatthew G. Knepley   const PetscInt *clp, *clperm = NULL;
6292c459fbc1SJed Brown   PetscInt        depth, numFields, numPoints, p, clsize;
62931b406b76SMatthew G. Knepley 
62941a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
62951b406b76SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
62969566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
62971a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
62981a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
62999566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
63009566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
63011b406b76SMatthew G. Knepley   if (depth == 1 && numFields < 2 && mode == ADD_VALUES) {
63029566063dSJacob Faibussowitsch     PetscCall(DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode));
63031b406b76SMatthew G. Knepley     PetscFunctionReturn(0);
63041b406b76SMatthew G. Knepley   }
63051a271a75SMatthew G. Knepley   /* Get points */
63069566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
6307c459fbc1SJed Brown   for (clsize=0,p=0; p<numPoints; p++) {
6308c459fbc1SJed Brown     PetscInt dof;
63099566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[2*p], &dof));
6310c459fbc1SJed Brown     clsize += dof;
6311c459fbc1SJed Brown   }
63129566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm));
63131a271a75SMatthew G. Knepley   /* Get array */
63149566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
63151a271a75SMatthew G. Knepley   /* Get values */
6316ef90cfe2SMatthew G. Knepley   if (numFields > 0) {
631797e99dd9SToby Isaac     PetscInt offset = 0, f;
6318552f7358SJed Brown     for (f = 0; f < numFields; ++f) {
631997e99dd9SToby Isaac       const PetscInt    **perms = NULL;
632097e99dd9SToby Isaac       const PetscScalar **flips = NULL;
632197e99dd9SToby Isaac 
63229566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips));
6323552f7358SJed Brown       switch (mode) {
6324552f7358SJed Brown       case INSERT_VALUES:
632597e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
632697e99dd9SToby Isaac           const PetscInt    point = points[2*p];
632797e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
632897e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
632997e99dd9SToby Isaac           updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array);
6330552f7358SJed Brown         } break;
6331552f7358SJed Brown       case INSERT_ALL_VALUES:
633297e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
633397e99dd9SToby Isaac           const PetscInt    point = points[2*p];
633497e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
633597e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
633697e99dd9SToby Isaac           updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array);
6337552f7358SJed Brown         } break;
6338a5e93ea8SMatthew G. Knepley       case INSERT_BC_VALUES:
633997e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
634097e99dd9SToby Isaac           const PetscInt    point = points[2*p];
634197e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
634297e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
6343ba322698SMatthew G. Knepley           updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array);
6344a5e93ea8SMatthew G. Knepley         } break;
6345552f7358SJed Brown       case ADD_VALUES:
634697e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
634797e99dd9SToby Isaac           const PetscInt    point = points[2*p];
634897e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
634997e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
635097e99dd9SToby Isaac           updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array);
6351552f7358SJed Brown         } break;
6352552f7358SJed Brown       case ADD_ALL_VALUES:
635397e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
635497e99dd9SToby Isaac           const PetscInt    point = points[2*p];
635597e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
635697e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
635797e99dd9SToby Isaac           updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array);
6358552f7358SJed Brown         } break;
6359304ab55fSMatthew G. Knepley       case ADD_BC_VALUES:
636097e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
636197e99dd9SToby Isaac           const PetscInt    point = points[2*p];
636297e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
636397e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
6364ba322698SMatthew G. Knepley           updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array);
6365304ab55fSMatthew G. Knepley         } break;
6366552f7358SJed Brown       default:
636798921bdaSJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
6368552f7358SJed Brown       }
63699566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips));
63701a271a75SMatthew G. Knepley     }
6371552f7358SJed Brown   } else {
63721a271a75SMatthew G. Knepley     PetscInt dof, off;
637397e99dd9SToby Isaac     const PetscInt    **perms = NULL;
637497e99dd9SToby Isaac     const PetscScalar **flips = NULL;
63751a271a75SMatthew G. Knepley 
63769566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips));
6377552f7358SJed Brown     switch (mode) {
6378552f7358SJed Brown     case INSERT_VALUES:
637997e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
638097e99dd9SToby Isaac         const PetscInt    point = points[2*p];
638197e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
638297e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
63839566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
638497e99dd9SToby Isaac         updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array);
6385552f7358SJed Brown       } break;
6386552f7358SJed Brown     case INSERT_ALL_VALUES:
638797e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
638897e99dd9SToby Isaac         const PetscInt    point = points[2*p];
638997e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
639097e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
63919566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
639297e99dd9SToby Isaac         updatePoint_private(section, point, dof, insert, PETSC_TRUE,  perm, flip, clperm, values, off, array);
6393552f7358SJed Brown       } break;
6394a5e93ea8SMatthew G. Knepley     case INSERT_BC_VALUES:
639597e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
639697e99dd9SToby Isaac         const PetscInt    point = points[2*p];
639797e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
639897e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
63999566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
640097e99dd9SToby Isaac         updatePointBC_private(section, point, dof, insert,  perm, flip, clperm, values, off, array);
6401a5e93ea8SMatthew G. Knepley       } break;
6402552f7358SJed Brown     case ADD_VALUES:
640397e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
640497e99dd9SToby Isaac         const PetscInt    point = points[2*p];
640597e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
640697e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
64079566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
640897e99dd9SToby Isaac         updatePoint_private(section, point, dof, add,    PETSC_FALSE, perm, flip, clperm, values, off, array);
6409552f7358SJed Brown       } break;
6410552f7358SJed Brown     case ADD_ALL_VALUES:
641197e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
641297e99dd9SToby Isaac         const PetscInt    point = points[2*p];
641397e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
641497e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
64159566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
641697e99dd9SToby Isaac         updatePoint_private(section, point, dof, add,    PETSC_TRUE,  perm, flip, clperm, values, off, array);
6417552f7358SJed Brown       } break;
6418304ab55fSMatthew G. Knepley     case ADD_BC_VALUES:
641997e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
642097e99dd9SToby Isaac         const PetscInt    point = points[2*p];
642197e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
642297e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
64239566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
642497e99dd9SToby Isaac         updatePointBC_private(section, point, dof, add,  perm, flip, clperm, values, off, array);
6425304ab55fSMatthew G. Knepley       } break;
6426552f7358SJed Brown     default:
642798921bdaSJacob Faibussowitsch       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
6428552f7358SJed Brown     }
64299566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips));
6430552f7358SJed Brown   }
64311a271a75SMatthew G. Knepley   /* Cleanup points */
64329566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
64331a271a75SMatthew G. Knepley   /* Cleanup array */
64349566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
6435552f7358SJed Brown   PetscFunctionReturn(0);
6436552f7358SJed Brown }
6437552f7358SJed Brown 
64385f790a90SMatthew G. Knepley /* Check whether the given point is in the label. If not, update the offset to skip this point */
64399fbee547SJacob Faibussowitsch static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset)
64405f790a90SMatthew G. Knepley {
64415f790a90SMatthew G. Knepley   PetscFunctionBegin;
64425f790a90SMatthew G. Knepley   if (label) {
6443d6177c40SToby Isaac     PetscBool contains;
6444d6177c40SToby Isaac     PetscInt  fdof;
64455f790a90SMatthew G. Knepley 
6446d6177c40SToby Isaac     PetscCall(DMLabelStratumHasPoint(label, labelId, point, &contains));
6447d6177c40SToby Isaac     if (!contains) {
64489566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
64495f790a90SMatthew G. Knepley       *offset += fdof;
64505f790a90SMatthew G. Knepley       PetscFunctionReturn(1);
64515f790a90SMatthew G. Knepley     }
64525f790a90SMatthew G. Knepley   }
64535f790a90SMatthew G. Knepley   PetscFunctionReturn(0);
64545f790a90SMatthew G. Knepley }
64555f790a90SMatthew G. Knepley 
645697529cf3SJed Brown /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */
64575f790a90SMatthew 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)
6458e07394fbSMatthew G. Knepley {
6459e07394fbSMatthew G. Knepley   PetscSection    clSection;
6460e07394fbSMatthew G. Knepley   IS              clPoints;
6461e07394fbSMatthew G. Knepley   PetscScalar    *array;
6462e07394fbSMatthew G. Knepley   PetscInt       *points = NULL;
646397529cf3SJed Brown   const PetscInt *clp;
6464e07394fbSMatthew G. Knepley   PetscInt        numFields, numPoints, p;
646597e99dd9SToby Isaac   PetscInt        offset = 0, f;
6466e07394fbSMatthew G. Knepley 
6467e07394fbSMatthew G. Knepley   PetscFunctionBeginHot;
6468e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
64699566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
6470e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
6471e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
64729566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
6473e07394fbSMatthew G. Knepley   /* Get points */
64749566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
6475e07394fbSMatthew G. Knepley   /* Get array */
64769566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
6477e07394fbSMatthew G. Knepley   /* Get values */
6478e07394fbSMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
647997e99dd9SToby Isaac     const PetscInt    **perms = NULL;
648097e99dd9SToby Isaac     const PetscScalar **flips = NULL;
648197e99dd9SToby Isaac 
6482e07394fbSMatthew G. Knepley     if (!fieldActive[f]) {
6483e07394fbSMatthew G. Knepley       for (p = 0; p < numPoints*2; p += 2) {
6484e07394fbSMatthew G. Knepley         PetscInt fdof;
64859566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof));
6486e07394fbSMatthew G. Knepley         offset += fdof;
6487e07394fbSMatthew G. Knepley       }
6488e07394fbSMatthew G. Knepley       continue;
6489e07394fbSMatthew G. Knepley     }
64909566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips));
6491e07394fbSMatthew G. Knepley     switch (mode) {
6492e07394fbSMatthew G. Knepley     case INSERT_VALUES:
649397e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
649497e99dd9SToby Isaac         const PetscInt    point = points[2*p];
649597e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
649697e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
64975f80ce2aSJacob Faibussowitsch         if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue;
64989566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array));
6499e07394fbSMatthew G. Knepley       } break;
6500e07394fbSMatthew G. Knepley     case INSERT_ALL_VALUES:
650197e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
650297e99dd9SToby Isaac         const PetscInt    point = points[2*p];
650397e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
650497e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
65055f80ce2aSJacob Faibussowitsch         if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue;
65069566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array));
6507e07394fbSMatthew G. Knepley       } break;
6508e07394fbSMatthew G. Knepley     case INSERT_BC_VALUES:
650997e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
651097e99dd9SToby Isaac         const PetscInt    point = points[2*p];
651197e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
651297e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
65135f80ce2aSJacob Faibussowitsch         if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue;
65149566063dSJacob Faibussowitsch         PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array));
6515e07394fbSMatthew G. Knepley       } break;
6516e07394fbSMatthew G. Knepley     case ADD_VALUES:
651797e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
651897e99dd9SToby Isaac         const PetscInt    point = points[2*p];
651997e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
652097e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
65215f80ce2aSJacob Faibussowitsch         if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue;
65229566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array));
6523e07394fbSMatthew G. Knepley       } break;
6524e07394fbSMatthew G. Knepley     case ADD_ALL_VALUES:
652597e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
652697e99dd9SToby Isaac         const PetscInt    point = points[2*p];
652797e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
652897e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
65295f80ce2aSJacob Faibussowitsch         if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue;
65309566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array));
6531e07394fbSMatthew G. Knepley       } break;
6532e07394fbSMatthew G. Knepley     default:
653398921bdaSJacob Faibussowitsch       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
6534e07394fbSMatthew G. Knepley     }
65359566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips));
6536e07394fbSMatthew G. Knepley   }
6537e07394fbSMatthew G. Knepley   /* Cleanup points */
65389566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
6539e07394fbSMatthew G. Knepley   /* Cleanup array */
65409566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
6541e07394fbSMatthew G. Knepley   PetscFunctionReturn(0);
6542e07394fbSMatthew G. Knepley }
6543e07394fbSMatthew G. Knepley 
65447cd05799SMatthew G. Knepley static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[])
6545552f7358SJed Brown {
6546552f7358SJed Brown   PetscMPIInt    rank;
6547552f7358SJed Brown   PetscInt       i, j;
6548552f7358SJed Brown 
6549552f7358SJed Brown   PetscFunctionBegin;
65509566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
655163a3b9bcSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat for point %" PetscInt_FMT "\n", rank, point));
655263a3b9bcSJacob Faibussowitsch   for (i = 0; i < numRIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, rindices[i]));
655363a3b9bcSJacob Faibussowitsch   for (i = 0; i < numCIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, cindices[i]));
6554b0ecff45SMatthew G. Knepley   numCIndices = numCIndices ? numCIndices : numRIndices;
6555557cf195SMatthew G. Knepley   if (!values) PetscFunctionReturn(0);
6556b0ecff45SMatthew G. Knepley   for (i = 0; i < numRIndices; i++) {
65579566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]", rank));
6558b0ecff45SMatthew G. Knepley     for (j = 0; j < numCIndices; j++) {
6559519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX)
65609566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j])));
6561552f7358SJed Brown #else
65629566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j]));
6563552f7358SJed Brown #endif
6564552f7358SJed Brown     }
65659566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
6566552f7358SJed Brown   }
6567552f7358SJed Brown   PetscFunctionReturn(0);
6568552f7358SJed Brown }
6569552f7358SJed Brown 
657005586334SMatthew G. Knepley /*
657105586334SMatthew G. Knepley   DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array
657205586334SMatthew G. Knepley 
657305586334SMatthew G. Knepley   Input Parameters:
657405586334SMatthew G. Knepley + section - The section for this data layout
657536fa2b79SJed Brown . islocal - Is the section (and thus indices being requested) local or global?
657605586334SMatthew G. Knepley . point   - The point contributing dofs with these indices
657705586334SMatthew G. Knepley . off     - The global offset of this point
657805586334SMatthew G. Knepley . loff    - The local offset of each field
6579a5b23f4aSJose E. Roman . setBC   - The flag determining whether to include indices of boundary values
658005586334SMatthew G. Knepley . perm    - A permutation of the dofs on this point, or NULL
658105586334SMatthew G. Knepley - indperm - A permutation of the entire indices array, or NULL
658205586334SMatthew G. Knepley 
658305586334SMatthew G. Knepley   Output Parameter:
658405586334SMatthew G. Knepley . indices - Indices for dofs on this point
658505586334SMatthew G. Knepley 
658605586334SMatthew G. Knepley   Level: developer
658705586334SMatthew G. Knepley 
658805586334SMatthew G. Knepley   Note: The indices could be local or global, depending on the value of 'off'.
658905586334SMatthew G. Knepley */
659036fa2b79SJed Brown PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal,PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[])
6591a6dfd86eSKarl Rupp {
6592e6ccafaeSMatthew G Knepley   PetscInt        dof;   /* The number of unknowns on this point */
6593552f7358SJed Brown   PetscInt        cdof;  /* The number of constraints on this point */
6594552f7358SJed Brown   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6595552f7358SJed Brown   PetscInt        cind = 0, k;
6596552f7358SJed Brown 
6597552f7358SJed Brown   PetscFunctionBegin;
659808401ef6SPierre Jolivet   PetscCheck(islocal || !setBC,PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC");
65999566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(section, point, &dof));
66009566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
6601552f7358SJed Brown   if (!cdof || setBC) {
660205586334SMatthew G. Knepley     for (k = 0; k < dof; ++k) {
660305586334SMatthew G. Knepley       const PetscInt preind = perm ? *loff+perm[k] : *loff+k;
660405586334SMatthew G. Knepley       const PetscInt ind    = indperm ? indperm[preind] : preind;
660505586334SMatthew G. Knepley 
660605586334SMatthew G. Knepley       indices[ind] = off + k;
6607552f7358SJed Brown     }
6608552f7358SJed Brown   } else {
66099566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
66104acb8e1eSToby Isaac     for (k = 0; k < dof; ++k) {
661105586334SMatthew G. Knepley       const PetscInt preind = perm ? *loff+perm[k] : *loff+k;
661205586334SMatthew G. Knepley       const PetscInt ind    = indperm ? indperm[preind] : preind;
661305586334SMatthew G. Knepley 
66144acb8e1eSToby Isaac       if ((cind < cdof) && (k == cdofs[cind])) {
66154acb8e1eSToby Isaac         /* Insert check for returning constrained indices */
661605586334SMatthew G. Knepley         indices[ind] = -(off+k+1);
66174acb8e1eSToby Isaac         ++cind;
66184acb8e1eSToby Isaac       } else {
661936fa2b79SJed Brown         indices[ind] = off + k - (islocal ? 0 : cind);
6620552f7358SJed Brown       }
6621552f7358SJed Brown     }
6622552f7358SJed Brown   }
6623e6ccafaeSMatthew G Knepley   *loff += dof;
6624552f7358SJed Brown   PetscFunctionReturn(0);
6625552f7358SJed Brown }
6626552f7358SJed Brown 
66277e29afd2SMatthew G. Knepley /*
662836fa2b79SJed Brown  DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering.
66297e29afd2SMatthew G. Knepley 
663036fa2b79SJed Brown  Input Parameters:
663136fa2b79SJed Brown + section - a section (global or local)
663236fa2b79SJed Brown - islocal - PETSC_TRUE if requesting local indices (i.e., section is local); PETSC_FALSE for global
663336fa2b79SJed Brown . point - point within section
663436fa2b79SJed Brown . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section
663536fa2b79SJed Brown . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field
663636fa2b79SJed Brown . setBC - identify constrained (boundary condition) points via involution.
663736fa2b79SJed Brown . perms - perms[f][permsoff][:] is a permutation of dofs within each field
663836fa2b79SJed Brown . permsoff - offset
663936fa2b79SJed Brown - indperm - index permutation
664036fa2b79SJed Brown 
664136fa2b79SJed Brown  Output Parameter:
664236fa2b79SJed Brown . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field
664336fa2b79SJed Brown . indices - array to hold indices (as defined by section) of each dof associated with point
664436fa2b79SJed Brown 
664536fa2b79SJed Brown  Notes:
664636fa2b79SJed Brown  If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs.
664736fa2b79SJed Brown  If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position
664836fa2b79SJed Brown  in the local vector.
664936fa2b79SJed Brown 
665036fa2b79SJed Brown  If section is global and setBC=false, the indices for constrained points are negative (and their value is not
665136fa2b79SJed Brown  significant).  It is invalid to call with a global section and setBC=true.
665236fa2b79SJed Brown 
665336fa2b79SJed Brown  Developer Note:
665436fa2b79SJed Brown  The section is only used for field layout, so islocal is technically a statement about the offset (off).  At some point
665536fa2b79SJed Brown  in the future, global sections may have fields set, in which case we could pass the global section and obtain the
665636fa2b79SJed Brown  offset could be obtained from the section instead of passing it explicitly as we do now.
665736fa2b79SJed Brown 
665836fa2b79SJed Brown  Example:
665936fa2b79SJed Brown  Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}.
666036fa2b79SJed Brown  When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE).
666136fa2b79SJed Brown  Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices.
666236fa2b79SJed 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.
666336fa2b79SJed Brown 
666436fa2b79SJed Brown  Level: developer
66657e29afd2SMatthew G. Knepley */
666636fa2b79SJed 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[])
6667a6dfd86eSKarl Rupp {
6668552f7358SJed Brown   PetscInt       numFields, foff, f;
6669552f7358SJed Brown 
6670552f7358SJed Brown   PetscFunctionBegin;
667108401ef6SPierre Jolivet   PetscCheck(islocal || !setBC,PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC");
66729566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
6673552f7358SJed Brown   for (f = 0, foff = 0; f < numFields; ++f) {
66744acb8e1eSToby Isaac     PetscInt        fdof, cfdof;
6675552f7358SJed Brown     const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
66764acb8e1eSToby Isaac     PetscInt        cind = 0, b;
66774acb8e1eSToby Isaac     const PetscInt  *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL;
6678552f7358SJed Brown 
66799566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
66809566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof));
6681552f7358SJed Brown     if (!cfdof || setBC) {
668205586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
668305586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b;
668405586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
668505586334SMatthew G. Knepley 
668605586334SMatthew G. Knepley         indices[ind] = off+foff+b;
668705586334SMatthew G. Knepley       }
6688552f7358SJed Brown     } else {
66899566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
669005586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
669105586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b;
669205586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
669305586334SMatthew G. Knepley 
66944acb8e1eSToby Isaac         if ((cind < cfdof) && (b == fcdofs[cind])) {
669505586334SMatthew G. Knepley           indices[ind] = -(off+foff+b+1);
6696552f7358SJed Brown           ++cind;
6697552f7358SJed Brown         } else {
669836fa2b79SJed Brown           indices[ind] = off + foff + b - (islocal ? 0 : cind);
6699552f7358SJed Brown         }
6700552f7358SJed Brown       }
6701552f7358SJed Brown     }
670236fa2b79SJed Brown     foff     += (setBC || islocal ? fdof : (fdof - cfdof));
6703552f7358SJed Brown     foffs[f] += fdof;
6704552f7358SJed Brown   }
6705552f7358SJed Brown   PetscFunctionReturn(0);
6706552f7358SJed Brown }
6707552f7358SJed Brown 
67087e29afd2SMatthew G. Knepley /*
67097e29afd2SMatthew G. Knepley   This version believes the globalSection offsets for each field, rather than just the point offset
67107e29afd2SMatthew G. Knepley 
67117e29afd2SMatthew G. Knepley  . foffs - The offset into 'indices' for each field, since it is segregated by field
6712645102dcSJed Brown 
6713645102dcSJed Brown  Notes:
6714645102dcSJed Brown  The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal.
6715645102dcSJed Brown  Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists.
67167e29afd2SMatthew G. Knepley */
6717645102dcSJed Brown static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[])
67187e29afd2SMatthew G. Knepley {
67197e29afd2SMatthew G. Knepley   PetscInt       numFields, foff, f;
67207e29afd2SMatthew G. Knepley 
67217e29afd2SMatthew G. Knepley   PetscFunctionBegin;
67229566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
67237e29afd2SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
67247e29afd2SMatthew G. Knepley     PetscInt        fdof, cfdof;
67257e29afd2SMatthew G. Knepley     const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
67267e29afd2SMatthew G. Knepley     PetscInt        cind = 0, b;
67277e29afd2SMatthew G. Knepley     const PetscInt  *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL;
67287e29afd2SMatthew G. Knepley 
67299566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
67309566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof));
67319566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldOffset(globalSection, point, f, &foff));
6732645102dcSJed Brown     if (!cfdof) {
673305586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
673405586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b;
673505586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
673605586334SMatthew G. Knepley 
673705586334SMatthew G. Knepley         indices[ind] = foff+b;
673805586334SMatthew G. Knepley       }
67397e29afd2SMatthew G. Knepley     } else {
67409566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
674105586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
674205586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b;
674305586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
674405586334SMatthew G. Knepley 
67457e29afd2SMatthew G. Knepley         if ((cind < cfdof) && (b == fcdofs[cind])) {
674605586334SMatthew G. Knepley           indices[ind] = -(foff+b+1);
67477e29afd2SMatthew G. Knepley           ++cind;
67487e29afd2SMatthew G. Knepley         } else {
674905586334SMatthew G. Knepley           indices[ind] = foff+b-cind;
67507e29afd2SMatthew G. Knepley         }
67517e29afd2SMatthew G. Knepley       }
67527e29afd2SMatthew G. Knepley     }
67537e29afd2SMatthew G. Knepley     foffs[f] += fdof;
67547e29afd2SMatthew G. Knepley   }
67557e29afd2SMatthew G. Knepley   PetscFunctionReturn(0);
67567e29afd2SMatthew G. Knepley }
67577e29afd2SMatthew G. Knepley 
67584acb8e1eSToby 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)
6759d3d1a6afSToby Isaac {
6760d3d1a6afSToby Isaac   Mat             cMat;
6761d3d1a6afSToby Isaac   PetscSection    aSec, cSec;
6762d3d1a6afSToby Isaac   IS              aIS;
6763d3d1a6afSToby Isaac   PetscInt        aStart = -1, aEnd = -1;
6764d3d1a6afSToby Isaac   const PetscInt  *anchors;
6765e17c06e0SMatthew G. Knepley   PetscInt        numFields, f, p, q, newP = 0;
6766d3d1a6afSToby Isaac   PetscInt        newNumPoints = 0, newNumIndices = 0;
6767d3d1a6afSToby Isaac   PetscInt        *newPoints, *indices, *newIndices;
6768d3d1a6afSToby Isaac   PetscInt        maxAnchor, maxDof;
6769d3d1a6afSToby Isaac   PetscInt        newOffsets[32];
6770d3d1a6afSToby Isaac   PetscInt        *pointMatOffsets[32];
6771d3d1a6afSToby Isaac   PetscInt        *newPointOffsets[32];
6772d3d1a6afSToby Isaac   PetscScalar     *pointMat[32];
67736ecaa68aSToby Isaac   PetscScalar     *newValues=NULL,*tmpValues;
6774d3d1a6afSToby Isaac   PetscBool       anyConstrained = PETSC_FALSE;
6775d3d1a6afSToby Isaac 
6776d3d1a6afSToby Isaac   PetscFunctionBegin;
6777d3d1a6afSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6778d3d1a6afSToby Isaac   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
67799566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
6780d3d1a6afSToby Isaac 
67819566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm,&aSec,&aIS));
6782d3d1a6afSToby Isaac   /* if there are point-to-point constraints */
6783d3d1a6afSToby Isaac   if (aSec) {
67849566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(newOffsets, 32));
67859566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(aIS,&anchors));
67869566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(aSec,&aStart,&aEnd));
6787d3d1a6afSToby Isaac     /* figure out how many points are going to be in the new element matrix
6788d3d1a6afSToby Isaac      * (we allow double counting, because it's all just going to be summed
6789d3d1a6afSToby Isaac      * into the global matrix anyway) */
6790d3d1a6afSToby Isaac     for (p = 0; p < 2*numPoints; p+=2) {
6791d3d1a6afSToby Isaac       PetscInt b    = points[p];
67924b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
6793d3d1a6afSToby Isaac 
67949566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section,b,&bSecDof));
67954b2f2278SToby Isaac       if (!bSecDof) {
67964b2f2278SToby Isaac         continue;
67974b2f2278SToby Isaac       }
6798d3d1a6afSToby Isaac       if (b >= aStart && b < aEnd) {
67999566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(aSec,b,&bDof));
6800d3d1a6afSToby Isaac       }
6801d3d1a6afSToby Isaac       if (bDof) {
6802d3d1a6afSToby Isaac         /* this point is constrained */
6803d3d1a6afSToby Isaac         /* it is going to be replaced by its anchors */
6804d3d1a6afSToby Isaac         PetscInt bOff, q;
6805d3d1a6afSToby Isaac 
6806d3d1a6afSToby Isaac         anyConstrained = PETSC_TRUE;
6807d3d1a6afSToby Isaac         newNumPoints  += bDof;
68089566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec,b,&bOff));
6809d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
6810d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q];
6811d3d1a6afSToby Isaac           PetscInt aDof;
6812d3d1a6afSToby Isaac 
68139566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section,a,&aDof));
6814d3d1a6afSToby Isaac           newNumIndices += aDof;
6815d3d1a6afSToby Isaac           for (f = 0; f < numFields; ++f) {
6816d3d1a6afSToby Isaac             PetscInt fDof;
6817d3d1a6afSToby Isaac 
68189566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, a, f, &fDof));
6819d3d1a6afSToby Isaac             newOffsets[f+1] += fDof;
6820d3d1a6afSToby Isaac           }
6821d3d1a6afSToby Isaac         }
6822d3d1a6afSToby Isaac       }
6823d3d1a6afSToby Isaac       else {
6824d3d1a6afSToby Isaac         /* this point is not constrained */
6825d3d1a6afSToby Isaac         newNumPoints++;
68264b2f2278SToby Isaac         newNumIndices += bSecDof;
6827d3d1a6afSToby Isaac         for (f = 0; f < numFields; ++f) {
6828d3d1a6afSToby Isaac           PetscInt fDof;
6829d3d1a6afSToby Isaac 
68309566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
6831d3d1a6afSToby Isaac           newOffsets[f+1] += fDof;
6832d3d1a6afSToby Isaac         }
6833d3d1a6afSToby Isaac       }
6834d3d1a6afSToby Isaac     }
6835d3d1a6afSToby Isaac   }
6836d3d1a6afSToby Isaac   if (!anyConstrained) {
683772b80496SMatthew G. Knepley     if (outNumPoints)  *outNumPoints  = 0;
683872b80496SMatthew G. Knepley     if (outNumIndices) *outNumIndices = 0;
683972b80496SMatthew G. Knepley     if (outPoints)     *outPoints     = NULL;
684072b80496SMatthew G. Knepley     if (outValues)     *outValues     = NULL;
68419566063dSJacob Faibussowitsch     if (aSec) PetscCall(ISRestoreIndices(aIS,&anchors));
6842d3d1a6afSToby Isaac     PetscFunctionReturn(0);
6843d3d1a6afSToby Isaac   }
6844d3d1a6afSToby Isaac 
68456ecaa68aSToby Isaac   if (outNumPoints)  *outNumPoints  = newNumPoints;
68466ecaa68aSToby Isaac   if (outNumIndices) *outNumIndices = newNumIndices;
68476ecaa68aSToby Isaac 
6848f13f9184SToby Isaac   for (f = 0; f < numFields; ++f) newOffsets[f+1] += newOffsets[f];
6849d3d1a6afSToby Isaac 
68506ecaa68aSToby Isaac   if (!outPoints && !outValues) {
68516ecaa68aSToby Isaac     if (offsets) {
68526ecaa68aSToby Isaac       for (f = 0; f <= numFields; f++) {
68536ecaa68aSToby Isaac         offsets[f] = newOffsets[f];
68546ecaa68aSToby Isaac       }
68556ecaa68aSToby Isaac     }
68569566063dSJacob Faibussowitsch     if (aSec) PetscCall(ISRestoreIndices(aIS,&anchors));
68576ecaa68aSToby Isaac     PetscFunctionReturn(0);
68586ecaa68aSToby Isaac   }
68596ecaa68aSToby Isaac 
68601dca8a05SBarry Smith   PetscCheck(!numFields || newOffsets[numFields] == newNumIndices,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %" PetscInt_FMT " should be %" PetscInt_FMT, newOffsets[numFields], newNumIndices);
6861d3d1a6afSToby Isaac 
68629566063dSJacob Faibussowitsch   PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, NULL));
6863d3d1a6afSToby Isaac 
6864d3d1a6afSToby Isaac   /* workspaces */
6865d3d1a6afSToby Isaac   if (numFields) {
6866d3d1a6afSToby Isaac     for (f = 0; f < numFields; f++) {
68679566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]));
68689566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]));
6869d3d1a6afSToby Isaac     }
6870d3d1a6afSToby Isaac   }
6871d3d1a6afSToby Isaac   else {
68729566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]));
68739566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm,numPoints,MPIU_INT,&newPointOffsets[0]));
6874d3d1a6afSToby Isaac   }
6875d3d1a6afSToby Isaac 
6876d3d1a6afSToby Isaac   /* get workspaces for the point-to-point matrices */
6877d3d1a6afSToby Isaac   if (numFields) {
68784b2f2278SToby Isaac     PetscInt totalOffset, totalMatOffset;
68794b2f2278SToby Isaac 
6880d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
6881d3d1a6afSToby Isaac       PetscInt b    = points[2*p];
68824b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
6883d3d1a6afSToby Isaac 
68849566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section,b,&bSecDof));
68854b2f2278SToby Isaac       if (!bSecDof) {
68864b2f2278SToby Isaac         for (f = 0; f < numFields; f++) {
68874b2f2278SToby Isaac           newPointOffsets[f][p + 1] = 0;
68884b2f2278SToby Isaac           pointMatOffsets[f][p + 1] = 0;
68894b2f2278SToby Isaac         }
68904b2f2278SToby Isaac         continue;
68914b2f2278SToby Isaac       }
6892d3d1a6afSToby Isaac       if (b >= aStart && b < aEnd) {
68939566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(aSec, b, &bDof));
6894d3d1a6afSToby Isaac       }
6895d3d1a6afSToby Isaac       if (bDof) {
6896d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
6897d3d1a6afSToby Isaac           PetscInt fDof, q, bOff, allFDof = 0;
6898d3d1a6afSToby Isaac 
68999566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
69009566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
6901d3d1a6afSToby Isaac           for (q = 0; q < bDof; q++) {
6902d3d1a6afSToby Isaac             PetscInt a = anchors[bOff + q];
6903d3d1a6afSToby Isaac             PetscInt aFDof;
6904d3d1a6afSToby Isaac 
69059566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, a, f, &aFDof));
6906d3d1a6afSToby Isaac             allFDof += aFDof;
6907d3d1a6afSToby Isaac           }
6908d3d1a6afSToby Isaac           newPointOffsets[f][p+1] = allFDof;
6909d3d1a6afSToby Isaac           pointMatOffsets[f][p+1] = fDof * allFDof;
6910d3d1a6afSToby Isaac         }
6911d3d1a6afSToby Isaac       }
6912d3d1a6afSToby Isaac       else {
6913d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
6914d3d1a6afSToby Isaac           PetscInt fDof;
6915d3d1a6afSToby Isaac 
69169566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
6917d3d1a6afSToby Isaac           newPointOffsets[f][p+1] = fDof;
6918d3d1a6afSToby Isaac           pointMatOffsets[f][p+1] = 0;
6919d3d1a6afSToby Isaac         }
6920d3d1a6afSToby Isaac       }
6921d3d1a6afSToby Isaac     }
69224b2f2278SToby Isaac     for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) {
69234b2f2278SToby Isaac       newPointOffsets[f][0] = totalOffset;
69244b2f2278SToby Isaac       pointMatOffsets[f][0] = totalMatOffset;
6925d3d1a6afSToby Isaac       for (p = 0; p < numPoints; p++) {
6926d3d1a6afSToby Isaac         newPointOffsets[f][p+1] += newPointOffsets[f][p];
6927d3d1a6afSToby Isaac         pointMatOffsets[f][p+1] += pointMatOffsets[f][p];
6928d3d1a6afSToby Isaac       }
692919f70fd5SToby Isaac       totalOffset    = newPointOffsets[f][numPoints];
693019f70fd5SToby Isaac       totalMatOffset = pointMatOffsets[f][numPoints];
69319566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]));
6932d3d1a6afSToby Isaac     }
6933d3d1a6afSToby Isaac   }
6934d3d1a6afSToby Isaac   else {
6935d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
6936d3d1a6afSToby Isaac       PetscInt b    = points[2*p];
69374b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
6938d3d1a6afSToby Isaac 
69399566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section,b,&bSecDof));
69404b2f2278SToby Isaac       if (!bSecDof) {
69414b2f2278SToby Isaac         newPointOffsets[0][p + 1] = 0;
69424b2f2278SToby Isaac         pointMatOffsets[0][p + 1] = 0;
69434b2f2278SToby Isaac         continue;
69444b2f2278SToby Isaac       }
6945d3d1a6afSToby Isaac       if (b >= aStart && b < aEnd) {
69469566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(aSec, b, &bDof));
6947d3d1a6afSToby Isaac       }
6948d3d1a6afSToby Isaac       if (bDof) {
69494b2f2278SToby Isaac         PetscInt bOff, q, allDof = 0;
6950d3d1a6afSToby Isaac 
69519566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
6952d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
6953d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aDof;
6954d3d1a6afSToby Isaac 
69559566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section, a, &aDof));
6956d3d1a6afSToby Isaac           allDof += aDof;
6957d3d1a6afSToby Isaac         }
6958d3d1a6afSToby Isaac         newPointOffsets[0][p+1] = allDof;
69594b2f2278SToby Isaac         pointMatOffsets[0][p+1] = bSecDof * allDof;
6960d3d1a6afSToby Isaac       }
6961d3d1a6afSToby Isaac       else {
69624b2f2278SToby Isaac         newPointOffsets[0][p+1] = bSecDof;
6963d3d1a6afSToby Isaac         pointMatOffsets[0][p+1] = 0;
6964d3d1a6afSToby Isaac       }
6965d3d1a6afSToby Isaac     }
6966d3d1a6afSToby Isaac     newPointOffsets[0][0] = 0;
6967d3d1a6afSToby Isaac     pointMatOffsets[0][0] = 0;
6968d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
6969d3d1a6afSToby Isaac       newPointOffsets[0][p+1] += newPointOffsets[0][p];
6970d3d1a6afSToby Isaac       pointMatOffsets[0][p+1] += pointMatOffsets[0][p];
6971d3d1a6afSToby Isaac     }
69729566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]));
6973d3d1a6afSToby Isaac   }
6974d3d1a6afSToby Isaac 
69756ecaa68aSToby Isaac   /* output arrays */
69769566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints));
69776ecaa68aSToby Isaac 
6978d3d1a6afSToby Isaac   /* get the point-to-point matrices; construct newPoints */
69799566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetMaxDof(aSec, &maxAnchor));
69809566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetMaxDof(section, &maxDof));
69819566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm,maxDof,MPIU_INT,&indices));
69829566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices));
6983d3d1a6afSToby Isaac   if (numFields) {
6984d3d1a6afSToby Isaac     for (p = 0, newP = 0; p < numPoints; p++) {
6985d3d1a6afSToby Isaac       PetscInt b    = points[2*p];
6986d3d1a6afSToby Isaac       PetscInt o    = points[2*p+1];
69874b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
6988d3d1a6afSToby Isaac 
69899566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
69904b2f2278SToby Isaac       if (!bSecDof) {
69914b2f2278SToby Isaac         continue;
69924b2f2278SToby Isaac       }
6993d3d1a6afSToby Isaac       if (b >= aStart && b < aEnd) {
69949566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(aSec, b, &bDof));
6995d3d1a6afSToby Isaac       }
6996d3d1a6afSToby Isaac       if (bDof) {
6997d3d1a6afSToby Isaac         PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q;
6998d3d1a6afSToby Isaac 
6999d3d1a6afSToby Isaac         fStart[0] = 0;
7000d3d1a6afSToby Isaac         fEnd[0]   = 0;
7001d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7002d3d1a6afSToby Isaac           PetscInt fDof;
7003d3d1a6afSToby Isaac 
70049566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(cSec, b, f, &fDof));
7005d3d1a6afSToby Isaac           fStart[f+1] = fStart[f] + fDof;
7006d3d1a6afSToby Isaac           fEnd[f+1]   = fStart[f+1];
7007d3d1a6afSToby Isaac         }
70089566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(cSec, b, &bOff));
70099566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices));
7010d3d1a6afSToby Isaac 
7011d3d1a6afSToby Isaac         fAnchorStart[0] = 0;
7012d3d1a6afSToby Isaac         fAnchorEnd[0]   = 0;
7013d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7014d3d1a6afSToby Isaac           PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p];
7015d3d1a6afSToby Isaac 
7016d3d1a6afSToby Isaac           fAnchorStart[f+1] = fAnchorStart[f] + fDof;
7017d3d1a6afSToby Isaac           fAnchorEnd[f+1]   = fAnchorStart[f + 1];
7018d3d1a6afSToby Isaac         }
70199566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7020d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7021d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aOff;
7022d3d1a6afSToby Isaac 
7023d3d1a6afSToby 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 */
7024d3d1a6afSToby Isaac           newPoints[2*(newP + q)]     = a;
7025d3d1a6afSToby Isaac           newPoints[2*(newP + q) + 1] = 0;
70269566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(section, a, &aOff));
70279566063dSJacob Faibussowitsch           PetscCall(DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices));
7028d3d1a6afSToby Isaac         }
7029d3d1a6afSToby Isaac         newP += bDof;
7030d3d1a6afSToby Isaac 
70316ecaa68aSToby Isaac         if (outValues) {
7032d3d1a6afSToby Isaac           /* get the point-to-point submatrix */
7033d3d1a6afSToby Isaac           for (f = 0; f < numFields; f++) {
70349566063dSJacob Faibussowitsch             PetscCall(MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p]));
7035d3d1a6afSToby Isaac           }
7036d3d1a6afSToby Isaac         }
70376ecaa68aSToby Isaac       }
7038d3d1a6afSToby Isaac       else {
7039d3d1a6afSToby Isaac         newPoints[2 * newP]     = b;
7040d3d1a6afSToby Isaac         newPoints[2 * newP + 1] = o;
7041d3d1a6afSToby Isaac         newP++;
7042d3d1a6afSToby Isaac       }
7043d3d1a6afSToby Isaac     }
7044d3d1a6afSToby Isaac   } else {
7045d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
7046d3d1a6afSToby Isaac       PetscInt b    = points[2*p];
7047d3d1a6afSToby Isaac       PetscInt o    = points[2*p+1];
70484b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7049d3d1a6afSToby Isaac 
70509566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
70514b2f2278SToby Isaac       if (!bSecDof) {
70524b2f2278SToby Isaac         continue;
70534b2f2278SToby Isaac       }
7054d3d1a6afSToby Isaac       if (b >= aStart && b < aEnd) {
70559566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7056d3d1a6afSToby Isaac       }
7057d3d1a6afSToby Isaac       if (bDof) {
7058d3d1a6afSToby Isaac         PetscInt bEnd = 0, bAnchorEnd = 0, bOff;
7059d3d1a6afSToby Isaac 
70609566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(cSec, b, &bOff));
70619566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices));
7062d3d1a6afSToby Isaac 
70639566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset (aSec, b, &bOff));
7064d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7065d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aOff;
7066d3d1a6afSToby Isaac 
7067d3d1a6afSToby 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 */
7068d3d1a6afSToby Isaac 
7069d3d1a6afSToby Isaac           newPoints[2*(newP + q)]     = a;
7070d3d1a6afSToby Isaac           newPoints[2*(newP + q) + 1] = 0;
70719566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(section, a, &aOff));
70729566063dSJacob Faibussowitsch           PetscCall(DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices));
7073d3d1a6afSToby Isaac         }
7074d3d1a6afSToby Isaac         newP += bDof;
7075d3d1a6afSToby Isaac 
7076d3d1a6afSToby Isaac         /* get the point-to-point submatrix */
70776ecaa68aSToby Isaac         if (outValues) {
70789566063dSJacob Faibussowitsch           PetscCall(MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p]));
7079d3d1a6afSToby Isaac         }
70806ecaa68aSToby Isaac       }
7081d3d1a6afSToby Isaac       else {
7082d3d1a6afSToby Isaac         newPoints[2 * newP]     = b;
7083d3d1a6afSToby Isaac         newPoints[2 * newP + 1] = o;
7084d3d1a6afSToby Isaac         newP++;
7085d3d1a6afSToby Isaac       }
7086d3d1a6afSToby Isaac     }
7087d3d1a6afSToby Isaac   }
7088d3d1a6afSToby Isaac 
70896ecaa68aSToby Isaac   if (outValues) {
70909566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues));
70919566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(tmpValues,newNumIndices*numIndices));
7092d3d1a6afSToby Isaac     /* multiply constraints on the right */
7093d3d1a6afSToby Isaac     if (numFields) {
7094d3d1a6afSToby Isaac       for (f = 0; f < numFields; f++) {
7095d3d1a6afSToby Isaac         PetscInt oldOff = offsets[f];
7096d3d1a6afSToby Isaac 
7097d3d1a6afSToby Isaac         for (p = 0; p < numPoints; p++) {
7098d3d1a6afSToby Isaac           PetscInt cStart = newPointOffsets[f][p];
7099d3d1a6afSToby Isaac           PetscInt b      = points[2 * p];
7100d3d1a6afSToby Isaac           PetscInt c, r, k;
7101d3d1a6afSToby Isaac           PetscInt dof;
7102d3d1a6afSToby Isaac 
71039566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section,b,f,&dof));
71044b2f2278SToby Isaac           if (!dof) {
71054b2f2278SToby Isaac             continue;
71064b2f2278SToby Isaac           }
7107d3d1a6afSToby Isaac           if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) {
7108d3d1a6afSToby Isaac             PetscInt nCols         = newPointOffsets[f][p+1]-cStart;
7109d3d1a6afSToby Isaac             const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p];
7110d3d1a6afSToby Isaac 
7111d3d1a6afSToby Isaac             for (r = 0; r < numIndices; r++) {
7112d3d1a6afSToby Isaac               for (c = 0; c < nCols; c++) {
7113d3d1a6afSToby Isaac                 for (k = 0; k < dof; k++) {
71144acb8e1eSToby Isaac                   tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c];
7115d3d1a6afSToby Isaac                 }
7116d3d1a6afSToby Isaac               }
7117d3d1a6afSToby Isaac             }
7118d3d1a6afSToby Isaac           }
7119d3d1a6afSToby Isaac           else {
7120d3d1a6afSToby Isaac             /* copy this column as is */
7121d3d1a6afSToby Isaac             for (r = 0; r < numIndices; r++) {
7122d3d1a6afSToby Isaac               for (c = 0; c < dof; c++) {
7123d3d1a6afSToby Isaac                 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c];
7124d3d1a6afSToby Isaac               }
7125d3d1a6afSToby Isaac             }
7126d3d1a6afSToby Isaac           }
7127d3d1a6afSToby Isaac           oldOff += dof;
7128d3d1a6afSToby Isaac         }
7129d3d1a6afSToby Isaac       }
7130d3d1a6afSToby Isaac     }
7131d3d1a6afSToby Isaac     else {
7132d3d1a6afSToby Isaac       PetscInt oldOff = 0;
7133d3d1a6afSToby Isaac       for (p = 0; p < numPoints; p++) {
7134d3d1a6afSToby Isaac         PetscInt cStart = newPointOffsets[0][p];
7135d3d1a6afSToby Isaac         PetscInt b      = points[2 * p];
7136d3d1a6afSToby Isaac         PetscInt c, r, k;
7137d3d1a6afSToby Isaac         PetscInt dof;
7138d3d1a6afSToby Isaac 
71399566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section,b,&dof));
71404b2f2278SToby Isaac         if (!dof) {
71414b2f2278SToby Isaac           continue;
71424b2f2278SToby Isaac         }
7143d3d1a6afSToby Isaac         if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) {
7144d3d1a6afSToby Isaac           PetscInt nCols         = newPointOffsets[0][p+1]-cStart;
7145d3d1a6afSToby Isaac           const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p];
7146d3d1a6afSToby Isaac 
7147d3d1a6afSToby Isaac           for (r = 0; r < numIndices; r++) {
7148d3d1a6afSToby Isaac             for (c = 0; c < nCols; c++) {
7149d3d1a6afSToby Isaac               for (k = 0; k < dof; k++) {
7150d3d1a6afSToby Isaac                 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k];
7151d3d1a6afSToby Isaac               }
7152d3d1a6afSToby Isaac             }
7153d3d1a6afSToby Isaac           }
7154d3d1a6afSToby Isaac         }
7155d3d1a6afSToby Isaac         else {
7156d3d1a6afSToby Isaac           /* copy this column as is */
7157d3d1a6afSToby Isaac           for (r = 0; r < numIndices; r++) {
7158d3d1a6afSToby Isaac             for (c = 0; c < dof; c++) {
7159d3d1a6afSToby Isaac               tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c];
7160d3d1a6afSToby Isaac             }
7161d3d1a6afSToby Isaac           }
7162d3d1a6afSToby Isaac         }
7163d3d1a6afSToby Isaac         oldOff += dof;
7164d3d1a6afSToby Isaac       }
7165d3d1a6afSToby Isaac     }
7166d3d1a6afSToby Isaac 
71676ecaa68aSToby Isaac     if (multiplyLeft) {
71689566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm,newNumIndices*newNumIndices,MPIU_SCALAR,&newValues));
71699566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(newValues,newNumIndices*newNumIndices));
7170d3d1a6afSToby Isaac       /* multiply constraints transpose on the left */
7171d3d1a6afSToby Isaac       if (numFields) {
7172d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7173d3d1a6afSToby Isaac           PetscInt oldOff = offsets[f];
7174d3d1a6afSToby Isaac 
7175d3d1a6afSToby Isaac           for (p = 0; p < numPoints; p++) {
7176d3d1a6afSToby Isaac             PetscInt rStart = newPointOffsets[f][p];
7177d3d1a6afSToby Isaac             PetscInt b      = points[2 * p];
7178d3d1a6afSToby Isaac             PetscInt c, r, k;
7179d3d1a6afSToby Isaac             PetscInt dof;
7180d3d1a6afSToby Isaac 
71819566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section,b,f,&dof));
7182d3d1a6afSToby Isaac             if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) {
7183d3d1a6afSToby Isaac               PetscInt nRows                        = newPointOffsets[f][p+1]-rStart;
7184d3d1a6afSToby Isaac               const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p];
7185d3d1a6afSToby Isaac 
7186d3d1a6afSToby Isaac               for (r = 0; r < nRows; r++) {
7187d3d1a6afSToby Isaac                 for (c = 0; c < newNumIndices; c++) {
7188d3d1a6afSToby Isaac                   for (k = 0; k < dof; k++) {
7189d3d1a6afSToby Isaac                     newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c];
7190d3d1a6afSToby Isaac                   }
7191d3d1a6afSToby Isaac                 }
7192d3d1a6afSToby Isaac               }
7193d3d1a6afSToby Isaac             }
7194d3d1a6afSToby Isaac             else {
7195d3d1a6afSToby Isaac               /* copy this row as is */
7196d3d1a6afSToby Isaac               for (r = 0; r < dof; r++) {
7197d3d1a6afSToby Isaac                 for (c = 0; c < newNumIndices; c++) {
7198d3d1a6afSToby Isaac                   newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c];
7199d3d1a6afSToby Isaac                 }
7200d3d1a6afSToby Isaac               }
7201d3d1a6afSToby Isaac             }
7202d3d1a6afSToby Isaac             oldOff += dof;
7203d3d1a6afSToby Isaac           }
7204d3d1a6afSToby Isaac         }
7205d3d1a6afSToby Isaac       }
7206d3d1a6afSToby Isaac       else {
7207d3d1a6afSToby Isaac         PetscInt oldOff = 0;
7208d3d1a6afSToby Isaac 
7209d3d1a6afSToby Isaac         for (p = 0; p < numPoints; p++) {
7210d3d1a6afSToby Isaac           PetscInt rStart = newPointOffsets[0][p];
7211d3d1a6afSToby Isaac           PetscInt b      = points[2 * p];
7212d3d1a6afSToby Isaac           PetscInt c, r, k;
7213d3d1a6afSToby Isaac           PetscInt dof;
7214d3d1a6afSToby Isaac 
72159566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section,b,&dof));
7216d3d1a6afSToby Isaac           if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) {
7217d3d1a6afSToby Isaac             PetscInt nRows                        = newPointOffsets[0][p+1]-rStart;
7218d3d1a6afSToby Isaac             const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p];
7219d3d1a6afSToby Isaac 
7220d3d1a6afSToby Isaac             for (r = 0; r < nRows; r++) {
7221d3d1a6afSToby Isaac               for (c = 0; c < newNumIndices; c++) {
7222d3d1a6afSToby Isaac                 for (k = 0; k < dof; k++) {
7223d3d1a6afSToby Isaac                   newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c];
7224d3d1a6afSToby Isaac                 }
7225d3d1a6afSToby Isaac               }
7226d3d1a6afSToby Isaac             }
7227d3d1a6afSToby Isaac           }
7228d3d1a6afSToby Isaac           else {
7229d3d1a6afSToby Isaac             /* copy this row as is */
72309fc93327SToby Isaac             for (r = 0; r < dof; r++) {
7231d3d1a6afSToby Isaac               for (c = 0; c < newNumIndices; c++) {
7232d3d1a6afSToby Isaac                 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c];
7233d3d1a6afSToby Isaac               }
7234d3d1a6afSToby Isaac             }
7235d3d1a6afSToby Isaac           }
7236d3d1a6afSToby Isaac           oldOff += dof;
7237d3d1a6afSToby Isaac         }
7238d3d1a6afSToby Isaac       }
7239d3d1a6afSToby Isaac 
72409566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues));
72416ecaa68aSToby Isaac     }
72426ecaa68aSToby Isaac     else {
72436ecaa68aSToby Isaac       newValues = tmpValues;
72446ecaa68aSToby Isaac     }
72456ecaa68aSToby Isaac   }
72466ecaa68aSToby Isaac 
7247d3d1a6afSToby Isaac   /* clean up */
72489566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm,maxDof,MPIU_INT,&indices));
72499566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices));
72506ecaa68aSToby Isaac 
7251d3d1a6afSToby Isaac   if (numFields) {
7252d3d1a6afSToby Isaac     for (f = 0; f < numFields; f++) {
72539566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]));
72549566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]));
72559566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]));
7256d3d1a6afSToby Isaac     }
7257d3d1a6afSToby Isaac   }
7258d3d1a6afSToby Isaac   else {
72599566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]));
72609566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]));
72619566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[0]));
7262d3d1a6afSToby Isaac   }
72639566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(aIS,&anchors));
7264d3d1a6afSToby Isaac 
7265d3d1a6afSToby Isaac   /* output */
72666ecaa68aSToby Isaac   if (outPoints) {
7267d3d1a6afSToby Isaac     *outPoints = newPoints;
72686ecaa68aSToby Isaac   }
72696ecaa68aSToby Isaac   else {
72709566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints));
72716ecaa68aSToby Isaac   }
727231620726SToby Isaac   if (outValues) {
7273d3d1a6afSToby Isaac     *outValues = newValues;
72746ecaa68aSToby Isaac   }
72756ecaa68aSToby Isaac   for (f = 0; f <= numFields; f++) {
7276d3d1a6afSToby Isaac     offsets[f] = newOffsets[f];
7277d3d1a6afSToby Isaac   }
7278d3d1a6afSToby Isaac   PetscFunctionReturn(0);
7279d3d1a6afSToby Isaac }
7280d3d1a6afSToby Isaac 
72814a1e0b3eSMatthew G. Knepley /*@C
728271f0bbf9SMatthew G. Knepley   DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections.
72837cd05799SMatthew G. Knepley 
72847cd05799SMatthew G. Knepley   Not collective
72857cd05799SMatthew G. Knepley 
72867cd05799SMatthew G. Knepley   Input Parameters:
72877cd05799SMatthew G. Knepley + dm         - The DM
728871f0bbf9SMatthew G. Knepley . section    - The PetscSection describing the points (a local section)
728971f0bbf9SMatthew G. Knepley . idxSection - The PetscSection from which to obtain indices (may be local or global)
729071f0bbf9SMatthew G. Knepley . point      - The point defining the closure
729171f0bbf9SMatthew G. Knepley - useClPerm  - Use the closure point permutation if available
72927cd05799SMatthew G. Knepley 
729371f0bbf9SMatthew G. Knepley   Output Parameters:
729471f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections
729571f0bbf9SMatthew G. Knepley . indices    - The dof indices
729671f0bbf9SMatthew G. Knepley . outOffsets - Array to write the field offsets into, or NULL
729771f0bbf9SMatthew G. Knepley - values     - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL
72987cd05799SMatthew G. Knepley 
729936fa2b79SJed Brown   Notes:
730036fa2b79SJed Brown   Must call DMPlexRestoreClosureIndices() to free allocated memory
730136fa2b79SJed Brown 
730236fa2b79SJed Brown   If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices.  The value
730336fa2b79SJed Brown   of those indices is not significant.  If idxSection is local, the constrained dofs will yield the involution -(idx+1)
730436fa2b79SJed Brown   of their index in a local vector.  A caller who does not wish to distinguish those points may recover the nonnegative
730536fa2b79SJed Brown   indices via involution, -(-(idx+1)+1)==idx.  Local indices are provided when idxSection == section, otherwise global
730636fa2b79SJed Brown   indices (with the above semantics) are implied.
73077cd05799SMatthew G. Knepley 
73087cd05799SMatthew G. Knepley   Level: advanced
73097cd05799SMatthew G. Knepley 
7310db781477SPatrick Sanan .seealso `DMPlexRestoreClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()`
73114a1e0b3eSMatthew G. Knepley @*/
731271f0bbf9SMatthew G. Knepley PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm,
731371f0bbf9SMatthew G. Knepley                                        PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[])
73147773e69fSMatthew G. Knepley {
731571f0bbf9SMatthew G. Knepley   /* Closure ordering */
73167773e69fSMatthew G. Knepley   PetscSection        clSection;
73177773e69fSMatthew G. Knepley   IS                  clPoints;
731871f0bbf9SMatthew G. Knepley   const PetscInt     *clp;
731971f0bbf9SMatthew G. Knepley   PetscInt           *points;
732071f0bbf9SMatthew G. Knepley   const PetscInt     *clperm = NULL;
732171f0bbf9SMatthew G. Knepley   /* Dof permutation and sign flips */
73224acb8e1eSToby Isaac   const PetscInt    **perms[32] = {NULL};
732371f0bbf9SMatthew G. Knepley   const PetscScalar **flips[32] = {NULL};
732471f0bbf9SMatthew G. Knepley   PetscScalar        *valCopy   = NULL;
732571f0bbf9SMatthew G. Knepley   /* Hanging node constraints */
732671f0bbf9SMatthew G. Knepley   PetscInt           *pointsC = NULL;
732771f0bbf9SMatthew G. Knepley   PetscScalar        *valuesC = NULL;
732871f0bbf9SMatthew G. Knepley   PetscInt            NclC, NiC;
732971f0bbf9SMatthew G. Knepley 
733071f0bbf9SMatthew G. Knepley   PetscInt           *idx;
733171f0bbf9SMatthew G. Knepley   PetscInt            Nf, Ncl, Ni = 0, offsets[32], p, f;
733271f0bbf9SMatthew G. Knepley   PetscBool           isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE;
73337773e69fSMatthew G. Knepley 
733471f0bbf9SMatthew G. Knepley   PetscFunctionBeginHot;
73357773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
73367773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
733736fa2b79SJed Brown   PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3);
7338dadcf809SJacob Faibussowitsch   if (numIndices) PetscValidIntPointer(numIndices, 6);
733971f0bbf9SMatthew G. Knepley   if (indices)    PetscValidPointer(indices, 7);
7340dadcf809SJacob Faibussowitsch   if (outOffsets) PetscValidIntPointer(outOffsets, 8);
734171f0bbf9SMatthew G. Knepley   if (values)     PetscValidPointer(values, 9);
73429566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &Nf));
734363a3b9bcSJacob Faibussowitsch   PetscCheck(Nf <= 31,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", Nf);
73449566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(offsets, 32));
734571f0bbf9SMatthew G. Knepley   /* 1) Get points in closure */
73469566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
7347c459fbc1SJed Brown   if (useClPerm) {
7348c459fbc1SJed Brown     PetscInt depth, clsize;
73499566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPointDepth(dm, point, &depth));
7350c459fbc1SJed Brown     for (clsize=0,p=0; p<Ncl; p++) {
7351c459fbc1SJed Brown       PetscInt dof;
73529566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, points[2*p], &dof));
7353c459fbc1SJed Brown       clsize += dof;
7354c459fbc1SJed Brown     }
73559566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm));
7356c459fbc1SJed Brown   }
735771f0bbf9SMatthew G. Knepley   /* 2) Get number of indices on these points and field offsets from section */
735871f0bbf9SMatthew G. Knepley   for (p = 0; p < Ncl*2; p += 2) {
73597773e69fSMatthew G. Knepley     PetscInt dof, fdof;
73607773e69fSMatthew G. Knepley 
73619566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[p], &dof));
73627773e69fSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
73639566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof));
73647773e69fSMatthew G. Knepley       offsets[f+1] += fdof;
73657773e69fSMatthew G. Knepley     }
736671f0bbf9SMatthew G. Knepley     Ni += dof;
73677773e69fSMatthew G. Knepley   }
73687773e69fSMatthew G. Knepley   for (f = 1; f < Nf; ++f) offsets[f+1] += offsets[f];
73691dca8a05SBarry Smith   PetscCheck(!Nf || offsets[Nf] == Ni,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid size for closure %" PetscInt_FMT " should be %" PetscInt_FMT, offsets[Nf], Ni);
737071f0bbf9SMatthew G. Knepley   /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */
737171f0bbf9SMatthew G. Knepley   for (f = 0; f < PetscMax(1, Nf); ++f) {
73729566063dSJacob Faibussowitsch     if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
73739566063dSJacob Faibussowitsch     else    PetscCall(PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f]));
737471f0bbf9SMatthew G. Knepley     /* may need to apply sign changes to the element matrix */
737571f0bbf9SMatthew G. Knepley     if (values && flips[f]) {
737671f0bbf9SMatthew G. Knepley       PetscInt foffset = offsets[f];
73776ecaa68aSToby Isaac 
737871f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
737971f0bbf9SMatthew G. Knepley         PetscInt           pnt  = points[2*p], fdof;
738071f0bbf9SMatthew G. Knepley         const PetscScalar *flip = flips[f] ? flips[f][p] : NULL;
738171f0bbf9SMatthew G. Knepley 
73829566063dSJacob Faibussowitsch         if (!Nf) PetscCall(PetscSectionGetDof(section, pnt, &fdof));
73839566063dSJacob Faibussowitsch         else     PetscCall(PetscSectionGetFieldDof(section, pnt, f, &fdof));
738471f0bbf9SMatthew G. Knepley         if (flip) {
738571f0bbf9SMatthew G. Knepley           PetscInt i, j, k;
738671f0bbf9SMatthew G. Knepley 
738771f0bbf9SMatthew G. Knepley           if (!valCopy) {
73889566063dSJacob Faibussowitsch             PetscCall(DMGetWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy));
738971f0bbf9SMatthew G. Knepley             for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j];
739071f0bbf9SMatthew G. Knepley             *values = valCopy;
739171f0bbf9SMatthew G. Knepley           }
739271f0bbf9SMatthew G. Knepley           for (i = 0; i < fdof; ++i) {
739371f0bbf9SMatthew G. Knepley             PetscScalar fval = flip[i];
739471f0bbf9SMatthew G. Knepley 
739571f0bbf9SMatthew G. Knepley             for (k = 0; k < Ni; ++k) {
739671f0bbf9SMatthew G. Knepley               valCopy[Ni * (foffset + i) + k] *= fval;
739771f0bbf9SMatthew G. Knepley               valCopy[Ni * k + (foffset + i)] *= fval;
73986ecaa68aSToby Isaac             }
73996ecaa68aSToby Isaac           }
740071f0bbf9SMatthew G. Knepley         }
740171f0bbf9SMatthew G. Knepley         foffset += fdof;
740271f0bbf9SMatthew G. Knepley       }
740371f0bbf9SMatthew G. Knepley     }
740471f0bbf9SMatthew G. Knepley   }
740571f0bbf9SMatthew G. Knepley   /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */
74069566063dSJacob Faibussowitsch   PetscCall(DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE));
740771f0bbf9SMatthew G. Knepley   if (NclC) {
74089566063dSJacob Faibussowitsch     if (valCopy) PetscCall(DMRestoreWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy));
740971f0bbf9SMatthew G. Knepley     for (f = 0; f < PetscMax(1, Nf); ++f) {
74109566063dSJacob Faibussowitsch       if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
74119566063dSJacob Faibussowitsch       else    PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]));
741271f0bbf9SMatthew G. Knepley     }
741371f0bbf9SMatthew G. Knepley     for (f = 0; f < PetscMax(1, Nf); ++f) {
74149566063dSJacob Faibussowitsch       if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f]));
74159566063dSJacob Faibussowitsch       else    PetscCall(PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f]));
741671f0bbf9SMatthew G. Knepley     }
74179566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
741871f0bbf9SMatthew G. Knepley     Ncl     = NclC;
741971f0bbf9SMatthew G. Knepley     Ni      = NiC;
742071f0bbf9SMatthew G. Knepley     points  = pointsC;
742171f0bbf9SMatthew G. Knepley     if (values) *values = valuesC;
742271f0bbf9SMatthew G. Knepley   }
742371f0bbf9SMatthew G. Knepley   /* 5) Calculate indices */
74249566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, Ni, MPIU_INT, &idx));
742571f0bbf9SMatthew G. Knepley   if (Nf) {
742671f0bbf9SMatthew G. Knepley     PetscInt  idxOff;
742771f0bbf9SMatthew G. Knepley     PetscBool useFieldOffsets;
742871f0bbf9SMatthew G. Knepley 
742971f0bbf9SMatthew G. Knepley     if (outOffsets) {for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f];}
74309566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets));
743171f0bbf9SMatthew G. Knepley     if (useFieldOffsets) {
743271f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
743371f0bbf9SMatthew G. Knepley         const PetscInt pnt = points[p*2];
743471f0bbf9SMatthew G. Knepley 
74359566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx));
74367773e69fSMatthew G. Knepley       }
74377773e69fSMatthew G. Knepley     } else {
743871f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
743971f0bbf9SMatthew G. Knepley         const PetscInt pnt = points[p*2];
744071f0bbf9SMatthew G. Knepley 
74419566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff));
744271f0bbf9SMatthew G. Knepley         /* Note that we pass a local section even though we're using global offsets.  This is because global sections do
744371f0bbf9SMatthew G. Knepley          * not (at the time of this writing) have fields set. They probably should, in which case we would pass the
744471f0bbf9SMatthew G. Knepley          * global section. */
74459566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx));
744671f0bbf9SMatthew G. Knepley       }
744771f0bbf9SMatthew G. Knepley     }
744871f0bbf9SMatthew G. Knepley   } else {
744971f0bbf9SMatthew G. Knepley     PetscInt off = 0, idxOff;
745071f0bbf9SMatthew G. Knepley 
745171f0bbf9SMatthew G. Knepley     for (p = 0; p < Ncl; ++p) {
745271f0bbf9SMatthew G. Knepley       const PetscInt  pnt  = points[p*2];
74534acb8e1eSToby Isaac       const PetscInt *perm = perms[0] ? perms[0][p] : NULL;
74544acb8e1eSToby Isaac 
74559566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff));
745671f0bbf9SMatthew G. Knepley       /* Note that we pass a local section even though we're using global offsets.  This is because global sections do
745771f0bbf9SMatthew G. Knepley        * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */
74589566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx));
74597773e69fSMatthew G. Knepley     }
74607773e69fSMatthew G. Knepley   }
746171f0bbf9SMatthew G. Knepley   /* 6) Cleanup */
746271f0bbf9SMatthew G. Knepley   for (f = 0; f < PetscMax(1, Nf); ++f) {
74639566063dSJacob Faibussowitsch     if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
74649566063dSJacob Faibussowitsch     else    PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]));
74654acb8e1eSToby Isaac   }
746671f0bbf9SMatthew G. Knepley   if (NclC) {
74679566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, NclC*2, MPIU_INT, &pointsC));
74687773e69fSMatthew G. Knepley   } else {
74699566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
74707773e69fSMatthew G. Knepley   }
747171f0bbf9SMatthew G. Knepley 
747271f0bbf9SMatthew G. Knepley   if (numIndices) *numIndices = Ni;
747371f0bbf9SMatthew G. Knepley   if (indices)    *indices    = idx;
74747773e69fSMatthew G. Knepley   PetscFunctionReturn(0);
74757773e69fSMatthew G. Knepley }
74767773e69fSMatthew G. Knepley 
74777cd05799SMatthew G. Knepley /*@C
747871f0bbf9SMatthew G. Knepley   DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections.
74797cd05799SMatthew G. Knepley 
74807cd05799SMatthew G. Knepley   Not collective
74817cd05799SMatthew G. Knepley 
74827cd05799SMatthew G. Knepley   Input Parameters:
74837cd05799SMatthew G. Knepley + dm         - The DM
748471f0bbf9SMatthew G. Knepley . section    - The PetscSection describing the points (a local section)
748571f0bbf9SMatthew G. Knepley . idxSection - The PetscSection from which to obtain indices (may be local or global)
748671f0bbf9SMatthew G. Knepley . point      - The point defining the closure
748771f0bbf9SMatthew G. Knepley - useClPerm  - Use the closure point permutation if available
748871f0bbf9SMatthew G. Knepley 
748971f0bbf9SMatthew G. Knepley   Output Parameters:
749071f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections
749171f0bbf9SMatthew G. Knepley . indices    - The dof indices
749271f0bbf9SMatthew G. Knepley . outOffsets - Array to write the field offsets into, or NULL
749371f0bbf9SMatthew G. Knepley - values     - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL
749471f0bbf9SMatthew G. Knepley 
749571f0bbf9SMatthew G. Knepley   Notes:
749671f0bbf9SMatthew G. Knepley   If values were modified, the user is responsible for calling DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values).
749771f0bbf9SMatthew G. Knepley 
749871f0bbf9SMatthew G. Knepley   If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices.  The value
749971f0bbf9SMatthew G. Knepley   of those indices is not significant.  If idxSection is local, the constrained dofs will yield the involution -(idx+1)
750071f0bbf9SMatthew G. Knepley   of their index in a local vector.  A caller who does not wish to distinguish those points may recover the nonnegative
750171f0bbf9SMatthew G. Knepley   indices via involution, -(-(idx+1)+1)==idx.  Local indices are provided when idxSection == section, otherwise global
750271f0bbf9SMatthew G. Knepley   indices (with the above semantics) are implied.
75037cd05799SMatthew G. Knepley 
75047cd05799SMatthew G. Knepley   Level: advanced
75057cd05799SMatthew G. Knepley 
7506db781477SPatrick Sanan .seealso `DMPlexGetClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()`
75077cd05799SMatthew G. Knepley @*/
750871f0bbf9SMatthew G. Knepley PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm,
750971f0bbf9SMatthew G. Knepley                                            PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[])
75107773e69fSMatthew G. Knepley {
75117773e69fSMatthew G. Knepley   PetscFunctionBegin;
75127773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7513064a246eSJacob Faibussowitsch   PetscValidPointer(indices, 7);
75149566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, indices));
75157773e69fSMatthew G. Knepley   PetscFunctionReturn(0);
75167773e69fSMatthew G. Knepley }
75177773e69fSMatthew G. Knepley 
75187f5d1fdeSMatthew G. Knepley /*@C
75197f5d1fdeSMatthew G. Knepley   DMPlexMatSetClosure - Set an array of the values on the closure of 'point'
75207f5d1fdeSMatthew G. Knepley 
75217f5d1fdeSMatthew G. Knepley   Not collective
75227f5d1fdeSMatthew G. Knepley 
75237f5d1fdeSMatthew G. Knepley   Input Parameters:
75247f5d1fdeSMatthew G. Knepley + dm - The DM
7525ebd6d717SJed Brown . section - The section describing the layout in v, or NULL to use the default section
7526ebd6d717SJed Brown . globalSection - The section describing the layout in v, or NULL to use the default global section
75277f5d1fdeSMatthew G. Knepley . A - The matrix
7528eaf898f9SPatrick Sanan . point - The point in the DM
75297f5d1fdeSMatthew G. Knepley . values - The array of values
75307f5d1fdeSMatthew G. Knepley - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions
75317f5d1fdeSMatthew G. Knepley 
75327f5d1fdeSMatthew G. Knepley   Fortran Notes:
75337f5d1fdeSMatthew G. Knepley   This routine is only available in Fortran 90, and you must include petsc.h90 in your code.
75347f5d1fdeSMatthew G. Knepley 
75357f5d1fdeSMatthew G. Knepley   Level: intermediate
75367f5d1fdeSMatthew G. Knepley 
7537db781477SPatrick Sanan .seealso `DMPlexMatSetClosureGeneral()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`
75387f5d1fdeSMatthew G. Knepley @*/
75397c1f9639SMatthew G Knepley PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
7540552f7358SJed Brown {
7541552f7358SJed Brown   DM_Plex           *mesh = (DM_Plex*) dm->data;
7542552f7358SJed Brown   PetscInt          *indices;
754371f0bbf9SMatthew G. Knepley   PetscInt           numIndices;
754471f0bbf9SMatthew G. Knepley   const PetscScalar *valuesOrig = values;
7545552f7358SJed Brown   PetscErrorCode     ierr;
7546552f7358SJed Brown 
7547552f7358SJed Brown   PetscFunctionBegin;
7548552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
75499566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
75503dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
75519566063dSJacob Faibussowitsch   if (!globalSection) PetscCall(DMGetGlobalSection(dm, &globalSection));
75523dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3);
75533dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 4);
7554552f7358SJed Brown 
75559566063dSJacob Faibussowitsch   PetscCall(DMPlexGetClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values));
75560d644c17SKarl Rupp 
75579566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values));
7558d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
75594a1e0b3eSMatthew G. Knepley   ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode);
7560552f7358SJed Brown   if (ierr) {
7561552f7358SJed Brown     PetscMPIInt    rank;
7562552f7358SJed Brown 
75639566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
75649566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
75659566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values));
75669566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values));
75679566063dSJacob Faibussowitsch     if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values));
7568c3e24edfSBarry Smith     SETERRQ(PetscObjectComm((PetscObject)dm),ierr,"Not possible to set matrix values");
7569552f7358SJed Brown   }
75704a1e0b3eSMatthew G. Knepley   if (mesh->printFEM > 1) {
75714a1e0b3eSMatthew G. Knepley     PetscInt i;
75729566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "  Indices:"));
757363a3b9bcSJacob Faibussowitsch     for (i = 0; i < numIndices; ++i) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, indices[i]));
75749566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
75754a1e0b3eSMatthew G. Knepley   }
757671f0bbf9SMatthew G. Knepley 
75779566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values));
75789566063dSJacob Faibussowitsch   if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values));
757971f0bbf9SMatthew G. Knepley   PetscFunctionReturn(0);
75804acb8e1eSToby Isaac }
758171f0bbf9SMatthew G. Knepley 
75824a1e0b3eSMatthew G. Knepley /*@C
75834a1e0b3eSMatthew G. Knepley   DMPlexMatSetClosure - Set an array of the values on the closure of 'point' using a different row and column section
75844a1e0b3eSMatthew G. Knepley 
75854a1e0b3eSMatthew G. Knepley   Not collective
75864a1e0b3eSMatthew G. Knepley 
75874a1e0b3eSMatthew G. Knepley   Input Parameters:
75884a1e0b3eSMatthew G. Knepley + dmRow - The DM for the row fields
75894a1e0b3eSMatthew G. Knepley . sectionRow - The section describing the layout, or NULL to use the default section in dmRow
75904a1e0b3eSMatthew G. Knepley . globalSectionRow - The section describing the layout, or NULL to use the default global section in dmRow
75914a1e0b3eSMatthew G. Knepley . dmCol - The DM for the column fields
75924a1e0b3eSMatthew G. Knepley . sectionCol - The section describing the layout, or NULL to use the default section in dmCol
75934a1e0b3eSMatthew G. Knepley . globalSectionCol - The section describing the layout, or NULL to use the default global section in dmCol
75944a1e0b3eSMatthew G. Knepley . A - The matrix
75954a1e0b3eSMatthew G. Knepley . point - The point in the DMs
75964a1e0b3eSMatthew G. Knepley . values - The array of values
75974a1e0b3eSMatthew G. Knepley - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions
75984a1e0b3eSMatthew G. Knepley 
75994a1e0b3eSMatthew G. Knepley   Level: intermediate
76004a1e0b3eSMatthew G. Knepley 
7601db781477SPatrick Sanan .seealso `DMPlexMatSetClosure()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`
76024a1e0b3eSMatthew G. Knepley @*/
760371f0bbf9SMatthew 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)
760471f0bbf9SMatthew G. Knepley {
760571f0bbf9SMatthew G. Knepley   DM_Plex           *mesh = (DM_Plex*) dmRow->data;
760671f0bbf9SMatthew G. Knepley   PetscInt          *indicesRow, *indicesCol;
760771f0bbf9SMatthew G. Knepley   PetscInt           numIndicesRow, numIndicesCol;
760871f0bbf9SMatthew G. Knepley   const PetscScalar *valuesOrig = values;
760971f0bbf9SMatthew G. Knepley   PetscErrorCode     ierr;
761071f0bbf9SMatthew G. Knepley 
761171f0bbf9SMatthew G. Knepley   PetscFunctionBegin;
761271f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1);
76139566063dSJacob Faibussowitsch   if (!sectionRow) PetscCall(DMGetLocalSection(dmRow, &sectionRow));
761471f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2);
76159566063dSJacob Faibussowitsch   if (!globalSectionRow) PetscCall(DMGetGlobalSection(dmRow, &globalSectionRow));
761671f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3);
761771f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(dmCol, DM_CLASSID, 4);
76189566063dSJacob Faibussowitsch   if (!sectionCol) PetscCall(DMGetLocalSection(dmCol, &sectionCol));
761971f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 5);
76209566063dSJacob Faibussowitsch   if (!globalSectionCol) PetscCall(DMGetGlobalSection(dmCol, &globalSectionCol));
762171f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 6);
762271f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 7);
762371f0bbf9SMatthew G. Knepley 
76249566063dSJacob Faibussowitsch   PetscCall(DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values));
76259566063dSJacob Faibussowitsch   PetscCall(DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values));
762671f0bbf9SMatthew G. Knepley 
76279566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values));
7628d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
76294a1e0b3eSMatthew G. Knepley   ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode);
763071f0bbf9SMatthew G. Knepley   if (ierr) {
763171f0bbf9SMatthew G. Knepley     PetscMPIInt    rank;
763271f0bbf9SMatthew G. Knepley 
76339566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
76349566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
76359566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values));
76369566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values));
76379566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **) &values));
76389566063dSJacob Faibussowitsch     if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values));
7639d3d1a6afSToby Isaac   }
764071f0bbf9SMatthew G. Knepley 
76419566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values));
76429566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values));
76439566063dSJacob Faibussowitsch   if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values));
7644552f7358SJed Brown   PetscFunctionReturn(0);
7645552f7358SJed Brown }
7646552f7358SJed Brown 
7647de41b84cSMatthew 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)
7648de41b84cSMatthew G. Knepley {
7649de41b84cSMatthew G. Knepley   DM_Plex        *mesh   = (DM_Plex*) dmf->data;
7650de41b84cSMatthew G. Knepley   PetscInt       *fpoints = NULL, *ftotpoints = NULL;
7651de41b84cSMatthew G. Knepley   PetscInt       *cpoints = NULL;
7652de41b84cSMatthew G. Knepley   PetscInt       *findices, *cindices;
765317c0192bSMatthew G. Knepley   const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */
7654de41b84cSMatthew G. Knepley   PetscInt        foffsets[32], coffsets[32];
7655412e9a14SMatthew G. Knepley   DMPolytopeType  ct;
76564ca5e9f5SMatthew G. Knepley   PetscInt        numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f;
7657de41b84cSMatthew G. Knepley   PetscErrorCode  ierr;
7658de41b84cSMatthew G. Knepley 
7659de41b84cSMatthew G. Knepley   PetscFunctionBegin;
7660de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 1);
7661de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 4);
76629566063dSJacob Faibussowitsch   if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection));
7663de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2);
76649566063dSJacob Faibussowitsch   if (!csection) PetscCall(DMGetLocalSection(dmc, &csection));
7665de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5);
76669566063dSJacob Faibussowitsch   if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection));
7667de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3);
76689566063dSJacob Faibussowitsch   if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection));
7669de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6);
7670de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 7);
76719566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(fsection, &numFields));
767263a3b9bcSJacob Faibussowitsch   PetscCheck(numFields <= 31,PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields);
76739566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(foffsets, 32));
76749566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(coffsets, 32));
7675de41b84cSMatthew G. Knepley   /* Column indices */
76769566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
76774ca5e9f5SMatthew G. Knepley   maxFPoints = numCPoints;
7678de41b84cSMatthew G. Knepley   /* Compress out points not in the section */
7679de41b84cSMatthew G. Knepley   /*   TODO: Squeeze out points with 0 dof as well */
76809566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd));
7681de41b84cSMatthew G. Knepley   for (p = 0, q = 0; p < numCPoints*2; p += 2) {
7682de41b84cSMatthew G. Knepley     if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) {
7683de41b84cSMatthew G. Knepley       cpoints[q*2]   = cpoints[p];
7684de41b84cSMatthew G. Knepley       cpoints[q*2+1] = cpoints[p+1];
7685de41b84cSMatthew G. Knepley       ++q;
7686de41b84cSMatthew G. Knepley     }
7687de41b84cSMatthew G. Knepley   }
7688de41b84cSMatthew G. Knepley   numCPoints = q;
7689de41b84cSMatthew G. Knepley   for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) {
7690de41b84cSMatthew G. Knepley     PetscInt fdof;
7691de41b84cSMatthew G. Knepley 
76929566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof));
76934ca5e9f5SMatthew G. Knepley     if (!dof) continue;
7694de41b84cSMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
76959566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof));
7696de41b84cSMatthew G. Knepley       coffsets[f+1] += fdof;
7697de41b84cSMatthew G. Knepley     }
7698de41b84cSMatthew G. Knepley     numCIndices += dof;
7699de41b84cSMatthew G. Knepley   }
7700de41b84cSMatthew G. Knepley   for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f];
7701de41b84cSMatthew G. Knepley   /* Row indices */
77029566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dmc, point, &ct));
7703412e9a14SMatthew G. Knepley   {
7704012bc364SMatthew G. Knepley     DMPlexTransform tr;
7705012bc364SMatthew G. Knepley     DMPolytopeType *rct;
7706012bc364SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt, Nt;
7707012bc364SMatthew G. Knepley 
77089566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr));
77099566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR));
77109566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt));
7711012bc364SMatthew G. Knepley     numSubcells = rsize[Nt-1];
77129566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformDestroy(&tr));
7713412e9a14SMatthew G. Knepley   }
77149566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints));
7715de41b84cSMatthew G. Knepley   for (r = 0, q = 0; r < numSubcells; ++r) {
7716de41b84cSMatthew G. Knepley     /* TODO Map from coarse to fine cells */
77179566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints));
7718de41b84cSMatthew G. Knepley     /* Compress out points not in the section */
77199566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd));
7720de41b84cSMatthew G. Knepley     for (p = 0; p < numFPoints*2; p += 2) {
7721de41b84cSMatthew G. Knepley       if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) {
77229566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof));
77234ca5e9f5SMatthew G. Knepley         if (!dof) continue;
77244ca5e9f5SMatthew G. Knepley         for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break;
77254ca5e9f5SMatthew G. Knepley         if (s < q) continue;
7726de41b84cSMatthew G. Knepley         ftotpoints[q*2]   = fpoints[p];
7727de41b84cSMatthew G. Knepley         ftotpoints[q*2+1] = fpoints[p+1];
7728de41b84cSMatthew G. Knepley         ++q;
7729de41b84cSMatthew G. Knepley       }
7730de41b84cSMatthew G. Knepley     }
77319566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints));
7732de41b84cSMatthew G. Knepley   }
7733de41b84cSMatthew G. Knepley   numFPoints = q;
7734de41b84cSMatthew G. Knepley   for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) {
7735de41b84cSMatthew G. Knepley     PetscInt fdof;
7736de41b84cSMatthew G. Knepley 
77379566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof));
77384ca5e9f5SMatthew G. Knepley     if (!dof) continue;
7739de41b84cSMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
77409566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof));
7741de41b84cSMatthew G. Knepley       foffsets[f+1] += fdof;
7742de41b84cSMatthew G. Knepley     }
7743de41b84cSMatthew G. Knepley     numFIndices += dof;
7744de41b84cSMatthew G. Knepley   }
7745de41b84cSMatthew G. Knepley   for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f];
7746de41b84cSMatthew G. Knepley 
77471dca8a05SBarry Smith   PetscCheck(!numFields || foffsets[numFields] == numFIndices,PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %" PetscInt_FMT " should be %" PetscInt_FMT, foffsets[numFields], numFIndices);
77481dca8a05SBarry Smith   PetscCheck(!numFields || coffsets[numFields] == numCIndices,PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %" PetscInt_FMT " should be %" PetscInt_FMT, coffsets[numFields], numCIndices);
77499566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices));
77509566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
7751de41b84cSMatthew G. Knepley   if (numFields) {
77524acb8e1eSToby Isaac     const PetscInt **permsF[32] = {NULL};
77534acb8e1eSToby Isaac     const PetscInt **permsC[32] = {NULL};
77544acb8e1eSToby Isaac 
77554acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
77569566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL));
77579566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL));
7758de41b84cSMatthew G. Knepley     }
77594acb8e1eSToby Isaac     for (p = 0; p < numFPoints; p++) {
77609566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff));
77619566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices));
77624acb8e1eSToby Isaac     }
77634acb8e1eSToby Isaac     for (p = 0; p < numCPoints; p++) {
77649566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff));
77659566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices));
77664acb8e1eSToby Isaac     }
77674acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
77689566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL));
77699566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL));
7770de41b84cSMatthew G. Knepley     }
7771de41b84cSMatthew G. Knepley   } else {
77724acb8e1eSToby Isaac     const PetscInt **permsF = NULL;
77734acb8e1eSToby Isaac     const PetscInt **permsC = NULL;
77744acb8e1eSToby Isaac 
77759566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL));
77769566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL));
77774acb8e1eSToby Isaac     for (p = 0, off = 0; p < numFPoints; p++) {
77784acb8e1eSToby Isaac       const PetscInt *perm = permsF ? permsF[p] : NULL;
77794acb8e1eSToby Isaac 
77809566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff));
77819566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices));
7782de41b84cSMatthew G. Knepley     }
77834acb8e1eSToby Isaac     for (p = 0, off = 0; p < numCPoints; p++) {
77844acb8e1eSToby Isaac       const PetscInt *perm = permsC ? permsC[p] : NULL;
77854acb8e1eSToby Isaac 
77869566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff));
77879566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices));
7788de41b84cSMatthew G. Knepley     }
77899566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL));
77909566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL));
7791de41b84cSMatthew G. Knepley   }
77929566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values));
77934acb8e1eSToby Isaac   /* TODO: flips */
7794d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
7795de41b84cSMatthew G. Knepley   ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode);
7796de41b84cSMatthew G. Knepley   if (ierr) {
7797de41b84cSMatthew G. Knepley     PetscMPIInt    rank;
7798de41b84cSMatthew G. Knepley 
77999566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
78009566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
78019566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values));
78029566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices));
78039566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
7804de41b84cSMatthew G. Knepley   }
78059566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints));
78069566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
78079566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices));
78089566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
7809de41b84cSMatthew G. Knepley   PetscFunctionReturn(0);
7810de41b84cSMatthew G. Knepley }
7811de41b84cSMatthew G. Knepley 
78127c927364SMatthew G. Knepley PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[])
78137c927364SMatthew G. Knepley {
78147c927364SMatthew G. Knepley   PetscInt      *fpoints = NULL, *ftotpoints = NULL;
78157c927364SMatthew G. Knepley   PetscInt      *cpoints = NULL;
78167c927364SMatthew G. Knepley   PetscInt       foffsets[32], coffsets[32];
781717c0192bSMatthew G. Knepley   const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */
7818412e9a14SMatthew G. Knepley   DMPolytopeType ct;
78197c927364SMatthew G. Knepley   PetscInt       numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f;
78207c927364SMatthew G. Knepley 
78217c927364SMatthew G. Knepley   PetscFunctionBegin;
78227c927364SMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 1);
78237c927364SMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 4);
78249566063dSJacob Faibussowitsch   if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection));
78257c927364SMatthew G. Knepley   PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2);
78269566063dSJacob Faibussowitsch   if (!csection) PetscCall(DMGetLocalSection(dmc, &csection));
78277c927364SMatthew G. Knepley   PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5);
78289566063dSJacob Faibussowitsch   if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection));
78297c927364SMatthew G. Knepley   PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3);
78309566063dSJacob Faibussowitsch   if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection));
78317c927364SMatthew G. Knepley   PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6);
78329566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(fsection, &numFields));
783363a3b9bcSJacob Faibussowitsch   PetscCheck(numFields <= 31,PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields);
78349566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(foffsets, 32));
78359566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(coffsets, 32));
78367c927364SMatthew G. Knepley   /* Column indices */
78379566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
78387c927364SMatthew G. Knepley   maxFPoints = numCPoints;
78397c927364SMatthew G. Knepley   /* Compress out points not in the section */
78407c927364SMatthew G. Knepley   /*   TODO: Squeeze out points with 0 dof as well */
78419566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd));
78427c927364SMatthew G. Knepley   for (p = 0, q = 0; p < numCPoints*2; p += 2) {
78437c927364SMatthew G. Knepley     if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) {
78447c927364SMatthew G. Knepley       cpoints[q*2]   = cpoints[p];
78457c927364SMatthew G. Knepley       cpoints[q*2+1] = cpoints[p+1];
78467c927364SMatthew G. Knepley       ++q;
78477c927364SMatthew G. Knepley     }
78487c927364SMatthew G. Knepley   }
78497c927364SMatthew G. Knepley   numCPoints = q;
78507c927364SMatthew G. Knepley   for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) {
78517c927364SMatthew G. Knepley     PetscInt fdof;
78527c927364SMatthew G. Knepley 
78539566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof));
78547c927364SMatthew G. Knepley     if (!dof) continue;
78557c927364SMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
78569566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof));
78577c927364SMatthew G. Knepley       coffsets[f+1] += fdof;
78587c927364SMatthew G. Knepley     }
78597c927364SMatthew G. Knepley     numCIndices += dof;
78607c927364SMatthew G. Knepley   }
78617c927364SMatthew G. Knepley   for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f];
78627c927364SMatthew G. Knepley   /* Row indices */
78639566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dmc, point, &ct));
7864412e9a14SMatthew G. Knepley   {
7865012bc364SMatthew G. Knepley     DMPlexTransform tr;
7866012bc364SMatthew G. Knepley     DMPolytopeType *rct;
7867012bc364SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt, Nt;
7868012bc364SMatthew G. Knepley 
78699566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr));
78709566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR));
78719566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt));
7872012bc364SMatthew G. Knepley     numSubcells = rsize[Nt-1];
78739566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformDestroy(&tr));
7874412e9a14SMatthew G. Knepley   }
78759566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints));
78767c927364SMatthew G. Knepley   for (r = 0, q = 0; r < numSubcells; ++r) {
78777c927364SMatthew G. Knepley     /* TODO Map from coarse to fine cells */
78789566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints));
78797c927364SMatthew G. Knepley     /* Compress out points not in the section */
78809566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd));
78817c927364SMatthew G. Knepley     for (p = 0; p < numFPoints*2; p += 2) {
78827c927364SMatthew G. Knepley       if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) {
78839566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof));
78847c927364SMatthew G. Knepley         if (!dof) continue;
78857c927364SMatthew G. Knepley         for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break;
78867c927364SMatthew G. Knepley         if (s < q) continue;
78877c927364SMatthew G. Knepley         ftotpoints[q*2]   = fpoints[p];
78887c927364SMatthew G. Knepley         ftotpoints[q*2+1] = fpoints[p+1];
78897c927364SMatthew G. Knepley         ++q;
78907c927364SMatthew G. Knepley       }
78917c927364SMatthew G. Knepley     }
78929566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints));
78937c927364SMatthew G. Knepley   }
78947c927364SMatthew G. Knepley   numFPoints = q;
78957c927364SMatthew G. Knepley   for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) {
78967c927364SMatthew G. Knepley     PetscInt fdof;
78977c927364SMatthew G. Knepley 
78989566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof));
78997c927364SMatthew G. Knepley     if (!dof) continue;
79007c927364SMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
79019566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof));
79027c927364SMatthew G. Knepley       foffsets[f+1] += fdof;
79037c927364SMatthew G. Knepley     }
79047c927364SMatthew G. Knepley     numFIndices += dof;
79057c927364SMatthew G. Knepley   }
79067c927364SMatthew G. Knepley   for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f];
79077c927364SMatthew G. Knepley 
79081dca8a05SBarry Smith   PetscCheck(!numFields || foffsets[numFields] == numFIndices,PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %" PetscInt_FMT " should be %" PetscInt_FMT, foffsets[numFields], numFIndices);
79091dca8a05SBarry Smith   PetscCheck(!numFields || coffsets[numFields] == numCIndices,PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %" PetscInt_FMT " should be %" PetscInt_FMT, coffsets[numFields], numCIndices);
79107c927364SMatthew G. Knepley   if (numFields) {
79114acb8e1eSToby Isaac     const PetscInt **permsF[32] = {NULL};
79124acb8e1eSToby Isaac     const PetscInt **permsC[32] = {NULL};
79134acb8e1eSToby Isaac 
79144acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
79159566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL));
79169566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL));
79177c927364SMatthew G. Knepley     }
79184acb8e1eSToby Isaac     for (p = 0; p < numFPoints; p++) {
79199566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff));
79209566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices));
79214acb8e1eSToby Isaac     }
79224acb8e1eSToby Isaac     for (p = 0; p < numCPoints; p++) {
79239566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff));
79249566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices));
79254acb8e1eSToby Isaac     }
79264acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
79279566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL));
79289566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL));
79297c927364SMatthew G. Knepley     }
79307c927364SMatthew G. Knepley   } else {
79314acb8e1eSToby Isaac     const PetscInt **permsF = NULL;
79324acb8e1eSToby Isaac     const PetscInt **permsC = NULL;
79334acb8e1eSToby Isaac 
79349566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL));
79359566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL));
79364acb8e1eSToby Isaac     for (p = 0, off = 0; p < numFPoints; p++) {
79374acb8e1eSToby Isaac       const PetscInt *perm = permsF ? permsF[p] : NULL;
79384acb8e1eSToby Isaac 
79399566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff));
79409566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices));
79417c927364SMatthew G. Knepley     }
79424acb8e1eSToby Isaac     for (p = 0, off = 0; p < numCPoints; p++) {
79434acb8e1eSToby Isaac       const PetscInt *perm = permsC ? permsC[p] : NULL;
79444acb8e1eSToby Isaac 
79459566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff));
79469566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices));
79477c927364SMatthew G. Knepley     }
79489566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL));
79499566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL));
79507c927364SMatthew G. Knepley   }
79519566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints));
79529566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
79537c927364SMatthew G. Knepley   PetscFunctionReturn(0);
79547c927364SMatthew G. Knepley }
79557c927364SMatthew G. Knepley 
79567cd05799SMatthew G. Knepley /*@C
79577cd05799SMatthew G. Knepley   DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0)
79587cd05799SMatthew G. Knepley 
79597cd05799SMatthew G. Knepley   Input Parameter:
79607cd05799SMatthew G. Knepley . dm   - The DMPlex object
79617cd05799SMatthew G. Knepley 
79627cd05799SMatthew G. Knepley   Output Parameter:
79637cd05799SMatthew G. Knepley . cellHeight - The height of a cell
79647cd05799SMatthew G. Knepley 
79657cd05799SMatthew G. Knepley   Level: developer
79667cd05799SMatthew G. Knepley 
7967db781477SPatrick Sanan .seealso `DMPlexSetVTKCellHeight()`
79687cd05799SMatthew G. Knepley @*/
7969552f7358SJed Brown PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight)
7970552f7358SJed Brown {
7971552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
7972552f7358SJed Brown 
7973552f7358SJed Brown   PetscFunctionBegin;
7974552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7975dadcf809SJacob Faibussowitsch   PetscValidIntPointer(cellHeight, 2);
7976552f7358SJed Brown   *cellHeight = mesh->vtkCellHeight;
7977552f7358SJed Brown   PetscFunctionReturn(0);
7978552f7358SJed Brown }
7979552f7358SJed Brown 
79807cd05799SMatthew G. Knepley /*@C
79817cd05799SMatthew G. Knepley   DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0)
79827cd05799SMatthew G. Knepley 
79837cd05799SMatthew G. Knepley   Input Parameters:
79847cd05799SMatthew G. Knepley + dm   - The DMPlex object
79857cd05799SMatthew G. Knepley - cellHeight - The height of a cell
79867cd05799SMatthew G. Knepley 
79877cd05799SMatthew G. Knepley   Level: developer
79887cd05799SMatthew G. Knepley 
7989db781477SPatrick Sanan .seealso `DMPlexGetVTKCellHeight()`
79907cd05799SMatthew G. Knepley @*/
7991552f7358SJed Brown PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight)
7992552f7358SJed Brown {
7993552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
7994552f7358SJed Brown 
7995552f7358SJed Brown   PetscFunctionBegin;
7996552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7997552f7358SJed Brown   mesh->vtkCellHeight = cellHeight;
7998552f7358SJed Brown   PetscFunctionReturn(0);
7999552f7358SJed Brown }
8000552f7358SJed Brown 
8001e6139122SMatthew G. Knepley /*@
8002e6139122SMatthew G. Knepley   DMPlexGetGhostCellStratum - Get the range of cells which are used to enforce FV boundary conditions
8003e6139122SMatthew G. Knepley 
8004e6139122SMatthew G. Knepley   Input Parameter:
8005e6139122SMatthew G. Knepley . dm - The DMPlex object
8006e6139122SMatthew G. Knepley 
8007e6139122SMatthew G. Knepley   Output Parameters:
80082a9f31c0SMatthew G. Knepley + gcStart - The first ghost cell, or NULL
80092a9f31c0SMatthew G. Knepley - gcEnd   - The upper bound on ghost cells, or NULL
8010e6139122SMatthew G. Knepley 
80112a9f31c0SMatthew G. Knepley   Level: advanced
8012e6139122SMatthew G. Knepley 
8013db781477SPatrick Sanan .seealso `DMPlexConstructGhostCells()`, `DMPlexGetGhostCellStratum()`
8014e6139122SMatthew G. Knepley @*/
8015e6139122SMatthew G. Knepley PetscErrorCode DMPlexGetGhostCellStratum(DM dm, PetscInt *gcStart, PetscInt *gcEnd)
8016e6139122SMatthew G. Knepley {
8017412e9a14SMatthew G. Knepley   DMLabel        ctLabel;
8018e6139122SMatthew G. Knepley 
8019e6139122SMatthew G. Knepley   PetscFunctionBegin;
8020e6139122SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
80219566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel));
80229566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_FV_GHOST, gcStart, gcEnd));
8023*695799ffSMatthew G. Knepley   // Reset label for fast lookup
8024*695799ffSMatthew G. Knepley   PetscCall(DMLabelMakeAllInvalid_Internal(ctLabel));
8025e6139122SMatthew G. Knepley   PetscFunctionReturn(0);
8026e6139122SMatthew G. Knepley }
8027e6139122SMatthew G. Knepley 
80289886b8cfSStefano Zampini PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering)
8029552f7358SJed Brown {
8030552f7358SJed Brown   PetscSection   section, globalSection;
8031552f7358SJed Brown   PetscInt      *numbers, p;
8032552f7358SJed Brown 
8033552f7358SJed Brown   PetscFunctionBegin;
80346c1ef331SVaclav Hapla   if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf));
80359566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section));
80369566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(section, pStart, pEnd));
8037552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
80389566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(section, p, 1));
8039552f7358SJed Brown   }
80409566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(section));
80419566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection));
80429566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(pEnd - pStart, &numbers));
8043552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
80449566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]));
8045ef48cebcSMatthew G. Knepley     if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift;
8046ef48cebcSMatthew G. Knepley     else                       numbers[p-pStart] += shift;
8047552f7358SJed Brown   }
80489566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering));
8049ef48cebcSMatthew G. Knepley   if (globalSize) {
8050ef48cebcSMatthew G. Knepley     PetscLayout layout;
80519566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout));
80529566063dSJacob Faibussowitsch     PetscCall(PetscLayoutGetSize(layout, globalSize));
80539566063dSJacob Faibussowitsch     PetscCall(PetscLayoutDestroy(&layout));
8054ef48cebcSMatthew G. Knepley   }
80559566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&section));
80569566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&globalSection));
8057552f7358SJed Brown   PetscFunctionReturn(0);
8058552f7358SJed Brown }
8059552f7358SJed Brown 
806081ed3555SMatthew G. Knepley PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers)
8061552f7358SJed Brown {
8062412e9a14SMatthew G. Knepley   PetscInt       cellHeight, cStart, cEnd;
8063552f7358SJed Brown 
8064552f7358SJed Brown   PetscFunctionBegin;
80659566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
80669566063dSJacob Faibussowitsch   if (includeHybrid) PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
80679566063dSJacob Faibussowitsch   else               PetscCall(DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd));
80689566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers));
806981ed3555SMatthew G. Knepley   PetscFunctionReturn(0);
8070552f7358SJed Brown }
807181ed3555SMatthew G. Knepley 
80728dab3259SMatthew G. Knepley /*@
80737cd05799SMatthew G. Knepley   DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process
80747cd05799SMatthew G. Knepley 
80757cd05799SMatthew G. Knepley   Input Parameter:
80767cd05799SMatthew G. Knepley . dm   - The DMPlex object
80777cd05799SMatthew G. Knepley 
80787cd05799SMatthew G. Knepley   Output Parameter:
80797cd05799SMatthew G. Knepley . globalCellNumbers - Global cell numbers for all cells on this process
80807cd05799SMatthew G. Knepley 
80817cd05799SMatthew G. Knepley   Level: developer
80827cd05799SMatthew G. Knepley 
8083db781477SPatrick Sanan .seealso `DMPlexGetVertexNumbering()`
80847cd05799SMatthew G. Knepley @*/
808581ed3555SMatthew G. Knepley PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers)
808681ed3555SMatthew G. Knepley {
808781ed3555SMatthew G. Knepley   DM_Plex       *mesh = (DM_Plex*) dm->data;
808881ed3555SMatthew G. Knepley 
808981ed3555SMatthew G. Knepley   PetscFunctionBegin;
809081ed3555SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
80919566063dSJacob Faibussowitsch   if (!mesh->globalCellNumbers) PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers));
8092552f7358SJed Brown   *globalCellNumbers = mesh->globalCellNumbers;
8093552f7358SJed Brown   PetscFunctionReturn(0);
8094552f7358SJed Brown }
8095552f7358SJed Brown 
809681ed3555SMatthew G. Knepley PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers)
809781ed3555SMatthew G. Knepley {
8098412e9a14SMatthew G. Knepley   PetscInt       vStart, vEnd;
809981ed3555SMatthew G. Knepley 
810081ed3555SMatthew G. Knepley   PetscFunctionBegin;
810181ed3555SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
81029566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
81039566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers));
810481ed3555SMatthew G. Knepley   PetscFunctionReturn(0);
810581ed3555SMatthew G. Knepley }
810681ed3555SMatthew G. Knepley 
81078dab3259SMatthew G. Knepley /*@
81086aa51ba9SJacob Faibussowitsch   DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process
81097cd05799SMatthew G. Knepley 
81107cd05799SMatthew G. Knepley   Input Parameter:
81117cd05799SMatthew G. Knepley . dm   - The DMPlex object
81127cd05799SMatthew G. Knepley 
81137cd05799SMatthew G. Knepley   Output Parameter:
81147cd05799SMatthew G. Knepley . globalVertexNumbers - Global vertex numbers for all vertices on this process
81157cd05799SMatthew G. Knepley 
81167cd05799SMatthew G. Knepley   Level: developer
81177cd05799SMatthew G. Knepley 
8118db781477SPatrick Sanan .seealso `DMPlexGetCellNumbering()`
81197cd05799SMatthew G. Knepley @*/
8120552f7358SJed Brown PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers)
8121552f7358SJed Brown {
8122552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
8123552f7358SJed Brown 
8124552f7358SJed Brown   PetscFunctionBegin;
8125552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
81269566063dSJacob Faibussowitsch   if (!mesh->globalVertexNumbers) PetscCall(DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers));
8127552f7358SJed Brown   *globalVertexNumbers = mesh->globalVertexNumbers;
8128552f7358SJed Brown   PetscFunctionReturn(0);
8129552f7358SJed Brown }
8130552f7358SJed Brown 
81318dab3259SMatthew G. Knepley /*@
81327cd05799SMatthew G. Knepley   DMPlexCreatePointNumbering - Create a global numbering for all points on this process
81337cd05799SMatthew G. Knepley 
81347cd05799SMatthew G. Knepley   Input Parameter:
81357cd05799SMatthew G. Knepley . dm   - The DMPlex object
81367cd05799SMatthew G. Knepley 
81377cd05799SMatthew G. Knepley   Output Parameter:
81387cd05799SMatthew G. Knepley . globalPointNumbers - Global numbers for all points on this process
81397cd05799SMatthew G. Knepley 
81407cd05799SMatthew G. Knepley   Level: developer
81417cd05799SMatthew G. Knepley 
8142db781477SPatrick Sanan .seealso `DMPlexGetCellNumbering()`
81437cd05799SMatthew G. Knepley @*/
8144ef48cebcSMatthew G. Knepley PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers)
8145ef48cebcSMatthew G. Knepley {
8146ef48cebcSMatthew G. Knepley   IS             nums[4];
8147862913ffSStefano Zampini   PetscInt       depths[4], gdepths[4], starts[4];
8148ef48cebcSMatthew G. Knepley   PetscInt       depth, d, shift = 0;
8149ef48cebcSMatthew G. Knepley 
8150ef48cebcSMatthew G. Knepley   PetscFunctionBegin;
8151ef48cebcSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
81529566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
81538abc87a0SMichael Lange   /* For unstratified meshes use dim instead of depth */
81549566063dSJacob Faibussowitsch   if (depth < 0) PetscCall(DMGetDimension(dm, &depth));
8155862913ffSStefano Zampini   for (d = 0; d <= depth; ++d) {
8156862913ffSStefano Zampini     PetscInt end;
8157862913ffSStefano Zampini 
8158862913ffSStefano Zampini     depths[d] = depth-d;
81599566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end));
8160862913ffSStefano Zampini     if (!(starts[d]-end)) { starts[d] = depths[d] = -1; }
8161862913ffSStefano Zampini   }
81629566063dSJacob Faibussowitsch   PetscCall(PetscSortIntWithArray(depth+1, starts, depths));
81631c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(depths, gdepths, depth+1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject) dm)));
8164862913ffSStefano Zampini   for (d = 0; d <= depth; ++d) {
81651dca8a05SBarry Smith     PetscCheck(starts[d] < 0 || depths[d] == gdepths[d],PETSC_COMM_SELF,PETSC_ERR_PLIB,"Expected depth %" PetscInt_FMT ", found %" PetscInt_FMT,depths[d],gdepths[d]);
8166862913ffSStefano Zampini   }
8167ef48cebcSMatthew G. Knepley   for (d = 0; d <= depth; ++d) {
8168ef48cebcSMatthew G. Knepley     PetscInt pStart, pEnd, gsize;
8169ef48cebcSMatthew G. Knepley 
81709566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd));
81719566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]));
8172ef48cebcSMatthew G. Knepley     shift += gsize;
8173ef48cebcSMatthew G. Knepley   }
81749566063dSJacob Faibussowitsch   PetscCall(ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers));
81759566063dSJacob Faibussowitsch   for (d = 0; d <= depth; ++d) PetscCall(ISDestroy(&nums[d]));
8176ef48cebcSMatthew G. Knepley   PetscFunctionReturn(0);
8177ef48cebcSMatthew G. Knepley }
8178ef48cebcSMatthew G. Knepley 
817908a22f4bSMatthew G. Knepley /*@
818008a22f4bSMatthew G. Knepley   DMPlexCreateRankField - Create a cell field whose value is the rank of the owner
818108a22f4bSMatthew G. Knepley 
818208a22f4bSMatthew G. Knepley   Input Parameter:
818308a22f4bSMatthew G. Knepley . dm - The DMPlex object
818408a22f4bSMatthew G. Knepley 
818508a22f4bSMatthew G. Knepley   Output Parameter:
818608a22f4bSMatthew G. Knepley . ranks - The rank field
818708a22f4bSMatthew G. Knepley 
818808a22f4bSMatthew G. Knepley   Options Database Keys:
818908a22f4bSMatthew G. Knepley . -dm_partition_view - Adds the rank field into the DM output from -dm_view using the same viewer
819008a22f4bSMatthew G. Knepley 
819108a22f4bSMatthew G. Knepley   Level: intermediate
819208a22f4bSMatthew G. Knepley 
8193db781477SPatrick Sanan .seealso: `DMView()`
819408a22f4bSMatthew G. Knepley @*/
819508a22f4bSMatthew G. Knepley PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks)
819608a22f4bSMatthew G. Knepley {
819708a22f4bSMatthew G. Knepley   DM             rdm;
819808a22f4bSMatthew G. Knepley   PetscFE        fe;
819908a22f4bSMatthew G. Knepley   PetscScalar   *r;
820008a22f4bSMatthew G. Knepley   PetscMPIInt    rank;
8201a55f9a55SMatthew G. Knepley   DMPolytopeType ct;
820208a22f4bSMatthew G. Knepley   PetscInt       dim, cStart, cEnd, c;
8203a55f9a55SMatthew G. Knepley   PetscBool      simplex;
820408a22f4bSMatthew G. Knepley 
820508a22f4bSMatthew G. Knepley   PetscFunctionBeginUser;
8206f95ace6aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8207f95ace6aSMatthew G. Knepley   PetscValidPointer(ranks, 2);
82089566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank));
82099566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &rdm));
82109566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(rdm, &dim));
82119566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd));
82129566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cStart, &ct));
8213a55f9a55SMatthew G. Knepley   simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE;
82149566063dSJacob Faibussowitsch   PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe));
82159566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject) fe, "rank"));
82169566063dSJacob Faibussowitsch   PetscCall(DMSetField(rdm, 0, NULL, (PetscObject) fe));
82179566063dSJacob Faibussowitsch   PetscCall(PetscFEDestroy(&fe));
82189566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(rdm));
82199566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(rdm, ranks));
82209566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject) *ranks, "partition"));
82219566063dSJacob Faibussowitsch   PetscCall(VecGetArray(*ranks, &r));
822208a22f4bSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
822308a22f4bSMatthew G. Knepley     PetscScalar *lr;
822408a22f4bSMatthew G. Knepley 
82259566063dSJacob Faibussowitsch     PetscCall(DMPlexPointGlobalRef(rdm, c, r, &lr));
822671f09efeSPierre Jolivet     if (lr) *lr = rank;
822708a22f4bSMatthew G. Knepley   }
82289566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(*ranks, &r));
82299566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&rdm));
823008a22f4bSMatthew G. Knepley   PetscFunctionReturn(0);
823108a22f4bSMatthew G. Knepley }
823208a22f4bSMatthew G. Knepley 
8233ca8062c8SMatthew G. Knepley /*@
823418e14f0cSMatthew G. Knepley   DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell
823518e14f0cSMatthew G. Knepley 
823618e14f0cSMatthew G. Knepley   Input Parameters:
823718e14f0cSMatthew G. Knepley + dm    - The DMPlex
823818e14f0cSMatthew G. Knepley - label - The DMLabel
823918e14f0cSMatthew G. Knepley 
824018e14f0cSMatthew G. Knepley   Output Parameter:
824118e14f0cSMatthew G. Knepley . val - The label value field
824218e14f0cSMatthew G. Knepley 
824318e14f0cSMatthew G. Knepley   Options Database Keys:
824418e14f0cSMatthew G. Knepley . -dm_label_view - Adds the label value field into the DM output from -dm_view using the same viewer
824518e14f0cSMatthew G. Knepley 
824618e14f0cSMatthew G. Knepley   Level: intermediate
824718e14f0cSMatthew G. Knepley 
8248db781477SPatrick Sanan .seealso: `DMView()`
824918e14f0cSMatthew G. Knepley @*/
825018e14f0cSMatthew G. Knepley PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val)
825118e14f0cSMatthew G. Knepley {
825218e14f0cSMatthew G. Knepley   DM             rdm;
825318e14f0cSMatthew G. Knepley   PetscFE        fe;
825418e14f0cSMatthew G. Knepley   PetscScalar   *v;
825518e14f0cSMatthew G. Knepley   PetscInt       dim, cStart, cEnd, c;
825618e14f0cSMatthew G. Knepley 
825718e14f0cSMatthew G. Knepley   PetscFunctionBeginUser;
825818e14f0cSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
825918e14f0cSMatthew G. Knepley   PetscValidPointer(label, 2);
826018e14f0cSMatthew G. Knepley   PetscValidPointer(val, 3);
82619566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &rdm));
82629566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(rdm, &dim));
82639566063dSJacob Faibussowitsch   PetscCall(PetscFECreateDefault(PetscObjectComm((PetscObject) rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe));
82649566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject) fe, "label_value"));
82659566063dSJacob Faibussowitsch   PetscCall(DMSetField(rdm, 0, NULL, (PetscObject) fe));
82669566063dSJacob Faibussowitsch   PetscCall(PetscFEDestroy(&fe));
82679566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(rdm));
82689566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd));
82699566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(rdm, val));
82709566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject) *val, "label_value"));
82719566063dSJacob Faibussowitsch   PetscCall(VecGetArray(*val, &v));
827218e14f0cSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
827318e14f0cSMatthew G. Knepley     PetscScalar *lv;
827418e14f0cSMatthew G. Knepley     PetscInt     cval;
827518e14f0cSMatthew G. Knepley 
82769566063dSJacob Faibussowitsch     PetscCall(DMPlexPointGlobalRef(rdm, c, v, &lv));
82779566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(label, c, &cval));
827818e14f0cSMatthew G. Knepley     *lv = cval;
827918e14f0cSMatthew G. Knepley   }
82809566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(*val, &v));
82819566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&rdm));
828218e14f0cSMatthew G. Knepley   PetscFunctionReturn(0);
828318e14f0cSMatthew G. Knepley }
828418e14f0cSMatthew G. Knepley 
828518e14f0cSMatthew G. Knepley /*@
8286ca8062c8SMatthew G. Knepley   DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric.
8287ca8062c8SMatthew G. Knepley 
828869916449SMatthew G. Knepley   Input Parameter:
828969916449SMatthew G. Knepley . dm - The DMPlex object
8290ca8062c8SMatthew G. Knepley 
829195eb5ee5SVaclav Hapla   Notes:
829295eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
829395eb5ee5SVaclav Hapla 
829495eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
8295ca8062c8SMatthew G. Knepley 
8296ca8062c8SMatthew G. Knepley   Level: developer
8297ca8062c8SMatthew G. Knepley 
8298db781477SPatrick Sanan .seealso: `DMCreate()`, `DMSetFromOptions()`
8299ca8062c8SMatthew G. Knepley @*/
8300ca8062c8SMatthew G. Knepley PetscErrorCode DMPlexCheckSymmetry(DM dm)
8301ca8062c8SMatthew G. Knepley {
8302ca8062c8SMatthew G. Knepley   PetscSection    coneSection, supportSection;
8303ca8062c8SMatthew G. Knepley   const PetscInt *cone, *support;
8304ca8062c8SMatthew G. Knepley   PetscInt        coneSize, c, supportSize, s;
830557beb4faSStefano Zampini   PetscInt        pStart, pEnd, p, pp, csize, ssize;
830657beb4faSStefano Zampini   PetscBool       storagecheck = PETSC_TRUE;
8307ca8062c8SMatthew G. Knepley 
8308ca8062c8SMatthew G. Knepley   PetscFunctionBegin;
8309ca8062c8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
83109566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(dm, NULL, "-sym_dm_view"));
83119566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSection(dm, &coneSection));
83129566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSupportSection(dm, &supportSection));
8313ca8062c8SMatthew G. Knepley   /* Check that point p is found in the support of its cone points, and vice versa */
83149566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
8315ca8062c8SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
83169566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
83179566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
8318ca8062c8SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
831942e66dfaSMatthew G. Knepley       PetscBool dup = PETSC_FALSE;
832042e66dfaSMatthew G. Knepley       PetscInt  d;
832142e66dfaSMatthew G. Knepley       for (d = c-1; d >= 0; --d) {
832242e66dfaSMatthew G. Knepley         if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;}
832342e66dfaSMatthew G. Knepley       }
83249566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, cone[c], &supportSize));
83259566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupport(dm, cone[c], &support));
8326ca8062c8SMatthew G. Knepley       for (s = 0; s < supportSize; ++s) {
8327ca8062c8SMatthew G. Knepley         if (support[s] == p) break;
8328ca8062c8SMatthew G. Knepley       }
832942e66dfaSMatthew G. Knepley       if ((s >= supportSize) || (dup && (support[s+1] != p))) {
833063a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", p));
8331ca8062c8SMatthew G. Knepley         for (s = 0; s < coneSize; ++s) {
833263a3b9bcSJacob Faibussowitsch           PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[s]));
8333ca8062c8SMatthew G. Knepley         }
83349566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
833563a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", cone[c]));
8336ca8062c8SMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
833763a3b9bcSJacob Faibussowitsch           PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[s]));
8338ca8062c8SMatthew G. Knepley         }
83399566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
834063a3b9bcSJacob Faibussowitsch         PetscCheck(!dup,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not repeatedly found in support of repeated cone point %" PetscInt_FMT, p, cone[c]);
8341f7d195e4SLawrence Mitchell         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in support of cone point %" PetscInt_FMT, p, cone[c]);
8342ca8062c8SMatthew G. Knepley       }
834342e66dfaSMatthew G. Knepley     }
83449566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTreeParent(dm, p, &pp, NULL));
834557beb4faSStefano Zampini     if (p != pp) { storagecheck = PETSC_FALSE; continue; }
83469566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
83479566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dm, p, &support));
8348ca8062c8SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
83499566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, support[s], &coneSize));
83509566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, support[s], &cone));
8351ca8062c8SMatthew G. Knepley       for (c = 0; c < coneSize; ++c) {
83529566063dSJacob Faibussowitsch         PetscCall(DMPlexGetTreeParent(dm, cone[c], &pp, NULL));
835357beb4faSStefano Zampini         if (cone[c] != pp) { c = 0; break; }
8354ca8062c8SMatthew G. Knepley         if (cone[c] == p) break;
8355ca8062c8SMatthew G. Knepley       }
8356ca8062c8SMatthew G. Knepley       if (c >= coneSize) {
835763a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", p));
8358ca8062c8SMatthew G. Knepley         for (c = 0; c < supportSize; ++c) {
835963a3b9bcSJacob Faibussowitsch           PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[c]));
8360ca8062c8SMatthew G. Knepley         }
83619566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
836263a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", support[s]));
8363ca8062c8SMatthew G. Knepley         for (c = 0; c < coneSize; ++c) {
836463a3b9bcSJacob Faibussowitsch           PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[c]));
8365ca8062c8SMatthew G. Knepley         }
83669566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
836763a3b9bcSJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in cone of support point %" PetscInt_FMT, p, support[s]);
8368ca8062c8SMatthew G. Knepley       }
8369ca8062c8SMatthew G. Knepley     }
8370ca8062c8SMatthew G. Knepley   }
837157beb4faSStefano Zampini   if (storagecheck) {
83729566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coneSection, &csize));
83739566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(supportSection, &ssize));
837463a3b9bcSJacob Faibussowitsch     PetscCheck(csize == ssize,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %" PetscInt_FMT " != Total support size %" PetscInt_FMT, csize, ssize);
837557beb4faSStefano Zampini   }
8376ca8062c8SMatthew G. Knepley   PetscFunctionReturn(0);
8377ca8062c8SMatthew G. Knepley }
8378ca8062c8SMatthew G. Knepley 
8379412e9a14SMatthew G. Knepley /*
8380412e9a14SMatthew G. Knepley   For submeshes with cohesive cells (see DMPlexConstructCohesiveCells()), we allow a special case where some of the boundary of a face (edges and vertices) are not duplicated. We call these special boundary points "unsplit", since the same edge or vertex appears in both copies of the face. These unsplit points throw off our counting, so we have to explicitly account for them here.
8381412e9a14SMatthew G. Knepley */
8382412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit)
8383412e9a14SMatthew G. Knepley {
8384412e9a14SMatthew G. Knepley   DMPolytopeType  cct;
8385412e9a14SMatthew G. Knepley   PetscInt        ptpoints[4];
8386412e9a14SMatthew G. Knepley   const PetscInt *cone, *ccone, *ptcone;
8387412e9a14SMatthew G. Knepley   PetscInt        coneSize, cp, cconeSize, ccp, npt = 0, pt;
8388412e9a14SMatthew G. Knepley 
8389412e9a14SMatthew G. Knepley   PetscFunctionBegin;
8390412e9a14SMatthew G. Knepley   *unsplit = 0;
8391412e9a14SMatthew G. Knepley   switch (ct) {
8392b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_POINT_PRISM_TENSOR:
8393b5a892a1SMatthew G. Knepley       ptpoints[npt++] = c;
8394b5a892a1SMatthew G. Knepley       break;
8395412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEG_PRISM_TENSOR:
83969566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, c, &cone));
83979566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
8398412e9a14SMatthew G. Knepley       for (cp = 0; cp < coneSize; ++cp) {
83999566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, cone[cp], &cct));
8400412e9a14SMatthew G. Knepley         if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp];
8401412e9a14SMatthew G. Knepley       }
8402412e9a14SMatthew G. Knepley       break;
8403412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:
8404412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
84059566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, c, &cone));
84069566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
8407412e9a14SMatthew G. Knepley       for (cp = 0; cp < coneSize; ++cp) {
84089566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, cone[cp], &ccone));
84099566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, cone[cp], &cconeSize));
8410412e9a14SMatthew G. Knepley         for (ccp = 0; ccp < cconeSize; ++ccp) {
84119566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCellType(dm, ccone[ccp], &cct));
8412412e9a14SMatthew G. Knepley           if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) {
8413412e9a14SMatthew G. Knepley             PetscInt p;
8414412e9a14SMatthew G. Knepley             for (p = 0; p < npt; ++p) if (ptpoints[p] == ccone[ccp]) break;
8415412e9a14SMatthew G. Knepley             if (p == npt) ptpoints[npt++] = ccone[ccp];
8416412e9a14SMatthew G. Knepley           }
8417412e9a14SMatthew G. Knepley         }
8418412e9a14SMatthew G. Knepley       }
8419412e9a14SMatthew G. Knepley       break;
8420412e9a14SMatthew G. Knepley     default: break;
8421412e9a14SMatthew G. Knepley   }
8422412e9a14SMatthew G. Knepley   for (pt = 0; pt < npt; ++pt) {
84239566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, ptpoints[pt], &ptcone));
8424412e9a14SMatthew G. Knepley     if (ptcone[0] == ptcone[1]) ++(*unsplit);
8425412e9a14SMatthew G. Knepley   }
8426412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
8427412e9a14SMatthew G. Knepley }
8428412e9a14SMatthew G. Knepley 
8429ca8062c8SMatthew G. Knepley /*@
8430ca8062c8SMatthew G. Knepley   DMPlexCheckSkeleton - Check that each cell has the correct number of vertices
8431ca8062c8SMatthew G. Knepley 
8432ca8062c8SMatthew G. Knepley   Input Parameters:
8433ca8062c8SMatthew G. Knepley + dm - The DMPlex object
843458723a97SMatthew G. Knepley - cellHeight - Normally 0
8435ca8062c8SMatthew G. Knepley 
843695eb5ee5SVaclav Hapla   Notes:
843795eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
843825c50c26SVaclav Hapla   Currently applicable only to homogeneous simplex or tensor meshes.
8439ca8062c8SMatthew G. Knepley 
844095eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
844195eb5ee5SVaclav Hapla 
8442ca8062c8SMatthew G. Knepley   Level: developer
8443ca8062c8SMatthew G. Knepley 
8444db781477SPatrick Sanan .seealso: `DMCreate()`, `DMSetFromOptions()`
8445ca8062c8SMatthew G. Knepley @*/
844625c50c26SVaclav Hapla PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight)
8447ca8062c8SMatthew G. Knepley {
8448412e9a14SMatthew G. Knepley   DMPlexInterpolatedFlag interp;
8449412e9a14SMatthew G. Knepley   DMPolytopeType         ct;
8450412e9a14SMatthew G. Knepley   PetscInt               vStart, vEnd, cStart, cEnd, c;
8451ca8062c8SMatthew G. Knepley 
8452ca8062c8SMatthew G. Knepley   PetscFunctionBegin;
8453ca8062c8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
84549566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolated(dm, &interp));
84559566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
84569566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
8457412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
8458412e9a14SMatthew G. Knepley     PetscInt *closure = NULL;
8459412e9a14SMatthew G. Knepley     PetscInt  coneSize, closureSize, cl, Nv = 0;
846058723a97SMatthew G. Knepley 
84619566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
846263a3b9bcSJacob Faibussowitsch     PetscCheck((PetscInt) ct >= 0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " has no cell type", c);
8463412e9a14SMatthew G. Knepley     if (ct == DM_POLYTOPE_UNKNOWN) continue;
8464412e9a14SMatthew G. Knepley     if (interp == DMPLEX_INTERPOLATED_FULL) {
84659566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
846663a3b9bcSJacob Faibussowitsch       PetscCheck(coneSize == DMPolytopeTypeGetConeSize(ct),PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " of type %s has cone size %" PetscInt_FMT " != %" PetscInt_FMT, c, DMPolytopeTypes[ct], coneSize, DMPolytopeTypeGetConeSize(ct));
8467412e9a14SMatthew G. Knepley     }
84689566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
846958723a97SMatthew G. Knepley     for (cl = 0; cl < closureSize*2; cl += 2) {
847058723a97SMatthew G. Knepley       const PetscInt p = closure[cl];
8471412e9a14SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) ++Nv;
847258723a97SMatthew G. Knepley     }
84739566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
8474412e9a14SMatthew G. Knepley     /* Special Case: Tensor faces with identified vertices */
8475412e9a14SMatthew G. Knepley     if (Nv < DMPolytopeTypeGetNumVertices(ct)) {
8476412e9a14SMatthew G. Knepley       PetscInt unsplit;
847742363296SMatthew G. Knepley 
84789566063dSJacob Faibussowitsch       PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
8479412e9a14SMatthew G. Knepley       if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue;
848042363296SMatthew G. Knepley     }
848163a3b9bcSJacob Faibussowitsch     PetscCheck(Nv == DMPolytopeTypeGetNumVertices(ct),PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " of type %s has %" PetscInt_FMT " vertices != %" PetscInt_FMT, c, DMPolytopeTypes[ct], Nv, DMPolytopeTypeGetNumVertices(ct));
848242363296SMatthew G. Knepley   }
8483ca8062c8SMatthew G. Knepley   PetscFunctionReturn(0);
8484ca8062c8SMatthew G. Knepley }
84859bf0dad6SMatthew G. Knepley 
84869bf0dad6SMatthew G. Knepley /*@
84879bf0dad6SMatthew 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
84889bf0dad6SMatthew G. Knepley 
84898f6815adSVaclav Hapla   Collective
8490899ea2b8SJacob Faibussowitsch 
84919bf0dad6SMatthew G. Knepley   Input Parameters:
84929bf0dad6SMatthew G. Knepley + dm - The DMPlex object
84939bf0dad6SMatthew G. Knepley - cellHeight - Normally 0
84949bf0dad6SMatthew G. Knepley 
849545da879fSVaclav Hapla   Notes:
849645da879fSVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
849745da879fSVaclav Hapla   This routine is only relevant for meshes that are fully interpolated across all ranks.
849845da879fSVaclav Hapla   It will error out if a partially interpolated mesh is given on some rank.
849945da879fSVaclav Hapla   It will do nothing for locally uninterpolated mesh (as there is nothing to check).
85009bf0dad6SMatthew G. Knepley 
850195eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
850295eb5ee5SVaclav Hapla 
85039bf0dad6SMatthew G. Knepley   Level: developer
85049bf0dad6SMatthew G. Knepley 
8505db781477SPatrick Sanan .seealso: `DMCreate()`, `DMPlexGetVTKCellHeight()`, `DMSetFromOptions()`
85069bf0dad6SMatthew G. Knepley @*/
850725c50c26SVaclav Hapla PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight)
85089bf0dad6SMatthew G. Knepley {
8509ab91121cSMatthew G. Knepley   PetscInt       dim, depth, vStart, vEnd, cStart, cEnd, c, h;
8510899ea2b8SJacob Faibussowitsch   DMPlexInterpolatedFlag interpEnum;
85119bf0dad6SMatthew G. Knepley 
85129bf0dad6SMatthew G. Knepley   PetscFunctionBegin;
85139bf0dad6SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
85148f6815adSVaclav Hapla   PetscCall(DMPlexIsInterpolatedCollective(dm, &interpEnum));
851545da879fSVaclav Hapla   if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(0);
85168f6815adSVaclav Hapla   if (interpEnum != DMPLEX_INTERPOLATED_FULL) {
85178f6815adSVaclav Hapla     PetscPrintf(PetscObjectComm((PetscObject)dm), "DMPlexCheckFaces() warning: Mesh is only partially interpolated, this is currently not supported");
85188f6815adSVaclav Hapla     PetscFunctionReturn(0);
8519899ea2b8SJacob Faibussowitsch   }
8520899ea2b8SJacob Faibussowitsch 
85219566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
85229566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
85239566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
8524ab91121cSMatthew G. Knepley   for (h = cellHeight; h < PetscMin(depth, dim); ++h) {
85259566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, h, &cStart, &cEnd));
85263554e41dSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
8527412e9a14SMatthew G. Knepley       const PetscInt      *cone, *ornt, *faceSizes, *faces;
8528412e9a14SMatthew G. Knepley       const DMPolytopeType *faceTypes;
8529ba2698f1SMatthew G. Knepley       DMPolytopeType        ct;
8530412e9a14SMatthew G. Knepley       PetscInt              numFaces, coneSize, f;
8531412e9a14SMatthew G. Knepley       PetscInt             *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit;
85329bf0dad6SMatthew G. Knepley 
85339566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, c, &ct));
85349566063dSJacob Faibussowitsch       PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
8535412e9a14SMatthew G. Knepley       if (unsplit) continue;
85369566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
85379566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, c, &cone));
85389566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeOrientation(dm, c, &ornt));
85399566063dSJacob Faibussowitsch       PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
85409bf0dad6SMatthew G. Knepley       for (cl = 0; cl < closureSize*2; cl += 2) {
85419bf0dad6SMatthew G. Knepley         const PetscInt p = closure[cl];
85429bf0dad6SMatthew G. Knepley         if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p;
85439bf0dad6SMatthew G. Knepley       }
85449566063dSJacob Faibussowitsch       PetscCall(DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces));
854563a3b9bcSJacob Faibussowitsch       PetscCheck(coneSize == numFaces,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " of type %s has %" PetscInt_FMT " faces but should have %" PetscInt_FMT, c, DMPolytopeTypes[ct], coneSize, numFaces);
85469bf0dad6SMatthew G. Knepley       for (f = 0; f < numFaces; ++f) {
8547d4961f80SStefano Zampini         DMPolytopeType fct;
85489bf0dad6SMatthew G. Knepley         PetscInt       *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v;
85499bf0dad6SMatthew G. Knepley 
85509566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, cone[f], &fct));
85519566063dSJacob Faibussowitsch         PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure));
85529bf0dad6SMatthew G. Knepley         for (cl = 0; cl < fclosureSize*2; cl += 2) {
85539bf0dad6SMatthew G. Knepley           const PetscInt p = fclosure[cl];
85549bf0dad6SMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p;
85559bf0dad6SMatthew G. Knepley         }
855663a3b9bcSJacob Faibussowitsch         PetscCheck(fnumCorners == faceSizes[f],PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %" PetscInt_FMT " of type %s (cone idx %" PetscInt_FMT ") of cell %" PetscInt_FMT " of type %s has %" PetscInt_FMT " vertices but should have %" PetscInt_FMT, cone[f], DMPolytopeTypes[fct], f, c, DMPolytopeTypes[ct], fnumCorners, faceSizes[f]);
85579bf0dad6SMatthew G. Knepley         for (v = 0; v < fnumCorners; ++v) {
8558b5a892a1SMatthew G. Knepley           if (fclosure[v] != faces[fOff+v]) {
8559b5a892a1SMatthew G. Knepley             PetscInt v1;
8560b5a892a1SMatthew G. Knepley 
85619566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "face closure:"));
856263a3b9bcSJacob Faibussowitsch             for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, fclosure[v1]));
85639566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "\ncell face:"));
856463a3b9bcSJacob Faibussowitsch             for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, faces[fOff+v1]));
85659566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
856663a3b9bcSJacob Faibussowitsch             SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %" PetscInt_FMT " of type %s (cone idx %" PetscInt_FMT ", ornt %" PetscInt_FMT ") of cell %" PetscInt_FMT " of type %s vertex %" PetscInt_FMT ", %" PetscInt_FMT " != %" PetscInt_FMT, cone[f], DMPolytopeTypes[fct], f, ornt[f], c, DMPolytopeTypes[ct], v, fclosure[v], faces[fOff+v]);
8567b5a892a1SMatthew G. Knepley           }
85689bf0dad6SMatthew G. Knepley         }
85699566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure));
8570412e9a14SMatthew G. Knepley         fOff += faceSizes[f];
85719bf0dad6SMatthew G. Knepley       }
85729566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces));
85739566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
85749bf0dad6SMatthew G. Knepley     }
85753554e41dSMatthew G. Knepley   }
8576552f7358SJed Brown   PetscFunctionReturn(0);
8577552f7358SJed Brown }
85783913d7c8SMatthew G. Knepley 
8579bb6a34a8SMatthew G. Knepley /*@
8580bb6a34a8SMatthew G. Knepley   DMPlexCheckGeometry - Check the geometry of mesh cells
8581bb6a34a8SMatthew G. Knepley 
8582bb6a34a8SMatthew G. Knepley   Input Parameter:
8583bb6a34a8SMatthew G. Knepley . dm - The DMPlex object
8584bb6a34a8SMatthew G. Knepley 
858595eb5ee5SVaclav Hapla   Notes:
858695eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
858795eb5ee5SVaclav Hapla 
858895eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
8589bb6a34a8SMatthew G. Knepley 
8590bb6a34a8SMatthew G. Knepley   Level: developer
8591bb6a34a8SMatthew G. Knepley 
8592db781477SPatrick Sanan .seealso: `DMCreate()`, `DMSetFromOptions()`
8593bb6a34a8SMatthew G. Knepley @*/
8594bb6a34a8SMatthew G. Knepley PetscErrorCode DMPlexCheckGeometry(DM dm)
8595bb6a34a8SMatthew G. Knepley {
8596a2a9e04cSMatthew G. Knepley   Vec       coordinates;
8597bb6a34a8SMatthew G. Knepley   PetscReal detJ, J[9], refVol = 1.0;
8598bb6a34a8SMatthew G. Knepley   PetscReal vol;
859951a74b61SMatthew G. Knepley   PetscInt  dim, depth, dE, d, cStart, cEnd, c;
8600bb6a34a8SMatthew G. Knepley 
8601bb6a34a8SMatthew G. Knepley   PetscFunctionBegin;
86029566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
86039566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dE));
860451a74b61SMatthew G. Knepley   if (dim != dE) PetscFunctionReturn(0);
86059566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
8606bb6a34a8SMatthew G. Knepley   for (d = 0; d < dim; ++d) refVol *= 2.0;
86079566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
8608a2a9e04cSMatthew G. Knepley   /* Make sure local coordinates are created, because that step is collective */
86099566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
8610412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
8611412e9a14SMatthew G. Knepley     DMPolytopeType ct;
8612412e9a14SMatthew G. Knepley     PetscInt       unsplit;
8613412e9a14SMatthew G. Knepley     PetscBool      ignoreZeroVol = PETSC_FALSE;
8614412e9a14SMatthew G. Knepley 
86159566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
8616412e9a14SMatthew G. Knepley     switch (ct) {
8617412e9a14SMatthew G. Knepley       case DM_POLYTOPE_SEG_PRISM_TENSOR:
8618412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM_TENSOR:
8619412e9a14SMatthew G. Knepley       case DM_POLYTOPE_QUAD_PRISM_TENSOR:
8620412e9a14SMatthew G. Knepley         ignoreZeroVol = PETSC_TRUE; break;
8621412e9a14SMatthew G. Knepley       default: break;
8622412e9a14SMatthew G. Knepley     }
8623412e9a14SMatthew G. Knepley     switch (ct) {
8624412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM:
8625412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM_TENSOR:
8626412e9a14SMatthew G. Knepley       case DM_POLYTOPE_QUAD_PRISM_TENSOR:
8627a2a9e04cSMatthew G. Knepley       case DM_POLYTOPE_PYRAMID:
8628412e9a14SMatthew G. Knepley         continue;
8629412e9a14SMatthew G. Knepley       default: break;
8630412e9a14SMatthew G. Knepley     }
86319566063dSJacob Faibussowitsch     PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
8632412e9a14SMatthew G. Knepley     if (unsplit) continue;
86339566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ));
86341dca8a05SBarry Smith     PetscCheck(detJ >= -PETSC_SMALL && (detJ > 0.0 || ignoreZeroVol),PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " of type %s is inverted, |J| = %g", c, DMPolytopeTypes[ct], (double) detJ);
863563a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FEM Volume %g\n", c, (double)(detJ*refVol)));
86366858538eSMatthew G. Knepley     /* This should work with periodicity since DG coordinates should be used */
86376858538eSMatthew G. Knepley     if (depth > 1) {
86389566063dSJacob Faibussowitsch       PetscCall(DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL));
86391dca8a05SBarry Smith       PetscCheck(vol >= -PETSC_SMALL && (vol > 0.0 || ignoreZeroVol),PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " of type %s is inverted, vol = %g", c, DMPolytopeTypes[ct], (double) vol);
864063a3b9bcSJacob Faibussowitsch       PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FVM Volume %g\n", c, (double) vol));
8641bb6a34a8SMatthew G. Knepley     }
8642bb6a34a8SMatthew G. Knepley   }
8643bb6a34a8SMatthew G. Knepley   PetscFunctionReturn(0);
8644bb6a34a8SMatthew G. Knepley }
8645bb6a34a8SMatthew G. Knepley 
864603da9461SVaclav Hapla /*@
86477726db96SVaclav Hapla   DMPlexCheckPointSF - Check that several necessary conditions are met for the Point SF of this plex.
86487726db96SVaclav Hapla 
86497726db96SVaclav Hapla   Collective
865003da9461SVaclav Hapla 
865103da9461SVaclav Hapla   Input Parameters:
86527726db96SVaclav Hapla + dm - The DMPlex object
86537726db96SVaclav Hapla - pointSF - The Point SF, or NULL for Point SF attached to DM
865403da9461SVaclav Hapla 
8655e83a0d2dSVaclav Hapla   Notes:
8656e83a0d2dSVaclav Hapla   This is mainly intended for debugging/testing purposes.
865703da9461SVaclav Hapla 
865895eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
865995eb5ee5SVaclav Hapla 
866003da9461SVaclav Hapla   Level: developer
866103da9461SVaclav Hapla 
8662db781477SPatrick Sanan .seealso: `DMGetPointSF()`, `DMSetFromOptions()`
866303da9461SVaclav Hapla @*/
86647726db96SVaclav Hapla PetscErrorCode DMPlexCheckPointSF(DM dm, PetscSF pointSF)
866503da9461SVaclav Hapla {
86667726db96SVaclav Hapla   PetscInt        l, nleaves, nroots, overlap;
86677726db96SVaclav Hapla   const PetscInt *locals;
86687726db96SVaclav Hapla   const PetscSFNode *remotes;
8669f0cfc026SVaclav Hapla   PetscBool       distributed;
86707726db96SVaclav Hapla   MPI_Comm        comm;
86717726db96SVaclav Hapla   PetscMPIInt     rank;
867203da9461SVaclav Hapla 
867303da9461SVaclav Hapla   PetscFunctionBegin;
867403da9461SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
86757726db96SVaclav Hapla   if (pointSF) PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2);
86767726db96SVaclav Hapla   else         pointSF = dm->sf;
86777726db96SVaclav Hapla   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
86787726db96SVaclav Hapla   PetscCheck(pointSF, comm, PETSC_ERR_ARG_WRONGSTATE, "DMPlex must have Point SF attached");
86797726db96SVaclav Hapla   PetscCallMPI(MPI_Comm_rank(comm, &rank));
86807726db96SVaclav Hapla   {
86817726db96SVaclav Hapla     PetscMPIInt    mpiFlag;
86827726db96SVaclav Hapla 
86837726db96SVaclav Hapla     PetscCallMPI(MPI_Comm_compare(comm, PetscObjectComm((PetscObject)pointSF),&mpiFlag));
86847726db96SVaclav Hapla     PetscCheck(mpiFlag == MPI_CONGRUENT || mpiFlag == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "DM and Point SF have different communicators (flag %d)",mpiFlag);
86857726db96SVaclav Hapla   }
86867726db96SVaclav Hapla   PetscCall(PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, &remotes));
86879566063dSJacob Faibussowitsch   PetscCall(DMPlexIsDistributed(dm, &distributed));
86887726db96SVaclav Hapla   if (!distributed) {
86897726db96SVaclav Hapla     PetscCheck(nroots < 0 || nleaves == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Undistributed DMPlex cannot have non-empty PointSF (has %" PetscInt_FMT " roots, %" PetscInt_FMT " leaves)", nroots, nleaves);
86908918e3e2SVaclav Hapla     PetscFunctionReturn(0);
86918918e3e2SVaclav Hapla   }
86927726db96SVaclav Hapla   PetscCheck(nroots >= 0, comm, PETSC_ERR_ARG_WRONGSTATE, "This DMPlex is distributed but its PointSF has no graph set (has %" PetscInt_FMT " roots, %" PetscInt_FMT " leaves)", nroots, nleaves);
86937726db96SVaclav Hapla   PetscCall(DMPlexGetOverlap(dm, &overlap));
869403da9461SVaclav Hapla 
86957726db96SVaclav Hapla   /* Check SF graph is compatible with DMPlex chart */
86967726db96SVaclav Hapla   {
86977726db96SVaclav Hapla     PetscInt pStart, pEnd, maxLeaf;
86987726db96SVaclav Hapla 
86997726db96SVaclav Hapla     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
87007726db96SVaclav Hapla     PetscCall(PetscSFGetLeafRange(pointSF, NULL, &maxLeaf));
87017726db96SVaclav Hapla     PetscCheck(pEnd - pStart == nroots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "pEnd - pStart = %" PetscInt_FMT " != nroots = %" PetscInt_FMT, pEnd-pStart, nroots);
87027726db96SVaclav Hapla     PetscCheck(maxLeaf < pEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "maxLeaf = %" PetscInt_FMT " >= pEnd = %" PetscInt_FMT, maxLeaf, pEnd);
87037726db96SVaclav Hapla   }
87047726db96SVaclav Hapla 
87057726db96SVaclav Hapla   /* Check Point SF has no local points referenced */
87067726db96SVaclav Hapla   for (l = 0; l < nleaves; l++) {
87077726db96SVaclav Hapla     PetscAssert(remotes[l].rank != (PetscInt) rank, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains local point %" PetscInt_FMT " <- (%" PetscInt_FMT ",%" PetscInt_FMT ")", locals ? locals[l] : l, remotes[l].rank, remotes[l].index);
87087726db96SVaclav Hapla   }
87097726db96SVaclav Hapla 
87107726db96SVaclav Hapla   /* Check there are no cells in interface */
87117726db96SVaclav Hapla   if (!overlap) {
87127726db96SVaclav Hapla     PetscInt cellHeight, cStart, cEnd;
87137726db96SVaclav Hapla 
87149566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
87159566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
8716f5869d18SMatthew G. Knepley     for (l = 0; l < nleaves; ++l) {
87177726db96SVaclav Hapla       const PetscInt point = locals ? locals[l] : l;
8718f5869d18SMatthew G. Knepley 
87197726db96SVaclav Hapla       PetscCheck(point < cStart || point >= cEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %" PetscInt_FMT " which is a cell", point);
87207726db96SVaclav Hapla     }
872103da9461SVaclav Hapla   }
8722ece87651SVaclav Hapla 
87237726db96SVaclav Hapla   /* If some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */
87247726db96SVaclav Hapla   {
87257726db96SVaclav Hapla     const PetscInt *rootdegree;
87267726db96SVaclav Hapla 
87277726db96SVaclav Hapla     PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree));
87287726db96SVaclav Hapla     PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree));
8729f5869d18SMatthew G. Knepley     for (l = 0; l < nleaves; ++l) {
87307726db96SVaclav Hapla       const PetscInt  point = locals ? locals[l] : l;
8731f5869d18SMatthew G. Knepley       const PetscInt *cone;
8732f5869d18SMatthew G. Knepley       PetscInt        coneSize, c, idx;
8733f5869d18SMatthew G. Knepley 
87349566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, point, &coneSize));
87359566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, point, &cone));
8736f5869d18SMatthew G. Knepley       for (c = 0; c < coneSize; ++c) {
8737f5869d18SMatthew G. Knepley         if (!rootdegree[cone[c]]) {
87387726db96SVaclav Hapla           if (locals) {
87399566063dSJacob Faibussowitsch             PetscCall(PetscFindInt(cone[c], nleaves, locals, &idx));
87407726db96SVaclav Hapla           } else {
87417726db96SVaclav Hapla             idx = (cone[c] < nleaves) ? cone[c] : -1;
87427726db96SVaclav Hapla           }
874363a3b9bcSJacob Faibussowitsch           PetscCheck(idx >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %" PetscInt_FMT " but not %" PetscInt_FMT " from its cone", point, cone[c]);
8744f5869d18SMatthew G. Knepley         }
8745f5869d18SMatthew G. Knepley       }
8746ece87651SVaclav Hapla     }
87477726db96SVaclav Hapla   }
874803da9461SVaclav Hapla   PetscFunctionReturn(0);
874903da9461SVaclav Hapla }
875003da9461SVaclav Hapla 
87517f9d8d6cSVaclav Hapla /*@
87527f9d8d6cSVaclav Hapla   DMPlexCheck - Perform various checks of Plex sanity
87537f9d8d6cSVaclav Hapla 
87547f9d8d6cSVaclav Hapla   Input Parameter:
87557f9d8d6cSVaclav Hapla . dm - The DMPlex object
87567f9d8d6cSVaclav Hapla 
87577f9d8d6cSVaclav Hapla   Notes:
87587f9d8d6cSVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
87597f9d8d6cSVaclav Hapla 
87607f9d8d6cSVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
87617f9d8d6cSVaclav Hapla 
87627f9d8d6cSVaclav Hapla   Currently does not include DMPlexCheckCellShape().
87637f9d8d6cSVaclav Hapla 
87647f9d8d6cSVaclav Hapla   Level: developer
87657f9d8d6cSVaclav Hapla 
87667f9d8d6cSVaclav Hapla .seealso: DMCreate(), DMSetFromOptions()
87677f9d8d6cSVaclav Hapla @*/
87687f9d8d6cSVaclav Hapla PetscErrorCode DMPlexCheck(DM dm)
8769b5a892a1SMatthew G. Knepley {
87707f9d8d6cSVaclav Hapla   PetscInt cellHeight;
87717f9d8d6cSVaclav Hapla 
8772b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
87737f9d8d6cSVaclav Hapla   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
87749566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckSymmetry(dm));
87759566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckSkeleton(dm, cellHeight));
87769566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckFaces(dm, cellHeight));
87779566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckGeometry(dm));
87787726db96SVaclav Hapla   PetscCall(DMPlexCheckPointSF(dm, NULL));
87799566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckInterfaceCones(dm));
8780b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
8781b5a892a1SMatthew G. Knepley }
8782b5a892a1SMatthew G. Knepley 
8783068a5610SStefano Zampini typedef struct cell_stats
8784068a5610SStefano Zampini {
8785068a5610SStefano Zampini   PetscReal min, max, sum, squaresum;
8786068a5610SStefano Zampini   PetscInt  count;
8787068a5610SStefano Zampini } cell_stats_t;
8788068a5610SStefano Zampini 
878925befc3bSSatish Balay static void MPIAPI cell_stats_reduce(void *a, void *b, int * len, MPI_Datatype *datatype)
8790068a5610SStefano Zampini {
8791068a5610SStefano Zampini   PetscInt i, N = *len;
8792068a5610SStefano Zampini 
8793068a5610SStefano Zampini   for (i = 0; i < N; i++) {
8794068a5610SStefano Zampini     cell_stats_t *A = (cell_stats_t *) a;
8795068a5610SStefano Zampini     cell_stats_t *B = (cell_stats_t *) b;
8796068a5610SStefano Zampini 
8797068a5610SStefano Zampini     B->min = PetscMin(A->min,B->min);
8798068a5610SStefano Zampini     B->max = PetscMax(A->max,B->max);
8799068a5610SStefano Zampini     B->sum += A->sum;
8800068a5610SStefano Zampini     B->squaresum += A->squaresum;
8801068a5610SStefano Zampini     B->count += A->count;
8802068a5610SStefano Zampini   }
8803068a5610SStefano Zampini }
8804068a5610SStefano Zampini 
8805068a5610SStefano Zampini /*@
880643fa8764SMatthew G. Knepley   DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics.
8807068a5610SStefano Zampini 
88088261a58bSMatthew G. Knepley   Collective on dm
88098261a58bSMatthew G. Knepley 
8810068a5610SStefano Zampini   Input Parameters:
8811068a5610SStefano Zampini + dm        - The DMPlex object
881243fa8764SMatthew G. Knepley . output    - If true, statistics will be displayed on stdout
881343fa8764SMatthew G. Knepley - condLimit - Display all cells above this condition number, or PETSC_DETERMINE for no cell output
8814068a5610SStefano Zampini 
881595eb5ee5SVaclav Hapla   Notes:
881695eb5ee5SVaclav Hapla   This is mainly intended for debugging/testing purposes.
881795eb5ee5SVaclav Hapla 
881895eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
8819068a5610SStefano Zampini 
8820068a5610SStefano Zampini   Level: developer
8821068a5610SStefano Zampini 
8822db781477SPatrick Sanan .seealso: `DMSetFromOptions()`, `DMPlexComputeOrthogonalQuality()`
8823068a5610SStefano Zampini @*/
882443fa8764SMatthew G. Knepley PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit)
8825068a5610SStefano Zampini {
8826068a5610SStefano Zampini   DM             dmCoarse;
882743fa8764SMatthew G. Knepley   cell_stats_t   stats, globalStats;
882843fa8764SMatthew G. Knepley   MPI_Comm       comm = PetscObjectComm((PetscObject)dm);
882943fa8764SMatthew G. Knepley   PetscReal      *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0;
883043fa8764SMatthew G. Knepley   PetscReal      limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL;
8831412e9a14SMatthew G. Knepley   PetscInt       cdim, cStart, cEnd, c, eStart, eEnd, count = 0;
883243fa8764SMatthew G. Knepley   PetscMPIInt    rank,size;
8833068a5610SStefano Zampini 
8834068a5610SStefano Zampini   PetscFunctionBegin;
8835068a5610SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8836068a5610SStefano Zampini   stats.min   = PETSC_MAX_REAL;
8837068a5610SStefano Zampini   stats.max   = PETSC_MIN_REAL;
8838068a5610SStefano Zampini   stats.sum   = stats.squaresum = 0.;
8839068a5610SStefano Zampini   stats.count = 0;
8840068a5610SStefano Zampini 
88419566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
88429566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
88439566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm,&cdim));
88449566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ));
88459566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSimplexOrBoxCells(dm,0,&cStart,&cEnd));
88469566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm,1,&eStart,&eEnd));
8847412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; c++) {
8848068a5610SStefano Zampini     PetscInt  i;
8849068a5610SStefano Zampini     PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ;
8850068a5610SStefano Zampini 
88519566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellGeometryAffineFEM(dm,c,NULL,J,invJ,&detJ));
885263a3b9bcSJacob Faibussowitsch     PetscCheck(detJ >= 0.0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " is inverted", c);
885343fa8764SMatthew G. Knepley     for (i = 0; i < PetscSqr(cdim); ++i) {
8854068a5610SStefano Zampini       frobJ    += J[i] * J[i];
8855068a5610SStefano Zampini       frobInvJ += invJ[i] * invJ[i];
8856068a5610SStefano Zampini     }
8857068a5610SStefano Zampini     cond2 = frobJ * frobInvJ;
8858068a5610SStefano Zampini     cond  = PetscSqrtReal(cond2);
8859068a5610SStefano Zampini 
8860068a5610SStefano Zampini     stats.min        = PetscMin(stats.min,cond);
8861068a5610SStefano Zampini     stats.max        = PetscMax(stats.max,cond);
8862068a5610SStefano Zampini     stats.sum       += cond;
8863068a5610SStefano Zampini     stats.squaresum += cond2;
8864068a5610SStefano Zampini     stats.count++;
88658261a58bSMatthew G. Knepley     if (output && cond > limit) {
886643fa8764SMatthew G. Knepley       PetscSection coordSection;
886743fa8764SMatthew G. Knepley       Vec          coordsLocal;
886843fa8764SMatthew G. Knepley       PetscScalar *coords = NULL;
886943fa8764SMatthew G. Knepley       PetscInt     Nv, d, clSize, cl, *closure = NULL;
887043fa8764SMatthew G. Knepley 
88719566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal));
88729566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinateSection(dm, &coordSection));
88739566063dSJacob Faibussowitsch       PetscCall(DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords));
887463a3b9bcSJacob Faibussowitsch       PetscCall(PetscSynchronizedPrintf(comm, "[%d] Cell %" PetscInt_FMT " cond %g\n", rank, c, (double) cond));
887543fa8764SMatthew G. Knepley       for (i = 0; i < Nv/cdim; ++i) {
887663a3b9bcSJacob Faibussowitsch         PetscCall(PetscSynchronizedPrintf(comm, "  Vertex %" PetscInt_FMT ": (", i));
887743fa8764SMatthew G. Knepley         for (d = 0; d < cdim; ++d) {
88789566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscSynchronizedPrintf(comm, ", "));
88799566063dSJacob Faibussowitsch           PetscCall(PetscSynchronizedPrintf(comm, "%g", (double) PetscRealPart(coords[i*cdim+d])));
888043fa8764SMatthew G. Knepley         }
88819566063dSJacob Faibussowitsch         PetscCall(PetscSynchronizedPrintf(comm, ")\n"));
888243fa8764SMatthew G. Knepley       }
88839566063dSJacob Faibussowitsch       PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure));
888443fa8764SMatthew G. Knepley       for (cl = 0; cl < clSize*2; cl += 2) {
888543fa8764SMatthew G. Knepley         const PetscInt edge = closure[cl];
888643fa8764SMatthew G. Knepley 
888743fa8764SMatthew G. Knepley         if ((edge >= eStart) && (edge < eEnd)) {
888843fa8764SMatthew G. Knepley           PetscReal len;
888943fa8764SMatthew G. Knepley 
88909566063dSJacob Faibussowitsch           PetscCall(DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL));
889163a3b9bcSJacob Faibussowitsch           PetscCall(PetscSynchronizedPrintf(comm, "  Edge %" PetscInt_FMT ": length %g\n", edge, (double) len));
889243fa8764SMatthew G. Knepley         }
889343fa8764SMatthew G. Knepley       }
88949566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure));
88959566063dSJacob Faibussowitsch       PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords));
889643fa8764SMatthew G. Knepley     }
8897068a5610SStefano Zampini   }
88989566063dSJacob Faibussowitsch   if (output) PetscCall(PetscSynchronizedFlush(comm, NULL));
8899068a5610SStefano Zampini 
8900068a5610SStefano Zampini   if (size > 1) {
8901068a5610SStefano Zampini     PetscMPIInt   blockLengths[2] = {4,1};
8902068a5610SStefano Zampini     MPI_Aint      blockOffsets[2] = {offsetof(cell_stats_t,min),offsetof(cell_stats_t,count)};
8903068a5610SStefano Zampini     MPI_Datatype  blockTypes[2]   = {MPIU_REAL,MPIU_INT}, statType;
8904068a5610SStefano Zampini     MPI_Op        statReduce;
8905068a5610SStefano Zampini 
89069566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_create_struct(2,blockLengths,blockOffsets,blockTypes,&statType));
89079566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_commit(&statType));
89089566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce));
89099566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&stats,&globalStats,1,statType,statReduce,0,comm));
89109566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Op_free(&statReduce));
89119566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_free(&statType));
8912068a5610SStefano Zampini   } else {
89139566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(&globalStats,&stats,1));
8914068a5610SStefano Zampini   }
8915dd400576SPatrick Sanan   if (rank == 0) {
8916068a5610SStefano Zampini     count = globalStats.count;
8917068a5610SStefano Zampini     min   = globalStats.min;
8918068a5610SStefano Zampini     max   = globalStats.max;
8919068a5610SStefano Zampini     mean  = globalStats.sum / globalStats.count;
8920068a5610SStefano Zampini     stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1),0)) : 0.0;
8921068a5610SStefano Zampini   }
8922068a5610SStefano Zampini 
8923068a5610SStefano Zampini   if (output) {
892463a3b9bcSJacob Faibussowitsch     PetscCall(PetscPrintf(comm,"Mesh with %" PetscInt_FMT " cells, shape condition numbers: min = %g, max = %g, mean = %g, stddev = %g\n", count, (double) min, (double) max, (double) mean, (double) stdev));
8925068a5610SStefano Zampini   }
89269566063dSJacob Faibussowitsch   PetscCall(PetscFree2(J,invJ));
8927068a5610SStefano Zampini 
89289566063dSJacob Faibussowitsch   PetscCall(DMGetCoarseDM(dm,&dmCoarse));
8929068a5610SStefano Zampini   if (dmCoarse) {
8930068a5610SStefano Zampini     PetscBool isplex;
8931068a5610SStefano Zampini 
89329566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)dmCoarse,DMPLEX,&isplex));
89331baa6e33SBarry Smith     if (isplex) PetscCall(DMPlexCheckCellShape(dmCoarse,output,condLimit));
8934068a5610SStefano Zampini   }
8935068a5610SStefano Zampini   PetscFunctionReturn(0);
8936068a5610SStefano Zampini }
8937068a5610SStefano Zampini 
8938f108dbd7SJacob Faibussowitsch /*@
8939f108dbd7SJacob Faibussowitsch   DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with
8940f108dbd7SJacob Faibussowitsch   orthogonal quality below given tolerance.
8941f108dbd7SJacob Faibussowitsch 
89426ed19f2fSJacob Faibussowitsch   Collective on dm
8943f108dbd7SJacob Faibussowitsch 
8944f108dbd7SJacob Faibussowitsch   Input Parameters:
8945f108dbd7SJacob Faibussowitsch + dm   - The DMPlex object
8946f108dbd7SJacob Faibussowitsch . fv   - Optional PetscFV object for pre-computed cell/face centroid information
8947f108dbd7SJacob Faibussowitsch - atol - [0, 1] Absolute tolerance for tagging cells.
8948f108dbd7SJacob Faibussowitsch 
8949f108dbd7SJacob Faibussowitsch   Output Parameters:
8950f108dbd7SJacob Faibussowitsch + OrthQual      - Vec containing orthogonal quality per cell
8951f108dbd7SJacob Faibussowitsch - OrthQualLabel - DMLabel tagging cells below atol with DM_ADAPT_REFINE
8952f108dbd7SJacob Faibussowitsch 
8953f108dbd7SJacob Faibussowitsch   Options Database Keys:
8954f108dbd7SJacob Faibussowitsch + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only PETSCVIEWERASCII is
8955f108dbd7SJacob Faibussowitsch supported.
8956f108dbd7SJacob Faibussowitsch - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector.
8957f108dbd7SJacob Faibussowitsch 
8958f108dbd7SJacob Faibussowitsch   Notes:
8959f108dbd7SJacob Faibussowitsch   Orthogonal quality is given by the following formula:
8960f108dbd7SJacob Faibussowitsch 
8961f108dbd7SJacob Faibussowitsch   \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right]
8962f108dbd7SJacob Faibussowitsch 
8963f108dbd7SJacob 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
8964f108dbd7SJacob Faibussowitsch   is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the
8965f108dbd7SJacob Faibussowitsch   current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by
8966f108dbd7SJacob Faibussowitsch   calculating the cosine of the angle between these vectors.
8967f108dbd7SJacob Faibussowitsch 
8968f108dbd7SJacob Faibussowitsch   Orthogonal quality ranges from 1 (best) to 0 (worst).
8969f108dbd7SJacob Faibussowitsch 
8970f108dbd7SJacob Faibussowitsch   This routine is mainly useful for FVM, however is not restricted to only FVM. The PetscFV object is optionally used to check for
8971f108dbd7SJacob Faibussowitsch   pre-computed FVM cell data, but if it is not passed in then this data will be computed.
8972f108dbd7SJacob Faibussowitsch 
8973f108dbd7SJacob Faibussowitsch   Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance.
8974f108dbd7SJacob Faibussowitsch 
8975f108dbd7SJacob Faibussowitsch   Level: intermediate
8976f108dbd7SJacob Faibussowitsch 
8977db781477SPatrick Sanan .seealso: `DMPlexCheckCellShape()`, `DMCreateLabel()`
8978f108dbd7SJacob Faibussowitsch @*/
8979f108dbd7SJacob Faibussowitsch PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel)
8980f108dbd7SJacob Faibussowitsch {
89816ed19f2fSJacob Faibussowitsch   PetscInt                nc, cellHeight, cStart, cEnd, cell, cellIter = 0;
89826ed19f2fSJacob Faibussowitsch   PetscInt                *idx;
89836ed19f2fSJacob Faibussowitsch   PetscScalar             *oqVals;
8984f108dbd7SJacob Faibussowitsch   const PetscScalar       *cellGeomArr, *faceGeomArr;
89856ed19f2fSJacob Faibussowitsch   PetscReal               *ci, *fi, *Ai;
8986f108dbd7SJacob Faibussowitsch   MPI_Comm                comm;
8987f108dbd7SJacob Faibussowitsch   Vec                     cellgeom, facegeom;
8988f108dbd7SJacob Faibussowitsch   DM                      dmFace, dmCell;
8989f108dbd7SJacob Faibussowitsch   IS                      glob;
8990f108dbd7SJacob Faibussowitsch   ISLocalToGlobalMapping  ltog;
8991f108dbd7SJacob Faibussowitsch   PetscViewer             vwr;
8992f108dbd7SJacob Faibussowitsch 
8993f108dbd7SJacob Faibussowitsch   PetscFunctionBegin;
8994f108dbd7SJacob Faibussowitsch   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
89956ed19f2fSJacob Faibussowitsch   if (fv) {PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2);}
8996f108dbd7SJacob Faibussowitsch   PetscValidPointer(OrthQual, 4);
89976bdcaf15SBarry Smith   PetscCheck(atol >= 0.0 && atol <= 1.0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Absolute tolerance %g not in [0,1]",(double)atol);
89989566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject) dm, &comm));
89999566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &nc));
900063a3b9bcSJacob Faibussowitsch   PetscCheck(nc >= 2,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %" PetscInt_FMT ")", nc);
90016ed19f2fSJacob Faibussowitsch   {
90026ed19f2fSJacob Faibussowitsch     DMPlexInterpolatedFlag interpFlag;
90036ed19f2fSJacob Faibussowitsch 
90049566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated(dm, &interpFlag));
9005f108dbd7SJacob Faibussowitsch     if (interpFlag != DMPLEX_INTERPOLATED_FULL) {
9006f108dbd7SJacob Faibussowitsch       PetscMPIInt rank;
9007f108dbd7SJacob Faibussowitsch 
90089566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(comm, &rank));
900998921bdaSJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank);
9010f108dbd7SJacob Faibussowitsch     }
90116ed19f2fSJacob Faibussowitsch   }
9012f108dbd7SJacob Faibussowitsch   if (OrthQualLabel) {
9013f108dbd7SJacob Faibussowitsch     PetscValidPointer(OrthQualLabel, 5);
90149566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(dm, "Orthogonal_Quality"));
90159566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel));
90166ed19f2fSJacob Faibussowitsch   } else {*OrthQualLabel = NULL;}
90179566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
90189566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
90199566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob));
90209566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreateIS(glob, &ltog));
90219566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH));
90229566063dSJacob Faibussowitsch   PetscCall(VecCreate(comm, OrthQual));
90239566063dSJacob Faibussowitsch   PetscCall(VecSetType(*OrthQual, VECSTANDARD));
90249566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(*OrthQual, cEnd-cStart, PETSC_DETERMINE));
90259566063dSJacob Faibussowitsch   PetscCall(VecSetLocalToGlobalMapping(*OrthQual, ltog));
90269566063dSJacob Faibussowitsch   PetscCall(VecSetUp(*OrthQual));
90279566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&glob));
90289566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&ltog));
90299566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL));
90309566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(cellgeom, &cellGeomArr));
90319566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(facegeom, &faceGeomArr));
90329566063dSJacob Faibussowitsch   PetscCall(VecGetDM(cellgeom, &dmCell));
90339566063dSJacob Faibussowitsch   PetscCall(VecGetDM(facegeom, &dmFace));
90349566063dSJacob Faibussowitsch   PetscCall(PetscMalloc5(cEnd-cStart, &idx, cEnd-cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai));
90356ed19f2fSJacob Faibussowitsch   for (cell = cStart; cell < cEnd; cellIter++,cell++) {
90366ed19f2fSJacob Faibussowitsch     PetscInt           cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE;
9037f108dbd7SJacob Faibussowitsch     PetscInt           cellarr[2], *adj = NULL;
9038f108dbd7SJacob Faibussowitsch     PetscScalar        *cArr, *fArr;
9039898cd552SSatish Balay     PetscReal          minvalc = 1.0, minvalf = 1.0;
9040f108dbd7SJacob Faibussowitsch     PetscFVCellGeom    *cg;
9041f108dbd7SJacob Faibussowitsch 
90426ed19f2fSJacob Faibussowitsch     idx[cellIter] = cell-cStart;
9043f108dbd7SJacob Faibussowitsch     cellarr[0] = cell;
9044f108dbd7SJacob Faibussowitsch     /* Make indexing into cellGeom easier */
90459566063dSJacob Faibussowitsch     PetscCall(DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg));
90469566063dSJacob Faibussowitsch     PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj));
9047f108dbd7SJacob Faibussowitsch     /* Technically 1 too big, but easier than fiddling with empty adjacency array */
90489566063dSJacob Faibussowitsch     PetscCall(PetscCalloc2(adjSize, &cArr, adjSize, &fArr));
90496ed19f2fSJacob Faibussowitsch     for (cellneigh = 0; cellneigh < adjSize; cellneighiter++,cellneigh++) {
90506ed19f2fSJacob Faibussowitsch       PetscInt         i;
90516ed19f2fSJacob Faibussowitsch       const PetscInt   neigh = adj[cellneigh];
9052f108dbd7SJacob Faibussowitsch       PetscReal        normci = 0, normfi = 0, normai = 0;
9053f108dbd7SJacob Faibussowitsch       PetscFVCellGeom  *cgneigh;
9054f108dbd7SJacob Faibussowitsch       PetscFVFaceGeom  *fg;
9055f108dbd7SJacob Faibussowitsch 
9056f108dbd7SJacob Faibussowitsch       /* Don't count ourselves in the neighbor list */
9057f108dbd7SJacob Faibussowitsch       if (neigh == cell) continue;
90589566063dSJacob Faibussowitsch       PetscCall(DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh));
9059f108dbd7SJacob Faibussowitsch       cellarr[1] = neigh;
90606ed19f2fSJacob Faibussowitsch       {
90616ed19f2fSJacob Faibussowitsch         PetscInt       numcovpts;
90626ed19f2fSJacob Faibussowitsch         const PetscInt *covpts;
90636ed19f2fSJacob Faibussowitsch 
90649566063dSJacob Faibussowitsch         PetscCall(DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts));
90659566063dSJacob Faibussowitsch         PetscCall(DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg));
90669566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts));
90676ed19f2fSJacob Faibussowitsch       }
9068f108dbd7SJacob Faibussowitsch 
9069f108dbd7SJacob Faibussowitsch       /* Compute c_i, f_i and their norms */
9070f108dbd7SJacob Faibussowitsch       for (i = 0; i < nc; i++) {
9071f108dbd7SJacob Faibussowitsch         ci[i] = cgneigh->centroid[i] - cg->centroid[i];
9072f108dbd7SJacob Faibussowitsch         fi[i] = fg->centroid[i] - cg->centroid[i];
9073f108dbd7SJacob Faibussowitsch         Ai[i] = fg->normal[i];
9074addd1e01SJunchao Zhang         normci += PetscPowReal(ci[i], 2);
9075addd1e01SJunchao Zhang         normfi += PetscPowReal(fi[i], 2);
9076addd1e01SJunchao Zhang         normai += PetscPowReal(Ai[i], 2);
9077f108dbd7SJacob Faibussowitsch       }
9078addd1e01SJunchao Zhang       normci = PetscSqrtReal(normci);
9079addd1e01SJunchao Zhang       normfi = PetscSqrtReal(normfi);
9080addd1e01SJunchao Zhang       normai = PetscSqrtReal(normai);
9081f108dbd7SJacob Faibussowitsch 
9082f108dbd7SJacob Faibussowitsch       /* Normalize and compute for each face-cell-normal pair */
9083f108dbd7SJacob Faibussowitsch       for (i = 0; i < nc; i++) {
9084f108dbd7SJacob Faibussowitsch         ci[i] = ci[i]/normci;
9085f108dbd7SJacob Faibussowitsch         fi[i] = fi[i]/normfi;
9086f108dbd7SJacob Faibussowitsch         Ai[i] = Ai[i]/normai;
9087f108dbd7SJacob Faibussowitsch         /* PetscAbs because I don't know if normals are guaranteed to point out */
9088f108dbd7SJacob Faibussowitsch         cArr[cellneighiter] += PetscAbs(Ai[i]*ci[i]);
9089f108dbd7SJacob Faibussowitsch         fArr[cellneighiter] += PetscAbs(Ai[i]*fi[i]);
9090f108dbd7SJacob Faibussowitsch       }
9091f108dbd7SJacob Faibussowitsch       if (PetscRealPart(cArr[cellneighiter]) < minvalc) {
9092f108dbd7SJacob Faibussowitsch         minvalc = PetscRealPart(cArr[cellneighiter]);
9093f108dbd7SJacob Faibussowitsch       }
9094f108dbd7SJacob Faibussowitsch       if (PetscRealPart(fArr[cellneighiter]) < minvalf) {
9095f108dbd7SJacob Faibussowitsch         minvalf = PetscRealPart(fArr[cellneighiter]);
9096f108dbd7SJacob Faibussowitsch       }
9097f108dbd7SJacob Faibussowitsch     }
90989566063dSJacob Faibussowitsch     PetscCall(PetscFree(adj));
90999566063dSJacob Faibussowitsch     PetscCall(PetscFree2(cArr, fArr));
9100f108dbd7SJacob Faibussowitsch     /* Defer to cell if they're equal */
91016ed19f2fSJacob Faibussowitsch     oqVals[cellIter] = PetscMin(minvalf, minvalc);
9102f108dbd7SJacob Faibussowitsch     if (OrthQualLabel) {
91039566063dSJacob Faibussowitsch       if (PetscRealPart(oqVals[cellIter]) <= atol) PetscCall(DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE));
9104f108dbd7SJacob Faibussowitsch     }
9105f108dbd7SJacob Faibussowitsch   }
91069566063dSJacob Faibussowitsch   PetscCall(VecSetValuesLocal(*OrthQual, cEnd-cStart, idx, oqVals, INSERT_VALUES));
91079566063dSJacob Faibussowitsch   PetscCall(VecAssemblyBegin(*OrthQual));
91089566063dSJacob Faibussowitsch   PetscCall(VecAssemblyEnd(*OrthQual));
91099566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(cellgeom, &cellGeomArr));
91109566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(facegeom, &faceGeomArr));
91119566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL));
9112f108dbd7SJacob Faibussowitsch   if (OrthQualLabel) {
91139566063dSJacob Faibussowitsch     if (vwr) PetscCall(DMLabelView(*OrthQualLabel, vwr));
9114f108dbd7SJacob Faibussowitsch   }
91159566063dSJacob Faibussowitsch   PetscCall(PetscFree5(idx, oqVals, ci, fi, Ai));
91169566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(&vwr));
91179566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view"));
9118f108dbd7SJacob Faibussowitsch   PetscFunctionReturn(0);
9119f108dbd7SJacob Faibussowitsch }
9120f108dbd7SJacob Faibussowitsch 
91211eb70e55SToby Isaac /* this is here insead of DMGetOutputDM because output DM still has constraints in the local indices that affect
91221eb70e55SToby Isaac  * interpolator construction */
91231eb70e55SToby Isaac static PetscErrorCode DMGetFullDM(DM dm, DM *odm)
91241eb70e55SToby Isaac {
91251eb70e55SToby Isaac   PetscSection   section, newSection, gsection;
91261eb70e55SToby Isaac   PetscSF        sf;
91271eb70e55SToby Isaac   PetscBool      hasConstraints, ghasConstraints;
91281eb70e55SToby Isaac 
91291eb70e55SToby Isaac   PetscFunctionBegin;
91301eb70e55SToby Isaac   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
91311eb70e55SToby Isaac   PetscValidPointer(odm,2);
91329566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
91339566063dSJacob Faibussowitsch   PetscCall(PetscSectionHasConstraints(section, &hasConstraints));
91349566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm)));
91351eb70e55SToby Isaac   if (!ghasConstraints) {
91369566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm));
91371eb70e55SToby Isaac     *odm = dm;
91381eb70e55SToby Isaac     PetscFunctionReturn(0);
91391eb70e55SToby Isaac   }
91409566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, odm));
91419566063dSJacob Faibussowitsch   PetscCall(DMCopyFields(dm, *odm));
91429566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(*odm, &newSection));
91439566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(*odm, &sf));
91449566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_FALSE, &gsection));
91459566063dSJacob Faibussowitsch   PetscCall(DMSetGlobalSection(*odm, gsection));
91469566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&gsection));
91471eb70e55SToby Isaac   PetscFunctionReturn(0);
91481eb70e55SToby Isaac }
91491eb70e55SToby Isaac 
91501eb70e55SToby Isaac static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift)
91511eb70e55SToby Isaac {
91521eb70e55SToby Isaac   DM             dmco, dmfo;
91531eb70e55SToby Isaac   Mat            interpo;
91541eb70e55SToby Isaac   Vec            rscale;
91551eb70e55SToby Isaac   Vec            cglobalo, clocal;
91561eb70e55SToby Isaac   Vec            fglobal, fglobalo, flocal;
91571eb70e55SToby Isaac   PetscBool      regular;
91581eb70e55SToby Isaac 
91591eb70e55SToby Isaac   PetscFunctionBegin;
91609566063dSJacob Faibussowitsch   PetscCall(DMGetFullDM(dmc, &dmco));
91619566063dSJacob Faibussowitsch   PetscCall(DMGetFullDM(dmf, &dmfo));
91629566063dSJacob Faibussowitsch   PetscCall(DMSetCoarseDM(dmfo, dmco));
91639566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRegularRefinement(dmf, &regular));
91649566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRegularRefinement(dmfo, regular));
91659566063dSJacob Faibussowitsch   PetscCall(DMCreateInterpolation(dmco, dmfo, &interpo, &rscale));
91669566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmco, &cglobalo));
91679566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dmc, &clocal));
91689566063dSJacob Faibussowitsch   PetscCall(VecSet(cglobalo, 0.));
91699566063dSJacob Faibussowitsch   PetscCall(VecSet(clocal, 0.));
91709566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmf, &fglobal));
91719566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmfo, &fglobalo));
91729566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dmf, &flocal));
91739566063dSJacob Faibussowitsch   PetscCall(VecSet(fglobal, 0.));
91749566063dSJacob Faibussowitsch   PetscCall(VecSet(fglobalo, 0.));
91759566063dSJacob Faibussowitsch   PetscCall(VecSet(flocal, 0.));
91769566063dSJacob Faibussowitsch   PetscCall(DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL));
91779566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo));
91789566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo));
91799566063dSJacob Faibussowitsch   PetscCall(MatMult(interpo, cglobalo, fglobalo));
91809566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal));
91819566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal));
91829566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal));
91839566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal));
91841eb70e55SToby Isaac   *shift = fglobal;
91859566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&flocal));
91869566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&fglobalo));
91879566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&clocal));
91889566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&cglobalo));
91899566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&rscale));
91909566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&interpo));
91919566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmfo));
91929566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmco));
91931eb70e55SToby Isaac   PetscFunctionReturn(0);
91941eb70e55SToby Isaac }
91951eb70e55SToby Isaac 
91961eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol)
91971eb70e55SToby Isaac {
91981eb70e55SToby Isaac   PetscObject    shifto;
91991eb70e55SToby Isaac   Vec            shift;
92001eb70e55SToby Isaac 
92011eb70e55SToby Isaac   PetscFunctionBegin;
92021eb70e55SToby Isaac   if (!interp) {
92031eb70e55SToby Isaac     Vec rscale;
92041eb70e55SToby Isaac 
92059566063dSJacob Faibussowitsch     PetscCall(DMCreateInterpolation(coarse, fine, &interp, &rscale));
92069566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&rscale));
92071eb70e55SToby Isaac   } else {
92089566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)interp));
92091eb70e55SToby Isaac   }
92109566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto));
92111eb70e55SToby Isaac   if (!shifto) {
92129566063dSJacob Faibussowitsch     PetscCall(DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift));
92139566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject) shift));
92141eb70e55SToby Isaac     shifto = (PetscObject) shift;
92159566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&shift));
92161eb70e55SToby Isaac   }
92171eb70e55SToby Isaac   shift = (Vec) shifto;
92189566063dSJacob Faibussowitsch   PetscCall(MatInterpolate(interp, coarseSol, fineSol));
92199566063dSJacob Faibussowitsch   PetscCall(VecAXPY(fineSol, 1.0, shift));
92209566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&interp));
92211eb70e55SToby Isaac   PetscFunctionReturn(0);
92221eb70e55SToby Isaac }
92231eb70e55SToby Isaac 
9224bceba477SMatthew G. Knepley /* Pointwise interpolation
9225bceba477SMatthew G. Knepley      Just code FEM for now
9226bceba477SMatthew G. Knepley      u^f = I u^c
92274ca5e9f5SMatthew G. Knepley      sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j
92284ca5e9f5SMatthew G. Knepley      u^f_i = sum_j psi^f_i I phi^c_j u^c_j
92294ca5e9f5SMatthew G. Knepley      I_{ij} = psi^f_i phi^c_j
9230bceba477SMatthew G. Knepley */
9231bceba477SMatthew G. Knepley PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling)
9232bceba477SMatthew G. Knepley {
9233bceba477SMatthew G. Knepley   PetscSection   gsc, gsf;
9234bceba477SMatthew G. Knepley   PetscInt       m, n;
9235a063dac3SMatthew G. Knepley   void          *ctx;
923668132eb9SMatthew G. Knepley   DM             cdm;
9237cf51de39SMatthew G. Knepley   PetscBool      regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE;
9238bceba477SMatthew G. Knepley 
9239bceba477SMatthew G. Knepley   PetscFunctionBegin;
92409566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmFine, &gsf));
92419566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m));
92429566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmCoarse, &gsc));
92439566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n));
924468132eb9SMatthew G. Knepley 
92459566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis));
92469566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation));
92479566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE));
92489566063dSJacob Faibussowitsch   PetscCall(MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype));
92499566063dSJacob Faibussowitsch   PetscCall(DMGetApplicationContext(dmFine, &ctx));
925068132eb9SMatthew G. Knepley 
92519566063dSJacob Faibussowitsch   PetscCall(DMGetCoarseDM(dmFine, &cdm));
92529566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRegularRefinement(dmFine, &regular));
92539566063dSJacob Faibussowitsch   if (!isRefined || (regular && cdm == dmCoarse)) PetscCall(DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx));
92549566063dSJacob Faibussowitsch   else                                            PetscCall(DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx));
92559566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view"));
92564db47ee9SStefano Zampini   if (scaling) {
92575d1c2e58SMatthew G. Knepley     /* Use naive scaling */
92589566063dSJacob Faibussowitsch     PetscCall(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling));
92594db47ee9SStefano Zampini   }
9260a063dac3SMatthew G. Knepley   PetscFunctionReturn(0);
9261a063dac3SMatthew G. Knepley }
9262bceba477SMatthew G. Knepley 
92636dbf9973SLawrence Mitchell PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat)
9264a063dac3SMatthew G. Knepley {
92656dbf9973SLawrence Mitchell   VecScatter     ctx;
926690748bafSMatthew G. Knepley 
9267a063dac3SMatthew G. Knepley   PetscFunctionBegin;
92689566063dSJacob Faibussowitsch   PetscCall(DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL));
92699566063dSJacob Faibussowitsch   PetscCall(MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat));
92709566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&ctx));
9271bceba477SMatthew G. Knepley   PetscFunctionReturn(0);
9272bceba477SMatthew G. Knepley }
9273bceba477SMatthew G. Knepley 
92743e9753d6SMatthew G. Knepley static void g0_identity_private(PetscInt dim, PetscInt Nf, PetscInt NfAux,
92753e9753d6SMatthew G. Knepley                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
92763e9753d6SMatthew G. Knepley                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
92773e9753d6SMatthew G. Knepley                                 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[])
92783e9753d6SMatthew G. Knepley {
927900635df3SMatthew G. Knepley   const PetscInt Nc = uOff[1] - uOff[0];
928000635df3SMatthew G. Knepley   PetscInt       c;
928100635df3SMatthew G. Knepley   for (c = 0; c < Nc; ++c) g0[c*Nc+c] = 1.0;
92823e9753d6SMatthew G. Knepley }
92833e9753d6SMatthew G. Knepley 
9284b4937a87SMatthew G. Knepley PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *mass)
9285b4937a87SMatthew G. Knepley {
9286b4937a87SMatthew G. Knepley   DM             dmc;
9287b4937a87SMatthew G. Knepley   PetscDS        ds;
9288b4937a87SMatthew G. Knepley   Vec            ones, locmass;
9289b4937a87SMatthew G. Knepley   IS             cellIS;
9290b4937a87SMatthew G. Knepley   PetscFormKey   key;
9291b4937a87SMatthew G. Knepley   PetscInt       depth;
9292b4937a87SMatthew G. Knepley 
9293b4937a87SMatthew G. Knepley   PetscFunctionBegin;
92949566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &dmc));
92959566063dSJacob Faibussowitsch   PetscCall(DMCopyDisc(dm, dmc));
92969566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dmc, &ds));
92979566063dSJacob Faibussowitsch   PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL));
92989566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmc, mass));
92999566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dmc, &ones));
93009566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dmc, &locmass));
93019566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmc, &depth));
93029566063dSJacob Faibussowitsch   PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS));
93039566063dSJacob Faibussowitsch   PetscCall(VecSet(locmass, 0.0));
93049566063dSJacob Faibussowitsch   PetscCall(VecSet(ones, 1.0));
9305b4937a87SMatthew G. Knepley   key.label = NULL;
9306b4937a87SMatthew G. Knepley   key.value = 0;
9307b4937a87SMatthew G. Knepley   key.field = 0;
9308b4937a87SMatthew G. Knepley   key.part  = 0;
93099566063dSJacob Faibussowitsch   PetscCall(DMPlexComputeJacobian_Action_Internal(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL));
93109566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&cellIS));
93119566063dSJacob Faibussowitsch   PetscCall(VecSet(*mass, 0.0));
93129566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmc, locmass, ADD_VALUES, *mass));
93139566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmc, locmass, ADD_VALUES, *mass));
93149566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dmc, &ones));
93159566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dmc, &locmass));
93169566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmc));
9317b4937a87SMatthew G. Knepley   PetscFunctionReturn(0);
9318b4937a87SMatthew G. Knepley }
9319b4937a87SMatthew G. Knepley 
9320bd041c0cSMatthew G. Knepley PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass)
9321bd041c0cSMatthew G. Knepley {
9322bd041c0cSMatthew G. Knepley   PetscSection   gsc, gsf;
9323bd041c0cSMatthew G. Knepley   PetscInt       m, n;
9324bd041c0cSMatthew G. Knepley   void          *ctx;
9325bd041c0cSMatthew G. Knepley   DM             cdm;
9326bd041c0cSMatthew G. Knepley   PetscBool      regular;
9327bd041c0cSMatthew G. Knepley 
9328bd041c0cSMatthew G. Knepley   PetscFunctionBegin;
93293e9753d6SMatthew G. Knepley   if (dmFine == dmCoarse) {
93303e9753d6SMatthew G. Knepley     DM            dmc;
93313e9753d6SMatthew G. Knepley     PetscDS       ds;
9332b4937a87SMatthew G. Knepley     PetscWeakForm wf;
93333e9753d6SMatthew G. Knepley     Vec           u;
93343e9753d6SMatthew G. Knepley     IS            cellIS;
933506ad1575SMatthew G. Knepley     PetscFormKey  key;
93363e9753d6SMatthew G. Knepley     PetscInt      depth;
93373e9753d6SMatthew G. Knepley 
93389566063dSJacob Faibussowitsch     PetscCall(DMClone(dmFine, &dmc));
93399566063dSJacob Faibussowitsch     PetscCall(DMCopyDisc(dmFine, dmc));
93409566063dSJacob Faibussowitsch     PetscCall(DMGetDS(dmc, &ds));
93419566063dSJacob Faibussowitsch     PetscCall(PetscDSGetWeakForm(ds, &wf));
93429566063dSJacob Faibussowitsch     PetscCall(PetscWeakFormClear(wf));
93439566063dSJacob Faibussowitsch     PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL));
93449566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(dmc, mass));
93459566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalVector(dmc, &u));
93469566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dmc, &depth));
93479566063dSJacob Faibussowitsch     PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS));
93489566063dSJacob Faibussowitsch     PetscCall(MatZeroEntries(*mass));
93496528b96dSMatthew G. Knepley     key.label = NULL;
93506528b96dSMatthew G. Knepley     key.value = 0;
93516528b96dSMatthew G. Knepley     key.field = 0;
935206ad1575SMatthew G. Knepley     key.part  = 0;
93539566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL));
93549566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&cellIS));
93559566063dSJacob Faibussowitsch     PetscCall(DMRestoreGlobalVector(dmc, &u));
93569566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&dmc));
93573e9753d6SMatthew G. Knepley   } else {
93589566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dmFine, &gsf));
93599566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m));
93609566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dmCoarse, &gsc));
93619566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n));
9362bd041c0cSMatthew G. Knepley 
93639566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass));
93649566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE));
93659566063dSJacob Faibussowitsch     PetscCall(MatSetType(*mass, dmCoarse->mattype));
93669566063dSJacob Faibussowitsch     PetscCall(DMGetApplicationContext(dmFine, &ctx));
9367bd041c0cSMatthew G. Knepley 
93689566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dmFine, &cdm));
93699566063dSJacob Faibussowitsch     PetscCall(DMPlexGetRegularRefinement(dmFine, &regular));
93709566063dSJacob Faibussowitsch     if (regular && cdm == dmCoarse) PetscCall(DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx));
93719566063dSJacob Faibussowitsch     else                            PetscCall(DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx));
93723e9753d6SMatthew G. Knepley   }
93739566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view"));
9374bd041c0cSMatthew G. Knepley   PetscFunctionReturn(0);
9375bd041c0cSMatthew G. Knepley }
9376bd041c0cSMatthew G. Knepley 
93770aef6b92SMatthew G. Knepley /*@
93780aef6b92SMatthew G. Knepley   DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh
93790aef6b92SMatthew G. Knepley 
93800aef6b92SMatthew G. Knepley   Input Parameter:
93810aef6b92SMatthew G. Knepley . dm - The DMPlex object
93820aef6b92SMatthew G. Knepley 
93830aef6b92SMatthew G. Knepley   Output Parameter:
93840aef6b92SMatthew G. Knepley . regular - The flag
93850aef6b92SMatthew G. Knepley 
93860aef6b92SMatthew G. Knepley   Level: intermediate
93870aef6b92SMatthew G. Knepley 
9388db781477SPatrick Sanan .seealso: `DMPlexSetRegularRefinement()`
93890aef6b92SMatthew G. Knepley @*/
93900aef6b92SMatthew G. Knepley PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular)
93910aef6b92SMatthew G. Knepley {
93920aef6b92SMatthew G. Knepley   PetscFunctionBegin;
93930aef6b92SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9394dadcf809SJacob Faibussowitsch   PetscValidBoolPointer(regular, 2);
93950aef6b92SMatthew G. Knepley   *regular = ((DM_Plex *) dm->data)->regularRefinement;
93960aef6b92SMatthew G. Knepley   PetscFunctionReturn(0);
93970aef6b92SMatthew G. Knepley }
93980aef6b92SMatthew G. Knepley 
93990aef6b92SMatthew G. Knepley /*@
94000aef6b92SMatthew G. Knepley   DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh
94010aef6b92SMatthew G. Knepley 
94020aef6b92SMatthew G. Knepley   Input Parameters:
94030aef6b92SMatthew G. Knepley + dm - The DMPlex object
94040aef6b92SMatthew G. Knepley - regular - The flag
94050aef6b92SMatthew G. Knepley 
94060aef6b92SMatthew G. Knepley   Level: intermediate
94070aef6b92SMatthew G. Knepley 
9408db781477SPatrick Sanan .seealso: `DMPlexGetRegularRefinement()`
94090aef6b92SMatthew G. Knepley @*/
94100aef6b92SMatthew G. Knepley PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular)
94110aef6b92SMatthew G. Knepley {
94120aef6b92SMatthew G. Knepley   PetscFunctionBegin;
94130aef6b92SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
94140aef6b92SMatthew G. Knepley   ((DM_Plex *) dm->data)->regularRefinement = regular;
94150aef6b92SMatthew G. Knepley   PetscFunctionReturn(0);
94160aef6b92SMatthew G. Knepley }
94170aef6b92SMatthew G. Knepley 
9418f7c74593SToby Isaac /* anchors */
9419a68b90caSToby Isaac /*@
9420f7c74593SToby Isaac   DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints.  Typically, the user will not have to
9421ebdb1bfaSJed Brown   call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetDefaultConstraints().
9422a68b90caSToby Isaac 
9423e228b242SToby Isaac   not collective
9424a68b90caSToby Isaac 
9425f899ff85SJose E. Roman   Input Parameter:
9426a68b90caSToby Isaac . dm - The DMPlex object
9427a68b90caSToby Isaac 
9428a68b90caSToby Isaac   Output Parameters:
9429a68b90caSToby Isaac + anchorSection - If not NULL, set to the section describing which points anchor the constrained points.
9430a68b90caSToby Isaac - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection
9431a68b90caSToby Isaac 
9432a68b90caSToby Isaac   Level: intermediate
9433a68b90caSToby Isaac 
9434db781477SPatrick Sanan .seealso: `DMPlexSetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()`
9435a68b90caSToby Isaac @*/
9436a17985deSToby Isaac PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS)
9437a68b90caSToby Isaac {
9438a68b90caSToby Isaac   DM_Plex *plex = (DM_Plex *)dm->data;
9439a68b90caSToby Isaac 
9440a68b90caSToby Isaac   PetscFunctionBegin;
9441a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
94429566063dSJacob Faibussowitsch   if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) PetscCall((*plex->createanchors)(dm));
9443a68b90caSToby Isaac   if (anchorSection) *anchorSection = plex->anchorSection;
9444a68b90caSToby Isaac   if (anchorIS) *anchorIS = plex->anchorIS;
9445a68b90caSToby Isaac   PetscFunctionReturn(0);
9446a68b90caSToby Isaac }
9447a68b90caSToby Isaac 
9448a68b90caSToby Isaac /*@
9449f7c74593SToby Isaac   DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints.  Unlike boundary conditions,
9450f7c74593SToby Isaac   when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a
9451a68b90caSToby Isaac   point's degrees of freedom to be a linear combination of other points' degrees of freedom.
9452a68b90caSToby Isaac 
9453a17985deSToby Isaac   After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling
9454ebdb1bfaSJed Brown   DMGetDefaultConstraints() and filling in the entries in the constraint matrix.
9455a68b90caSToby Isaac 
9456e228b242SToby Isaac   collective on dm
9457a68b90caSToby Isaac 
9458a68b90caSToby Isaac   Input Parameters:
9459a68b90caSToby Isaac + dm - The DMPlex object
9460e228b242SToby 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).
9461e228b242SToby Isaac - anchorIS - The list of all anchor points.  Must have a local communicator (PETSC_COMM_SELF or derivative).
9462a68b90caSToby Isaac 
9463a68b90caSToby Isaac   The reference counts of anchorSection and anchorIS are incremented.
9464a68b90caSToby Isaac 
9465a68b90caSToby Isaac   Level: intermediate
9466a68b90caSToby Isaac 
9467db781477SPatrick Sanan .seealso: `DMPlexGetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()`
9468a68b90caSToby Isaac @*/
9469a17985deSToby Isaac PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS)
9470a68b90caSToby Isaac {
9471a68b90caSToby Isaac   DM_Plex        *plex = (DM_Plex *)dm->data;
9472e228b242SToby Isaac   PetscMPIInt    result;
9473a68b90caSToby Isaac 
9474a68b90caSToby Isaac   PetscFunctionBegin;
9475a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9476e228b242SToby Isaac   if (anchorSection) {
9477e228b242SToby Isaac     PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2);
94789566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result));
94791dca8a05SBarry Smith     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator");
9480e228b242SToby Isaac   }
9481e228b242SToby Isaac   if (anchorIS) {
9482e228b242SToby Isaac     PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3);
94839566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result));
94841dca8a05SBarry Smith     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator");
9485e228b242SToby Isaac   }
9486a68b90caSToby Isaac 
94879566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)anchorSection));
94889566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&plex->anchorSection));
9489a68b90caSToby Isaac   plex->anchorSection = anchorSection;
9490a68b90caSToby Isaac 
94919566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)anchorIS));
94929566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&plex->anchorIS));
9493a68b90caSToby Isaac   plex->anchorIS = anchorIS;
9494a68b90caSToby Isaac 
9495cf9c20a2SJed Brown   if (PetscUnlikelyDebug(anchorIS && anchorSection)) {
9496a68b90caSToby Isaac     PetscInt size, a, pStart, pEnd;
9497a68b90caSToby Isaac     const PetscInt *anchors;
9498a68b90caSToby Isaac 
94999566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(anchorSection,&pStart,&pEnd));
95009566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(anchorIS,&size));
95019566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(anchorIS,&anchors));
9502a68b90caSToby Isaac     for (a = 0; a < size; a++) {
9503a68b90caSToby Isaac       PetscInt p;
9504a68b90caSToby Isaac 
9505a68b90caSToby Isaac       p = anchors[a];
9506a68b90caSToby Isaac       if (p >= pStart && p < pEnd) {
9507a68b90caSToby Isaac         PetscInt dof;
9508a68b90caSToby Isaac 
95099566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(anchorSection,p,&dof));
9510a68b90caSToby Isaac         if (dof) {
9511a68b90caSToby Isaac 
95129566063dSJacob Faibussowitsch           PetscCall(ISRestoreIndices(anchorIS,&anchors));
951363a3b9bcSJacob Faibussowitsch           SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %" PetscInt_FMT " cannot be constrained and an anchor",p);
9514a68b90caSToby Isaac         }
9515a68b90caSToby Isaac       }
9516a68b90caSToby Isaac     }
95179566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(anchorIS,&anchors));
9518a68b90caSToby Isaac   }
9519f7c74593SToby Isaac   /* reset the generic constraints */
95209566063dSJacob Faibussowitsch   PetscCall(DMSetDefaultConstraints(dm,NULL,NULL,NULL));
9521a68b90caSToby Isaac   PetscFunctionReturn(0);
9522a68b90caSToby Isaac }
9523a68b90caSToby Isaac 
9524f7c74593SToby Isaac static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec)
9525a68b90caSToby Isaac {
9526f7c74593SToby Isaac   PetscSection anchorSection;
95276995de1eSToby Isaac   PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f;
9528a68b90caSToby Isaac 
9529a68b90caSToby Isaac   PetscFunctionBegin;
9530a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
95319566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm,&anchorSection,NULL));
95329566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF,cSec));
95339566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section,&numFields));
95346995de1eSToby Isaac   if (numFields) {
9535719ab38cSToby Isaac     PetscInt f;
95369566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(*cSec,numFields));
9537719ab38cSToby Isaac 
9538719ab38cSToby Isaac     for (f = 0; f < numFields; f++) {
9539719ab38cSToby Isaac       PetscInt numComp;
9540719ab38cSToby Isaac 
95419566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldComponents(section,f,&numComp));
95429566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldComponents(*cSec,f,numComp));
9543719ab38cSToby Isaac     }
95446995de1eSToby Isaac   }
95459566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(anchorSection,&pStart,&pEnd));
95469566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section,&sStart,&sEnd));
95476995de1eSToby Isaac   pStart = PetscMax(pStart,sStart);
95486995de1eSToby Isaac   pEnd   = PetscMin(pEnd,sEnd);
95496995de1eSToby Isaac   pEnd   = PetscMax(pStart,pEnd);
95509566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*cSec,pStart,pEnd));
9551a68b90caSToby Isaac   for (p = pStart; p < pEnd; p++) {
95529566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(anchorSection,p,&dof));
9553a68b90caSToby Isaac     if (dof) {
95549566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section,p,&dof));
95559566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(*cSec,p,dof));
9556a68b90caSToby Isaac       for (f = 0; f < numFields; f++) {
95579566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(section,p,f,&dof));
95589566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetFieldDof(*cSec,p,f,dof));
9559a68b90caSToby Isaac       }
9560a68b90caSToby Isaac     }
9561a68b90caSToby Isaac   }
95629566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(*cSec));
95639566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject) *cSec, "Constraint Section"));
9564a68b90caSToby Isaac   PetscFunctionReturn(0);
9565a68b90caSToby Isaac }
9566a68b90caSToby Isaac 
9567f7c74593SToby Isaac static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat)
9568a68b90caSToby Isaac {
9569f7c74593SToby Isaac   PetscSection   aSec;
9570ae65431dSMatthew G. Knepley   PetscInt       pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j;
95710ac89760SToby Isaac   const PetscInt *anchors;
95720ac89760SToby Isaac   PetscInt       numFields, f;
957366ad2231SToby Isaac   IS             aIS;
9574e19f7ee6SMark Adams   MatType        mtype;
9575e19f7ee6SMark Adams   PetscBool      iscuda,iskokkos;
95760ac89760SToby Isaac 
95770ac89760SToby Isaac   PetscFunctionBegin;
95780ac89760SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
95799566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(cSec, &m));
95809566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(section, &n));
95819566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_SELF,cMat));
95829566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*cMat,m,n,m,n));
95839566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dm->mattype,MATSEQAIJCUSPARSE,&iscuda));
95849566063dSJacob Faibussowitsch   if (!iscuda) PetscCall(PetscStrcmp(dm->mattype,MATMPIAIJCUSPARSE,&iscuda));
95859566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dm->mattype,MATSEQAIJKOKKOS,&iskokkos));
95869566063dSJacob Faibussowitsch   if (!iskokkos) PetscCall(PetscStrcmp(dm->mattype,MATMPIAIJKOKKOS,&iskokkos));
9587e19f7ee6SMark Adams   if (iscuda) mtype = MATSEQAIJCUSPARSE;
9588e19f7ee6SMark Adams   else if (iskokkos) mtype = MATSEQAIJKOKKOS;
9589e19f7ee6SMark Adams   else mtype = MATSEQAIJ;
95909566063dSJacob Faibussowitsch   PetscCall(MatSetType(*cMat,mtype));
95919566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm,&aSec,&aIS));
95929566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(aIS,&anchors));
95936995de1eSToby Isaac   /* cSec will be a subset of aSec and section */
95949566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(cSec,&pStart,&pEnd));
95959566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section,&sStart,&sEnd));
95969566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m+1,&i));
95970ac89760SToby Isaac   i[0] = 0;
95989566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section,&numFields));
95990ac89760SToby Isaac   for (p = pStart; p < pEnd; p++) {
9600f19733c5SToby Isaac     PetscInt rDof, rOff, r;
9601f19733c5SToby Isaac 
96029566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(aSec,p,&rDof));
9603f19733c5SToby Isaac     if (!rDof) continue;
96049566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(aSec,p,&rOff));
96050ac89760SToby Isaac     if (numFields) {
96060ac89760SToby Isaac       for (f = 0; f < numFields; f++) {
96070ac89760SToby Isaac         annz = 0;
9608f19733c5SToby Isaac         for (r = 0; r < rDof; r++) {
9609f19733c5SToby Isaac           a = anchors[rOff + r];
9610ae65431dSMatthew G. Knepley           if (a < sStart || a >= sEnd) continue;
96119566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section,a,f,&aDof));
96120ac89760SToby Isaac           annz += aDof;
96130ac89760SToby Isaac         }
96149566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(cSec,p,f,&dof));
96159566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldOffset(cSec,p,f,&off));
96160ac89760SToby Isaac         for (q = 0; q < dof; q++) {
96170ac89760SToby Isaac           i[off + q + 1] = i[off + q] + annz;
96180ac89760SToby Isaac         }
96190ac89760SToby Isaac       }
96202f7452b8SBarry Smith     } else {
96210ac89760SToby Isaac       annz = 0;
96229566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec,p,&dof));
96230ac89760SToby Isaac       for (q = 0; q < dof; q++) {
9624ae65431dSMatthew G. Knepley         a = anchors[rOff + q];
9625ae65431dSMatthew G. Knepley         if (a < sStart || a >= sEnd) continue;
96269566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section,a,&aDof));
96270ac89760SToby Isaac         annz += aDof;
96280ac89760SToby Isaac       }
96299566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec,p,&dof));
96309566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(cSec,p,&off));
96310ac89760SToby Isaac       for (q = 0; q < dof; q++) {
96320ac89760SToby Isaac         i[off + q + 1] = i[off + q] + annz;
96330ac89760SToby Isaac       }
96340ac89760SToby Isaac     }
96350ac89760SToby Isaac   }
96360ac89760SToby Isaac   nnz = i[m];
96379566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nnz,&j));
96380ac89760SToby Isaac   offset = 0;
96390ac89760SToby Isaac   for (p = pStart; p < pEnd; p++) {
96400ac89760SToby Isaac     if (numFields) {
96410ac89760SToby Isaac       for (f = 0; f < numFields; f++) {
96429566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(cSec,p,f,&dof));
96430ac89760SToby Isaac         for (q = 0; q < dof; q++) {
96440ac89760SToby Isaac           PetscInt rDof, rOff, r;
96459566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(aSec,p,&rDof));
96469566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(aSec,p,&rOff));
96470ac89760SToby Isaac           for (r = 0; r < rDof; r++) {
96480ac89760SToby Isaac             PetscInt s;
96490ac89760SToby Isaac 
96500ac89760SToby Isaac             a = anchors[rOff + r];
9651ae65431dSMatthew G. Knepley             if (a < sStart || a >= sEnd) continue;
96529566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section,a,f,&aDof));
96539566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldOffset(section,a,f,&aOff));
96540ac89760SToby Isaac             for (s = 0; s < aDof; s++) {
96550ac89760SToby Isaac               j[offset++] = aOff + s;
96560ac89760SToby Isaac             }
96570ac89760SToby Isaac           }
96580ac89760SToby Isaac         }
96590ac89760SToby Isaac       }
96602f7452b8SBarry Smith     } else {
96619566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec,p,&dof));
96620ac89760SToby Isaac       for (q = 0; q < dof; q++) {
96630ac89760SToby Isaac         PetscInt rDof, rOff, r;
96649566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(aSec,p,&rDof));
96659566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec,p,&rOff));
96660ac89760SToby Isaac         for (r = 0; r < rDof; r++) {
96670ac89760SToby Isaac           PetscInt s;
96680ac89760SToby Isaac 
96690ac89760SToby Isaac           a = anchors[rOff + r];
9670ae65431dSMatthew G. Knepley           if (a < sStart || a >= sEnd) continue;
96719566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section,a,&aDof));
96729566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(section,a,&aOff));
96730ac89760SToby Isaac           for (s = 0; s < aDof; s++) {
96740ac89760SToby Isaac             j[offset++] = aOff + s;
96750ac89760SToby Isaac           }
96760ac89760SToby Isaac         }
96770ac89760SToby Isaac       }
96780ac89760SToby Isaac     }
96790ac89760SToby Isaac   }
96809566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL));
96819566063dSJacob Faibussowitsch   PetscCall(PetscFree(i));
96829566063dSJacob Faibussowitsch   PetscCall(PetscFree(j));
96839566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(aIS,&anchors));
96840ac89760SToby Isaac   PetscFunctionReturn(0);
96850ac89760SToby Isaac }
96860ac89760SToby Isaac 
968766ad2231SToby Isaac PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm)
968866ad2231SToby Isaac {
9689f7c74593SToby Isaac   DM_Plex        *plex = (DM_Plex *)dm->data;
9690f7c74593SToby Isaac   PetscSection   anchorSection, section, cSec;
969166ad2231SToby Isaac   Mat            cMat;
969266ad2231SToby Isaac 
969366ad2231SToby Isaac   PetscFunctionBegin;
969466ad2231SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
96959566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm,&anchorSection,NULL));
969666ad2231SToby Isaac   if (anchorSection) {
969744a7f3ddSMatthew G. Knepley     PetscInt Nf;
9698e228b242SToby Isaac 
96999566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm,&section));
97009566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateConstraintSection_Anchors(dm,section,&cSec));
97019566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat));
97029566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm,&Nf));
97039566063dSJacob Faibussowitsch     if (Nf && plex->computeanchormatrix) PetscCall((*plex->computeanchormatrix)(dm,section,cSec,cMat));
97049566063dSJacob Faibussowitsch     PetscCall(DMSetDefaultConstraints(dm,cSec,cMat,NULL));
97059566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&cSec));
97069566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&cMat));
970766ad2231SToby Isaac   }
970866ad2231SToby Isaac   PetscFunctionReturn(0);
970966ad2231SToby Isaac }
9710a93c429eSMatthew G. Knepley 
9711a93c429eSMatthew G. Knepley PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm)
9712a93c429eSMatthew G. Knepley {
9713a93c429eSMatthew G. Knepley   IS             subis;
9714a93c429eSMatthew G. Knepley   PetscSection   section, subsection;
9715a93c429eSMatthew G. Knepley 
9716a93c429eSMatthew G. Knepley   PetscFunctionBegin;
97179566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
971828b400f6SJacob Faibussowitsch   PetscCheck(section,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain");
971928b400f6SJacob Faibussowitsch   PetscCheck(subdm,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain");
9720a93c429eSMatthew G. Knepley   /* Create subdomain */
97219566063dSJacob Faibussowitsch   PetscCall(DMPlexFilter(dm, label, value, subdm));
9722a93c429eSMatthew G. Knepley   /* Create submodel */
97239566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSubpointIS(*subdm, &subis));
97249566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreateSubmeshSection(section, subis, &subsection));
97259566063dSJacob Faibussowitsch   PetscCall(DMSetLocalSection(*subdm, subsection));
97269566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&subsection));
97279566063dSJacob Faibussowitsch   PetscCall(DMCopyDisc(dm, *subdm));
9728a93c429eSMatthew G. Knepley   /* Create map from submodel to global model */
9729a93c429eSMatthew G. Knepley   if (is) {
9730a93c429eSMatthew G. Knepley     PetscSection    sectionGlobal, subsectionGlobal;
9731a93c429eSMatthew G. Knepley     IS              spIS;
9732a93c429eSMatthew G. Knepley     const PetscInt *spmap;
9733a93c429eSMatthew G. Knepley     PetscInt       *subIndices;
9734a93c429eSMatthew G. Knepley     PetscInt        subSize = 0, subOff = 0, pStart, pEnd, p;
9735a93c429eSMatthew G. Knepley     PetscInt        Nf, f, bs = -1, bsLocal[2], bsMinMax[2];
9736a93c429eSMatthew G. Knepley 
97379566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSubpointIS(*subdm, &spIS));
97389566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(spIS, &spmap));
97399566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetNumFields(section, &Nf));
97409566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dm, &sectionGlobal));
97419566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(*subdm, &subsectionGlobal));
97429566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(subsection, &pStart, &pEnd));
9743a93c429eSMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
9744a93c429eSMatthew G. Knepley       PetscInt gdof, pSubSize  = 0;
9745a93c429eSMatthew G. Knepley 
97469566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof));
9747a93c429eSMatthew G. Knepley       if (gdof > 0) {
9748a93c429eSMatthew G. Knepley         for (f = 0; f < Nf; ++f) {
9749a93c429eSMatthew G. Knepley           PetscInt fdof, fcdof;
9750a93c429eSMatthew G. Knepley 
97519566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(subsection, p, f, &fdof));
97529566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof));
9753a93c429eSMatthew G. Knepley           pSubSize += fdof-fcdof;
9754a93c429eSMatthew G. Knepley         }
9755a93c429eSMatthew G. Knepley         subSize += pSubSize;
9756a93c429eSMatthew G. Knepley         if (pSubSize) {
9757a93c429eSMatthew G. Knepley           if (bs < 0) {
9758a93c429eSMatthew G. Knepley             bs = pSubSize;
9759a93c429eSMatthew G. Knepley           } else if (bs != pSubSize) {
9760a93c429eSMatthew G. Knepley             /* Layout does not admit a pointwise block size */
9761a93c429eSMatthew G. Knepley             bs = 1;
9762a93c429eSMatthew G. Knepley           }
9763a93c429eSMatthew G. Knepley         }
9764a93c429eSMatthew G. Knepley       }
9765a93c429eSMatthew G. Knepley     }
9766a93c429eSMatthew G. Knepley     /* Must have same blocksize on all procs (some might have no points) */
9767a93c429eSMatthew G. Knepley     bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs;
97689566063dSJacob Faibussowitsch     PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax));
9769a93c429eSMatthew G. Knepley     if (bsMinMax[0] != bsMinMax[1]) {bs = 1;}
9770a93c429eSMatthew G. Knepley     else                            {bs = bsMinMax[0];}
97719566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(subSize, &subIndices));
9772a93c429eSMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
9773a93c429eSMatthew G. Knepley       PetscInt gdof, goff;
9774a93c429eSMatthew G. Knepley 
97759566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(subsectionGlobal, p, &gdof));
9776a93c429eSMatthew G. Knepley       if (gdof > 0) {
9777a93c429eSMatthew G. Knepley         const PetscInt point = spmap[p];
9778a93c429eSMatthew G. Knepley 
97799566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(sectionGlobal, point, &goff));
9780a93c429eSMatthew G. Knepley         for (f = 0; f < Nf; ++f) {
9781a93c429eSMatthew G. Knepley           PetscInt fdof, fcdof, fc, f2, poff = 0;
9782a93c429eSMatthew G. Knepley 
9783a93c429eSMatthew G. Knepley           /* Can get rid of this loop by storing field information in the global section */
9784a93c429eSMatthew G. Knepley           for (f2 = 0; f2 < f; ++f2) {
97859566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, p, f2, &fdof));
97869566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof));
9787a93c429eSMatthew G. Knepley             poff += fdof-fcdof;
9788a93c429eSMatthew G. Knepley           }
97899566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof));
97909566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof));
9791a93c429eSMatthew G. Knepley           for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) {
9792a93c429eSMatthew G. Knepley             subIndices[subOff] = goff+poff+fc;
9793a93c429eSMatthew G. Knepley           }
9794a93c429eSMatthew G. Knepley         }
9795a93c429eSMatthew G. Knepley       }
9796a93c429eSMatthew G. Knepley     }
97979566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(spIS, &spmap));
97989566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is));
9799a93c429eSMatthew G. Knepley     if (bs > 1) {
9800a93c429eSMatthew G. Knepley       /* We need to check that the block size does not come from non-contiguous fields */
9801a93c429eSMatthew G. Knepley       PetscInt i, j, set = 1;
9802a93c429eSMatthew G. Knepley       for (i = 0; i < subSize; i += bs) {
9803a93c429eSMatthew G. Knepley         for (j = 0; j < bs; ++j) {
9804a93c429eSMatthew G. Knepley           if (subIndices[i+j] != subIndices[i]+j) {set = 0; break;}
9805a93c429eSMatthew G. Knepley         }
9806a93c429eSMatthew G. Knepley       }
98079566063dSJacob Faibussowitsch       if (set) PetscCall(ISSetBlockSize(*is, bs));
9808a93c429eSMatthew G. Knepley     }
9809a93c429eSMatthew G. Knepley     /* Attach nullspace */
9810a93c429eSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
9811a93c429eSMatthew G. Knepley       (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f];
9812a93c429eSMatthew G. Knepley       if ((*subdm)->nullspaceConstructors[f]) break;
9813a93c429eSMatthew G. Knepley     }
9814a93c429eSMatthew G. Knepley     if (f < Nf) {
9815a93c429eSMatthew G. Knepley       MatNullSpace nullSpace;
98169566063dSJacob Faibussowitsch       PetscCall((*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace));
98176823f3c5SBlaise Bourdin 
98189566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace));
98199566063dSJacob Faibussowitsch       PetscCall(MatNullSpaceDestroy(&nullSpace));
9820a93c429eSMatthew G. Knepley     }
9821a93c429eSMatthew G. Knepley   }
9822a93c429eSMatthew G. Knepley   PetscFunctionReturn(0);
9823a93c429eSMatthew G. Knepley }
9824c0f0dcc3SMatthew G. Knepley 
9825c0f0dcc3SMatthew G. Knepley /*@
9826c0f0dcc3SMatthew G. Knepley   DMPlexMonitorThroughput - Report the cell throughput of FE integration
9827c0f0dcc3SMatthew G. Knepley 
9828c0f0dcc3SMatthew G. Knepley   Input Parameter:
9829c0f0dcc3SMatthew G. Knepley - dm - The DM
9830c0f0dcc3SMatthew G. Knepley 
9831c0f0dcc3SMatthew G. Knepley   Level: developer
9832c0f0dcc3SMatthew G. Knepley 
9833c0f0dcc3SMatthew G. Knepley   Options Database Keys:
9834c0f0dcc3SMatthew G. Knepley . -dm_plex_monitor_throughput - Activate the monitor
9835c0f0dcc3SMatthew G. Knepley 
9836db781477SPatrick Sanan .seealso: `DMSetFromOptions()`, `DMPlexCreate()`
9837c0f0dcc3SMatthew G. Knepley @*/
9838c0f0dcc3SMatthew G. Knepley PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy)
9839c0f0dcc3SMatthew G. Knepley {
9840e5ed2c37SJose E. Roman #if defined(PETSC_USE_LOG)
9841c0f0dcc3SMatthew G. Knepley   PetscStageLog      stageLog;
9842c0f0dcc3SMatthew G. Knepley   PetscLogEvent      event;
9843c0f0dcc3SMatthew G. Knepley   PetscLogStage      stage;
9844c0f0dcc3SMatthew G. Knepley   PetscEventPerfInfo eventInfo;
9845c0f0dcc3SMatthew G. Knepley   PetscReal          cellRate, flopRate;
9846c0f0dcc3SMatthew G. Knepley   PetscInt           cStart, cEnd, Nf, N;
9847c0f0dcc3SMatthew G. Knepley   const char        *name;
9848e5ed2c37SJose E. Roman #endif
9849c0f0dcc3SMatthew G. Knepley 
9850c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
9851c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9852c0f0dcc3SMatthew G. Knepley #if defined(PETSC_USE_LOG)
98539566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject) dm, &name));
98549566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
98559566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
98569566063dSJacob Faibussowitsch   PetscCall(PetscLogGetStageLog(&stageLog));
98579566063dSJacob Faibussowitsch   PetscCall(PetscStageLogGetCurrent(stageLog, &stage));
98589566063dSJacob Faibussowitsch   PetscCall(PetscLogEventGetId("DMPlexResidualFE", &event));
98599566063dSJacob Faibussowitsch   PetscCall(PetscLogEventGetPerfInfo(stage, event, &eventInfo));
9860c0f0dcc3SMatthew G. Knepley   N        = (cEnd - cStart)*Nf*eventInfo.count;
9861c0f0dcc3SMatthew G. Knepley   flopRate = eventInfo.flops/eventInfo.time;
9862c0f0dcc3SMatthew G. Knepley   cellRate = N/eventInfo.time;
986363a3b9bcSJacob Faibussowitsch   PetscCall(PetscPrintf(PetscObjectComm((PetscObject) dm), "DM (%s) FE Residual Integration: %" PetscInt_FMT " 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)));
9864c0f0dcc3SMatthew G. Knepley #else
9865c0f0dcc3SMatthew G. Knepley   SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Plex Throughput Monitor is not supported if logging is turned off. Reconfigure using --with-log.");
9866c0f0dcc3SMatthew G. Knepley #endif
9867c0f0dcc3SMatthew G. Knepley   PetscFunctionReturn(0);
9868c0f0dcc3SMatthew G. Knepley }
9869