xref: /petsc/src/dm/impls/plex/plex.c (revision 5f34f2dc1c2621700176370c8c2a53775adcdbf1)
1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h>   /*I      "petscdmplex.h"   I*/
2695799ffSMatthew 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));
94695799ffSMatthew G. Knepley     // Reset label for fast lookup
95695799ffSMatthew 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;
434*5f34f2dcSJed Brown   PetscBool      isvtk, ishdf5, isdraw, isglvis, iscgns;
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));
443*5f34f2dcSJed Brown   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERCGNS,  &iscgns));
444*5f34f2dcSJed Brown   if (isvtk || ishdf5 || isdraw || isglvis || iscgns) {
445684b87d9SLisandro Dalcin     PetscInt    i,numFields;
446684b87d9SLisandro Dalcin     PetscObject fe;
447ef31f671SMatthew G. Knepley     PetscBool   fem = PETSC_FALSE;
448684b87d9SLisandro Dalcin     Vec         locv = v;
449684b87d9SLisandro Dalcin     const char  *name;
450684b87d9SLisandro Dalcin     PetscInt    step;
451684b87d9SLisandro Dalcin     PetscReal   time;
452ef31f671SMatthew G. Knepley 
4539566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &numFields));
454684b87d9SLisandro Dalcin     for (i=0; i<numFields; i++) {
4559566063dSJacob Faibussowitsch       PetscCall(DMGetField(dm, i, NULL, &fe));
456684b87d9SLisandro Dalcin       if (fe->classid == PETSCFE_CLASSID) { fem = PETSC_TRUE; break; }
457ef31f671SMatthew G. Knepley     }
458684b87d9SLisandro Dalcin     if (fem) {
459798534f6SMatthew G. Knepley       PetscObject isZero;
460798534f6SMatthew G. Knepley 
4619566063dSJacob Faibussowitsch       PetscCall(DMGetLocalVector(dm, &locv));
4629566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject) v, &name));
4639566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject) locv, name));
4649566063dSJacob Faibussowitsch       PetscCall(PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero));
4659566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero));
4669566063dSJacob Faibussowitsch       PetscCall(VecCopy(v, locv));
4679566063dSJacob Faibussowitsch       PetscCall(DMGetOutputSequenceNumber(dm, NULL, &time));
4689566063dSJacob Faibussowitsch       PetscCall(DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL));
469ef31f671SMatthew G. Knepley     }
470552f7358SJed Brown     if (isvtk) {
4719566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_VTK(locv, viewer));
472b136c2c9SMatthew G. Knepley     } else if (ishdf5) {
473b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
4749566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_HDF5_Internal(locv, viewer));
475b136c2c9SMatthew G. Knepley #else
476b136c2c9SMatthew G. Knepley       SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
477b136c2c9SMatthew G. Knepley #endif
478f13a32a3SMatthew G. Knepley     } else if (isdraw) {
4799566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_Draw(locv, viewer));
480684b87d9SLisandro Dalcin     } else if (isglvis) {
4819566063dSJacob Faibussowitsch       PetscCall(DMGetOutputSequenceNumber(dm, &step, NULL));
4829566063dSJacob Faibussowitsch       PetscCall(PetscViewerGLVisSetSnapId(viewer, step));
4839566063dSJacob Faibussowitsch       PetscCall(VecView_GLVis(locv, viewer));
484*5f34f2dcSJed Brown     } else if (iscgns) {
485*5f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS)
486*5f34f2dcSJed Brown       PetscCall(VecView_Plex_Local_CGNS(locv, viewer));
487*5f34f2dcSJed Brown #else
488*5f34f2dcSJed Brown       SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "CGNS not supported in this build.\nPlease reconfigure using --download-cgns");
489*5f34f2dcSJed Brown #endif
490684b87d9SLisandro Dalcin     }
491798534f6SMatthew G. Knepley     if (fem) {
4929566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL));
4939566063dSJacob Faibussowitsch       PetscCall(DMRestoreLocalVector(dm, &locv));
494798534f6SMatthew G. Knepley     }
495552f7358SJed Brown   } else {
496684b87d9SLisandro Dalcin     PetscBool isseq;
497684b87d9SLisandro Dalcin 
4989566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq));
4999566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
5009566063dSJacob Faibussowitsch     else       PetscCall(VecView_MPI(v, viewer));
501552f7358SJed Brown   }
502552f7358SJed Brown   PetscFunctionReturn(0);
503552f7358SJed Brown }
504552f7358SJed Brown 
505552f7358SJed Brown PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer)
506552f7358SJed Brown {
507552f7358SJed Brown   DM        dm;
508*5f34f2dcSJed Brown   PetscBool isvtk, ishdf5, isdraw, isglvis, isexodusii, iscgns;
509552f7358SJed Brown 
510552f7358SJed Brown   PetscFunctionBegin;
5119566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
51228b400f6SJacob Faibussowitsch   PetscCheck(dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
5139566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK,      &isvtk));
5149566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,     &ishdf5));
5159566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW,     &isdraw));
5169566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS,    &isglvis));
517*5f34f2dcSJed Brown   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERCGNS,     &iscgns));
5189566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii));
519*5f34f2dcSJed Brown   if (isvtk || isdraw || isglvis || iscgns) {
520552f7358SJed Brown     Vec         locv;
521798534f6SMatthew G. Knepley     PetscObject isZero;
522552f7358SJed Brown     const char *name;
523552f7358SJed Brown 
5249566063dSJacob Faibussowitsch     PetscCall(DMGetLocalVector(dm, &locv));
5259566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject) v, &name));
5269566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject) locv, name));
5279566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv));
5289566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv));
5299566063dSJacob Faibussowitsch     PetscCall(PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero));
5309566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero));
5319566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_Local(locv, viewer));
5329566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL));
5339566063dSJacob Faibussowitsch     PetscCall(DMRestoreLocalVector(dm, &locv));
534b136c2c9SMatthew G. Knepley   } else if (ishdf5) {
535b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
5369566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_HDF5_Internal(v, viewer));
537b136c2c9SMatthew G. Knepley #else
538b136c2c9SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
539b136c2c9SMatthew G. Knepley #endif
5406823f3c5SBlaise Bourdin   } else if (isexodusii) {
5416823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII)
5429566063dSJacob Faibussowitsch     PetscCall(VecView_PlexExodusII_Internal(v, viewer));
5436823f3c5SBlaise Bourdin #else
5446823f3c5SBlaise Bourdin     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii");
5456823f3c5SBlaise Bourdin #endif
546552f7358SJed Brown   } else {
547684b87d9SLisandro Dalcin     PetscBool isseq;
548684b87d9SLisandro Dalcin 
5499566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq));
5509566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
5519566063dSJacob Faibussowitsch     else       PetscCall(VecView_MPI(v, viewer));
552552f7358SJed Brown   }
553552f7358SJed Brown   PetscFunctionReturn(0);
554552f7358SJed Brown }
555552f7358SJed Brown 
556d930f514SMatthew G. Knepley PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer)
557d930f514SMatthew G. Knepley {
558d930f514SMatthew G. Knepley   DM                dm;
559d930f514SMatthew G. Knepley   MPI_Comm          comm;
560d930f514SMatthew G. Knepley   PetscViewerFormat format;
561d930f514SMatthew G. Knepley   Vec               v;
562d930f514SMatthew G. Knepley   PetscBool         isvtk, ishdf5;
563d930f514SMatthew G. Knepley 
564d930f514SMatthew G. Knepley   PetscFunctionBegin;
5659566063dSJacob Faibussowitsch   PetscCall(VecGetDM(originalv, &dm));
5669566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject) originalv, &comm));
56728b400f6SJacob Faibussowitsch   PetscCheck(dm,comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
5689566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
5699566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
5709566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK,  &isvtk));
571d930f514SMatthew G. Knepley   if (format == PETSC_VIEWER_NATIVE) {
572a8ad634aSStefano Zampini     /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */
573a8ad634aSStefano Zampini     /* this need a better fix */
574a8ad634aSStefano Zampini     if (dm->useNatural) {
575a8ad634aSStefano Zampini       if (dm->sfNatural) {
576d930f514SMatthew G. Knepley         const char *vecname;
577d930f514SMatthew G. Knepley         PetscInt    n, nroots;
578d930f514SMatthew G. Knepley 
5799566063dSJacob Faibussowitsch         PetscCall(VecGetLocalSize(originalv, &n));
5809566063dSJacob Faibussowitsch         PetscCall(PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL));
581d930f514SMatthew G. Knepley         if (n == nroots) {
5829566063dSJacob Faibussowitsch           PetscCall(DMGetGlobalVector(dm, &v));
5839566063dSJacob Faibussowitsch           PetscCall(DMPlexGlobalToNaturalBegin(dm, originalv, v));
5849566063dSJacob Faibussowitsch           PetscCall(DMPlexGlobalToNaturalEnd(dm, originalv, v));
5859566063dSJacob Faibussowitsch           PetscCall(PetscObjectGetName((PetscObject) originalv, &vecname));
5869566063dSJacob Faibussowitsch           PetscCall(PetscObjectSetName((PetscObject) v, vecname));
587d930f514SMatthew G. Knepley         } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors");
588d930f514SMatthew G. Knepley       } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created");
589a8ad634aSStefano Zampini     } else v = originalv;
590a8ad634aSStefano Zampini   } else v = originalv;
591a8ad634aSStefano Zampini 
592d930f514SMatthew G. Knepley   if (ishdf5) {
593d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
5949566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_HDF5_Native_Internal(v, viewer));
595d930f514SMatthew G. Knepley #else
596d930f514SMatthew G. Knepley     SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
597d930f514SMatthew G. Knepley #endif
598d930f514SMatthew G. Knepley   } else if (isvtk) {
599d930f514SMatthew G. Knepley     SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5.");
600d930f514SMatthew G. Knepley   } else {
601d930f514SMatthew G. Knepley     PetscBool isseq;
602d930f514SMatthew G. Knepley 
6039566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq));
6049566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
6059566063dSJacob Faibussowitsch     else       PetscCall(VecView_MPI(v, viewer));
606d930f514SMatthew G. Knepley   }
6079566063dSJacob Faibussowitsch   if (v != originalv) PetscCall(DMRestoreGlobalVector(dm, &v));
608d930f514SMatthew G. Knepley   PetscFunctionReturn(0);
609d930f514SMatthew G. Knepley }
610d930f514SMatthew G. Knepley 
6112c40f234SMatthew G. Knepley PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer)
6122c40f234SMatthew G. Knepley {
6132c40f234SMatthew G. Knepley   DM             dm;
6142c40f234SMatthew G. Knepley   PetscBool      ishdf5;
6152c40f234SMatthew G. Knepley 
6162c40f234SMatthew G. Knepley   PetscFunctionBegin;
6179566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
61828b400f6SJacob Faibussowitsch   PetscCheck(dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
6199566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
6202c40f234SMatthew G. Knepley   if (ishdf5) {
6212c40f234SMatthew G. Knepley     DM          dmBC;
6222c40f234SMatthew G. Knepley     Vec         gv;
6232c40f234SMatthew G. Knepley     const char *name;
6242c40f234SMatthew G. Knepley 
6259566063dSJacob Faibussowitsch     PetscCall(DMGetOutputDM(dm, &dmBC));
6269566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalVector(dmBC, &gv));
6279566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject) v, &name));
6289566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject) gv, name));
6299566063dSJacob Faibussowitsch     PetscCall(VecLoad_Default(gv, viewer));
6309566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v));
6319566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v));
6329566063dSJacob Faibussowitsch     PetscCall(DMRestoreGlobalVector(dmBC, &gv));
6331baa6e33SBarry Smith   } else PetscCall(VecLoad_Default(v, viewer));
6342c40f234SMatthew G. Knepley   PetscFunctionReturn(0);
6352c40f234SMatthew G. Knepley }
6362c40f234SMatthew G. Knepley 
6372c40f234SMatthew G. Knepley PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer)
6382c40f234SMatthew G. Knepley {
6392c40f234SMatthew G. Knepley   DM             dm;
6406823f3c5SBlaise Bourdin   PetscBool      ishdf5,isexodusii;
6412c40f234SMatthew G. Knepley 
6422c40f234SMatthew G. Knepley   PetscFunctionBegin;
6439566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
64428b400f6SJacob Faibussowitsch   PetscCheck(dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
6459566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,     &ishdf5));
6469566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii));
6472c40f234SMatthew G. Knepley   if (ishdf5) {
648878b459fSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
6499566063dSJacob Faibussowitsch     PetscCall(VecLoad_Plex_HDF5_Internal(v, viewer));
650b136c2c9SMatthew G. Knepley #else
651b136c2c9SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
652878b459fSMatthew G. Knepley #endif
6536823f3c5SBlaise Bourdin   } else if (isexodusii) {
6546823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII)
6559566063dSJacob Faibussowitsch     PetscCall(VecLoad_PlexExodusII_Internal(v, viewer));
6566823f3c5SBlaise Bourdin #else
6576823f3c5SBlaise Bourdin     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii");
6586823f3c5SBlaise Bourdin #endif
6591baa6e33SBarry Smith   } else PetscCall(VecLoad_Default(v, viewer));
660552f7358SJed Brown   PetscFunctionReturn(0);
661552f7358SJed Brown }
662552f7358SJed Brown 
663d930f514SMatthew G. Knepley PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer)
664d930f514SMatthew G. Knepley {
665d930f514SMatthew G. Knepley   DM                dm;
666d930f514SMatthew G. Knepley   PetscViewerFormat format;
667d930f514SMatthew G. Knepley   PetscBool         ishdf5;
668d930f514SMatthew G. Knepley 
669d930f514SMatthew G. Knepley   PetscFunctionBegin;
6709566063dSJacob Faibussowitsch   PetscCall(VecGetDM(originalv, &dm));
67128b400f6SJacob Faibussowitsch   PetscCheck(dm,PetscObjectComm((PetscObject) originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
6729566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
6739566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
674d930f514SMatthew G. Knepley   if (format == PETSC_VIEWER_NATIVE) {
675a8ad634aSStefano Zampini     if (dm->useNatural) {
676d930f514SMatthew G. Knepley       if (dm->sfNatural) {
677d930f514SMatthew G. Knepley         if (ishdf5) {
678d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
679d930f514SMatthew G. Knepley           Vec         v;
680d930f514SMatthew G. Knepley           const char *vecname;
681d930f514SMatthew G. Knepley 
6829566063dSJacob Faibussowitsch           PetscCall(DMGetGlobalVector(dm, &v));
6839566063dSJacob Faibussowitsch           PetscCall(PetscObjectGetName((PetscObject) originalv, &vecname));
6849566063dSJacob Faibussowitsch           PetscCall(PetscObjectSetName((PetscObject) v, vecname));
6859566063dSJacob Faibussowitsch           PetscCall(VecLoad_Plex_HDF5_Native_Internal(v, viewer));
6869566063dSJacob Faibussowitsch           PetscCall(DMPlexNaturalToGlobalBegin(dm, v, originalv));
6879566063dSJacob Faibussowitsch           PetscCall(DMPlexNaturalToGlobalEnd(dm, v, originalv));
6889566063dSJacob Faibussowitsch           PetscCall(DMRestoreGlobalVector(dm, &v));
689d930f514SMatthew G. Knepley #else
690d930f514SMatthew G. Knepley           SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
691d930f514SMatthew G. Knepley #endif
692d930f514SMatthew G. Knepley         } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5.");
693d930f514SMatthew G. Knepley       }
6941baa6e33SBarry Smith     } else PetscCall(VecLoad_Default(originalv, viewer));
695d930f514SMatthew G. Knepley   }
696d930f514SMatthew G. Knepley   PetscFunctionReturn(0);
697d930f514SMatthew G. Knepley }
698d930f514SMatthew G. Knepley 
6997cd05799SMatthew G. Knepley PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer)
700731e8ddeSMatthew G. Knepley {
701731e8ddeSMatthew G. Knepley   PetscSection       coordSection;
702731e8ddeSMatthew G. Knepley   Vec                coordinates;
703ba2698f1SMatthew G. Knepley   DMLabel            depthLabel, celltypeLabel;
704731e8ddeSMatthew G. Knepley   const char        *name[4];
705731e8ddeSMatthew G. Knepley   const PetscScalar *a;
706731e8ddeSMatthew G. Knepley   PetscInt           dim, pStart, pEnd, cStart, cEnd, c;
707731e8ddeSMatthew G. Knepley 
708731e8ddeSMatthew G. Knepley   PetscFunctionBegin;
7099566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
7109566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
7119566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
7129566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
7139566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &celltypeLabel));
7149566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
7159566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(coordSection, &pStart, &pEnd));
7169566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(coordinates, &a));
717731e8ddeSMatthew G. Knepley   name[0]     = "vertex";
718731e8ddeSMatthew G. Knepley   name[1]     = "edge";
719731e8ddeSMatthew G. Knepley   name[dim-1] = "face";
720731e8ddeSMatthew G. Knepley   name[dim]   = "cell";
721731e8ddeSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
722731e8ddeSMatthew G. Knepley     PetscInt *closure = NULL;
723ba2698f1SMatthew G. Knepley     PetscInt  closureSize, cl, ct;
724731e8ddeSMatthew G. Knepley 
7259566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(celltypeLabel, c, &ct));
72663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Geometry for cell %" PetscInt_FMT " polytope type %s:\n", c, DMPolytopeTypes[ct]));
7279566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
7289566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
729731e8ddeSMatthew G. Knepley     for (cl = 0; cl < closureSize*2; cl += 2) {
730731e8ddeSMatthew G. Knepley       PetscInt point = closure[cl], depth, dof, off, d, p;
731731e8ddeSMatthew G. Knepley 
732731e8ddeSMatthew G. Knepley       if ((point < pStart) || (point >= pEnd)) continue;
7339566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(coordSection, point, &dof));
734731e8ddeSMatthew G. Knepley       if (!dof) continue;
7359566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(depthLabel, point, &depth));
7369566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, point, &off));
73763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s %" PetscInt_FMT " coords:", name[depth], point));
738731e8ddeSMatthew G. Knepley       for (p = 0; p < dof/dim; ++p) {
7399566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " ("));
740731e8ddeSMatthew G. Knepley         for (d = 0; d < dim; ++d) {
7419566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
7429566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "%g", (double) PetscRealPart(a[off+p*dim+d])));
743731e8ddeSMatthew G. Knepley         }
7449566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, ")"));
745731e8ddeSMatthew G. Knepley       }
7469566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
747731e8ddeSMatthew G. Knepley     }
7489566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
7499566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
750731e8ddeSMatthew G. Knepley   }
7519566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(coordinates, &a));
752731e8ddeSMatthew G. Knepley   PetscFunctionReturn(0);
753731e8ddeSMatthew G. Knepley }
754731e8ddeSMatthew G. Knepley 
75519ad8254SMatthew G. Knepley typedef enum {CS_CARTESIAN, CS_POLAR, CS_CYLINDRICAL, CS_SPHERICAL} CoordSystem;
75619ad8254SMatthew G. Knepley const char *CoordSystems[] = {"cartesian", "polar", "cylindrical", "spherical", "CoordSystem", "CS_", NULL};
75719ad8254SMatthew G. Knepley 
75819ad8254SMatthew G. Knepley static PetscErrorCode DMPlexView_Ascii_Coordinates(PetscViewer viewer, CoordSystem cs, PetscInt dim, const PetscScalar x[])
75919ad8254SMatthew G. Knepley {
76019ad8254SMatthew G. Knepley   PetscInt       i;
76119ad8254SMatthew G. Knepley 
76219ad8254SMatthew G. Knepley   PetscFunctionBegin;
76319ad8254SMatthew G. Knepley   if (dim > 3) {
7649566063dSJacob Faibussowitsch     for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double) PetscRealPart(x[i])));
76519ad8254SMatthew G. Knepley   } else {
766bd83fdcbSStefano Zampini     PetscReal coords[3], trcoords[3] = {0., 0., 0.};
76719ad8254SMatthew G. Knepley 
76819ad8254SMatthew G. Knepley     for (i = 0; i < dim; ++i) coords[i] = PetscRealPart(x[i]);
76919ad8254SMatthew G. Knepley     switch (cs) {
77019ad8254SMatthew G. Knepley       case CS_CARTESIAN: for (i = 0; i < dim; ++i) trcoords[i] = coords[i];break;
77119ad8254SMatthew G. Knepley       case CS_POLAR:
77263a3b9bcSJacob Faibussowitsch         PetscCheck(dim == 2,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Polar coordinates are for 2 dimension, not %" PetscInt_FMT, dim);
77319ad8254SMatthew G. Knepley         trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]));
77419ad8254SMatthew G. Knepley         trcoords[1] = PetscAtan2Real(coords[1], coords[0]);
77519ad8254SMatthew G. Knepley         break;
77619ad8254SMatthew G. Knepley       case CS_CYLINDRICAL:
77763a3b9bcSJacob Faibussowitsch         PetscCheck(dim == 3,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cylindrical coordinates are for 3 dimension, not %" PetscInt_FMT, dim);
77819ad8254SMatthew G. Knepley         trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]));
77919ad8254SMatthew G. Knepley         trcoords[1] = PetscAtan2Real(coords[1], coords[0]);
78019ad8254SMatthew G. Knepley         trcoords[2] = coords[2];
78119ad8254SMatthew G. Knepley         break;
78219ad8254SMatthew G. Knepley       case CS_SPHERICAL:
78363a3b9bcSJacob Faibussowitsch         PetscCheck(dim == 3,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Spherical coordinates are for 3 dimension, not %" PetscInt_FMT, dim);
78419ad8254SMatthew G. Knepley         trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]) + PetscSqr(coords[2]));
78519ad8254SMatthew G. Knepley         trcoords[1] = PetscAtan2Real(PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])), coords[2]);
78619ad8254SMatthew G. Knepley         trcoords[2] = PetscAtan2Real(coords[1], coords[0]);
78719ad8254SMatthew G. Knepley         break;
78819ad8254SMatthew G. Knepley     }
7899566063dSJacob Faibussowitsch     for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double) trcoords[i]));
79019ad8254SMatthew G. Knepley   }
79119ad8254SMatthew G. Knepley   PetscFunctionReturn(0);
79219ad8254SMatthew G. Knepley }
79319ad8254SMatthew G. Knepley 
7947cd05799SMatthew G. Knepley static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer)
795552f7358SJed Brown {
796552f7358SJed Brown   DM_Plex          *mesh = (DM_Plex*) dm->data;
7976858538eSMatthew G. Knepley   DM                cdm, cdmCell;
7986858538eSMatthew G. Knepley   PetscSection      coordSection, coordSectionCell;
7996858538eSMatthew G. Knepley   Vec               coordinates, coordinatesCell;
800552f7358SJed Brown   PetscViewerFormat format;
801552f7358SJed Brown 
802552f7358SJed Brown   PetscFunctionBegin;
8039566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
8046858538eSMatthew G. Knepley   PetscCall(DMGetCoordinateSection(dm, &coordSection));
8059566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
8066858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dm, &cdmCell));
8076858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell));
8086858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell));
8099566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
810552f7358SJed Brown   if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
811552f7358SJed Brown     const char *name;
812f73eea6eSMatthew G. Knepley     PetscInt    dim, cellHeight, maxConeSize, maxSupportSize;
8139318fe57SMatthew G. Knepley     PetscInt    pStart, pEnd, p, numLabels, l;
814552f7358SJed Brown     PetscMPIInt rank, size;
815552f7358SJed Brown 
8169566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
8179566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
8189566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject) dm, &name));
8199566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
8209566063dSJacob Faibussowitsch     PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
8219566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
8229566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
82363a3b9bcSJacob Faibussowitsch     if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s"));
82463a3b9bcSJacob Faibussowitsch     else      PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s"));
82563a3b9bcSJacob Faibussowitsch     if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, "  Cells are at height %" PetscInt_FMT "\n", cellHeight));
82663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Supports:\n"));
8279566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
82863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %" PetscInt_FMT "\n", rank, maxSupportSize));
829552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
830552f7358SJed Brown       PetscInt dof, off, s;
831552f7358SJed Brown 
8329566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
8339566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
834552f7358SJed Brown       for (s = off; s < off+dof; ++s) {
83563a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " ----> %" PetscInt_FMT "\n", rank, p, mesh->supports[s]));
836552f7358SJed Brown       }
837552f7358SJed Brown     }
8389566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
83963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Cones:\n"));
84063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %" PetscInt_FMT "\n", rank, maxConeSize));
841552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
842552f7358SJed Brown       PetscInt dof, off, c;
843552f7358SJed Brown 
8449566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
8459566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
846552f7358SJed Brown       for (c = off; c < off+dof; ++c) {
84763a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " <---- %" PetscInt_FMT " (%" PetscInt_FMT ")\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]));
848552f7358SJed Brown       }
849552f7358SJed Brown     }
8509566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
8519566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
8523d2e540fSStefano Zampini     if (coordSection && coordinates) {
85319ad8254SMatthew G. Knepley       CoordSystem        cs = CS_CARTESIAN;
8546858538eSMatthew G. Knepley       const PetscScalar *array, *arrayCell = NULL;
8556858538eSMatthew G. Knepley       PetscInt           Nf, Nc, pvStart, pvEnd, pcStart = PETSC_MAX_INT, pcEnd = PETSC_MIN_INT, pStart, pEnd, p;
85619ad8254SMatthew G. Knepley       PetscMPIInt        rank;
85719ad8254SMatthew G. Knepley       const char        *name;
85819ad8254SMatthew G. Knepley 
8599566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetEnum(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_coord_system", CoordSystems, (PetscEnum *) &cs, NULL));
8609566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
8619566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetNumFields(coordSection, &Nf));
86263a3b9bcSJacob Faibussowitsch       PetscCheck(Nf == 1,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate section should have 1 field, not %" PetscInt_FMT, Nf);
8639566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldComponents(coordSection, 0, &Nc));
8646858538eSMatthew G. Knepley       PetscCall(PetscSectionGetChart(coordSection, &pvStart, &pvEnd));
8656858538eSMatthew G. Knepley       if (coordSectionCell) PetscCall(PetscSectionGetChart(coordSectionCell, &pcStart, &pcEnd));
8666858538eSMatthew G. Knepley       pStart =  PetscMin(pvStart, pcStart);
8676858538eSMatthew G. Knepley       pEnd   =  PetscMax(pvEnd,   pcEnd);
8689566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject) coordinates, &name));
86963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s with %" PetscInt_FMT " fields\n", name, Nf));
87063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  field 0 with %" PetscInt_FMT " components\n", Nc));
8719566063dSJacob Faibussowitsch       if (cs != CS_CARTESIAN) PetscCall(PetscViewerASCIIPrintf(viewer, "  output coordinate system: %s\n", CoordSystems[cs]));
87219ad8254SMatthew G. Knepley 
8739566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(coordinates, &array));
8746858538eSMatthew G. Knepley       if (coordinatesCell) PetscCall(VecGetArrayRead(coordinatesCell, &arrayCell));
8759566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushSynchronized(viewer));
8769566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank));
87719ad8254SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
87819ad8254SMatthew G. Knepley         PetscInt dof, off;
87919ad8254SMatthew G. Knepley 
8806858538eSMatthew G. Knepley         if (p >= pvStart && p < pvEnd) {
8819566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(coordSection, p, &dof));
8829566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(coordSection, p, &off));
8836858538eSMatthew G. Knepley           if (dof) {
88463a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "  (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off));
8859566063dSJacob Faibussowitsch             PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &array[off]));
8869566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
88719ad8254SMatthew G. Knepley           }
8886858538eSMatthew G. Knepley         }
8896858538eSMatthew G. Knepley         if (cdmCell && p >= pcStart && p < pcEnd) {
8906858538eSMatthew G. Knepley           PetscCall(PetscSectionGetDof(coordSectionCell, p, &dof));
8916858538eSMatthew G. Knepley           PetscCall(PetscSectionGetOffset(coordSectionCell, p, &off));
8926858538eSMatthew G. Knepley           if (dof) {
8936858538eSMatthew G. Knepley             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "  (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off));
8946858538eSMatthew G. Knepley             PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &arrayCell[off]));
8956858538eSMatthew G. Knepley             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
8966858538eSMatthew G. Knepley           }
8976858538eSMatthew G. Knepley         }
8986858538eSMatthew G. Knepley       }
8999566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
9009566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopSynchronized(viewer));
9019566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(coordinates, &array));
9026858538eSMatthew G. Knepley       if (coordinatesCell) PetscCall(VecRestoreArrayRead(coordinatesCell, &arrayCell));
9033d2e540fSStefano Zampini     }
9049566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
9059566063dSJacob Faibussowitsch     if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n"));
9069318fe57SMatthew G. Knepley     for (l = 0; l < numLabels; ++l) {
9079318fe57SMatthew G. Knepley       DMLabel     label;
9089318fe57SMatthew G. Knepley       PetscBool   isdepth;
9099318fe57SMatthew G. Knepley       const char *name;
9109318fe57SMatthew G. Knepley 
9119566063dSJacob Faibussowitsch       PetscCall(DMGetLabelName(dm, l, &name));
9129566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "depth", &isdepth));
9139318fe57SMatthew G. Knepley       if (isdepth) continue;
9149566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, name, &label));
9159566063dSJacob Faibussowitsch       PetscCall(DMLabelView(label, viewer));
9169318fe57SMatthew G. Knepley     }
917552f7358SJed Brown     if (size > 1) {
918552f7358SJed Brown       PetscSF sf;
919552f7358SJed Brown 
9209566063dSJacob Faibussowitsch       PetscCall(DMGetPointSF(dm, &sf));
9219566063dSJacob Faibussowitsch       PetscCall(PetscSFView(sf, viewer));
922552f7358SJed Brown     }
9239566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
924552f7358SJed Brown   } else if (format == PETSC_VIEWER_ASCII_LATEX) {
9250588280cSMatthew G. Knepley     const char  *name, *color;
9260588280cSMatthew G. Knepley     const char  *defcolors[3]  = {"gray", "orange", "green"};
9270588280cSMatthew G. Knepley     const char  *deflcolors[4] = {"blue", "cyan", "red", "magenta"};
928fe1cc32dSStefano Zampini     char         lname[PETSC_MAX_PATH_LEN];
929552f7358SJed Brown     PetscReal    scale         = 2.0;
93078081901SStefano Zampini     PetscReal    tikzscale     = 1.0;
931b7f6ffafSMatthew G. Knepley     PetscBool    useNumbers    = PETSC_TRUE, drawNumbers[4], drawColors[4], useLabels, useColors, plotEdges, drawHasse = PETSC_FALSE;
9320588280cSMatthew G. Knepley     double       tcoords[3];
933552f7358SJed Brown     PetscScalar *coords;
934b7f6ffafSMatthew G. Knepley     PetscInt     numLabels, l, numColors, numLColors, dim, d, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p, n;
935552f7358SJed Brown     PetscMPIInt  rank, size;
9360588280cSMatthew G. Knepley     char         **names, **colors, **lcolors;
937b7f6ffafSMatthew G. Knepley     PetscBool    flg, lflg;
938fe1cc32dSStefano Zampini     PetscBT      wp = NULL;
939fe1cc32dSStefano Zampini     PetscInt     pEnd, pStart;
940552f7358SJed Brown 
9419566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
9429566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dm, &depth));
9439566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
9440588280cSMatthew G. Knepley     numLabels  = PetscMax(numLabels, 10);
9450588280cSMatthew G. Knepley     numColors  = 10;
9460588280cSMatthew G. Knepley     numLColors = 10;
9479566063dSJacob Faibussowitsch     PetscCall(PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors));
9489566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_scale", &scale, NULL));
9499566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL));
9509566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL));
951b7f6ffafSMatthew G. Knepley     for (d = 0; d < 4; ++d) drawNumbers[d] = useNumbers;
952b7f6ffafSMatthew G. Knepley     for (d = 0; d < 4; ++d) drawColors[d]  = PETSC_TRUE;
953b7f6ffafSMatthew G. Knepley     n = 4;
9549566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBoolArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers_depth", drawNumbers, &n, &flg));
9551dca8a05SBarry 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);
9569566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBoolArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors_depth", drawColors, &n, &flg));
9571dca8a05SBarry 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);
9589566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels));
9590588280cSMatthew G. Knepley     if (!useLabels) numLabels = 0;
9609566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors));
9610588280cSMatthew G. Knepley     if (!useColors) {
9620588280cSMatthew G. Knepley       numColors = 3;
9639566063dSJacob Faibussowitsch       for (c = 0; c < numColors; ++c) PetscCall(PetscStrallocpy(defcolors[c], &colors[c]));
9640588280cSMatthew G. Knepley     }
9659566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors));
9660588280cSMatthew G. Knepley     if (!useColors) {
9670588280cSMatthew G. Knepley       numLColors = 4;
9689566063dSJacob Faibussowitsch       for (c = 0; c < numLColors; ++c) PetscCall(PetscStrallocpy(deflcolors[c], &lcolors[c]));
9690588280cSMatthew G. Knepley     }
9709566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetString(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg));
971b7f6ffafSMatthew G. Knepley     plotEdges = (PetscBool)(depth > 1 && drawNumbers[1] && dim < 3);
9729566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg));
9731dca8a05SBarry Smith     PetscCheck(!flg || !plotEdges || depth >= dim,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Mesh must be interpolated");
974202fd40aSStefano Zampini     if (depth < dim) plotEdges = PETSC_FALSE;
9759566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_hasse", &drawHasse, NULL));
976fe1cc32dSStefano Zampini 
977fe1cc32dSStefano Zampini     /* filter points with labelvalue != labeldefaultvalue */
9789566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
9799566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
9809566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd));
9819566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
982fe1cc32dSStefano Zampini     if (lflg) {
983fe1cc32dSStefano Zampini       DMLabel lbl;
984fe1cc32dSStefano Zampini 
9859566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, lname, &lbl));
986fe1cc32dSStefano Zampini       if (lbl) {
987fe1cc32dSStefano Zampini         PetscInt val, defval;
988fe1cc32dSStefano Zampini 
9899566063dSJacob Faibussowitsch         PetscCall(DMLabelGetDefaultValue(lbl, &defval));
9909566063dSJacob Faibussowitsch         PetscCall(PetscBTCreate(pEnd-pStart, &wp));
991fe1cc32dSStefano Zampini         for (c = pStart;  c < pEnd; c++) {
992fe1cc32dSStefano Zampini           PetscInt *closure = NULL;
993fe1cc32dSStefano Zampini           PetscInt  closureSize;
994fe1cc32dSStefano Zampini 
9959566063dSJacob Faibussowitsch           PetscCall(DMLabelGetValue(lbl, c, &val));
996fe1cc32dSStefano Zampini           if (val == defval) continue;
997fe1cc32dSStefano Zampini 
9989566063dSJacob Faibussowitsch           PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
999fe1cc32dSStefano Zampini           for (p = 0; p < closureSize*2; p += 2) {
10009566063dSJacob Faibussowitsch             PetscCall(PetscBTSet(wp, closure[p] - pStart));
1001fe1cc32dSStefano Zampini           }
10029566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1003fe1cc32dSStefano Zampini         }
1004fe1cc32dSStefano Zampini       }
1005fe1cc32dSStefano Zampini     }
1006fe1cc32dSStefano Zampini 
10079566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
10089566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
10099566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject) dm, &name));
10109566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\
10110588280cSMatthew G. Knepley \\documentclass[tikz]{standalone}\n\n\
1012552f7358SJed Brown \\usepackage{pgflibraryshapes}\n\
1013552f7358SJed Brown \\usetikzlibrary{backgrounds}\n\
1014552f7358SJed Brown \\usetikzlibrary{arrows}\n\
10155f80ce2aSJacob Faibussowitsch \\begin{document}\n"));
10160588280cSMatthew G. Knepley     if (size > 1) {
10179566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s for process ", name));
1018770b213bSMatthew G Knepley       for (p = 0; p < size; ++p) {
101963a3b9bcSJacob Faibussowitsch         if (p) PetscCall(PetscViewerASCIIPrintf(viewer, (p == size-1) ? ", and " :  ", "));
102063a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%" PetscInt_FMT "}", colors[p%numColors], p));
1021770b213bSMatthew G Knepley       }
10229566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, ".\n\n\n"));
10230588280cSMatthew G. Knepley     }
1024b7f6ffafSMatthew G. Knepley     if (drawHasse) {
1025b7f6ffafSMatthew G. Knepley       PetscInt maxStratum = PetscMax(vEnd-vStart, PetscMax(eEnd-eStart, cEnd-cStart));
1026b7f6ffafSMatthew G. Knepley 
102763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vStart}{%" PetscInt_FMT "}\n", vStart));
102863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vEnd}{%" PetscInt_FMT "}\n", vEnd-1));
102963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numVertices}{%" PetscInt_FMT "}\n", vEnd-vStart));
10309566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vShift}{%.2f}\n", 3 + (maxStratum-(vEnd-vStart))/2.));
103163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eStart}{%" PetscInt_FMT "}\n", eStart));
103263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eEnd}{%" PetscInt_FMT "}\n", eEnd-1));
10339566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eShift}{%.2f}\n", 3 + (maxStratum-(eEnd-eStart))/2.));
103463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numEdges}{%" PetscInt_FMT "}\n", eEnd-eStart));
103563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cStart}{%" PetscInt_FMT "}\n", cStart));
103663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cEnd}{%" PetscInt_FMT "}\n", cEnd-1));
103763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numCells}{%" PetscInt_FMT "}\n", cEnd-cStart));
10389566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cShift}{%.2f}\n", 3 + (maxStratum-(cEnd-cStart))/2.));
1039b7f6ffafSMatthew G. Knepley     }
10409566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double) tikzscale));
1041fe1cc32dSStefano Zampini 
1042552f7358SJed Brown     /* Plot vertices */
10439566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
10449566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
1045552f7358SJed Brown     for (v = vStart; v < vEnd; ++v) {
1046552f7358SJed Brown       PetscInt  off, dof, d;
10470588280cSMatthew G. Knepley       PetscBool isLabeled = PETSC_FALSE;
1048552f7358SJed Brown 
1049fe1cc32dSStefano Zampini       if (wp && !PetscBTLookup(wp,v - pStart)) continue;
10509566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(coordSection, v, &dof));
10519566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, v, &off));
10529566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path ("));
105363a3b9bcSJacob Faibussowitsch       PetscCheck(dof <= 3,PETSC_COMM_SELF,PETSC_ERR_PLIB,"coordSection vertex %" PetscInt_FMT " has dof %" PetscInt_FMT " > 3",v,dof);
10540588280cSMatthew G. Knepley       for (d = 0; d < dof; ++d) {
10550588280cSMatthew G. Knepley         tcoords[d] = (double) (scale*PetscRealPart(coords[off+d]));
1056c068d9bbSLisandro Dalcin         tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
10570588280cSMatthew G. Knepley       }
10580588280cSMatthew G. Knepley       /* Rotate coordinates since PGF makes z point out of the page instead of up */
10590588280cSMatthew G. Knepley       if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;}
1060552f7358SJed Brown       for (d = 0; d < dof; ++d) {
10619566063dSJacob Faibussowitsch         if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
10629566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) tcoords[d]));
1063552f7358SJed Brown       }
1064b7f6ffafSMatthew G. Knepley       if (drawHasse) color = colors[0%numColors];
1065b7f6ffafSMatthew G. Knepley       else           color = colors[rank%numColors];
10660588280cSMatthew G. Knepley       for (l = 0; l < numLabels; ++l) {
10670588280cSMatthew G. Knepley         PetscInt val;
10689566063dSJacob Faibussowitsch         PetscCall(DMGetLabelValue(dm, names[l], v, &val));
10690588280cSMatthew G. Knepley         if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;}
10700588280cSMatthew G. Knepley       }
1071b7f6ffafSMatthew G. Knepley       if (drawNumbers[0]) {
107263a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", v, rank, color, v));
1073b7f6ffafSMatthew G. Knepley       } else if (drawColors[0]) {
107463a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color));
10751baa6e33SBarry Smith       } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", v, rank));
1076552f7358SJed Brown     }
10779566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
10789566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
1079b7f6ffafSMatthew G. Knepley     /* Plot edges */
1080b7f6ffafSMatthew G. Knepley     if (plotEdges) {
10819566063dSJacob Faibussowitsch       PetscCall(VecGetArray(coordinates, &coords));
10829566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\path\n"));
1083b7f6ffafSMatthew G. Knepley       for (e = eStart; e < eEnd; ++e) {
1084b7f6ffafSMatthew G. Knepley         const PetscInt *cone;
1085b7f6ffafSMatthew G. Knepley         PetscInt        coneSize, offA, offB, dof, d;
1086b7f6ffafSMatthew G. Knepley 
1087b7f6ffafSMatthew G. Knepley         if (wp && !PetscBTLookup(wp,e - pStart)) continue;
10889566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, e, &coneSize));
108963a3b9bcSJacob Faibussowitsch         PetscCheck(coneSize == 2,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %" PetscInt_FMT " cone should have two vertices, not %" PetscInt_FMT, e, coneSize);
10909566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, e, &cone));
10919566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(coordSection, cone[0], &dof));
10929566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(coordSection, cone[0], &offA));
10939566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(coordSection, cone[1], &offB));
10949566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "("));
1095b7f6ffafSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
1096b7f6ffafSMatthew G. Knepley           tcoords[d] = (double) (0.5*scale*PetscRealPart(coords[offA+d]+coords[offB+d]));
1097b7f6ffafSMatthew G. Knepley           tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
1098b7f6ffafSMatthew G. Knepley         }
1099b7f6ffafSMatthew G. Knepley         /* Rotate coordinates since PGF makes z point out of the page instead of up */
1100b7f6ffafSMatthew G. Knepley         if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;}
1101b7f6ffafSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
11029566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
11039566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d]));
1104b7f6ffafSMatthew G. Knepley         }
1105b7f6ffafSMatthew G. Knepley         if (drawHasse) color = colors[1%numColors];
1106b7f6ffafSMatthew G. Knepley         else           color = colors[rank%numColors];
1107b7f6ffafSMatthew G. Knepley         for (l = 0; l < numLabels; ++l) {
1108b7f6ffafSMatthew G. Knepley           PetscInt val;
11099566063dSJacob Faibussowitsch           PetscCall(DMGetLabelValue(dm, names[l], v, &val));
1110b7f6ffafSMatthew G. Knepley           if (val >= 0) {color = lcolors[l%numLColors]; break;}
1111b7f6ffafSMatthew G. Knepley         }
111263a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "} --\n", e, rank, color, e));
1113b7f6ffafSMatthew G. Knepley       }
11149566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(coordinates, &coords));
11159566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
11169566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "(0,0);\n"));
1117b7f6ffafSMatthew G. Knepley     }
1118846a3e8bSMatthew G. Knepley     /* Plot cells */
1119b7f6ffafSMatthew G. Knepley     if (dim == 3 || !drawNumbers[1]) {
1120846a3e8bSMatthew G. Knepley       for (e = eStart; e < eEnd; ++e) {
1121846a3e8bSMatthew G. Knepley         const PetscInt *cone;
1122846a3e8bSMatthew G. Knepley 
1123fe1cc32dSStefano Zampini         if (wp && !PetscBTLookup(wp,e - pStart)) continue;
1124846a3e8bSMatthew G. Knepley         color = colors[rank%numColors];
1125846a3e8bSMatthew G. Knepley         for (l = 0; l < numLabels; ++l) {
1126846a3e8bSMatthew G. Knepley           PetscInt val;
11279566063dSJacob Faibussowitsch           PetscCall(DMGetLabelValue(dm, names[l], e, &val));
1128846a3e8bSMatthew G. Knepley           if (val >= 0) {color = lcolors[l%numLColors]; break;}
1129846a3e8bSMatthew G. Knepley         }
11309566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, e, &cone));
113163a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", color, cone[0], rank, cone[1], rank));
1132846a3e8bSMatthew G. Knepley       }
1133846a3e8bSMatthew G. Knepley     } else {
1134b7f6ffafSMatthew G. Knepley        DMPolytopeType ct;
1135846a3e8bSMatthew G. Knepley 
1136b7f6ffafSMatthew G. Knepley       /* Drawing a 2D polygon */
1137b7f6ffafSMatthew G. Knepley       for (c = cStart; c < cEnd; ++c) {
1138fe1cc32dSStefano Zampini         if (wp && !PetscBTLookup(wp, c - pStart)) continue;
11399566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, c, &ct));
1140b7f6ffafSMatthew G. Knepley         if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR ||
1141b7f6ffafSMatthew G. Knepley             ct == DM_POLYTOPE_TRI_PRISM_TENSOR ||
1142b7f6ffafSMatthew G. Knepley             ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) {
1143b7f6ffafSMatthew G. Knepley           const PetscInt *cone;
1144b7f6ffafSMatthew G. Knepley           PetscInt        coneSize, e;
1145b7f6ffafSMatthew G. Knepley 
11469566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCone(dm, c, &cone));
11479566063dSJacob Faibussowitsch           PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
1148b7f6ffafSMatthew G. Knepley           for (e = 0; e < coneSize; ++e) {
1149b7f6ffafSMatthew G. Knepley             const PetscInt *econe;
1150b7f6ffafSMatthew G. Knepley 
11519566063dSJacob Faibussowitsch             PetscCall(DMPlexGetCone(dm, cone[e], &econe));
115263a3b9bcSJacob 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));
1153b7f6ffafSMatthew G. Knepley           }
1154b7f6ffafSMatthew G. Knepley         } else {
1155b7f6ffafSMatthew G. Knepley           PetscInt *closure = NULL;
1156b7f6ffafSMatthew G. Knepley           PetscInt  closureSize, Nv = 0, v;
1157b7f6ffafSMatthew G. Knepley 
11589566063dSJacob Faibussowitsch           PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1159846a3e8bSMatthew G. Knepley           for (p = 0; p < closureSize*2; p += 2) {
1160846a3e8bSMatthew G. Knepley             const PetscInt point = closure[p];
1161846a3e8bSMatthew G. Knepley 
1162b7f6ffafSMatthew G. Knepley             if ((point >= vStart) && (point < vEnd)) closure[Nv++] = point;
1163846a3e8bSMatthew G. Knepley           }
11649566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]));
1165b7f6ffafSMatthew G. Knepley           for (v = 0; v <= Nv; ++v) {
1166b7f6ffafSMatthew G. Knepley             const PetscInt vertex = closure[v%Nv];
1167b7f6ffafSMatthew G. Knepley 
1168b7f6ffafSMatthew G. Knepley             if (v > 0) {
1169b7f6ffafSMatthew G. Knepley               if (plotEdges) {
1170b7f6ffafSMatthew G. Knepley                 const PetscInt *edge;
1171b7f6ffafSMatthew G. Knepley                 PetscInt        endpoints[2], ne;
1172b7f6ffafSMatthew G. Knepley 
1173b7f6ffafSMatthew G. Knepley                 endpoints[0] = closure[v-1]; endpoints[1] = vertex;
11749566063dSJacob Faibussowitsch                 PetscCall(DMPlexGetJoin(dm, 2, endpoints, &ne, &edge));
117563a3b9bcSJacob Faibussowitsch                 PetscCheck(ne == 1,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find edge for vertices %" PetscInt_FMT ", %" PetscInt_FMT, endpoints[0], endpoints[1]);
117663a3b9bcSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- (%" PetscInt_FMT "_%d) -- ", edge[0], rank));
11779566063dSJacob Faibussowitsch                 PetscCall(DMPlexRestoreJoin(dm, 2, endpoints, &ne, &edge));
11781baa6e33SBarry Smith               } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- "));
1179b7f6ffafSMatthew G. Knepley             }
118063a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(%" PetscInt_FMT "_%d)", vertex, rank));
1181b7f6ffafSMatthew G. Knepley           }
11829566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ";\n"));
11839566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1184846a3e8bSMatthew G. Knepley         }
1185846a3e8bSMatthew G. Knepley       }
1186b7f6ffafSMatthew G. Knepley     }
11879566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
1188846a3e8bSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
1189846a3e8bSMatthew G. Knepley       double    ccoords[3] = {0.0, 0.0, 0.0};
1190846a3e8bSMatthew G. Knepley       PetscBool isLabeled  = PETSC_FALSE;
1191846a3e8bSMatthew G. Knepley       PetscInt *closure    = NULL;
1192846a3e8bSMatthew G. Knepley       PetscInt  closureSize, dof, d, n = 0;
1193846a3e8bSMatthew G. Knepley 
1194fe1cc32dSStefano Zampini       if (wp && !PetscBTLookup(wp,c - pStart)) continue;
11959566063dSJacob Faibussowitsch       PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
11969566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path ("));
1197846a3e8bSMatthew G. Knepley       for (p = 0; p < closureSize*2; p += 2) {
1198846a3e8bSMatthew G. Knepley         const PetscInt point = closure[p];
1199846a3e8bSMatthew G. Knepley         PetscInt       off;
1200846a3e8bSMatthew G. Knepley 
1201846a3e8bSMatthew G. Knepley         if ((point < vStart) || (point >= vEnd)) continue;
12029566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(coordSection, point, &dof));
12039566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(coordSection, point, &off));
1204846a3e8bSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
1205846a3e8bSMatthew G. Knepley           tcoords[d] = (double) (scale*PetscRealPart(coords[off+d]));
1206846a3e8bSMatthew G. Knepley           tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
1207846a3e8bSMatthew G. Knepley         }
1208846a3e8bSMatthew G. Knepley         /* Rotate coordinates since PGF makes z point out of the page instead of up */
1209846a3e8bSMatthew G. Knepley         if (dof == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;}
1210846a3e8bSMatthew G. Knepley         for (d = 0; d < dof; ++d) {ccoords[d] += tcoords[d];}
1211846a3e8bSMatthew G. Knepley         ++n;
1212846a3e8bSMatthew G. Knepley       }
1213846a3e8bSMatthew G. Knepley       for (d = 0; d < dof; ++d) {ccoords[d] /= n;}
12149566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1215846a3e8bSMatthew G. Knepley       for (d = 0; d < dof; ++d) {
12169566063dSJacob Faibussowitsch         if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
12179566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) ccoords[d]));
1218846a3e8bSMatthew G. Knepley       }
1219b7f6ffafSMatthew G. Knepley       if (drawHasse) color = colors[depth%numColors];
1220b7f6ffafSMatthew G. Knepley       else           color = colors[rank%numColors];
1221846a3e8bSMatthew G. Knepley       for (l = 0; l < numLabels; ++l) {
1222846a3e8bSMatthew G. Knepley         PetscInt val;
12239566063dSJacob Faibussowitsch         PetscCall(DMGetLabelValue(dm, names[l], c, &val));
1224846a3e8bSMatthew G. Knepley         if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;}
1225846a3e8bSMatthew G. Knepley       }
1226b7f6ffafSMatthew G. Knepley       if (drawNumbers[dim]) {
122763a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", c, rank, color, c));
1228b7f6ffafSMatthew G. Knepley       } else if (drawColors[dim]) {
122963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color));
12301baa6e33SBarry Smith       } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", c, rank));
1231846a3e8bSMatthew G. Knepley     }
12329566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
1233b7f6ffafSMatthew G. Knepley     if (drawHasse) {
1234b7f6ffafSMatthew G. Knepley       color = colors[depth%numColors];
12359566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Cells\n"));
12369566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\c in {\\cStart,...,\\cEnd}\n"));
12379566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
12389566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\c_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\cShift+\\c-\\cStart,0) {\\c};\n", rank, color));
12399566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1240552f7358SJed Brown 
1241b7f6ffafSMatthew G. Knepley       color = colors[1%numColors];
12429566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Edges\n"));
12439566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\e in {\\eStart,...,\\eEnd}\n"));
12449566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
12459566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\e_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\eShift+\\e-\\eStart,1) {\\e};\n", rank, color));
12469566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1247b7f6ffafSMatthew G. Knepley 
1248b7f6ffafSMatthew G. Knepley       color = colors[0%numColors];
12499566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Vertices\n"));
12509566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\v in {\\vStart,...,\\vEnd}\n"));
12519566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
12529566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\v_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\vShift+\\v-\\vStart,2) {\\v};\n", rank, color));
12539566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1254b7f6ffafSMatthew G. Knepley 
1255b7f6ffafSMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
1256b7f6ffafSMatthew G. Knepley         const PetscInt *cone;
1257b7f6ffafSMatthew G. Knepley         PetscInt        coneSize, cp;
1258b7f6ffafSMatthew G. Knepley 
12599566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, p, &cone));
12609566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
1261b7f6ffafSMatthew G. Knepley         for (cp = 0; cp < coneSize; ++cp) {
126263a3b9bcSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "\\draw[->, shorten >=1pt] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", cone[cp], rank, p, rank));
1263552f7358SJed Brown         }
12640588280cSMatthew G. Knepley       }
12650588280cSMatthew G. Knepley     }
12669566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
12679566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
12689566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n"));
126963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{document}\n"));
12709566063dSJacob Faibussowitsch     for (l = 0; l < numLabels;  ++l) PetscCall(PetscFree(names[l]));
12719566063dSJacob Faibussowitsch     for (c = 0; c < numColors;  ++c) PetscCall(PetscFree(colors[c]));
12729566063dSJacob Faibussowitsch     for (c = 0; c < numLColors; ++c) PetscCall(PetscFree(lcolors[c]));
12739566063dSJacob Faibussowitsch     PetscCall(PetscFree3(names, colors, lcolors));
12749566063dSJacob Faibussowitsch     PetscCall(PetscBTDestroy(&wp));
12750f7d6e4aSStefano Zampini   } else if (format == PETSC_VIEWER_LOAD_BALANCE) {
12760f7d6e4aSStefano Zampini     Vec                    cown,acown;
12770f7d6e4aSStefano Zampini     VecScatter             sct;
12780f7d6e4aSStefano Zampini     ISLocalToGlobalMapping g2l;
12790f7d6e4aSStefano Zampini     IS                     gid,acis;
12800f7d6e4aSStefano Zampini     MPI_Comm               comm,ncomm = MPI_COMM_NULL;
12810f7d6e4aSStefano Zampini     MPI_Group              ggroup,ngroup;
12820f7d6e4aSStefano Zampini     PetscScalar            *array,nid;
12830f7d6e4aSStefano Zampini     const PetscInt         *idxs;
12840f7d6e4aSStefano Zampini     PetscInt               *idxs2,*start,*adjacency,*work;
12850f7d6e4aSStefano Zampini     PetscInt64             lm[3],gm[3];
12860f7d6e4aSStefano Zampini     PetscInt               i,c,cStart,cEnd,cum,numVertices,ect,ectn,cellHeight;
12870f7d6e4aSStefano Zampini     PetscMPIInt            d1,d2,rank;
12880f7d6e4aSStefano Zampini 
12899566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)dm,&comm));
12909566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm,&rank));
1291b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
12929566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_split_type(comm,MPI_COMM_TYPE_SHARED,rank,MPI_INFO_NULL,&ncomm));
12930f7d6e4aSStefano Zampini #endif
12940f7d6e4aSStefano Zampini     if (ncomm != MPI_COMM_NULL) {
12959566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_group(comm,&ggroup));
12969566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_group(ncomm,&ngroup));
12970f7d6e4aSStefano Zampini       d1   = 0;
12989566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_translate_ranks(ngroup,1,&d1,ggroup,&d2));
12990f7d6e4aSStefano Zampini       nid  = d2;
13009566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_free(&ggroup));
13019566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_free(&ngroup));
13029566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_free(&ncomm));
13030f7d6e4aSStefano Zampini     } else nid = 0.0;
13040f7d6e4aSStefano Zampini 
13050f7d6e4aSStefano Zampini     /* Get connectivity */
13069566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm,&cellHeight));
13079566063dSJacob Faibussowitsch     PetscCall(DMPlexCreatePartitionerGraph(dm,cellHeight,&numVertices,&start,&adjacency,&gid));
13080f7d6e4aSStefano Zampini 
13090f7d6e4aSStefano Zampini     /* filter overlapped local cells */
13109566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm,cellHeight,&cStart,&cEnd));
13119566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(gid,&idxs));
13129566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(gid,&cum));
13139566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(cum,&idxs2));
13140f7d6e4aSStefano Zampini     for (c = cStart, cum = 0; c < cEnd; c++) {
13150f7d6e4aSStefano Zampini       if (idxs[c-cStart] < 0) continue;
13160f7d6e4aSStefano Zampini       idxs2[cum++] = idxs[c-cStart];
13170f7d6e4aSStefano Zampini     }
13189566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(gid,&idxs));
131963a3b9bcSJacob Faibussowitsch     PetscCheck(numVertices == cum,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected %" PetscInt_FMT " != %" PetscInt_FMT,numVertices,cum);
13209566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&gid));
13219566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm,numVertices,idxs2,PETSC_OWN_POINTER,&gid));
13220f7d6e4aSStefano Zampini 
13230f7d6e4aSStefano Zampini     /* support for node-aware cell locality */
13249566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm,start[numVertices],adjacency,PETSC_USE_POINTER,&acis));
13259566063dSJacob Faibussowitsch     PetscCall(VecCreateSeq(PETSC_COMM_SELF,start[numVertices],&acown));
13269566063dSJacob Faibussowitsch     PetscCall(VecCreateMPI(comm,numVertices,PETSC_DECIDE,&cown));
13279566063dSJacob Faibussowitsch     PetscCall(VecGetArray(cown,&array));
13280f7d6e4aSStefano Zampini     for (c = 0; c < numVertices; c++) array[c] = nid;
13299566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(cown,&array));
13309566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(cown,acis,acown,NULL,&sct));
13319566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD));
13329566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD));
13339566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&acis));
13349566063dSJacob Faibussowitsch     PetscCall(VecScatterDestroy(&sct));
13359566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&cown));
13360f7d6e4aSStefano Zampini 
13370f7d6e4aSStefano Zampini     /* compute edgeCut */
13380f7d6e4aSStefano Zampini     for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum,start[c+1]-start[c]);
13399566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(cum,&work));
13409566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(gid,&g2l));
13419566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingSetType(g2l,ISLOCALTOGLOBALMAPPINGHASH));
13429566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&gid));
13439566063dSJacob Faibussowitsch     PetscCall(VecGetArray(acown,&array));
13440f7d6e4aSStefano Zampini     for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) {
13450f7d6e4aSStefano Zampini       PetscInt totl;
13460f7d6e4aSStefano Zampini 
13470f7d6e4aSStefano Zampini       totl = start[c+1]-start[c];
13489566063dSJacob Faibussowitsch       PetscCall(ISGlobalToLocalMappingApply(g2l,IS_GTOLM_MASK,totl,adjacency+start[c],NULL,work));
13490f7d6e4aSStefano Zampini       for (i = 0; i < totl; i++) {
13500f7d6e4aSStefano Zampini         if (work[i] < 0) {
13510f7d6e4aSStefano Zampini           ect  += 1;
13520f7d6e4aSStefano Zampini           ectn += (array[i + start[c]] != nid) ? 0 : 1;
13530f7d6e4aSStefano Zampini         }
13540f7d6e4aSStefano Zampini       }
13550f7d6e4aSStefano Zampini     }
13569566063dSJacob Faibussowitsch     PetscCall(PetscFree(work));
13579566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(acown,&array));
13580f7d6e4aSStefano Zampini     lm[0] = numVertices > 0 ?  numVertices : PETSC_MAX_INT;
13590f7d6e4aSStefano Zampini     lm[1] = -numVertices;
13601c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(lm,gm,2,MPIU_INT64,MPI_MIN,comm));
136163a3b9bcSJacob 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]));
13620f7d6e4aSStefano Zampini     lm[0] = ect; /* edgeCut */
13630f7d6e4aSStefano Zampini     lm[1] = ectn; /* node-aware edgeCut */
13640f7d6e4aSStefano Zampini     lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */
13651c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(lm,gm,3,MPIU_INT64,MPI_SUM,comm));
136663a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,", empty %" PetscInt_FMT ")\n",(PetscInt)gm[2]));
1367b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
136863a3b9bcSJacob 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.));
13690f7d6e4aSStefano Zampini #else
137063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Edge Cut: %" PetscInt_FMT " (on node %.3f)\n",(PetscInt)(gm[0]/2),0.0));
13710f7d6e4aSStefano Zampini #endif
13729566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&g2l));
13739566063dSJacob Faibussowitsch     PetscCall(PetscFree(start));
13749566063dSJacob Faibussowitsch     PetscCall(PetscFree(adjacency));
13759566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&acown));
1376552f7358SJed Brown   } else {
1377412e9a14SMatthew G. Knepley     const char    *name;
1378d80ece95SMatthew G. Knepley     PetscInt      *sizes, *hybsizes, *ghostsizes;
1379412e9a14SMatthew G. Knepley     PetscInt       locDepth, depth, cellHeight, dim, d;
1380d80ece95SMatthew G. Knepley     PetscInt       pStart, pEnd, p, gcStart, gcEnd, gcNum;
1381ca7bf7eeSMatthew G. Knepley     PetscInt       numLabels, l, maxSize = 17;
13829318fe57SMatthew G. Knepley     DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN;
1383412e9a14SMatthew G. Knepley     MPI_Comm       comm;
1384412e9a14SMatthew G. Knepley     PetscMPIInt    size, rank;
1385552f7358SJed Brown 
13869566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject) dm, &comm));
13879566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(comm, &size));
13889566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
13899566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
13909566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
13919566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject) dm, &name));
139263a3b9bcSJacob Faibussowitsch     if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s"));
139363a3b9bcSJacob Faibussowitsch     else      PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s"));
139463a3b9bcSJacob Faibussowitsch     if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, "  Cells are at height %" PetscInt_FMT "\n", cellHeight));
13959566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dm, &locDepth));
13961c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm));
13979566063dSJacob Faibussowitsch     PetscCall(DMPlexGetGhostCellStratum(dm, &gcStart, &gcEnd));
1398d80ece95SMatthew G. Knepley     gcNum = gcEnd - gcStart;
13999566063dSJacob Faibussowitsch     if (size < maxSize) PetscCall(PetscCalloc3(size, &sizes, size, &hybsizes, size, &ghostsizes));
14009566063dSJacob Faibussowitsch     else                PetscCall(PetscCalloc3(3,    &sizes, 3,    &hybsizes, 3,    &ghostsizes));
1401412e9a14SMatthew G. Knepley     for (d = 0; d <= depth; d++) {
1402412e9a14SMatthew G. Knepley       PetscInt Nc[2] = {0, 0}, ict;
1403412e9a14SMatthew G. Knepley 
14049566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
14059566063dSJacob Faibussowitsch       if (pStart < pEnd) PetscCall(DMPlexGetCellType(dm, pStart, &ct0));
1406412e9a14SMatthew G. Knepley       ict  = ct0;
14079566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Bcast(&ict, 1, MPIU_INT, 0, comm));
1408412e9a14SMatthew G. Knepley       ct0  = (DMPolytopeType) ict;
1409412e9a14SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
1410412e9a14SMatthew G. Knepley         DMPolytopeType ct;
1411412e9a14SMatthew G. Knepley 
14129566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, p, &ct));
1413412e9a14SMatthew G. Knepley         if (ct == ct0) ++Nc[0];
1414412e9a14SMatthew G. Knepley         else           ++Nc[1];
1415412e9a14SMatthew G. Knepley       }
1416ca7bf7eeSMatthew G. Knepley       if (size < maxSize) {
14179566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Gather(&Nc[0], 1, MPIU_INT, sizes,    1, MPIU_INT, 0, comm));
14189566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm));
14199566063dSJacob Faibussowitsch         if (d == depth) PetscCallMPI(MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm));
142063a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Number of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d));
1421834065abSMatthew G. Knepley         for (p = 0; p < size; ++p) {
1422dd400576SPatrick Sanan           if (rank == 0) {
142363a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sizes[p]+hybsizes[p]));
142463a3b9bcSJacob Faibussowitsch             if (hybsizes[p]   > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ")", hybsizes[p]));
142563a3b9bcSJacob Faibussowitsch             if (ghostsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "]", ghostsizes[p]));
1426834065abSMatthew G. Knepley           }
1427cbb7f117SMark Adams         }
1428ca7bf7eeSMatthew G. Knepley       } else {
1429ca7bf7eeSMatthew G. Knepley         PetscInt locMinMax[2];
1430ca7bf7eeSMatthew G. Knepley 
1431ca7bf7eeSMatthew G. Knepley         locMinMax[0] = Nc[0]+Nc[1]; locMinMax[1] = Nc[0]+Nc[1];
14329566063dSJacob Faibussowitsch         PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, sizes));
1433ca7bf7eeSMatthew G. Knepley         locMinMax[0] = Nc[1]; locMinMax[1] = Nc[1];
14349566063dSJacob Faibussowitsch         PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, hybsizes));
1435ca7bf7eeSMatthew G. Knepley         if (d == depth) {
1436ca7bf7eeSMatthew G. Knepley           locMinMax[0] = gcNum; locMinMax[1] = gcNum;
14379566063dSJacob Faibussowitsch           PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, ghostsizes));
1438ca7bf7eeSMatthew G. Knepley         }
143963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Min/Max of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d));
14409566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1]));
14419566063dSJacob Faibussowitsch         if (hybsizes[0]   > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT "/%" PetscInt_FMT ")", hybsizes[0], hybsizes[1]));
14429566063dSJacob Faibussowitsch         if (ghostsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "/%" PetscInt_FMT "]", ghostsizes[0], ghostsizes[1]));
1443ca7bf7eeSMatthew G. Knepley       }
14449566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
1445552f7358SJed Brown     }
14469566063dSJacob Faibussowitsch     PetscCall(PetscFree3(sizes, hybsizes, ghostsizes));
14479318fe57SMatthew G. Knepley     {
14489318fe57SMatthew G. Knepley       const PetscReal *maxCell;
14499318fe57SMatthew G. Knepley       const PetscReal *L;
14506858538eSMatthew G. Knepley       PetscBool        localized;
14519318fe57SMatthew G. Knepley 
14524fb89dddSMatthew G. Knepley       PetscCall(DMGetPeriodicity(dm, &maxCell, NULL, &L));
14539566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocalized(dm, &localized));
14546858538eSMatthew G. Knepley       if (L || localized) {
14556858538eSMatthew G. Knepley         PetscCall(PetscViewerASCIIPrintf(viewer, "Periodic mesh"));
14569566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
14576858538eSMatthew G. Knepley         if (L) {
14586858538eSMatthew G. Knepley           PetscCall(PetscViewerASCIIPrintf(viewer, " ("));
14599318fe57SMatthew G. Knepley           for (d = 0; d < dim; ++d) {
14606858538eSMatthew G. Knepley             if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
14616858538eSMatthew G. Knepley             PetscCall(PetscViewerASCIIPrintf(viewer, "%s", L[d] > 0.0 ? "PERIODIC" : "NONE"));
14629318fe57SMatthew G. Knepley           }
14636858538eSMatthew G. Knepley           PetscCall(PetscViewerASCIIPrintf(viewer, ")"));
14646858538eSMatthew G. Knepley         }
14656858538eSMatthew G. Knepley         PetscCall(PetscViewerASCIIPrintf(viewer, " coordinates %s\n", localized ? "localized" : "not localized"));
14669566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
14679318fe57SMatthew G. Knepley       }
14689318fe57SMatthew G. Knepley     }
14699566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
14709566063dSJacob Faibussowitsch     if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n"));
1471a57dd577SMatthew G Knepley     for (l = 0; l < numLabels; ++l) {
1472a57dd577SMatthew G Knepley       DMLabel         label;
1473a57dd577SMatthew G Knepley       const char     *name;
1474a57dd577SMatthew G Knepley       IS              valueIS;
1475a57dd577SMatthew G Knepley       const PetscInt *values;
1476a57dd577SMatthew G Knepley       PetscInt        numValues, v;
1477a57dd577SMatthew G Knepley 
14789566063dSJacob Faibussowitsch       PetscCall(DMGetLabelName(dm, l, &name));
14799566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, name, &label));
14809566063dSJacob Faibussowitsch       PetscCall(DMLabelGetNumValues(label, &numValues));
148163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  %s: %" PetscInt_FMT " strata with value/size (", name, numValues));
14829566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValueIS(label, &valueIS));
14839566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(valueIS, &values));
14849566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
1485a57dd577SMatthew G Knepley       for (v = 0; v < numValues; ++v) {
1486a57dd577SMatthew G Knepley         PetscInt size;
1487a57dd577SMatthew G Knepley 
14889566063dSJacob Faibussowitsch         PetscCall(DMLabelGetStratumSize(label, values[v], &size));
14899566063dSJacob Faibussowitsch         if (v > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
149063a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " (%" PetscInt_FMT ")", values[v], size));
1491a57dd577SMatthew G Knepley       }
14929566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, ")\n"));
14939566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
14949566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(valueIS, &values));
14959566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&valueIS));
1496a57dd577SMatthew G Knepley     }
1497c1cad2e7SMatthew G. Knepley     {
1498c1cad2e7SMatthew G. Knepley       char    **labelNames;
1499c1cad2e7SMatthew G. Knepley       PetscInt  Nl = numLabels;
1500c1cad2e7SMatthew G. Knepley       PetscBool flg;
1501c1cad2e7SMatthew G. Knepley 
15029566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Nl, &labelNames));
15039566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetStringArray(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_plex_view_labels", labelNames, &Nl, &flg));
1504c1cad2e7SMatthew G. Knepley       for (l = 0; l < Nl; ++l) {
1505c1cad2e7SMatthew G. Knepley         DMLabel label;
1506c1cad2e7SMatthew G. Knepley 
15079566063dSJacob Faibussowitsch         PetscCall(DMHasLabel(dm, labelNames[l], &flg));
1508c1cad2e7SMatthew G. Knepley         if (flg) {
15099566063dSJacob Faibussowitsch           PetscCall(DMGetLabel(dm, labelNames[l], &label));
15109566063dSJacob Faibussowitsch           PetscCall(DMLabelView(label, viewer));
1511c1cad2e7SMatthew G. Knepley         }
15129566063dSJacob Faibussowitsch         PetscCall(PetscFree(labelNames[l]));
1513c1cad2e7SMatthew G. Knepley       }
15149566063dSJacob Faibussowitsch       PetscCall(PetscFree(labelNames));
1515c1cad2e7SMatthew G. Knepley     }
151634aa8a36SMatthew G. Knepley     /* If no fields are specified, people do not want to see adjacency */
151734aa8a36SMatthew G. Knepley     if (dm->Nf) {
151834aa8a36SMatthew G. Knepley       PetscInt f;
151934aa8a36SMatthew G. Knepley 
152034aa8a36SMatthew G. Knepley       for (f = 0; f < dm->Nf; ++f) {
152134aa8a36SMatthew G. Knepley         const char *name;
152234aa8a36SMatthew G. Knepley 
15239566063dSJacob Faibussowitsch         PetscCall(PetscObjectGetName(dm->fields[f].disc, &name));
15249566063dSJacob Faibussowitsch         if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Field %s:\n", name));
15259566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
15269566063dSJacob Faibussowitsch         if (dm->fields[f].label) PetscCall(DMLabelView(dm->fields[f].label, viewer));
152734aa8a36SMatthew G. Knepley         if (dm->fields[f].adjacency[0]) {
15289566063dSJacob Faibussowitsch           if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n"));
15299566063dSJacob Faibussowitsch           else                            PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM\n"));
153034aa8a36SMatthew G. Knepley         } else {
15319566063dSJacob Faibussowitsch           if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FEM\n"));
15329566063dSJacob Faibussowitsch           else                            PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n"));
153334aa8a36SMatthew G. Knepley         }
15349566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
153534aa8a36SMatthew G. Knepley       }
153634aa8a36SMatthew G. Knepley     }
15379566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dm, &cdm));
15388e7ff633SMatthew G. Knepley     if (cdm) {
15399566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(viewer));
15409566063dSJacob Faibussowitsch       PetscCall(DMPlexView_Ascii(cdm, viewer));
15419566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(viewer));
15428e7ff633SMatthew G. Knepley     }
1543552f7358SJed Brown   }
1544552f7358SJed Brown   PetscFunctionReturn(0);
1545552f7358SJed Brown }
1546552f7358SJed Brown 
1547e5c487bfSMatthew G. Knepley static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[])
1548e5c487bfSMatthew G. Knepley {
1549e5c487bfSMatthew G. Knepley   DMPolytopeType ct;
1550e5c487bfSMatthew G. Knepley   PetscMPIInt    rank;
1551a12d352dSMatthew G. Knepley   PetscInt       cdim;
1552e5c487bfSMatthew G. Knepley 
1553e5c487bfSMatthew G. Knepley   PetscFunctionBegin;
15549566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank));
15559566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cell, &ct));
15569566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
1557e5c487bfSMatthew G. Knepley   switch (ct) {
1558a12d352dSMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
1559a12d352dSMatthew G. Knepley   case DM_POLYTOPE_POINT_PRISM_TENSOR:
1560a12d352dSMatthew G. Knepley     switch (cdim) {
1561a12d352dSMatthew G. Knepley     case 1:
1562a12d352dSMatthew G. Knepley     {
1563a12d352dSMatthew G. Knepley       const PetscReal y  = 0.5;  /* TODO Put it in the middle of the viewport */
1564a12d352dSMatthew G. Knepley       const PetscReal dy = 0.05; /* TODO Make it a fraction of the total length */
1565a12d352dSMatthew G. Knepley 
15669566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y,    PetscRealPart(coords[1]), y,    PETSC_DRAW_BLACK));
15679566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y+dy, PetscRealPart(coords[0]), y-dy, PETSC_DRAW_BLACK));
15689566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[1]), y+dy, PetscRealPart(coords[1]), y-dy, PETSC_DRAW_BLACK));
1569a12d352dSMatthew G. Knepley     }
1570a12d352dSMatthew G. Knepley     break;
1571a12d352dSMatthew G. Knepley     case 2:
1572a12d352dSMatthew G. Knepley     {
1573a12d352dSMatthew G. Knepley       const PetscReal dx = (PetscRealPart(coords[3]) - PetscRealPart(coords[1]));
1574a12d352dSMatthew G. Knepley       const PetscReal dy = (PetscRealPart(coords[2]) - PetscRealPart(coords[0]));
1575a12d352dSMatthew G. Knepley       const PetscReal l  = 0.1/PetscSqrtReal(dx*dx + dy*dy);
1576a12d352dSMatthew G. Knepley 
15779566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
15789566063dSJacob 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));
15799566063dSJacob 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));
1580a12d352dSMatthew G. Knepley     }
1581a12d352dSMatthew G. Knepley     break;
158263a3b9bcSJacob Faibussowitsch     default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of dimension %" PetscInt_FMT, cdim);
1583a12d352dSMatthew G. Knepley     }
1584a12d352dSMatthew G. Knepley     break;
1585e5c487bfSMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
15869566063dSJacob Faibussowitsch     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]),
1587e5c487bfSMatthew G. Knepley                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2,
1588e5c487bfSMatthew G. Knepley                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2,
15895f80ce2aSJacob Faibussowitsch                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2));
15909566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
15919566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK));
15929566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK));
1593e5c487bfSMatthew G. Knepley     break;
1594e5c487bfSMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
15959566063dSJacob Faibussowitsch     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]),
1596e5c487bfSMatthew G. Knepley                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2,
1597e5c487bfSMatthew G. Knepley                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2,
15985f80ce2aSJacob Faibussowitsch                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2));
15999566063dSJacob Faibussowitsch     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]),
1600e5c487bfSMatthew G. Knepley                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2,
1601e5c487bfSMatthew G. Knepley                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2,
16025f80ce2aSJacob Faibussowitsch                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2));
16039566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
16049566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK));
16059566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK));
16069566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK));
1607e5c487bfSMatthew G. Knepley     break;
160898921bdaSJacob Faibussowitsch   default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]);
1609e5c487bfSMatthew G. Knepley   }
1610e5c487bfSMatthew G. Knepley   PetscFunctionReturn(0);
1611e5c487bfSMatthew G. Knepley }
1612e5c487bfSMatthew G. Knepley 
1613e5c487bfSMatthew G. Knepley static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[])
1614e5c487bfSMatthew G. Knepley {
1615e5c487bfSMatthew G. Knepley   DMPolytopeType ct;
1616e5c487bfSMatthew G. Knepley   PetscReal      centroid[2] = {0., 0.};
1617e5c487bfSMatthew G. Knepley   PetscMPIInt    rank;
1618e5c487bfSMatthew G. Knepley   PetscInt       fillColor, v, e, d;
1619e5c487bfSMatthew G. Knepley 
1620e5c487bfSMatthew G. Knepley   PetscFunctionBegin;
16219566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank));
16229566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cell, &ct));
1623e5c487bfSMatthew G. Knepley   fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2;
1624e5c487bfSMatthew G. Knepley   switch (ct) {
1625e5c487bfSMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
1626e5c487bfSMatthew G. Knepley     {
1627e5c487bfSMatthew G. Knepley       PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.};
1628e5c487bfSMatthew G. Knepley 
1629e5c487bfSMatthew G. Knepley       for (v = 0; v < 3; ++v) {centroid[0] += PetscRealPart(coords[v*2+0])/3.;centroid[1] += PetscRealPart(coords[v*2+1])/3.;}
1630e5c487bfSMatthew G. Knepley       for (e = 0; e < 3; ++e) {
1631e5c487bfSMatthew G. Knepley         refCoords[0] = refVertices[e*2+0];
1632e5c487bfSMatthew G. Knepley         refCoords[1] = refVertices[e*2+1];
1633e5c487bfSMatthew G. Knepley         for (d = 1; d <= edgeDiv; ++d) {
1634e5c487bfSMatthew G. Knepley           refCoords[d*2+0] = refCoords[0] + (refVertices[(e+1)%3 * 2 + 0] - refCoords[0])*d/edgeDiv;
1635e5c487bfSMatthew G. Knepley           refCoords[d*2+1] = refCoords[1] + (refVertices[(e+1)%3 * 2 + 1] - refCoords[1])*d/edgeDiv;
1636e5c487bfSMatthew G. Knepley         }
16379566063dSJacob Faibussowitsch         PetscCall(DMPlexReferenceToCoordinates(dm, cell, edgeDiv+1, refCoords, edgeCoords));
1638e5c487bfSMatthew G. Knepley         for (d = 0; d < edgeDiv; ++d) {
16399566063dSJacob 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));
16409566063dSJacob 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));
1641e5c487bfSMatthew G. Knepley         }
1642e5c487bfSMatthew G. Knepley       }
1643e5c487bfSMatthew G. Knepley     }
1644e5c487bfSMatthew G. Knepley     break;
164598921bdaSJacob Faibussowitsch   default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]);
1646e5c487bfSMatthew G. Knepley   }
1647e5c487bfSMatthew G. Knepley   PetscFunctionReturn(0);
1648e5c487bfSMatthew G. Knepley }
1649e5c487bfSMatthew G. Knepley 
16507cd05799SMatthew G. Knepley static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer)
1651e412dcbdSMatthew G. Knepley {
1652e412dcbdSMatthew G. Knepley   PetscDraw          draw;
1653e412dcbdSMatthew G. Knepley   DM                 cdm;
1654e412dcbdSMatthew G. Knepley   PetscSection       coordSection;
1655e412dcbdSMatthew G. Knepley   Vec                coordinates;
1656e412dcbdSMatthew G. Knepley   const PetscScalar *coords;
165729494db1SLisandro Dalcin   PetscReal          xyl[2],xyr[2],bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL};
1658e5c487bfSMatthew G. Knepley   PetscReal         *refCoords, *edgeCoords;
1659e5c487bfSMatthew G. Knepley   PetscBool          isnull, drawAffine = PETSC_TRUE;
1660e5c487bfSMatthew G. Knepley   PetscInt           dim, vStart, vEnd, cStart, cEnd, c, N, edgeDiv = 4;
1661e412dcbdSMatthew G. Knepley 
1662e412dcbdSMatthew G. Knepley   PetscFunctionBegin;
16639566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dim));
166463a3b9bcSJacob Faibussowitsch   PetscCheck(dim <= 2,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT, dim);
16659566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL));
16669566063dSJacob Faibussowitsch   if (!drawAffine) PetscCall(PetscMalloc2((edgeDiv+1)*dim, &refCoords, (edgeDiv+1)*dim, &edgeCoords));
16679566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
16689566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(cdm, &coordSection));
16699566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
16709566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
16719566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
1672e412dcbdSMatthew G. Knepley 
16739566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
16749566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
1675e412dcbdSMatthew G. Knepley   if (isnull) PetscFunctionReturn(0);
16769566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "Mesh"));
1677e412dcbdSMatthew G. Knepley 
16789566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(coordinates, &N));
16799566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(coordinates, &coords));
1680e412dcbdSMatthew G. Knepley   for (c = 0; c < N; c += dim) {
16810c81f2a8SMatthew G. Knepley     bound[0] = PetscMin(bound[0], PetscRealPart(coords[c]));   bound[2] = PetscMax(bound[2], PetscRealPart(coords[c]));
16820c81f2a8SMatthew G. Knepley     bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1]));
1683e412dcbdSMatthew G. Knepley   }
16849566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(coordinates, &coords));
16851c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&bound[0],xyl,2,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)dm)));
16861c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&bound[2],xyr,2,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)dm)));
16879566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1]));
16889566063dSJacob Faibussowitsch   PetscCall(PetscDrawClear(draw));
1689e412dcbdSMatthew G. Knepley 
1690cf3064d3SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1691cf3064d3SMatthew G. Knepley     PetscScalar *coords = NULL;
1692ba2698f1SMatthew G. Knepley     PetscInt     numCoords;
1693cf3064d3SMatthew G. Knepley 
16949566063dSJacob Faibussowitsch     PetscCall(DMPlexVecGetClosureAtDepth_Internal(dm, coordSection, coordinates, c, 0, &numCoords, &coords));
16951baa6e33SBarry Smith     if (drawAffine) PetscCall(DMPlexDrawCell(dm, draw, c, coords));
16961baa6e33SBarry Smith     else PetscCall(DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords));
16979566063dSJacob Faibussowitsch     PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords));
1698cf3064d3SMatthew G. Knepley   }
16999566063dSJacob Faibussowitsch   if (!drawAffine) PetscCall(PetscFree2(refCoords, edgeCoords));
17009566063dSJacob Faibussowitsch   PetscCall(PetscDrawFlush(draw));
17019566063dSJacob Faibussowitsch   PetscCall(PetscDrawPause(draw));
17029566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave(draw));
1703e412dcbdSMatthew G. Knepley   PetscFunctionReturn(0);
1704e412dcbdSMatthew G. Knepley }
1705e412dcbdSMatthew G. Knepley 
17061e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII)
17071e50132fSMatthew G. Knepley #include <exodusII.h>
17086823f3c5SBlaise Bourdin #include <petscviewerexodusii.h>
17091e50132fSMatthew G. Knepley #endif
17101e50132fSMatthew G. Knepley 
1711552f7358SJed Brown PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer)
1712552f7358SJed Brown {
1713*5f34f2dcSJed Brown   PetscBool      iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus, iscgns;
1714002a2709SMatthew G. Knepley   char           name[PETSC_MAX_PATH_LEN];
1715552f7358SJed Brown 
1716552f7358SJed Brown   PetscFunctionBegin;
1717552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1718552f7358SJed Brown   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
17199566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII,    &iascii));
17209566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK,      &isvtk));
17219566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,     &ishdf5));
17229566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW,     &isdraw));
17239566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS,    &isglvis));
17249566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodus));
1725*5f34f2dcSJed Brown   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERCGNS,     &iscgns));
1726552f7358SJed Brown   if (iascii) {
17278135c375SStefano Zampini     PetscViewerFormat format;
17289566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
17291baa6e33SBarry Smith     if (format == PETSC_VIEWER_ASCII_GLVIS) PetscCall(DMPlexView_GLVis(dm, viewer));
17301baa6e33SBarry Smith     else PetscCall(DMPlexView_Ascii(dm, viewer));
1731c6ccd67eSMatthew G. Knepley   } else if (ishdf5) {
1732c6ccd67eSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
17339566063dSJacob Faibussowitsch     PetscCall(DMPlexView_HDF5_Internal(dm, viewer));
1734c6ccd67eSMatthew G. Knepley #else
1735c6ccd67eSMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1736552f7358SJed Brown #endif
1737e412dcbdSMatthew G. Knepley   } else if (isvtk) {
17389566063dSJacob Faibussowitsch     PetscCall(DMPlexVTKWriteAll((PetscObject) dm,viewer));
1739e412dcbdSMatthew G. Knepley   } else if (isdraw) {
17409566063dSJacob Faibussowitsch     PetscCall(DMPlexView_Draw(dm, viewer));
17418135c375SStefano Zampini   } else if (isglvis) {
17429566063dSJacob Faibussowitsch     PetscCall(DMPlexView_GLVis(dm, viewer));
17431e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII)
17441e50132fSMatthew G. Knepley   } else if (isexodus) {
17456823f3c5SBlaise Bourdin /*
17466823f3c5SBlaise Bourdin       exodusII requires that all sets be part of exactly one cell set.
17476823f3c5SBlaise Bourdin       If the dm does not have a "Cell Sets" label defined, we create one
17486823f3c5SBlaise Bourdin       with ID 1, containig all cells.
17496823f3c5SBlaise Bourdin       Note that if the Cell Sets label is defined but does not cover all cells,
17506823f3c5SBlaise Bourdin       we may still have a problem. This should probably be checked here or in the viewer;
17516823f3c5SBlaise Bourdin     */
17526823f3c5SBlaise Bourdin     PetscInt numCS;
17539566063dSJacob Faibussowitsch     PetscCall(DMGetLabelSize(dm,"Cell Sets",&numCS));
17546823f3c5SBlaise Bourdin     if (!numCS) {
17551e50132fSMatthew G. Knepley       PetscInt cStart, cEnd, c;
17569566063dSJacob Faibussowitsch       PetscCall(DMCreateLabel(dm, "Cell Sets"));
17579566063dSJacob Faibussowitsch       PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
17589566063dSJacob Faibussowitsch       for (c = cStart; c < cEnd; ++c) PetscCall(DMSetLabelValue(dm, "Cell Sets", c, 1));
17596823f3c5SBlaise Bourdin     }
17609566063dSJacob Faibussowitsch     PetscCall(DMView_PlexExodusII(dm, viewer));
17611e50132fSMatthew G. Knepley #endif
1762*5f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS)
1763*5f34f2dcSJed Brown   } else if (iscgns) {
1764*5f34f2dcSJed Brown     PetscCall(DMView_PlexCGNS(dm, viewer));
1765*5f34f2dcSJed Brown #endif
17661baa6e33SBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name);
1767cb3ba0daSMatthew G. Knepley   /* Optionally view the partition */
17689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_partition_view", &flg));
1769cb3ba0daSMatthew G. Knepley   if (flg) {
1770cb3ba0daSMatthew G. Knepley     Vec ranks;
17719566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateRankField(dm, &ranks));
17729566063dSJacob Faibussowitsch     PetscCall(VecView(ranks, viewer));
17739566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&ranks));
1774cb3ba0daSMatthew G. Knepley   }
1775002a2709SMatthew G. Knepley   /* Optionally view a label */
17769566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetString(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_label_view", name, sizeof(name), &flg));
1777002a2709SMatthew G. Knepley   if (flg) {
1778002a2709SMatthew G. Knepley     DMLabel label;
1779002a2709SMatthew G. Knepley     Vec     val;
1780002a2709SMatthew G. Knepley 
17819566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, name, &label));
178228b400f6SJacob Faibussowitsch     PetscCheck(label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name);
17839566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateLabelField(dm, label, &val));
17849566063dSJacob Faibussowitsch     PetscCall(VecView(val, viewer));
17859566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&val));
1786002a2709SMatthew G. Knepley   }
1787552f7358SJed Brown   PetscFunctionReturn(0);
1788552f7358SJed Brown }
1789552f7358SJed Brown 
17907f96f51bSksagiyam /*@
17917f96f51bSksagiyam   DMPlexTopologyView - Saves a DMPlex topology into a file
17927f96f51bSksagiyam 
17937f96f51bSksagiyam   Collective on DM
17947f96f51bSksagiyam 
17957f96f51bSksagiyam   Input Parameters:
17967f96f51bSksagiyam + dm     - The DM whose topology is to be saved
17977f96f51bSksagiyam - viewer - The PetscViewer for saving
17987f96f51bSksagiyam 
17997f96f51bSksagiyam   Level: advanced
18007f96f51bSksagiyam 
1801db781477SPatrick Sanan .seealso: `DMView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexTopologyLoad()`
18027f96f51bSksagiyam @*/
18037f96f51bSksagiyam PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer)
18047f96f51bSksagiyam {
18057f96f51bSksagiyam   PetscBool      ishdf5;
18067f96f51bSksagiyam 
18077f96f51bSksagiyam   PetscFunctionBegin;
18087f96f51bSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
18097f96f51bSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
18109566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
18119566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_TopologyView,viewer,0,0,0));
18127f96f51bSksagiyam   if (ishdf5) {
18137f96f51bSksagiyam #if defined(PETSC_HAVE_HDF5)
18147f96f51bSksagiyam     PetscViewerFormat format;
18159566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
18167f96f51bSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
18177f96f51bSksagiyam       IS globalPointNumbering;
18187f96f51bSksagiyam 
18199566063dSJacob Faibussowitsch       PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering));
18209566063dSJacob Faibussowitsch       PetscCall(DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer));
18219566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&globalPointNumbering));
182298921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]);
18237f96f51bSksagiyam #else
18247f96f51bSksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
18257f96f51bSksagiyam #endif
18267f96f51bSksagiyam   }
18279566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_TopologyView,viewer,0,0,0));
18287f96f51bSksagiyam   PetscFunctionReturn(0);
18297f96f51bSksagiyam }
18307f96f51bSksagiyam 
183177b8e257Sksagiyam /*@
183277b8e257Sksagiyam   DMPlexCoordinatesView - Saves DMPlex coordinates into a file
183377b8e257Sksagiyam 
183477b8e257Sksagiyam   Collective on DM
183577b8e257Sksagiyam 
183677b8e257Sksagiyam   Input Parameters:
183777b8e257Sksagiyam + dm     - The DM whose coordinates are to be saved
183877b8e257Sksagiyam - viewer - The PetscViewer for saving
183977b8e257Sksagiyam 
184077b8e257Sksagiyam   Level: advanced
184177b8e257Sksagiyam 
1842db781477SPatrick Sanan .seealso: `DMView()`, `DMPlexTopologyView()`, `DMPlexLabelsView()`, `DMPlexCoordinatesLoad()`
184377b8e257Sksagiyam @*/
184477b8e257Sksagiyam PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer)
184577b8e257Sksagiyam {
184677b8e257Sksagiyam   PetscBool      ishdf5;
184777b8e257Sksagiyam 
184877b8e257Sksagiyam   PetscFunctionBegin;
184977b8e257Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
185077b8e257Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
18519566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
18529566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesView,viewer,0,0,0));
185377b8e257Sksagiyam   if (ishdf5) {
185477b8e257Sksagiyam #if defined(PETSC_HAVE_HDF5)
185577b8e257Sksagiyam     PetscViewerFormat format;
18569566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
185777b8e257Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
18589566063dSJacob Faibussowitsch       PetscCall(DMPlexCoordinatesView_HDF5_Internal(dm, viewer));
185998921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
186077b8e257Sksagiyam #else
186177b8e257Sksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
186277b8e257Sksagiyam #endif
186377b8e257Sksagiyam   }
18649566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesView,viewer,0,0,0));
186577b8e257Sksagiyam   PetscFunctionReturn(0);
186677b8e257Sksagiyam }
186777b8e257Sksagiyam 
1868bd6565f1Sksagiyam /*@
1869bd6565f1Sksagiyam   DMPlexLabelsView - Saves DMPlex labels into a file
1870bd6565f1Sksagiyam 
1871bd6565f1Sksagiyam   Collective on DM
1872bd6565f1Sksagiyam 
1873bd6565f1Sksagiyam   Input Parameters:
1874bd6565f1Sksagiyam + dm     - The DM whose labels are to be saved
1875bd6565f1Sksagiyam - viewer - The PetscViewer for saving
1876bd6565f1Sksagiyam 
1877bd6565f1Sksagiyam   Level: advanced
1878bd6565f1Sksagiyam 
1879db781477SPatrick Sanan .seealso: `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsLoad()`
1880bd6565f1Sksagiyam @*/
1881bd6565f1Sksagiyam PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer)
1882bd6565f1Sksagiyam {
1883bd6565f1Sksagiyam   PetscBool      ishdf5;
1884bd6565f1Sksagiyam 
1885bd6565f1Sksagiyam   PetscFunctionBegin;
1886bd6565f1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1887bd6565f1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
18889566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
18899566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LabelsView,viewer,0,0,0));
1890bd6565f1Sksagiyam   if (ishdf5) {
1891bd6565f1Sksagiyam #if defined(PETSC_HAVE_HDF5)
1892bd6565f1Sksagiyam     IS                globalPointNumbering;
1893bd6565f1Sksagiyam     PetscViewerFormat format;
1894bd6565f1Sksagiyam 
18959566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
1896bd6565f1Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
18979566063dSJacob Faibussowitsch       PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering));
18989566063dSJacob Faibussowitsch       PetscCall(DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer));
18999566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&globalPointNumbering));
190098921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
1901bd6565f1Sksagiyam #else
1902bd6565f1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1903bd6565f1Sksagiyam #endif
1904bd6565f1Sksagiyam   }
19059566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LabelsView,viewer,0,0,0));
1906bd6565f1Sksagiyam   PetscFunctionReturn(0);
1907bd6565f1Sksagiyam }
1908bd6565f1Sksagiyam 
1909021affd3Sksagiyam /*@
1910021affd3Sksagiyam   DMPlexSectionView - Saves a section associated with a DMPlex
1911021affd3Sksagiyam 
1912021affd3Sksagiyam   Collective on DM
1913021affd3Sksagiyam 
1914021affd3Sksagiyam   Input Parameters:
1915021affd3Sksagiyam + dm         - The DM that contains the topology on which the section to be saved is defined
1916021affd3Sksagiyam . viewer     - The PetscViewer for saving
1917021affd3Sksagiyam - sectiondm  - The DM that contains the section to be saved
1918021affd3Sksagiyam 
1919021affd3Sksagiyam   Level: advanced
1920021affd3Sksagiyam 
1921021affd3Sksagiyam   Notes:
1922021affd3Sksagiyam   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.
1923021affd3Sksagiyam 
1924021affd3Sksagiyam   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.
1925021affd3Sksagiyam 
1926db781477SPatrick Sanan .seealso: `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, `PetscSectionView()`, `DMPlexSectionLoad()`
1927021affd3Sksagiyam @*/
1928021affd3Sksagiyam PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm)
1929021affd3Sksagiyam {
1930021affd3Sksagiyam   PetscBool      ishdf5;
1931021affd3Sksagiyam 
1932021affd3Sksagiyam   PetscFunctionBegin;
1933021affd3Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1934021affd3Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1935021affd3Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
19369566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5));
19379566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_SectionView,viewer,0,0,0));
1938021affd3Sksagiyam   if (ishdf5) {
1939021affd3Sksagiyam #if defined(PETSC_HAVE_HDF5)
19409566063dSJacob Faibussowitsch     PetscCall(DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm));
1941021affd3Sksagiyam #else
1942021affd3Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1943021affd3Sksagiyam #endif
1944021affd3Sksagiyam   }
19459566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_SectionView,viewer,0,0,0));
1946021affd3Sksagiyam   PetscFunctionReturn(0);
1947021affd3Sksagiyam }
1948021affd3Sksagiyam 
19493e97647fSksagiyam /*@
19503e97647fSksagiyam   DMPlexGlobalVectorView - Saves a global vector
19513e97647fSksagiyam 
19523e97647fSksagiyam   Collective on DM
19533e97647fSksagiyam 
19543e97647fSksagiyam   Input Parameters:
19553e97647fSksagiyam + dm        - The DM that represents the topology
19563e97647fSksagiyam . viewer    - The PetscViewer to save data with
19573e97647fSksagiyam . sectiondm - The DM that contains the global section on which vec is defined
19583e97647fSksagiyam - vec       - The global vector to be saved
19593e97647fSksagiyam 
19603e97647fSksagiyam   Level: advanced
19613e97647fSksagiyam 
19623e97647fSksagiyam   Notes:
19633e97647fSksagiyam   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.
19643e97647fSksagiyam 
19653e97647fSksagiyam   Typical calling sequence
19663e97647fSksagiyam $       DMCreate(PETSC_COMM_WORLD, &dm);
19673e97647fSksagiyam $       DMSetType(dm, DMPLEX);
19683e97647fSksagiyam $       PetscObjectSetName((PetscObject)dm, "topologydm_name");
19693e97647fSksagiyam $       DMClone(dm, &sectiondm);
19703e97647fSksagiyam $       PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
19713e97647fSksagiyam $       PetscSectionCreate(PETSC_COMM_WORLD, &section);
19723e97647fSksagiyam $       DMPlexGetChart(sectiondm, &pStart, &pEnd);
19733e97647fSksagiyam $       PetscSectionSetChart(section, pStart, pEnd);
19743e97647fSksagiyam $       PetscSectionSetUp(section);
19753e97647fSksagiyam $       DMSetLocalSection(sectiondm, section);
19763e97647fSksagiyam $       PetscSectionDestroy(&section);
19773e97647fSksagiyam $       DMGetGlobalVector(sectiondm, &vec);
19783e97647fSksagiyam $       PetscObjectSetName((PetscObject)vec, "vec_name");
19793e97647fSksagiyam $       DMPlexTopologyView(dm, viewer);
19803e97647fSksagiyam $       DMPlexSectionView(dm, viewer, sectiondm);
19813e97647fSksagiyam $       DMPlexGlobalVectorView(dm, viewer, sectiondm, vec);
19823e97647fSksagiyam $       DMRestoreGlobalVector(sectiondm, &vec);
19833e97647fSksagiyam $       DMDestroy(&sectiondm);
19843e97647fSksagiyam $       DMDestroy(&dm);
19853e97647fSksagiyam 
1986db781477SPatrick Sanan .seealso: `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexLocalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`
19873e97647fSksagiyam @*/
19883e97647fSksagiyam PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec)
19893e97647fSksagiyam {
19903e97647fSksagiyam   PetscBool       ishdf5;
19913e97647fSksagiyam 
19923e97647fSksagiyam   PetscFunctionBegin;
19933e97647fSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
19943e97647fSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
19953e97647fSksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
19963e97647fSksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 4);
19973e97647fSksagiyam   /* Check consistency */
19983e97647fSksagiyam   {
19993e97647fSksagiyam     PetscSection  section;
20003e97647fSksagiyam     PetscBool     includesConstraints;
20013e97647fSksagiyam     PetscInt      m, m1;
20023e97647fSksagiyam 
20039566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
20049566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(sectiondm, &section));
20059566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
20069566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
20079566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
200863a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m);
20093e97647fSksagiyam   }
20109566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
20119566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorView,viewer,0,0,0));
20123e97647fSksagiyam   if (ishdf5) {
20133e97647fSksagiyam #if defined(PETSC_HAVE_HDF5)
20149566063dSJacob Faibussowitsch     PetscCall(DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec));
20153e97647fSksagiyam #else
20163e97647fSksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
20173e97647fSksagiyam #endif
20183e97647fSksagiyam   }
20199566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorView,viewer,0,0,0));
20203e97647fSksagiyam   PetscFunctionReturn(0);
20213e97647fSksagiyam }
20223e97647fSksagiyam 
20233e97647fSksagiyam /*@
20243e97647fSksagiyam   DMPlexLocalVectorView - Saves a local vector
20253e97647fSksagiyam 
20263e97647fSksagiyam   Collective on DM
20273e97647fSksagiyam 
20283e97647fSksagiyam   Input Parameters:
20293e97647fSksagiyam + dm        - The DM that represents the topology
20303e97647fSksagiyam . viewer    - The PetscViewer to save data with
20313e97647fSksagiyam . sectiondm - The DM that contains the local section on which vec is defined; may be the same as dm
20323e97647fSksagiyam - vec       - The local vector to be saved
20333e97647fSksagiyam 
20343e97647fSksagiyam   Level: advanced
20353e97647fSksagiyam 
20363e97647fSksagiyam   Notes:
20373e97647fSksagiyam   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.
20383e97647fSksagiyam 
20393e97647fSksagiyam   Typical calling sequence
20403e97647fSksagiyam $       DMCreate(PETSC_COMM_WORLD, &dm);
20413e97647fSksagiyam $       DMSetType(dm, DMPLEX);
20423e97647fSksagiyam $       PetscObjectSetName((PetscObject)dm, "topologydm_name");
20433e97647fSksagiyam $       DMClone(dm, &sectiondm);
20443e97647fSksagiyam $       PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
20453e97647fSksagiyam $       PetscSectionCreate(PETSC_COMM_WORLD, &section);
20463e97647fSksagiyam $       DMPlexGetChart(sectiondm, &pStart, &pEnd);
20473e97647fSksagiyam $       PetscSectionSetChart(section, pStart, pEnd);
20483e97647fSksagiyam $       PetscSectionSetUp(section);
20493e97647fSksagiyam $       DMSetLocalSection(sectiondm, section);
20503e97647fSksagiyam $       DMGetLocalVector(sectiondm, &vec);
20513e97647fSksagiyam $       PetscObjectSetName((PetscObject)vec, "vec_name");
20523e97647fSksagiyam $       DMPlexTopologyView(dm, viewer);
20533e97647fSksagiyam $       DMPlexSectionView(dm, viewer, sectiondm);
20543e97647fSksagiyam $       DMPlexLocalVectorView(dm, viewer, sectiondm, vec);
20553e97647fSksagiyam $       DMRestoreLocalVector(sectiondm, &vec);
20563e97647fSksagiyam $       DMDestroy(&sectiondm);
20573e97647fSksagiyam $       DMDestroy(&dm);
20583e97647fSksagiyam 
2059db781477SPatrick Sanan .seealso: `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexGlobalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`
20603e97647fSksagiyam @*/
20613e97647fSksagiyam PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec)
20623e97647fSksagiyam {
20633e97647fSksagiyam   PetscBool       ishdf5;
20643e97647fSksagiyam 
20653e97647fSksagiyam   PetscFunctionBegin;
20663e97647fSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
20673e97647fSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
20683e97647fSksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
20693e97647fSksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 4);
20703e97647fSksagiyam   /* Check consistency */
20713e97647fSksagiyam   {
20723e97647fSksagiyam     PetscSection  section;
20733e97647fSksagiyam     PetscBool     includesConstraints;
20743e97647fSksagiyam     PetscInt      m, m1;
20753e97647fSksagiyam 
20769566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
20779566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(sectiondm, &section));
20789566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
20799566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
20809566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
208163a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m);
20823e97647fSksagiyam   }
20839566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
20849566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorView,viewer,0,0,0));
20853e97647fSksagiyam   if (ishdf5) {
20863e97647fSksagiyam #if defined(PETSC_HAVE_HDF5)
20879566063dSJacob Faibussowitsch     PetscCall(DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec));
20883e97647fSksagiyam #else
20893e97647fSksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
20903e97647fSksagiyam #endif
20913e97647fSksagiyam   }
20929566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorView,viewer,0,0,0));
20933e97647fSksagiyam   PetscFunctionReturn(0);
20943e97647fSksagiyam }
20953e97647fSksagiyam 
20962c40f234SMatthew G. Knepley PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer)
20972c40f234SMatthew G. Knepley {
2098d4f5a9a0SVaclav Hapla   PetscBool      ishdf5;
20992c40f234SMatthew G. Knepley 
21002c40f234SMatthew G. Knepley   PetscFunctionBegin;
21012c40f234SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
21022c40f234SMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
21039566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,   &ishdf5));
2104d4f5a9a0SVaclav Hapla   if (ishdf5) {
21052c40f234SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
21069c48423bSVaclav Hapla     PetscViewerFormat format;
21079566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
21089c48423bSVaclav Hapla     if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) {
21099566063dSJacob Faibussowitsch       PetscCall(DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer));
2110509517efSVaclav Hapla     } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
21119566063dSJacob Faibussowitsch       PetscCall(DMPlexLoad_HDF5_Internal(dm, viewer));
211298921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2113b458e8f1SJose E. Roman     PetscFunctionReturn(0);
21142c40f234SMatthew G. Knepley #else
21152c40f234SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2116552f7358SJed Brown #endif
211798921bdaSJacob Faibussowitsch   } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name);
2118552f7358SJed Brown }
2119552f7358SJed Brown 
2120ea8e1828Sksagiyam /*@
2121ea8e1828Sksagiyam   DMPlexTopologyLoad - Loads a topology into a DMPlex
2122ea8e1828Sksagiyam 
2123ea8e1828Sksagiyam   Collective on DM
2124ea8e1828Sksagiyam 
2125ea8e1828Sksagiyam   Input Parameters:
2126ea8e1828Sksagiyam + dm     - The DM into which the topology is loaded
2127ea8e1828Sksagiyam - viewer - The PetscViewer for the saved topology
2128ea8e1828Sksagiyam 
2129dec9e869Sksagiyam   Output Parameters:
2130f84dd6b4Sksagiyam . 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
2131dec9e869Sksagiyam 
2132ea8e1828Sksagiyam   Level: advanced
2133ea8e1828Sksagiyam 
2134db781477SPatrick Sanan .seealso: `DMLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`
2135ea8e1828Sksagiyam @*/
2136f84dd6b4Sksagiyam PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF)
2137ea8e1828Sksagiyam {
2138ea8e1828Sksagiyam   PetscBool      ishdf5;
2139ea8e1828Sksagiyam 
2140ea8e1828Sksagiyam   PetscFunctionBegin;
2141ea8e1828Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2142ea8e1828Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2143f84dd6b4Sksagiyam   if (globalToLocalPointSF) PetscValidPointer(globalToLocalPointSF, 3);
21449566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
21459566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_TopologyLoad,viewer,0,0,0));
2146ea8e1828Sksagiyam   if (ishdf5) {
2147ea8e1828Sksagiyam #if defined(PETSC_HAVE_HDF5)
2148ea8e1828Sksagiyam     PetscViewerFormat format;
21499566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
2150ea8e1828Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
21519566063dSJacob Faibussowitsch       PetscCall(DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
215298921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2153ea8e1828Sksagiyam #else
2154ea8e1828Sksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2155ea8e1828Sksagiyam #endif
2156ea8e1828Sksagiyam   }
21579566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_TopologyLoad,viewer,0,0,0));
2158ea8e1828Sksagiyam   PetscFunctionReturn(0);
2159ea8e1828Sksagiyam }
2160ea8e1828Sksagiyam 
21613e701f1cSksagiyam /*@
21623e701f1cSksagiyam   DMPlexCoordinatesLoad - Loads coordinates into a DMPlex
21633e701f1cSksagiyam 
21643e701f1cSksagiyam   Collective on DM
21653e701f1cSksagiyam 
21663e701f1cSksagiyam   Input Parameters:
21673e701f1cSksagiyam + dm     - The DM into which the coordinates are loaded
2168c9ad657eSksagiyam . viewer - The PetscViewer for the saved coordinates
2169c9ad657eSksagiyam - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer
21703e701f1cSksagiyam 
21713e701f1cSksagiyam   Level: advanced
21723e701f1cSksagiyam 
2173db781477SPatrick Sanan .seealso: `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`
21743e701f1cSksagiyam @*/
2175c9ad657eSksagiyam PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF)
21763e701f1cSksagiyam {
21773e701f1cSksagiyam   PetscBool      ishdf5;
21783e701f1cSksagiyam 
21793e701f1cSksagiyam   PetscFunctionBegin;
21803e701f1cSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
21813e701f1cSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2182c9ad657eSksagiyam   PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3);
21839566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
21849566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesLoad,viewer,0,0,0));
21853e701f1cSksagiyam   if (ishdf5) {
21863e701f1cSksagiyam #if defined(PETSC_HAVE_HDF5)
21873e701f1cSksagiyam     PetscViewerFormat format;
21889566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
21893e701f1cSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
21909566063dSJacob Faibussowitsch       PetscCall(DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
219198921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
21923e701f1cSksagiyam #else
21933e701f1cSksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
21943e701f1cSksagiyam #endif
21953e701f1cSksagiyam   }
21969566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesLoad,viewer,0,0,0));
21973e701f1cSksagiyam   PetscFunctionReturn(0);
21983e701f1cSksagiyam }
21993e701f1cSksagiyam 
2200b08ad5deSksagiyam /*@
2201b08ad5deSksagiyam   DMPlexLabelsLoad - Loads labels into a DMPlex
2202b08ad5deSksagiyam 
2203b08ad5deSksagiyam   Collective on DM
2204b08ad5deSksagiyam 
2205b08ad5deSksagiyam   Input Parameters:
2206b08ad5deSksagiyam + dm     - The DM into which the labels are loaded
2207e6368b79SVaclav Hapla . viewer - The PetscViewer for the saved labels
2208e6368b79SVaclav Hapla - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer
2209b08ad5deSksagiyam 
2210b08ad5deSksagiyam   Level: advanced
2211b08ad5deSksagiyam 
2212e6368b79SVaclav Hapla   Notes:
2213e6368b79SVaclav Hapla   The PetscSF argument must not be NULL if the DM is distributed, otherwise an error occurs.
2214e6368b79SVaclav Hapla 
2215db781477SPatrick Sanan .seealso: `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`
2216b08ad5deSksagiyam @*/
2217e6368b79SVaclav Hapla PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF)
2218b08ad5deSksagiyam {
2219b08ad5deSksagiyam   PetscBool      ishdf5;
2220b08ad5deSksagiyam 
2221b08ad5deSksagiyam   PetscFunctionBegin;
2222b08ad5deSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2223b08ad5deSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2224e6368b79SVaclav Hapla   if (globalToLocalPointSF) PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3);
22259566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
22269566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LabelsLoad,viewer,0,0,0));
2227b08ad5deSksagiyam   if (ishdf5) {
2228b08ad5deSksagiyam #if defined(PETSC_HAVE_HDF5)
2229b08ad5deSksagiyam     PetscViewerFormat format;
2230b08ad5deSksagiyam 
22319566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
2232b08ad5deSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
22339566063dSJacob Faibussowitsch       PetscCall(DMPlexLabelsLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
223498921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2235b08ad5deSksagiyam #else
2236b08ad5deSksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2237b08ad5deSksagiyam #endif
2238b08ad5deSksagiyam   }
22399566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LabelsLoad,viewer,0,0,0));
2240b08ad5deSksagiyam   PetscFunctionReturn(0);
2241b08ad5deSksagiyam }
2242b08ad5deSksagiyam 
2243f84dd6b4Sksagiyam /*@
2244f84dd6b4Sksagiyam   DMPlexSectionLoad - Loads section into a DMPlex
2245f84dd6b4Sksagiyam 
2246f84dd6b4Sksagiyam   Collective on DM
2247f84dd6b4Sksagiyam 
2248f84dd6b4Sksagiyam   Input Parameters:
2249f84dd6b4Sksagiyam + dm          - The DM that represents the topology
2250f84dd6b4Sksagiyam . viewer      - The PetscViewer that represents the on-disk section (sectionA)
2251f84dd6b4Sksagiyam . sectiondm   - The DM into which the on-disk section (sectionA) is migrated
2252f84dd6b4Sksagiyam - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer
2253f84dd6b4Sksagiyam 
2254f84dd6b4Sksagiyam   Output Parameters
2255f84dd6b4Sksagiyam + 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)
2256f84dd6b4Sksagiyam - 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)
2257f84dd6b4Sksagiyam 
2258f84dd6b4Sksagiyam   Level: advanced
2259f84dd6b4Sksagiyam 
2260f84dd6b4Sksagiyam   Notes:
2261f84dd6b4Sksagiyam   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.
2262f84dd6b4Sksagiyam 
2263f84dd6b4Sksagiyam   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.
2264f84dd6b4Sksagiyam 
2265f84dd6b4Sksagiyam   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.
2266f84dd6b4Sksagiyam 
2267f84dd6b4Sksagiyam   Example using 2 processes:
2268f84dd6b4Sksagiyam $  NX (number of points on dm): 4
2269f84dd6b4Sksagiyam $  sectionA                   : the on-disk section
2270f84dd6b4Sksagiyam $  vecA                       : a vector associated with sectionA
2271f84dd6b4Sksagiyam $  sectionB                   : sectiondm's local section constructed in this function
2272f84dd6b4Sksagiyam $  vecB (local)               : a vector associated with sectiondm's local section
2273f84dd6b4Sksagiyam $  vecB (global)              : a vector associated with sectiondm's global section
2274f84dd6b4Sksagiyam $
2275f84dd6b4Sksagiyam $                                     rank 0    rank 1
2276f84dd6b4Sksagiyam $  vecA (global)                  : [.0 .4 .1 | .2 .3]        <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad()
2277f84dd6b4Sksagiyam $  sectionA->atlasOff             :       0 2 | 1             <- loaded in PetscSectionLoad()
2278f84dd6b4Sksagiyam $  sectionA->atlasDof             :       1 3 | 1             <- loaded in PetscSectionLoad()
2279f84dd6b4Sksagiyam $  sectionA's global point numbers:       0 2 | 3             <- loaded in DMPlexSectionLoad()
2280f84dd6b4Sksagiyam $  [0, NX)                        :       0 1 | 2 3           <- conceptual partition used in globalToLocalPointSF
2281f84dd6b4Sksagiyam $  sectionB's global point numbers:     0 1 3 | 3 2           <- associated with [0, NX) by globalToLocalPointSF
2282f84dd6b4Sksagiyam $  sectionB->atlasDof             :     1 0 1 | 1 3
2283f84dd6b4Sksagiyam $  sectionB->atlasOff (no perm)   :     0 1 1 | 0 1
2284f84dd6b4Sksagiyam $  vecB (local)                   :   [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF
2285f84dd6b4Sksagiyam $  vecB (global)                  :    [.0 .4 | .1 .2 .3]     <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF
2286f84dd6b4Sksagiyam $
2287f84dd6b4Sksagiyam $  where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0.
2288f84dd6b4Sksagiyam 
2289db781477SPatrick Sanan .seealso: `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`, `PetscSectionLoad()`, `DMPlexSectionView()`
2290f84dd6b4Sksagiyam @*/
2291f84dd6b4Sksagiyam PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF globalToLocalPointSF, PetscSF *globalDofSF, PetscSF *localDofSF)
2292f84dd6b4Sksagiyam {
2293f84dd6b4Sksagiyam   PetscBool      ishdf5;
2294f84dd6b4Sksagiyam 
2295f84dd6b4Sksagiyam   PetscFunctionBegin;
2296f84dd6b4Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2297f84dd6b4Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2298f84dd6b4Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
2299f84dd6b4Sksagiyam   PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4);
2300f84dd6b4Sksagiyam   if (globalDofSF) PetscValidPointer(globalDofSF, 5);
2301f84dd6b4Sksagiyam   if (localDofSF) PetscValidPointer(localDofSF, 6);
23029566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5));
23039566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_SectionLoad,viewer,0,0,0));
2304f84dd6b4Sksagiyam   if (ishdf5) {
2305f84dd6b4Sksagiyam #if defined(PETSC_HAVE_HDF5)
23069566063dSJacob Faibussowitsch     PetscCall(DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF));
2307f84dd6b4Sksagiyam #else
2308f84dd6b4Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2309f84dd6b4Sksagiyam #endif
2310f84dd6b4Sksagiyam   }
23119566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_SectionLoad,viewer,0,0,0));
2312f84dd6b4Sksagiyam   PetscFunctionReturn(0);
2313f84dd6b4Sksagiyam }
2314f84dd6b4Sksagiyam 
23158be3dfe1Sksagiyam /*@
23168be3dfe1Sksagiyam   DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector
23178be3dfe1Sksagiyam 
23188be3dfe1Sksagiyam   Collective on DM
23198be3dfe1Sksagiyam 
23208be3dfe1Sksagiyam   Input Parameters:
23218be3dfe1Sksagiyam + dm        - The DM that represents the topology
23228be3dfe1Sksagiyam . viewer    - The PetscViewer that represents the on-disk vector data
23238be3dfe1Sksagiyam . sectiondm - The DM that contains the global section on which vec is defined
23248be3dfe1Sksagiyam . sf        - The SF that migrates the on-disk vector data into vec
23258be3dfe1Sksagiyam - vec       - The global vector to set values of
23268be3dfe1Sksagiyam 
23278be3dfe1Sksagiyam   Level: advanced
23288be3dfe1Sksagiyam 
23298be3dfe1Sksagiyam   Notes:
23308be3dfe1Sksagiyam   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.
23318be3dfe1Sksagiyam 
23328be3dfe1Sksagiyam   Typical calling sequence
23338be3dfe1Sksagiyam $       DMCreate(PETSC_COMM_WORLD, &dm);
23348be3dfe1Sksagiyam $       DMSetType(dm, DMPLEX);
23358be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)dm, "topologydm_name");
23368be3dfe1Sksagiyam $       DMPlexTopologyLoad(dm, viewer, &sfX);
23378be3dfe1Sksagiyam $       DMClone(dm, &sectiondm);
23388be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
23398be3dfe1Sksagiyam $       DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL);
23408be3dfe1Sksagiyam $       DMGetGlobalVector(sectiondm, &vec);
23418be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)vec, "vec_name");
23428be3dfe1Sksagiyam $       DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec);
23438be3dfe1Sksagiyam $       DMRestoreGlobalVector(sectiondm, &vec);
23448be3dfe1Sksagiyam $       PetscSFDestroy(&gsf);
23458be3dfe1Sksagiyam $       PetscSFDestroy(&sfX);
23468be3dfe1Sksagiyam $       DMDestroy(&sectiondm);
23478be3dfe1Sksagiyam $       DMDestroy(&dm);
23488be3dfe1Sksagiyam 
2349db781477SPatrick Sanan .seealso: `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexLocalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`
23508be3dfe1Sksagiyam @*/
23518be3dfe1Sksagiyam PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec)
23528be3dfe1Sksagiyam {
23538be3dfe1Sksagiyam   PetscBool       ishdf5;
23548be3dfe1Sksagiyam 
23558be3dfe1Sksagiyam   PetscFunctionBegin;
23568be3dfe1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
23578be3dfe1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
23588be3dfe1Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
23598be3dfe1Sksagiyam   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4);
23608be3dfe1Sksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 5);
23618be3dfe1Sksagiyam   /* Check consistency */
23628be3dfe1Sksagiyam   {
23638be3dfe1Sksagiyam     PetscSection  section;
23648be3dfe1Sksagiyam     PetscBool     includesConstraints;
23658be3dfe1Sksagiyam     PetscInt      m, m1;
23668be3dfe1Sksagiyam 
23679566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
23689566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(sectiondm, &section));
23699566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
23709566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
23719566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
237263a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m);
23738be3dfe1Sksagiyam   }
23749566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5));
23759566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorLoad,viewer,0,0,0));
23768be3dfe1Sksagiyam   if (ishdf5) {
23778be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5)
23789566063dSJacob Faibussowitsch     PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec));
23798be3dfe1Sksagiyam #else
23808be3dfe1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
23818be3dfe1Sksagiyam #endif
23828be3dfe1Sksagiyam   }
23839566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorLoad,viewer,0,0,0));
23848be3dfe1Sksagiyam   PetscFunctionReturn(0);
23858be3dfe1Sksagiyam }
23868be3dfe1Sksagiyam 
23878be3dfe1Sksagiyam /*@
23888be3dfe1Sksagiyam   DMPlexLocalVectorLoad - Loads on-disk vector data into a local vector
23898be3dfe1Sksagiyam 
23908be3dfe1Sksagiyam   Collective on DM
23918be3dfe1Sksagiyam 
23928be3dfe1Sksagiyam   Input Parameters:
23938be3dfe1Sksagiyam + dm        - The DM that represents the topology
23948be3dfe1Sksagiyam . viewer    - The PetscViewer that represents the on-disk vector data
23958be3dfe1Sksagiyam . sectiondm - The DM that contains the local section on which vec is defined
23968be3dfe1Sksagiyam . sf        - The SF that migrates the on-disk vector data into vec
23978be3dfe1Sksagiyam - vec       - The local vector to set values of
23988be3dfe1Sksagiyam 
23998be3dfe1Sksagiyam   Level: advanced
24008be3dfe1Sksagiyam 
24018be3dfe1Sksagiyam   Notes:
24028be3dfe1Sksagiyam   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.
24038be3dfe1Sksagiyam 
24048be3dfe1Sksagiyam   Typical calling sequence
24058be3dfe1Sksagiyam $       DMCreate(PETSC_COMM_WORLD, &dm);
24068be3dfe1Sksagiyam $       DMSetType(dm, DMPLEX);
24078be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)dm, "topologydm_name");
24088be3dfe1Sksagiyam $       DMPlexTopologyLoad(dm, viewer, &sfX);
24098be3dfe1Sksagiyam $       DMClone(dm, &sectiondm);
24108be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
24118be3dfe1Sksagiyam $       DMPlexSectionLoad(dm, viewer, sectiondm, sfX, NULL, &lsf);
24128be3dfe1Sksagiyam $       DMGetLocalVector(sectiondm, &vec);
24138be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)vec, "vec_name");
24148be3dfe1Sksagiyam $       DMPlexLocalVectorLoad(dm, viewer, sectiondm, lsf, vec);
24158be3dfe1Sksagiyam $       DMRestoreLocalVector(sectiondm, &vec);
24168be3dfe1Sksagiyam $       PetscSFDestroy(&lsf);
24178be3dfe1Sksagiyam $       PetscSFDestroy(&sfX);
24188be3dfe1Sksagiyam $       DMDestroy(&sectiondm);
24198be3dfe1Sksagiyam $       DMDestroy(&dm);
24208be3dfe1Sksagiyam 
2421db781477SPatrick Sanan .seealso: `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`
24228be3dfe1Sksagiyam @*/
24238be3dfe1Sksagiyam PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec)
24248be3dfe1Sksagiyam {
24258be3dfe1Sksagiyam   PetscBool       ishdf5;
24268be3dfe1Sksagiyam 
24278be3dfe1Sksagiyam   PetscFunctionBegin;
24288be3dfe1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
24298be3dfe1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
24308be3dfe1Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
24318be3dfe1Sksagiyam   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4);
24328be3dfe1Sksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 5);
24338be3dfe1Sksagiyam   /* Check consistency */
24348be3dfe1Sksagiyam   {
24358be3dfe1Sksagiyam     PetscSection  section;
24368be3dfe1Sksagiyam     PetscBool     includesConstraints;
24378be3dfe1Sksagiyam     PetscInt      m, m1;
24388be3dfe1Sksagiyam 
24399566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
24409566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(sectiondm, &section));
24419566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
24429566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
24439566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
244463a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m);
24458be3dfe1Sksagiyam   }
24469566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5));
24479566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorLoad,viewer,0,0,0));
24488be3dfe1Sksagiyam   if (ishdf5) {
24498be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5)
24509566063dSJacob Faibussowitsch     PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec));
24518be3dfe1Sksagiyam #else
24528be3dfe1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
24538be3dfe1Sksagiyam #endif
24548be3dfe1Sksagiyam   }
24559566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorLoad,viewer,0,0,0));
24568be3dfe1Sksagiyam   PetscFunctionReturn(0);
24578be3dfe1Sksagiyam }
24588be3dfe1Sksagiyam 
2459552f7358SJed Brown PetscErrorCode DMDestroy_Plex(DM dm)
2460552f7358SJed Brown {
2461552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2462552f7358SJed Brown 
2463552f7358SJed Brown   PetscFunctionBegin;
24649566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMSetUpGLVisViewer_C",NULL));
24659566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertBoundaryValues_C", NULL));
24669566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMCreateNeumannOverlap_C", NULL));
24679566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMInterpolateSolution_C", NULL));
24682e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertTimeDerviativeBoundaryValues_C", NULL));
24692e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexGetOverlap_C", NULL));
24702e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexDistributeGetDefault_C", NULL));
24712e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexDistributeSetDefault_C", NULL));
24722e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"MatComputeNeumannOverlap_C",NULL));
24736bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexReorderGetDefault_C", NULL));
24746bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexReorderSetDefault_C", NULL));
2475c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexGetOverlap_C",NULL));
2476c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexSetOverlap_C",NULL));
24770d644c17SKarl Rupp   if (--mesh->refct > 0) PetscFunctionReturn(0);
24789566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->coneSection));
24799566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->cones));
24809566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->coneOrientations));
24819566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->supportSection));
24829566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->subdomainSection));
24839566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->supports));
24849566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->facesTmp));
24859566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->tetgenOpts));
24869566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->triangleOpts));
24879566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->transformType));
24889566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerDestroy(&mesh->partitioner));
24899566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&mesh->subpointMap));
24909566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->subpointIS));
24919566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->globalVertexNumbers));
24929566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->globalCellNumbers));
24939566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->anchorSection));
24949566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->anchorIS));
24959566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->parentSection));
24969566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->parents));
24979566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->childIDs));
24989566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->childSection));
24999566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->children));
25009566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&mesh->referenceTree));
25019566063dSJacob Faibussowitsch   PetscCall(PetscGridHashDestroy(&mesh->lbox));
25029566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->neighbors));
25039566063dSJacob Faibussowitsch   if (mesh->metricCtx) PetscCall(PetscFree(mesh->metricCtx));
2504552f7358SJed Brown   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
25059566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh));
2506552f7358SJed Brown   PetscFunctionReturn(0);
2507552f7358SJed Brown }
2508552f7358SJed Brown 
2509b412c318SBarry Smith PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J)
2510552f7358SJed Brown {
25118d1174e4SMatthew G. Knepley   PetscSection           sectionGlobal;
2512acd755d7SMatthew G. Knepley   PetscInt               bs = -1, mbs;
25139fca9976SJed Brown   PetscInt               localSize, localStart = 0;
2514837628f4SStefano Zampini   PetscBool              isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS;
2515b412c318SBarry Smith   MatType                mtype;
25161428887cSShri Abhyankar   ISLocalToGlobalMapping ltog;
2517552f7358SJed Brown 
2518552f7358SJed Brown   PetscFunctionBegin;
25199566063dSJacob Faibussowitsch   PetscCall(MatInitializePackage());
2520b412c318SBarry Smith   mtype = dm->mattype;
25219566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dm, &sectionGlobal));
25229566063dSJacob Faibussowitsch   /* PetscCall(PetscSectionGetStorageSize(sectionGlobal, &localSize)); */
25239566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize));
25249fca9976SJed Brown   PetscCallMPI(MPI_Exscan(&localSize, &localStart, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) dm)));
25259566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), J));
25269566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE));
25279566063dSJacob Faibussowitsch   PetscCall(MatSetType(*J, mtype));
25289566063dSJacob Faibussowitsch   PetscCall(MatSetFromOptions(*J));
25299566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(*J, &mbs));
2530acd755d7SMatthew G. Knepley   if (mbs > 1) bs = mbs;
25319566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSHELL, &isShell));
25329566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATBAIJ, &isBlock));
25339566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock));
25349566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock));
25359566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSBAIJ, &isSymBlock));
25369566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock));
25379566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock));
25389566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATIS, &isMatIS));
2539552f7358SJed Brown   if (!isShell) {
2540837628f4SStefano Zampini     PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS);
25419fca9976SJed Brown     PetscInt  *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *pblocks;
2542fad22124SMatthew G Knepley     PetscInt  pStart, pEnd, p, dof, cdof;
2543552f7358SJed Brown 
25449566063dSJacob Faibussowitsch     PetscCall(DMGetLocalToGlobalMapping(dm,&ltog));
25459fca9976SJed Brown 
25469fca9976SJed Brown     PetscCall(PetscCalloc1(localSize, &pblocks));
25479566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(sectionGlobal, &pStart, &pEnd));
2548e432b41dSStefano Zampini     for (p = pStart; p < pEnd; ++p) {
25499fca9976SJed Brown       PetscInt bdof, offset;
2550a9d99c84SMatthew G. Knepley 
25519566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sectionGlobal, p, &dof));
25529fca9976SJed Brown       PetscCall(PetscSectionGetOffset(sectionGlobal, p, &offset));
25539566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetConstraintDof(sectionGlobal, p, &cdof));
25549fca9976SJed Brown       for (PetscInt i=0; i < dof - cdof; i++)
25559fca9976SJed Brown         pblocks[offset - localStart + i] = dof - cdof;
25561d17a0a3SMatthew G. Knepley       dof  = dof < 0 ? -(dof+1) : dof;
25571d17a0a3SMatthew G. Knepley       bdof = cdof && (dof-cdof) ? 1 : dof;
25581d17a0a3SMatthew G. Knepley       if (dof) {
25591d17a0a3SMatthew G. Knepley         if (bs < 0)          {bs = bdof;}
25609fca9976SJed Brown         else if (bs != bdof) {bs = 1;}
2561552f7358SJed Brown       }
25622a28c762SMatthew G Knepley     }
25632a28c762SMatthew G Knepley     /* Must have same blocksize on all procs (some might have no points) */
2564e432b41dSStefano Zampini     bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs;
2565e432b41dSStefano Zampini     bsLocal[1] = bs;
25669566063dSJacob Faibussowitsch     PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax));
2567e432b41dSStefano Zampini     if (bsMinMax[0] != bsMinMax[1]) bs = 1;
2568e432b41dSStefano Zampini     else bs = bsMinMax[0];
25696fd5c86aSStefano Zampini     bs = PetscMax(1,bs);
25709566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(*J,ltog,ltog));
25710682b8bbSJed Brown     if (dm->prealloc_skip) { // User will likely use MatSetPreallocationCOO(), but still set structural parameters
25729566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSize(*J, bs));
25739566063dSJacob Faibussowitsch       PetscCall(MatSetUp(*J));
25740682b8bbSJed Brown     } else {
25759566063dSJacob Faibussowitsch       PetscCall(PetscCalloc4(localSize/bs, &dnz, localSize/bs, &onz, localSize/bs, &dnzu, localSize/bs, &onzu));
25769566063dSJacob Faibussowitsch       PetscCall(DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix));
25779566063dSJacob Faibussowitsch       PetscCall(PetscFree4(dnz, onz, dnzu, onzu));
2578552f7358SJed Brown     }
25799fca9976SJed Brown     { // Consolidate blocks
25809fca9976SJed Brown       PetscInt nblocks = 0;
25819fca9976SJed Brown       for (PetscInt i=0; i<localSize; i += PetscMax(1, pblocks[i])) {
25829fca9976SJed Brown         if (pblocks[i] == 0) continue;
25839fca9976SJed Brown         pblocks[nblocks++] = pblocks[i]; // nblocks always <= i
25849fca9976SJed Brown         for (PetscInt j=1; j<pblocks[i]; j++) {
25859fca9976SJed 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]);
25869fca9976SJed Brown         }
25879fca9976SJed Brown       }
25889fca9976SJed Brown       PetscCall(MatSetVariableBlockSizes(*J, nblocks, pblocks));
25899fca9976SJed Brown     }
25909fca9976SJed Brown     PetscCall(PetscFree(pblocks));
2591aa0f6e3cSJed Brown   }
25929566063dSJacob Faibussowitsch   PetscCall(MatSetDM(*J, dm));
2593552f7358SJed Brown   PetscFunctionReturn(0);
2594552f7358SJed Brown }
2595552f7358SJed Brown 
25967cd05799SMatthew G. Knepley /*@
2597a8f00d21SMatthew G. Knepley   DMPlexGetSubdomainSection - Returns the section associated with the subdomain
2598be36d101SStefano Zampini 
2599be36d101SStefano Zampini   Not collective
2600be36d101SStefano Zampini 
2601be36d101SStefano Zampini   Input Parameter:
2602be36d101SStefano Zampini . mesh - The DMPlex
2603be36d101SStefano Zampini 
2604be36d101SStefano Zampini   Output Parameters:
2605be36d101SStefano Zampini . subsection - The subdomain section
2606be36d101SStefano Zampini 
2607be36d101SStefano Zampini   Level: developer
2608be36d101SStefano Zampini 
2609be36d101SStefano Zampini .seealso:
26107cd05799SMatthew G. Knepley @*/
2611be36d101SStefano Zampini PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection)
2612be36d101SStefano Zampini {
2613be36d101SStefano Zampini   DM_Plex       *mesh = (DM_Plex*) dm->data;
2614be36d101SStefano Zampini 
2615be36d101SStefano Zampini   PetscFunctionBegin;
2616be36d101SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2617be36d101SStefano Zampini   if (!mesh->subdomainSection) {
2618be36d101SStefano Zampini     PetscSection section;
2619be36d101SStefano Zampini     PetscSF      sf;
2620be36d101SStefano Zampini 
26219566063dSJacob Faibussowitsch     PetscCall(PetscSFCreate(PETSC_COMM_SELF,&sf));
26229566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm,&section));
26239566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreateGlobalSection(section,sf,PETSC_FALSE,PETSC_TRUE,&mesh->subdomainSection));
26249566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sf));
2625be36d101SStefano Zampini   }
2626be36d101SStefano Zampini   *subsection = mesh->subdomainSection;
2627be36d101SStefano Zampini   PetscFunctionReturn(0);
2628be36d101SStefano Zampini }
2629be36d101SStefano Zampini 
2630552f7358SJed Brown /*@
2631552f7358SJed Brown   DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd)
2632552f7358SJed Brown 
2633552f7358SJed Brown   Not collective
2634552f7358SJed Brown 
2635552f7358SJed Brown   Input Parameter:
2636552f7358SJed Brown . mesh - The DMPlex
2637552f7358SJed Brown 
2638552f7358SJed Brown   Output Parameters:
2639552f7358SJed Brown + pStart - The first mesh point
2640552f7358SJed Brown - pEnd   - The upper bound for mesh points
2641552f7358SJed Brown 
2642552f7358SJed Brown   Level: beginner
2643552f7358SJed Brown 
2644db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetChart()`
2645552f7358SJed Brown @*/
2646552f7358SJed Brown PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd)
2647552f7358SJed Brown {
2648552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2649552f7358SJed Brown 
2650552f7358SJed Brown   PetscFunctionBegin;
2651552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
26529566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->coneSection, pStart, pEnd));
2653552f7358SJed Brown   PetscFunctionReturn(0);
2654552f7358SJed Brown }
2655552f7358SJed Brown 
2656552f7358SJed Brown /*@
2657552f7358SJed Brown   DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd)
2658552f7358SJed Brown 
2659552f7358SJed Brown   Not collective
2660552f7358SJed Brown 
2661552f7358SJed Brown   Input Parameters:
2662552f7358SJed Brown + mesh - The DMPlex
2663552f7358SJed Brown . pStart - The first mesh point
2664552f7358SJed Brown - pEnd   - The upper bound for mesh points
2665552f7358SJed Brown 
2666552f7358SJed Brown   Output Parameters:
2667552f7358SJed Brown 
2668552f7358SJed Brown   Level: beginner
2669552f7358SJed Brown 
2670db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetChart()`
2671552f7358SJed Brown @*/
2672552f7358SJed Brown PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd)
2673552f7358SJed Brown {
2674552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2675552f7358SJed Brown 
2676552f7358SJed Brown   PetscFunctionBegin;
2677552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
26789566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(mesh->coneSection, pStart, pEnd));
26799566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(mesh->supportSection, pStart, pEnd));
2680552f7358SJed Brown   PetscFunctionReturn(0);
2681552f7358SJed Brown }
2682552f7358SJed Brown 
2683552f7358SJed Brown /*@
2684eaf898f9SPatrick Sanan   DMPlexGetConeSize - Return the number of in-edges for this point in the DAG
2685552f7358SJed Brown 
2686552f7358SJed Brown   Not collective
2687552f7358SJed Brown 
2688552f7358SJed Brown   Input Parameters:
2689552f7358SJed Brown + mesh - The DMPlex
2690eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
2691552f7358SJed Brown 
2692552f7358SJed Brown   Output Parameter:
2693552f7358SJed Brown . size - The cone size for point p
2694552f7358SJed Brown 
2695552f7358SJed Brown   Level: beginner
2696552f7358SJed Brown 
2697db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`
2698552f7358SJed Brown @*/
2699552f7358SJed Brown PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size)
2700552f7358SJed Brown {
2701552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2702552f7358SJed Brown 
2703552f7358SJed Brown   PetscFunctionBegin;
2704552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2705dadcf809SJacob Faibussowitsch   PetscValidIntPointer(size, 3);
27069566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, size));
2707552f7358SJed Brown   PetscFunctionReturn(0);
2708552f7358SJed Brown }
2709552f7358SJed Brown 
2710552f7358SJed Brown /*@
2711eaf898f9SPatrick Sanan   DMPlexSetConeSize - Set the number of in-edges for this point in the DAG
2712552f7358SJed Brown 
2713552f7358SJed Brown   Not collective
2714552f7358SJed Brown 
2715552f7358SJed Brown   Input Parameters:
2716552f7358SJed Brown + mesh - The DMPlex
2717eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
2718552f7358SJed Brown - size - The cone size for point p
2719552f7358SJed Brown 
2720552f7358SJed Brown   Output Parameter:
2721552f7358SJed Brown 
2722552f7358SJed Brown   Note:
2723552f7358SJed Brown   This should be called after DMPlexSetChart().
2724552f7358SJed Brown 
2725552f7358SJed Brown   Level: beginner
2726552f7358SJed Brown 
2727db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetConeSize()`, `DMPlexSetChart()`
2728552f7358SJed Brown @*/
2729552f7358SJed Brown PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size)
2730552f7358SJed Brown {
2731552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2732552f7358SJed Brown 
2733552f7358SJed Brown   PetscFunctionBegin;
2734552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
27359566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetDof(mesh->coneSection, p, size));
2736552f7358SJed Brown   PetscFunctionReturn(0);
2737552f7358SJed Brown }
2738552f7358SJed Brown 
2739f5a469b9SMatthew G. Knepley /*@
2740eaf898f9SPatrick Sanan   DMPlexAddConeSize - Add the given number of in-edges to this point in the DAG
2741f5a469b9SMatthew G. Knepley 
2742f5a469b9SMatthew G. Knepley   Not collective
2743f5a469b9SMatthew G. Knepley 
2744f5a469b9SMatthew G. Knepley   Input Parameters:
2745f5a469b9SMatthew G. Knepley + mesh - The DMPlex
2746eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
2747f5a469b9SMatthew G. Knepley - size - The additional cone size for point p
2748f5a469b9SMatthew G. Knepley 
2749f5a469b9SMatthew G. Knepley   Output Parameter:
2750f5a469b9SMatthew G. Knepley 
2751f5a469b9SMatthew G. Knepley   Note:
2752f5a469b9SMatthew G. Knepley   This should be called after DMPlexSetChart().
2753f5a469b9SMatthew G. Knepley 
2754f5a469b9SMatthew G. Knepley   Level: beginner
2755f5a469b9SMatthew G. Knepley 
2756db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexGetConeSize()`, `DMPlexSetChart()`
2757f5a469b9SMatthew G. Knepley @*/
2758f5a469b9SMatthew G. Knepley PetscErrorCode DMPlexAddConeSize(DM dm, PetscInt p, PetscInt size)
2759f5a469b9SMatthew G. Knepley {
2760f5a469b9SMatthew G. Knepley   DM_Plex       *mesh = (DM_Plex*) dm->data;
2761f5a469b9SMatthew G. Knepley   PetscFunctionBegin;
2762f5a469b9SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
27639566063dSJacob Faibussowitsch   PetscCall(PetscSectionAddDof(mesh->coneSection, p, size));
2764f5a469b9SMatthew G. Knepley   PetscFunctionReturn(0);
2765f5a469b9SMatthew G. Knepley }
2766f5a469b9SMatthew G. Knepley 
2767552f7358SJed Brown /*@C
2768eaf898f9SPatrick Sanan   DMPlexGetCone - Return the points on the in-edges for this point in the DAG
2769552f7358SJed Brown 
2770552f7358SJed Brown   Not collective
2771552f7358SJed Brown 
2772552f7358SJed Brown   Input Parameters:
2773833c876bSVaclav Hapla + dm - The DMPlex
2774eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
2775552f7358SJed Brown 
2776552f7358SJed Brown   Output Parameter:
2777552f7358SJed Brown . cone - An array of points which are on the in-edges for point p
2778552f7358SJed Brown 
2779552f7358SJed Brown   Level: beginner
2780552f7358SJed Brown 
27813813dfbdSMatthew G Knepley   Fortran Notes:
27823813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
27833813dfbdSMatthew G Knepley   include petsc.h90 in your code.
2784922102d1SVaclav Hapla   You must also call DMPlexRestoreCone() after you finish using the returned array.
2785922102d1SVaclav Hapla   DMPlexRestoreCone() is not needed/available in C.
27863813dfbdSMatthew G Knepley 
2787db781477SPatrick Sanan .seealso: `DMPlexGetConeSize()`, `DMPlexSetCone()`, `DMPlexGetConeTuple()`, `DMPlexSetChart()`
2788552f7358SJed Brown @*/
2789552f7358SJed Brown PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[])
2790552f7358SJed Brown {
2791552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2792552f7358SJed Brown   PetscInt       off;
2793552f7358SJed Brown 
2794552f7358SJed Brown   PetscFunctionBegin;
2795552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2796552f7358SJed Brown   PetscValidPointer(cone, 3);
27979566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
2798552f7358SJed Brown   *cone = &mesh->cones[off];
2799552f7358SJed Brown   PetscFunctionReturn(0);
2800552f7358SJed Brown }
2801552f7358SJed Brown 
28020ce7577fSVaclav Hapla /*@C
28030ce7577fSVaclav Hapla   DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG
28040ce7577fSVaclav Hapla 
28050ce7577fSVaclav Hapla   Not collective
28060ce7577fSVaclav Hapla 
28070ce7577fSVaclav Hapla   Input Parameters:
28080ce7577fSVaclav Hapla + dm - The DMPlex
28090ce7577fSVaclav Hapla - p - The IS of points, which must lie in the chart set with DMPlexSetChart()
28100ce7577fSVaclav Hapla 
2811d8d19677SJose E. Roman   Output Parameters:
28120ce7577fSVaclav Hapla + pConesSection - PetscSection describing the layout of pCones
28130ce7577fSVaclav Hapla - pCones - An array of points which are on the in-edges for the point set p
28140ce7577fSVaclav Hapla 
28150ce7577fSVaclav Hapla   Level: intermediate
28160ce7577fSVaclav Hapla 
2817db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeRecursive()`, `DMPlexSetChart()`
28180ce7577fSVaclav Hapla @*/
28190ce7577fSVaclav Hapla PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones)
28200ce7577fSVaclav Hapla {
28210ce7577fSVaclav Hapla   PetscSection        cs, newcs;
28220ce7577fSVaclav Hapla   PetscInt            *cones;
28230ce7577fSVaclav Hapla   PetscInt            *newarr=NULL;
28240ce7577fSVaclav Hapla   PetscInt            n;
28250ce7577fSVaclav Hapla 
28260ce7577fSVaclav Hapla   PetscFunctionBegin;
28279566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCones(dm, &cones));
28289566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSection(dm, &cs));
28299566063dSJacob Faibussowitsch   PetscCall(PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void**)&newarr) : NULL));
28300ce7577fSVaclav Hapla   if (pConesSection) *pConesSection = newcs;
28310ce7577fSVaclav Hapla   if (pCones) {
28329566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(newcs, &n));
28339566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones));
28340ce7577fSVaclav Hapla   }
28350ce7577fSVaclav Hapla   PetscFunctionReturn(0);
28360ce7577fSVaclav Hapla }
28370ce7577fSVaclav Hapla 
2838af9eab45SVaclav Hapla /*@
2839af9eab45SVaclav Hapla   DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices.
2840d4636a37SVaclav Hapla 
2841d4636a37SVaclav Hapla   Not collective
2842d4636a37SVaclav Hapla 
2843d4636a37SVaclav Hapla   Input Parameters:
2844d4636a37SVaclav Hapla + dm - The DMPlex
2845af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart()
2846d4636a37SVaclav Hapla 
2847d4636a37SVaclav Hapla   Output Parameter:
2848af9eab45SVaclav Hapla . expandedPoints - An array of vertices recursively expanded from input points
2849d4636a37SVaclav Hapla 
2850d4636a37SVaclav Hapla   Level: advanced
2851d4636a37SVaclav Hapla 
2852af9eab45SVaclav Hapla   Notes:
2853af9eab45SVaclav Hapla   Like DMPlexGetConeRecursive but returns only the 0-depth IS (i.e. vertices only) and no sections.
2854af9eab45SVaclav Hapla   There is no corresponding Restore function, just call ISDestroy() on the returned IS to deallocate.
2855af9eab45SVaclav Hapla 
2856db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetDepth()`
2857d4636a37SVaclav Hapla @*/
2858af9eab45SVaclav Hapla PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints)
2859d4636a37SVaclav Hapla {
2860af9eab45SVaclav Hapla   IS                  *expandedPointsAll;
2861af9eab45SVaclav Hapla   PetscInt            depth;
2862d4636a37SVaclav Hapla 
2863d4636a37SVaclav Hapla   PetscFunctionBegin;
2864af9eab45SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2865af9eab45SVaclav Hapla   PetscValidHeaderSpecific(points, IS_CLASSID, 2);
2866af9eab45SVaclav Hapla   PetscValidPointer(expandedPoints, 3);
28679566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL));
2868af9eab45SVaclav Hapla   *expandedPoints = expandedPointsAll[0];
28699566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)expandedPointsAll[0]));
28709566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL));
2871af9eab45SVaclav Hapla   PetscFunctionReturn(0);
2872af9eab45SVaclav Hapla }
2873af9eab45SVaclav Hapla 
2874af9eab45SVaclav Hapla /*@
2875af9eab45SVaclav 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).
2876af9eab45SVaclav Hapla 
2877af9eab45SVaclav Hapla   Not collective
2878af9eab45SVaclav Hapla 
2879af9eab45SVaclav Hapla   Input Parameters:
2880af9eab45SVaclav Hapla + dm - The DMPlex
2881af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart()
2882af9eab45SVaclav Hapla 
2883d8d19677SJose E. Roman   Output Parameters:
2884af9eab45SVaclav Hapla + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth()
2885af9eab45SVaclav Hapla . expandedPoints - (optional) An array of index sets with recursively expanded cones
2886af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points
2887af9eab45SVaclav Hapla 
2888af9eab45SVaclav Hapla   Level: advanced
2889af9eab45SVaclav Hapla 
2890af9eab45SVaclav Hapla   Notes:
2891af9eab45SVaclav Hapla   Like DMPlexGetConeTuple() but recursive.
2892af9eab45SVaclav Hapla 
2893af9eab45SVaclav 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.
2894af9eab45SVaclav Hapla   For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc.
2895af9eab45SVaclav Hapla 
2896af9eab45SVaclav 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:
2897af9eab45SVaclav Hapla   (1) DAG points in expandedPoints[d+1] with depth d+1 to their cone points in expandedPoints[d];
2898af9eab45SVaclav Hapla   (2) DAG points in expandedPoints[d+1] with depth in [0,d] to the same points in expandedPoints[d].
2899af9eab45SVaclav Hapla 
2900db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, `DMPlexGetDepth()`
2901af9eab45SVaclav Hapla @*/
2902af9eab45SVaclav Hapla PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[])
2903af9eab45SVaclav Hapla {
2904af9eab45SVaclav Hapla   const PetscInt      *arr0=NULL, *cone=NULL;
2905af9eab45SVaclav Hapla   PetscInt            *arr=NULL, *newarr=NULL;
2906af9eab45SVaclav Hapla   PetscInt            d, depth_, i, n, newn, cn, co, start, end;
2907af9eab45SVaclav Hapla   IS                  *expandedPoints_;
2908af9eab45SVaclav Hapla   PetscSection        *sections_;
2909af9eab45SVaclav Hapla 
2910af9eab45SVaclav Hapla   PetscFunctionBegin;
2911af9eab45SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2912af9eab45SVaclav Hapla   PetscValidHeaderSpecific(points, IS_CLASSID, 2);
2913af9eab45SVaclav Hapla   if (depth) PetscValidIntPointer(depth, 3);
2914af9eab45SVaclav Hapla   if (expandedPoints) PetscValidPointer(expandedPoints, 4);
2915af9eab45SVaclav Hapla   if (sections) PetscValidPointer(sections, 5);
29169566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(points, &n));
29179566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(points, &arr0));
29189566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth_));
29199566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(depth_, &expandedPoints_));
29209566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(depth_, &sections_));
2921af9eab45SVaclav Hapla   arr = (PetscInt*) arr0; /* this is ok because first generation of arr is not modified */
2922af9eab45SVaclav Hapla   for (d=depth_-1; d>=0; d--) {
29239566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &sections_[d]));
29249566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(sections_[d], 0, n));
2925af9eab45SVaclav Hapla     for (i=0; i<n; i++) {
29269566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d+1, &start, &end));
2927af9eab45SVaclav Hapla       if (arr[i] >= start && arr[i] < end) {
29289566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, arr[i], &cn));
29299566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetDof(sections_[d], i, cn));
2930af9eab45SVaclav Hapla       } else {
29319566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetDof(sections_[d], i, 1));
2932af9eab45SVaclav Hapla       }
2933af9eab45SVaclav Hapla     }
29349566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(sections_[d]));
29359566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(sections_[d], &newn));
29369566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(newn, &newarr));
2937af9eab45SVaclav Hapla     for (i=0; i<n; i++) {
29389566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sections_[d], i, &cn));
29399566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(sections_[d], i, &co));
2940af9eab45SVaclav Hapla       if (cn > 1) {
29419566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, arr[i], &cone));
29429566063dSJacob Faibussowitsch         PetscCall(PetscMemcpy(&newarr[co], cone, cn*sizeof(PetscInt)));
2943af9eab45SVaclav Hapla       } else {
2944af9eab45SVaclav Hapla         newarr[co] = arr[i];
2945af9eab45SVaclav Hapla       }
2946af9eab45SVaclav Hapla     }
29479566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d]));
2948af9eab45SVaclav Hapla     arr = newarr;
2949af9eab45SVaclav Hapla     n = newn;
2950af9eab45SVaclav Hapla   }
29519566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(points, &arr0));
2952af9eab45SVaclav Hapla   *depth = depth_;
2953af9eab45SVaclav Hapla   if (expandedPoints) *expandedPoints = expandedPoints_;
2954af9eab45SVaclav Hapla   else {
29559566063dSJacob Faibussowitsch     for (d=0; d<depth_; d++) PetscCall(ISDestroy(&expandedPoints_[d]));
29569566063dSJacob Faibussowitsch     PetscCall(PetscFree(expandedPoints_));
2957af9eab45SVaclav Hapla   }
2958af9eab45SVaclav Hapla   if (sections) *sections = sections_;
2959af9eab45SVaclav Hapla   else {
29609566063dSJacob Faibussowitsch     for (d=0; d<depth_; d++) PetscCall(PetscSectionDestroy(&sections_[d]));
29619566063dSJacob Faibussowitsch     PetscCall(PetscFree(sections_));
2962af9eab45SVaclav Hapla   }
2963af9eab45SVaclav Hapla   PetscFunctionReturn(0);
2964af9eab45SVaclav Hapla }
2965af9eab45SVaclav Hapla 
2966af9eab45SVaclav Hapla /*@
2967af9eab45SVaclav Hapla   DMPlexRestoreConeRecursive - Deallocates arrays created by DMPlexGetConeRecursive
2968af9eab45SVaclav Hapla 
2969af9eab45SVaclav Hapla   Not collective
2970af9eab45SVaclav Hapla 
2971af9eab45SVaclav Hapla   Input Parameters:
2972af9eab45SVaclav Hapla + dm - The DMPlex
2973af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart()
2974af9eab45SVaclav Hapla 
2975d8d19677SJose E. Roman   Output Parameters:
2976af9eab45SVaclav Hapla + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth()
2977af9eab45SVaclav Hapla . expandedPoints - (optional) An array of recursively expanded cones
2978af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points
2979af9eab45SVaclav Hapla 
2980af9eab45SVaclav Hapla   Level: advanced
2981af9eab45SVaclav Hapla 
2982af9eab45SVaclav Hapla   Notes:
2983af9eab45SVaclav Hapla   See DMPlexGetConeRecursive() for details.
2984af9eab45SVaclav Hapla 
2985db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, `DMPlexGetDepth()`
2986af9eab45SVaclav Hapla @*/
2987af9eab45SVaclav Hapla PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[])
2988af9eab45SVaclav Hapla {
2989af9eab45SVaclav Hapla   PetscInt            d, depth_;
2990af9eab45SVaclav Hapla 
2991af9eab45SVaclav Hapla   PetscFunctionBegin;
29929566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth_));
29931dca8a05SBarry Smith   PetscCheck(!depth || *depth == depth_,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive");
2994af9eab45SVaclav Hapla   if (depth) *depth = 0;
2995af9eab45SVaclav Hapla   if (expandedPoints) {
29969566063dSJacob Faibussowitsch     for (d=0; d<depth_; d++) PetscCall(ISDestroy(&((*expandedPoints)[d])));
29979566063dSJacob Faibussowitsch     PetscCall(PetscFree(*expandedPoints));
2998af9eab45SVaclav Hapla   }
2999af9eab45SVaclav Hapla   if (sections)  {
30009566063dSJacob Faibussowitsch     for (d=0; d<depth_; d++) PetscCall(PetscSectionDestroy(&((*sections)[d])));
30019566063dSJacob Faibussowitsch     PetscCall(PetscFree(*sections));
3002af9eab45SVaclav Hapla   }
3003d4636a37SVaclav Hapla   PetscFunctionReturn(0);
3004d4636a37SVaclav Hapla }
3005d4636a37SVaclav Hapla 
3006552f7358SJed Brown /*@
300792371b87SBarry 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
3008552f7358SJed Brown 
3009552f7358SJed Brown   Not collective
3010552f7358SJed Brown 
3011552f7358SJed Brown   Input Parameters:
3012552f7358SJed Brown + mesh - The DMPlex
3013eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
3014552f7358SJed Brown - cone - An array of points which are on the in-edges for point p
3015552f7358SJed Brown 
3016552f7358SJed Brown   Output Parameter:
3017552f7358SJed Brown 
3018552f7358SJed Brown   Note:
3019552f7358SJed Brown   This should be called after all calls to DMPlexSetConeSize() and DMSetUp().
3020552f7358SJed Brown 
3021552f7358SJed Brown   Level: beginner
3022552f7358SJed Brown 
3023db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`, `DMPlexSetSupport()`, `DMPlexSetSupportSize()`
3024552f7358SJed Brown @*/
3025552f7358SJed Brown PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[])
3026552f7358SJed Brown {
3027552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3028552f7358SJed Brown   PetscInt       pStart, pEnd;
3029552f7358SJed Brown   PetscInt       dof, off, c;
3030552f7358SJed Brown 
3031552f7358SJed Brown   PetscFunctionBegin;
3032552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
30339566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
30349566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
3035dadcf809SJacob Faibussowitsch   if (dof) PetscValidIntPointer(cone, 3);
30369566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
303763a3b9bcSJacob 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);
3038552f7358SJed Brown   for (c = 0; c < dof; ++c) {
303963a3b9bcSJacob 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);
3040552f7358SJed Brown     mesh->cones[off+c] = cone[c];
3041552f7358SJed Brown   }
3042552f7358SJed Brown   PetscFunctionReturn(0);
3043552f7358SJed Brown }
3044552f7358SJed Brown 
3045552f7358SJed Brown /*@C
3046eaf898f9SPatrick Sanan   DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG
3047552f7358SJed Brown 
3048552f7358SJed Brown   Not collective
3049552f7358SJed Brown 
3050552f7358SJed Brown   Input Parameters:
3051552f7358SJed Brown + mesh - The DMPlex
3052eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
3053552f7358SJed Brown 
3054552f7358SJed Brown   Output Parameter:
3055552f7358SJed Brown . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an
3056b5a892a1SMatthew G. Knepley                     integer giving the prescription for cone traversal.
3057552f7358SJed Brown 
3058552f7358SJed Brown   Level: beginner
3059552f7358SJed Brown 
3060b5a892a1SMatthew G. Knepley   Notes:
3061b5a892a1SMatthew G. Knepley   The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always
3062b5a892a1SMatthew G. Knepley   the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection
3063b5a892a1SMatthew G. Knepley   of o, however it is not necessarily the inverse. To get the inverse, use DMPolytopeTypeComposeOrientationInv()
3064b5a892a1SMatthew G. Knepley   with the identity.
3065b5a892a1SMatthew G. Knepley 
30663813dfbdSMatthew G Knepley   Fortran Notes:
30673813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
30683813dfbdSMatthew G Knepley   include petsc.h90 in your code.
30693b12b3d8SVaclav Hapla   You must also call DMPlexRestoreConeOrientation() after you finish using the returned array.
3070922102d1SVaclav Hapla   DMPlexRestoreConeOrientation() is not needed/available in C.
30713813dfbdSMatthew G Knepley 
3072db781477SPatrick Sanan .seealso: `DMPolytopeTypeComposeOrientation()`, `DMPolytopeTypeComposeOrientationInv()`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetCone()`, `DMPlexSetChart()`
3073552f7358SJed Brown @*/
3074552f7358SJed Brown PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[])
3075552f7358SJed Brown {
3076552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3077552f7358SJed Brown   PetscInt       off;
3078552f7358SJed Brown 
3079552f7358SJed Brown   PetscFunctionBegin;
3080552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
308176bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
3082552f7358SJed Brown     PetscInt dof;
30839566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
3084552f7358SJed Brown     if (dof) PetscValidPointer(coneOrientation, 3);
3085552f7358SJed Brown   }
30869566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
30870d644c17SKarl Rupp 
3088552f7358SJed Brown   *coneOrientation = &mesh->coneOrientations[off];
3089552f7358SJed Brown   PetscFunctionReturn(0);
3090552f7358SJed Brown }
3091552f7358SJed Brown 
3092552f7358SJed Brown /*@
3093eaf898f9SPatrick Sanan   DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG
3094552f7358SJed Brown 
3095552f7358SJed Brown   Not collective
3096552f7358SJed Brown 
3097552f7358SJed Brown   Input Parameters:
3098552f7358SJed Brown + mesh - The DMPlex
3099eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
3100b5a892a1SMatthew G. Knepley - coneOrientation - An array of orientations
3101552f7358SJed Brown   Output Parameter:
3102552f7358SJed Brown 
3103b5a892a1SMatthew G. Knepley   Notes:
3104552f7358SJed Brown   This should be called after all calls to DMPlexSetConeSize() and DMSetUp().
3105552f7358SJed Brown 
3106b5a892a1SMatthew G. Knepley   The meaning of coneOrientation is detailed in DMPlexGetConeOrientation().
3107b5a892a1SMatthew G. Knepley 
3108552f7358SJed Brown   Level: beginner
3109552f7358SJed Brown 
3110db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetConeOrientation()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
3111552f7358SJed Brown @*/
3112552f7358SJed Brown PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[])
3113552f7358SJed Brown {
3114552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3115552f7358SJed Brown   PetscInt       pStart, pEnd;
3116552f7358SJed Brown   PetscInt       dof, off, c;
3117552f7358SJed Brown 
3118552f7358SJed Brown   PetscFunctionBegin;
3119552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
31209566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
31219566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
3122dadcf809SJacob Faibussowitsch   if (dof) PetscValidIntPointer(coneOrientation, 3);
31239566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
312463a3b9bcSJacob 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);
3125552f7358SJed Brown   for (c = 0; c < dof; ++c) {
3126552f7358SJed Brown     PetscInt cdof, o = coneOrientation[c];
3127552f7358SJed Brown 
31289566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof));
31291dca8a05SBarry 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);
3130552f7358SJed Brown     mesh->coneOrientations[off+c] = o;
3131552f7358SJed Brown   }
3132552f7358SJed Brown   PetscFunctionReturn(0);
3133552f7358SJed Brown }
3134552f7358SJed Brown 
31357cd05799SMatthew G. Knepley /*@
3136eaf898f9SPatrick Sanan   DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG
31377cd05799SMatthew G. Knepley 
31387cd05799SMatthew G. Knepley   Not collective
31397cd05799SMatthew G. Knepley 
31407cd05799SMatthew G. Knepley   Input Parameters:
31417cd05799SMatthew G. Knepley + mesh - The DMPlex
3142eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
31437cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put
31447cd05799SMatthew G. Knepley - conePoint - The mesh point to insert
31457cd05799SMatthew G. Knepley 
31467cd05799SMatthew G. Knepley   Level: beginner
31477cd05799SMatthew G. Knepley 
3148db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
31497cd05799SMatthew G. Knepley @*/
3150552f7358SJed Brown PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint)
3151552f7358SJed Brown {
3152552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3153552f7358SJed Brown   PetscInt       pStart, pEnd;
3154552f7358SJed Brown   PetscInt       dof, off;
3155552f7358SJed Brown 
3156552f7358SJed Brown   PetscFunctionBegin;
3157552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
31589566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
315963a3b9bcSJacob 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);
316063a3b9bcSJacob 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);
31619566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
31629566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
316363a3b9bcSJacob 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);
3164552f7358SJed Brown   mesh->cones[off+conePos] = conePoint;
3165552f7358SJed Brown   PetscFunctionReturn(0);
3166552f7358SJed Brown }
3167552f7358SJed Brown 
31687cd05799SMatthew G. Knepley /*@
3169eaf898f9SPatrick Sanan   DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG
31707cd05799SMatthew G. Knepley 
31717cd05799SMatthew G. Knepley   Not collective
31727cd05799SMatthew G. Knepley 
31737cd05799SMatthew G. Knepley   Input Parameters:
31747cd05799SMatthew G. Knepley + mesh - The DMPlex
3175eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
31767cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put
31777cd05799SMatthew G. Knepley - coneOrientation - The point orientation to insert
31787cd05799SMatthew G. Knepley 
31797cd05799SMatthew G. Knepley   Level: beginner
31807cd05799SMatthew G. Knepley 
3181b5a892a1SMatthew G. Knepley   Notes:
3182b5a892a1SMatthew G. Knepley   The meaning of coneOrientation values is detailed in DMPlexGetConeOrientation().
3183b5a892a1SMatthew G. Knepley 
3184db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
31857cd05799SMatthew G. Knepley @*/
318677c88f5bSMatthew G Knepley PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation)
318777c88f5bSMatthew G Knepley {
318877c88f5bSMatthew G Knepley   DM_Plex       *mesh = (DM_Plex*) dm->data;
318977c88f5bSMatthew G Knepley   PetscInt       pStart, pEnd;
319077c88f5bSMatthew G Knepley   PetscInt       dof, off;
319177c88f5bSMatthew G Knepley 
319277c88f5bSMatthew G Knepley   PetscFunctionBegin;
319377c88f5bSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
31949566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
319563a3b9bcSJacob 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);
31969566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
31979566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
319863a3b9bcSJacob 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);
319977c88f5bSMatthew G Knepley   mesh->coneOrientations[off+conePos] = coneOrientation;
320077c88f5bSMatthew G Knepley   PetscFunctionReturn(0);
320177c88f5bSMatthew G Knepley }
320277c88f5bSMatthew G Knepley 
3203552f7358SJed Brown /*@
3204eaf898f9SPatrick Sanan   DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG
3205552f7358SJed Brown 
3206552f7358SJed Brown   Not collective
3207552f7358SJed Brown 
3208552f7358SJed Brown   Input Parameters:
3209552f7358SJed Brown + mesh - The DMPlex
3210eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
3211552f7358SJed Brown 
3212552f7358SJed Brown   Output Parameter:
3213552f7358SJed Brown . size - The support size for point p
3214552f7358SJed Brown 
3215552f7358SJed Brown   Level: beginner
3216552f7358SJed Brown 
3217db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`, `DMPlexGetConeSize()`
3218552f7358SJed Brown @*/
3219552f7358SJed Brown PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size)
3220552f7358SJed Brown {
3221552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3222552f7358SJed Brown 
3223552f7358SJed Brown   PetscFunctionBegin;
3224552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3225dadcf809SJacob Faibussowitsch   PetscValidIntPointer(size, 3);
32269566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, size));
3227552f7358SJed Brown   PetscFunctionReturn(0);
3228552f7358SJed Brown }
3229552f7358SJed Brown 
3230552f7358SJed Brown /*@
3231eaf898f9SPatrick Sanan   DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG
3232552f7358SJed Brown 
3233552f7358SJed Brown   Not collective
3234552f7358SJed Brown 
3235552f7358SJed Brown   Input Parameters:
3236552f7358SJed Brown + mesh - The DMPlex
3237eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
3238552f7358SJed Brown - size - The support size for point p
3239552f7358SJed Brown 
3240552f7358SJed Brown   Output Parameter:
3241552f7358SJed Brown 
3242552f7358SJed Brown   Note:
3243552f7358SJed Brown   This should be called after DMPlexSetChart().
3244552f7358SJed Brown 
3245552f7358SJed Brown   Level: beginner
3246552f7358SJed Brown 
3247db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetSupportSize()`, `DMPlexSetChart()`
3248552f7358SJed Brown @*/
3249552f7358SJed Brown PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size)
3250552f7358SJed Brown {
3251552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3252552f7358SJed Brown 
3253552f7358SJed Brown   PetscFunctionBegin;
3254552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
32559566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetDof(mesh->supportSection, p, size));
3256552f7358SJed Brown   PetscFunctionReturn(0);
3257552f7358SJed Brown }
3258552f7358SJed Brown 
3259552f7358SJed Brown /*@C
3260eaf898f9SPatrick Sanan   DMPlexGetSupport - Return the points on the out-edges for this point in the DAG
3261552f7358SJed Brown 
3262552f7358SJed Brown   Not collective
3263552f7358SJed Brown 
3264552f7358SJed Brown   Input Parameters:
3265552f7358SJed Brown + mesh - The DMPlex
3266eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
3267552f7358SJed Brown 
3268552f7358SJed Brown   Output Parameter:
3269552f7358SJed Brown . support - An array of points which are on the out-edges for point p
3270552f7358SJed Brown 
3271552f7358SJed Brown   Level: beginner
3272552f7358SJed Brown 
32733813dfbdSMatthew G Knepley   Fortran Notes:
32743813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
32753813dfbdSMatthew G Knepley   include petsc.h90 in your code.
32763b12b3d8SVaclav Hapla   You must also call DMPlexRestoreSupport() after you finish using the returned array.
3277922102d1SVaclav Hapla   DMPlexRestoreSupport() is not needed/available in C.
32783813dfbdSMatthew G Knepley 
3279db781477SPatrick Sanan .seealso: `DMPlexGetSupportSize()`, `DMPlexSetSupport()`, `DMPlexGetCone()`, `DMPlexSetChart()`
3280552f7358SJed Brown @*/
3281552f7358SJed Brown PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[])
3282552f7358SJed Brown {
3283552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3284552f7358SJed Brown   PetscInt       off;
3285552f7358SJed Brown 
3286552f7358SJed Brown   PetscFunctionBegin;
3287552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3288552f7358SJed Brown   PetscValidPointer(support, 3);
32899566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
3290552f7358SJed Brown   *support = &mesh->supports[off];
3291552f7358SJed Brown   PetscFunctionReturn(0);
3292552f7358SJed Brown }
3293552f7358SJed Brown 
3294552f7358SJed Brown /*@
329592371b87SBarry 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
3296552f7358SJed Brown 
3297552f7358SJed Brown   Not collective
3298552f7358SJed Brown 
3299552f7358SJed Brown   Input Parameters:
3300552f7358SJed Brown + mesh - The DMPlex
3301eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
330292371b87SBarry Smith - support - An array of points which are on the out-edges for point p
3303552f7358SJed Brown 
3304552f7358SJed Brown   Output Parameter:
3305552f7358SJed Brown 
3306552f7358SJed Brown   Note:
3307552f7358SJed Brown   This should be called after all calls to DMPlexSetSupportSize() and DMSetUp().
3308552f7358SJed Brown 
3309552f7358SJed Brown   Level: beginner
3310552f7358SJed Brown 
3311db781477SPatrick Sanan .seealso: `DMPlexSetCone()`, `DMPlexSetConeSize()`, `DMPlexCreate()`, `DMPlexGetSupport()`, `DMPlexSetChart()`, `DMPlexSetSupportSize()`, `DMSetUp()`
3312552f7358SJed Brown @*/
3313552f7358SJed Brown PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[])
3314552f7358SJed Brown {
3315552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3316552f7358SJed Brown   PetscInt       pStart, pEnd;
3317552f7358SJed Brown   PetscInt       dof, off, c;
3318552f7358SJed Brown 
3319552f7358SJed Brown   PetscFunctionBegin;
3320552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
33219566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd));
33229566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
3323dadcf809SJacob Faibussowitsch   if (dof) PetscValidIntPointer(support, 3);
33249566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
332563a3b9bcSJacob 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);
3326552f7358SJed Brown   for (c = 0; c < dof; ++c) {
332763a3b9bcSJacob 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);
3328552f7358SJed Brown     mesh->supports[off+c] = support[c];
3329552f7358SJed Brown   }
3330552f7358SJed Brown   PetscFunctionReturn(0);
3331552f7358SJed Brown }
3332552f7358SJed Brown 
33337cd05799SMatthew G. Knepley /*@
3334eaf898f9SPatrick Sanan   DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG
33357cd05799SMatthew G. Knepley 
33367cd05799SMatthew G. Knepley   Not collective
33377cd05799SMatthew G. Knepley 
33387cd05799SMatthew G. Knepley   Input Parameters:
33397cd05799SMatthew G. Knepley + mesh - The DMPlex
3340eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
33417cd05799SMatthew G. Knepley . supportPos - The local index in the cone where the point should be put
33427cd05799SMatthew G. Knepley - supportPoint - The mesh point to insert
33437cd05799SMatthew G. Knepley 
33447cd05799SMatthew G. Knepley   Level: beginner
33457cd05799SMatthew G. Knepley 
3346db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
33477cd05799SMatthew G. Knepley @*/
3348552f7358SJed Brown PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint)
3349552f7358SJed Brown {
3350552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3351552f7358SJed Brown   PetscInt       pStart, pEnd;
3352552f7358SJed Brown   PetscInt       dof, off;
3353552f7358SJed Brown 
3354552f7358SJed Brown   PetscFunctionBegin;
3355552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
33569566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd));
33579566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
33589566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
335963a3b9bcSJacob 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);
336063a3b9bcSJacob 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);
336163a3b9bcSJacob 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);
3362552f7358SJed Brown   mesh->supports[off+supportPos] = supportPoint;
3363552f7358SJed Brown   PetscFunctionReturn(0);
3364552f7358SJed Brown }
3365552f7358SJed Brown 
3366b5a892a1SMatthew G. Knepley /* Converts an orientation o in the current numbering to the previous scheme used in Plex */
3367b5a892a1SMatthew G. Knepley PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o)
3368b5a892a1SMatthew G. Knepley {
3369b5a892a1SMatthew G. Knepley   switch (ct) {
3370b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:
3371b5a892a1SMatthew G. Knepley       if (o == -1) return -2;
3372b5a892a1SMatthew G. Knepley       break;
3373b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:
3374b5a892a1SMatthew G. Knepley       if (o == -3) return -1;
3375b5a892a1SMatthew G. Knepley       if (o == -2) return -3;
3376b5a892a1SMatthew G. Knepley       if (o == -1) return -2;
3377b5a892a1SMatthew G. Knepley       break;
3378b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:
3379b5a892a1SMatthew G. Knepley       if (o == -4) return -2;
3380b5a892a1SMatthew G. Knepley       if (o == -3) return -1;
3381b5a892a1SMatthew G. Knepley       if (o == -2) return -4;
3382b5a892a1SMatthew G. Knepley       if (o == -1) return -3;
3383b5a892a1SMatthew G. Knepley       break;
3384b5a892a1SMatthew G. Knepley     default: return o;
3385b5a892a1SMatthew G. Knepley   }
3386b5a892a1SMatthew G. Knepley   return o;
3387b5a892a1SMatthew G. Knepley }
3388b5a892a1SMatthew G. Knepley 
3389b5a892a1SMatthew G. Knepley /* Converts an orientation o in the previous scheme used in Plex to the current numbering */
3390b5a892a1SMatthew G. Knepley PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o)
3391b5a892a1SMatthew G. Knepley {
3392b5a892a1SMatthew G. Knepley   switch (ct) {
3393b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:
3394b5a892a1SMatthew G. Knepley       if ((o == -2) || (o == 1)) return -1;
3395b5a892a1SMatthew G. Knepley       if (o == -1) return 0;
3396b5a892a1SMatthew G. Knepley       break;
3397b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:
3398b5a892a1SMatthew G. Knepley       if (o == -3) return -2;
3399b5a892a1SMatthew G. Knepley       if (o == -2) return -1;
3400b5a892a1SMatthew G. Knepley       if (o == -1) return -3;
3401b5a892a1SMatthew G. Knepley       break;
3402b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:
3403b5a892a1SMatthew G. Knepley       if (o == -4) return -2;
3404b5a892a1SMatthew G. Knepley       if (o == -3) return -1;
3405b5a892a1SMatthew G. Knepley       if (o == -2) return -4;
3406b5a892a1SMatthew G. Knepley       if (o == -1) return -3;
3407b5a892a1SMatthew G. Knepley       break;
3408b5a892a1SMatthew G. Knepley     default: return o;
3409b5a892a1SMatthew G. Knepley   }
3410b5a892a1SMatthew G. Knepley   return o;
3411b5a892a1SMatthew G. Knepley }
3412b5a892a1SMatthew G. Knepley 
3413b5a892a1SMatthew G. Knepley /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */
3414b5a892a1SMatthew G. Knepley PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm)
3415b5a892a1SMatthew G. Knepley {
3416b5a892a1SMatthew G. Knepley   PetscInt       pStart, pEnd, p;
3417b5a892a1SMatthew G. Knepley 
3418b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
34199566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
3420b5a892a1SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
3421b5a892a1SMatthew G. Knepley     const PetscInt *cone, *ornt;
3422b5a892a1SMatthew G. Knepley     PetscInt        coneSize, c;
3423b5a892a1SMatthew G. Knepley 
34249566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
34259566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
34269566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dm, p, &ornt));
3427b5a892a1SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
3428b5a892a1SMatthew G. Knepley       DMPolytopeType ct;
3429b5a892a1SMatthew G. Knepley       const PetscInt o = ornt[c];
3430b5a892a1SMatthew G. Knepley 
34319566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, cone[c], &ct));
3432b5a892a1SMatthew G. Knepley       switch (ct) {
3433b5a892a1SMatthew G. Knepley         case DM_POLYTOPE_SEGMENT:
34349566063dSJacob Faibussowitsch           if ((o == -2) || (o == 1)) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
34359566063dSJacob Faibussowitsch           if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, 0));
3436b5a892a1SMatthew G. Knepley           break;
3437b5a892a1SMatthew G. Knepley         case DM_POLYTOPE_TRIANGLE:
34389566063dSJacob Faibussowitsch           if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2));
34399566063dSJacob Faibussowitsch           if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
34409566063dSJacob Faibussowitsch           if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3));
3441b5a892a1SMatthew G. Knepley           break;
3442b5a892a1SMatthew G. Knepley         case DM_POLYTOPE_QUADRILATERAL:
34439566063dSJacob Faibussowitsch           if (o == -4) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2));
34449566063dSJacob Faibussowitsch           if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
34459566063dSJacob Faibussowitsch           if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -4));
34469566063dSJacob Faibussowitsch           if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3));
3447b5a892a1SMatthew G. Knepley           break;
3448b5a892a1SMatthew G. Knepley         default: break;
3449b5a892a1SMatthew G. Knepley       }
3450b5a892a1SMatthew G. Knepley     }
3451b5a892a1SMatthew G. Knepley   }
3452b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
3453b5a892a1SMatthew G. Knepley }
3454b5a892a1SMatthew G. Knepley 
3455012bc364SMatthew G. Knepley static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3456b5a892a1SMatthew G. Knepley {
3457b5a892a1SMatthew G. Knepley   DMPolytopeType  ct = DM_POLYTOPE_UNKNOWN;
3458b5a892a1SMatthew G. Knepley   PetscInt       *closure;
3459b5a892a1SMatthew G. Knepley   const PetscInt *tmp = NULL, *tmpO = NULL;
3460b5a892a1SMatthew G. Knepley   PetscInt        off = 0, tmpSize, t;
3461b5a892a1SMatthew G. Knepley 
3462b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3463b5a892a1SMatthew G. Knepley   if (ornt) {
34649566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, p, &ct));
3465b5a892a1SMatthew G. Knepley     if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN;
3466b5a892a1SMatthew G. Knepley   }
3467b5a892a1SMatthew G. Knepley   if (*points) {
3468b5a892a1SMatthew G. Knepley     closure = *points;
3469b5a892a1SMatthew G. Knepley   } else {
3470b5a892a1SMatthew G. Knepley     PetscInt maxConeSize, maxSupportSize;
34719566063dSJacob Faibussowitsch     PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
34729566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, 2*(PetscMax(maxConeSize, maxSupportSize)+1), MPIU_INT, &closure));
3473b5a892a1SMatthew G. Knepley   }
3474b5a892a1SMatthew G. Knepley   if (useCone) {
34759566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &tmpSize));
34769566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &tmp));
34779566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dm, p, &tmpO));
3478b5a892a1SMatthew G. Knepley   } else {
34799566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dm, p, &tmpSize));
34809566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dm, p, &tmp));
3481b5a892a1SMatthew G. Knepley   }
3482b5a892a1SMatthew G. Knepley   if (ct == DM_POLYTOPE_UNKNOWN) {
3483b5a892a1SMatthew G. Knepley     closure[off++] = p;
3484b5a892a1SMatthew G. Knepley     closure[off++] = 0;
3485b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3486b5a892a1SMatthew G. Knepley       closure[off++] = tmp[t];
3487b5a892a1SMatthew G. Knepley       closure[off++] = tmpO ? tmpO[t] : 0;
3488b5a892a1SMatthew G. Knepley     }
3489b5a892a1SMatthew G. Knepley   } else {
34905f80ce2aSJacob Faibussowitsch     const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, ornt);
3491b5a892a1SMatthew G. Knepley 
3492b5a892a1SMatthew G. Knepley     /* We assume that cells with a valid type have faces with a valid type */
3493b5a892a1SMatthew G. Knepley     closure[off++] = p;
3494b5a892a1SMatthew G. Knepley     closure[off++] = ornt;
3495b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3496b5a892a1SMatthew G. Knepley       DMPolytopeType ft;
3497b5a892a1SMatthew G. Knepley 
34989566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, tmp[t], &ft));
3499b5a892a1SMatthew G. Knepley       closure[off++] = tmp[arr[t]];
3500b5a892a1SMatthew G. Knepley       closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0;
3501b5a892a1SMatthew G. Knepley     }
3502b5a892a1SMatthew G. Knepley   }
3503b5a892a1SMatthew G. Knepley   if (numPoints) *numPoints = tmpSize+1;
3504b5a892a1SMatthew G. Knepley   if (points)    *points    = closure;
3505b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
3506b5a892a1SMatthew G. Knepley }
3507b5a892a1SMatthew G. Knepley 
3508b5a892a1SMatthew G. Knepley /* We need a special tensor verison becasue we want to allow duplicate points in the endcaps for hybrid cells */
3509b5a892a1SMatthew G. Knepley static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points)
3510b5a892a1SMatthew G. Knepley {
3511b5a892a1SMatthew G. Knepley   const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, o);
3512b5a892a1SMatthew G. Knepley   const PetscInt *cone, *ornt;
3513b5a892a1SMatthew G. Knepley   PetscInt       *pts,  *closure = NULL;
3514b5a892a1SMatthew G. Knepley   DMPolytopeType  ft;
3515b5a892a1SMatthew G. Knepley   PetscInt        maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize;
3516b5a892a1SMatthew G. Knepley   PetscInt        dim, coneSize, c, d, clSize, cl;
3517b5a892a1SMatthew G. Knepley 
3518b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
35199566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
35209566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, point, &coneSize));
35219566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, point, &cone));
35229566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeOrientation(dm, point, &ornt));
35239566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
3524b5a892a1SMatthew G. Knepley   coneSeries    = (maxConeSize    > 1) ? ((PetscPowInt(maxConeSize,    dim+1)-1)/(maxConeSize-1))    : dim+1;
3525b5a892a1SMatthew G. Knepley   supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim+1)-1)/(maxSupportSize-1)) : dim+1;
3526b5a892a1SMatthew G. Knepley   maxSize       = PetscMax(coneSeries, supportSeries);
3527b5a892a1SMatthew G. Knepley   if (*points) {pts  = *points;}
35289566063dSJacob Faibussowitsch   else         PetscCall(DMGetWorkArray(dm, 2*maxSize, MPIU_INT, &pts));
3529b5a892a1SMatthew G. Knepley   c    = 0;
3530b5a892a1SMatthew G. Knepley   pts[c++] = point;
3531b5a892a1SMatthew G. Knepley   pts[c++] = o;
35329566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cone[arr[0*2+0]], &ft));
35339566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0*2+0]], DMPolytopeTypeComposeOrientation(ft, arr[0*2+1], ornt[0]), useCone, &clSize, &closure));
3534b5a892a1SMatthew G. Knepley   for (cl = 0; cl < clSize*2; cl += 2) {pts[c++] = closure[cl]; pts[c++] = closure[cl+1];}
35359566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1*2+0]], DMPolytopeTypeComposeOrientation(ft, arr[1*2+1], ornt[1]), useCone, &clSize, &closure));
3536b5a892a1SMatthew G. Knepley   for (cl = 0; cl < clSize*2; cl += 2) {pts[c++] = closure[cl]; pts[c++] = closure[cl+1];}
35379566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure));
3538b5a892a1SMatthew G. Knepley   for (d = 2; d < coneSize; ++d) {
35399566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, cone[arr[d*2+0]], &ft));
3540b5a892a1SMatthew G. Knepley     pts[c++] = cone[arr[d*2+0]];
3541b5a892a1SMatthew G. Knepley     pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d*2+1], ornt[d]);
3542b5a892a1SMatthew G. Knepley   }
3543b5a892a1SMatthew G. Knepley   if (dim >= 3) {
3544b5a892a1SMatthew G. Knepley     for (d = 2; d < coneSize; ++d) {
3545b5a892a1SMatthew G. Knepley       const PetscInt  fpoint = cone[arr[d*2+0]];
3546b5a892a1SMatthew G. Knepley       const PetscInt *fcone, *fornt;
3547b5a892a1SMatthew G. Knepley       PetscInt        fconeSize, fc, i;
3548b5a892a1SMatthew G. Knepley 
35499566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, fpoint, &ft));
3550b5a892a1SMatthew G. Knepley       const PetscInt *farr = DMPolytopeTypeGetArrangment(ft, DMPolytopeTypeComposeOrientation(ft, arr[d*2+1], ornt[d]));
35519566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, fpoint, &fconeSize));
35529566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, fpoint, &fcone));
35539566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeOrientation(dm, fpoint, &fornt));
3554b5a892a1SMatthew G. Knepley       for (fc = 0; fc < fconeSize; ++fc) {
3555b5a892a1SMatthew G. Knepley         const PetscInt cp = fcone[farr[fc*2+0]];
3556b5a892a1SMatthew G. Knepley         const PetscInt co = farr[fc*2+1];
3557b5a892a1SMatthew G. Knepley 
3558b5a892a1SMatthew G. Knepley         for (i = 0; i < c; i += 2) if (pts[i] == cp) break;
3559b5a892a1SMatthew G. Knepley         if (i == c) {
35609566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCellType(dm, cp, &ft));
3561b5a892a1SMatthew G. Knepley           pts[c++] = cp;
3562b5a892a1SMatthew G. Knepley           pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc*2+0]]);
3563b5a892a1SMatthew G. Knepley         }
3564b5a892a1SMatthew G. Knepley       }
3565b5a892a1SMatthew G. Knepley     }
3566b5a892a1SMatthew G. Knepley   }
3567b5a892a1SMatthew G. Knepley   *numPoints = c/2;
3568b5a892a1SMatthew G. Knepley   *points    = pts;
3569b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
3570b5a892a1SMatthew G. Knepley }
3571b5a892a1SMatthew G. Knepley 
3572b5a892a1SMatthew G. Knepley PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3573b5a892a1SMatthew G. Knepley {
3574b5a892a1SMatthew G. Knepley   DMPolytopeType ct;
3575b5a892a1SMatthew G. Knepley   PetscInt      *closure, *fifo;
3576b5a892a1SMatthew G. Knepley   PetscInt       closureSize = 0, fifoStart = 0, fifoSize = 0;
3577b5a892a1SMatthew G. Knepley   PetscInt       maxConeSize, maxSupportSize, coneSeries, supportSeries;
3578b5a892a1SMatthew G. Knepley   PetscInt       depth, maxSize;
3579b5a892a1SMatthew G. Knepley 
3580b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
35819566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
3582b5a892a1SMatthew G. Knepley   if (depth == 1) {
35839566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points));
3584b5a892a1SMatthew G. Knepley     PetscFunctionReturn(0);
3585b5a892a1SMatthew G. Knepley   }
35869566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, p, &ct));
3587b5a892a1SMatthew G. Knepley   if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN;
3588b5a892a1SMatthew G. Knepley   if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || ct == DM_POLYTOPE_TRI_PRISM_TENSOR || ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) {
35899566063dSJacob Faibussowitsch     PetscCall(DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points));
3590b5a892a1SMatthew G. Knepley     PetscFunctionReturn(0);
3591b5a892a1SMatthew G. Knepley   }
35929566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
3593b5a892a1SMatthew G. Knepley   coneSeries    = (maxConeSize    > 1) ? ((PetscPowInt(maxConeSize,    depth+1)-1)/(maxConeSize-1))    : depth+1;
3594b5a892a1SMatthew G. Knepley   supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth+1)-1)/(maxSupportSize-1)) : depth+1;
3595b5a892a1SMatthew G. Knepley   maxSize       = PetscMax(coneSeries, supportSeries);
35969566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, 3*maxSize, MPIU_INT, &fifo));
3597b5a892a1SMatthew G. Knepley   if (*points) {closure = *points;}
35989566063dSJacob Faibussowitsch   else         PetscCall(DMGetWorkArray(dm, 2*maxSize, MPIU_INT, &closure));
3599b5a892a1SMatthew G. Knepley   closure[closureSize++] = p;
3600b5a892a1SMatthew G. Knepley   closure[closureSize++] = ornt;
3601b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = p;
3602b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = ornt;
3603b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = ct;
3604b5a892a1SMatthew G. Knepley   /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */
3605b5a892a1SMatthew G. Knepley   while (fifoSize - fifoStart) {
3606b5a892a1SMatthew G. Knepley     const PetscInt       q    = fifo[fifoStart++];
3607b5a892a1SMatthew G. Knepley     const PetscInt       o    = fifo[fifoStart++];
3608b5a892a1SMatthew G. Knepley     const DMPolytopeType qt   = (DMPolytopeType) fifo[fifoStart++];
3609b5a892a1SMatthew G. Knepley     const PetscInt      *qarr = DMPolytopeTypeGetArrangment(qt, o);
3610b5a892a1SMatthew G. Knepley     const PetscInt      *tmp, *tmpO;
3611b5a892a1SMatthew G. Knepley     PetscInt             tmpSize, t;
3612b5a892a1SMatthew G. Knepley 
3613b5a892a1SMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) {
3614b5a892a1SMatthew G. Knepley       PetscInt nO = DMPolytopeTypeGetNumArrangments(qt)/2;
361563a3b9bcSJacob 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);
3616b5a892a1SMatthew G. Knepley     }
3617b5a892a1SMatthew G. Knepley     if (useCone) {
36189566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, q, &tmpSize));
36199566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, q, &tmp));
36209566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeOrientation(dm, q, &tmpO));
3621b5a892a1SMatthew G. Knepley     } else {
36229566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, q, &tmpSize));
36239566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupport(dm, q, &tmp));
3624b5a892a1SMatthew G. Knepley       tmpO = NULL;
3625b5a892a1SMatthew G. Knepley     }
3626b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3627b5a892a1SMatthew G. Knepley       const PetscInt ip = useCone && qarr ? qarr[t*2]   : t;
3628b5a892a1SMatthew G. Knepley       const PetscInt io = useCone && qarr ? qarr[t*2+1] : 0;
3629b5a892a1SMatthew G. Knepley       const PetscInt cp = tmp[ip];
36309566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, cp, &ct));
3631b5a892a1SMatthew G. Knepley       const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0;
3632b5a892a1SMatthew G. Knepley       PetscInt       c;
3633b5a892a1SMatthew G. Knepley 
3634b5a892a1SMatthew G. Knepley       /* Check for duplicate */
3635b5a892a1SMatthew G. Knepley       for (c = 0; c < closureSize; c += 2) {
3636b5a892a1SMatthew G. Knepley         if (closure[c] == cp) break;
3637b5a892a1SMatthew G. Knepley       }
3638b5a892a1SMatthew G. Knepley       if (c == closureSize) {
3639b5a892a1SMatthew G. Knepley         closure[closureSize++] = cp;
3640b5a892a1SMatthew G. Knepley         closure[closureSize++] = co;
3641b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = cp;
3642b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = co;
3643b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = ct;
3644b5a892a1SMatthew G. Knepley       }
3645b5a892a1SMatthew G. Knepley     }
3646b5a892a1SMatthew G. Knepley   }
36479566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 3*maxSize, MPIU_INT, &fifo));
3648b5a892a1SMatthew G. Knepley   if (numPoints) *numPoints = closureSize/2;
3649b5a892a1SMatthew G. Knepley   if (points)    *points    = closure;
3650b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
3651b5a892a1SMatthew G. Knepley }
3652b5a892a1SMatthew G. Knepley 
3653552f7358SJed Brown /*@C
3654eaf898f9SPatrick Sanan   DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG
3655552f7358SJed Brown 
3656552f7358SJed Brown   Not collective
3657552f7358SJed Brown 
3658552f7358SJed Brown   Input Parameters:
3659b5a892a1SMatthew G. Knepley + dm      - The DMPlex
3660b5a892a1SMatthew G. Knepley . p       - The mesh point
36616b867d5aSJose E. Roman - useCone - PETSC_TRUE for the closure, otherwise return the star
3662552f7358SJed Brown 
36636b867d5aSJose E. Roman   Input/Output Parameter:
36646b867d5aSJose E. Roman . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...];
36656b867d5aSJose E. Roman            if NULL on input, internal storage will be returned, otherwise the provided array is used
36666b867d5aSJose E. Roman 
36676b867d5aSJose E. Roman   Output Parameter:
36686b867d5aSJose E. Roman . numPoints - The number of points in the closure, so points[] is of size 2*numPoints
3669552f7358SJed Brown 
3670552f7358SJed Brown   Note:
36710298fd71SBarry Smith   If using internal storage (points is NULL on input), each call overwrites the last output.
3672552f7358SJed Brown 
36733813dfbdSMatthew G Knepley   Fortran Notes:
3674b5a892a1SMatthew G. Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must include petsc.h90 in your code.
36753813dfbdSMatthew G Knepley 
36763813dfbdSMatthew G Knepley   The numPoints argument is not present in the Fortran 90 binding since it is internal to the array.
36773813dfbdSMatthew G Knepley 
3678552f7358SJed Brown   Level: beginner
3679552f7358SJed Brown 
3680db781477SPatrick Sanan .seealso: `DMPlexRestoreTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()`
3681552f7358SJed Brown @*/
3682552f7358SJed Brown PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3683552f7358SJed Brown {
3684b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3685552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3686b5a892a1SMatthew G. Knepley   if (numPoints) PetscValidIntPointer(numPoints, 4);
3687b5a892a1SMatthew G. Knepley   if (points)    PetscValidPointer(points, 5);
36889566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points));
36899bf0dad6SMatthew G. Knepley   PetscFunctionReturn(0);
36909bf0dad6SMatthew G. Knepley }
36919bf0dad6SMatthew G. Knepley 
3692552f7358SJed Brown /*@C
3693eaf898f9SPatrick Sanan   DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG
3694552f7358SJed Brown 
3695552f7358SJed Brown   Not collective
3696552f7358SJed Brown 
3697552f7358SJed Brown   Input Parameters:
3698b5a892a1SMatthew G. Knepley + dm        - The DMPlex
3699b5a892a1SMatthew G. Knepley . p         - The mesh point
3700b5a892a1SMatthew G. Knepley . useCone   - PETSC_TRUE for the closure, otherwise return the star
3701b5a892a1SMatthew G. Knepley . numPoints - The number of points in the closure, so points[] is of size 2*numPoints
3702b5a892a1SMatthew G. Knepley - points    - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]
3703552f7358SJed Brown 
3704552f7358SJed Brown   Note:
37050298fd71SBarry Smith   If not using internal storage (points is not NULL on input), this call is unnecessary
3706552f7358SJed Brown 
37073813dfbdSMatthew G Knepley   Fortran Notes:
3708b5a892a1SMatthew G. Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must include petsc.h90 in your code.
37093813dfbdSMatthew G Knepley 
37103813dfbdSMatthew G Knepley   The numPoints argument is not present in the Fortran 90 binding since it is internal to the array.
37113813dfbdSMatthew G Knepley 
3712552f7358SJed Brown   Level: beginner
3713552f7358SJed Brown 
3714db781477SPatrick Sanan .seealso: `DMPlexGetTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()`
3715552f7358SJed Brown @*/
3716552f7358SJed Brown PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3717552f7358SJed Brown {
3718b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3719552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
37204ff43b2cSJed Brown   if (numPoints) *numPoints = 0;
37219566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, points));
3722552f7358SJed Brown   PetscFunctionReturn(0);
3723552f7358SJed Brown }
3724552f7358SJed Brown 
3725552f7358SJed Brown /*@
3726eaf898f9SPatrick Sanan   DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG
3727552f7358SJed Brown 
3728552f7358SJed Brown   Not collective
3729552f7358SJed Brown 
3730552f7358SJed Brown   Input Parameter:
3731552f7358SJed Brown . mesh - The DMPlex
3732552f7358SJed Brown 
3733552f7358SJed Brown   Output Parameters:
3734552f7358SJed Brown + maxConeSize - The maximum number of in-edges
3735552f7358SJed Brown - maxSupportSize - The maximum number of out-edges
3736552f7358SJed Brown 
3737552f7358SJed Brown   Level: beginner
3738552f7358SJed Brown 
3739db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`
3740552f7358SJed Brown @*/
3741552f7358SJed Brown PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize)
3742552f7358SJed Brown {
3743552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
3744552f7358SJed Brown 
3745552f7358SJed Brown   PetscFunctionBegin;
3746552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
37471baa6e33SBarry Smith   if (maxConeSize) PetscCall(PetscSectionGetMaxDof(mesh->coneSection, maxConeSize));
37481baa6e33SBarry Smith   if (maxSupportSize) PetscCall(PetscSectionGetMaxDof(mesh->supportSection, maxSupportSize));
3749552f7358SJed Brown   PetscFunctionReturn(0);
3750552f7358SJed Brown }
3751552f7358SJed Brown 
3752552f7358SJed Brown PetscErrorCode DMSetUp_Plex(DM dm)
3753552f7358SJed Brown {
3754552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
37556302a7fbSVaclav Hapla   PetscInt       size, maxSupportSize;
3756552f7358SJed Brown 
3757552f7358SJed Brown   PetscFunctionBegin;
3758552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
37599566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(mesh->coneSection));
37609566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(mesh->coneSection, &size));
37619566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, &mesh->cones));
37629566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(size, &mesh->coneOrientations));
37639566063dSJacob Faibussowitsch   PetscCall(PetscLogObjectMemory((PetscObject) dm, size*2*sizeof(PetscInt)));
37646302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize));
37656302a7fbSVaclav Hapla   if (maxSupportSize) {
37669566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(mesh->supportSection));
37679566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &size));
37689566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(size, &mesh->supports));
37699566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectMemory((PetscObject) dm, size*sizeof(PetscInt)));
3770552f7358SJed Brown   }
3771552f7358SJed Brown   PetscFunctionReturn(0);
3772552f7358SJed Brown }
3773552f7358SJed Brown 
3774276c5506SMatthew G. Knepley PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm)
3775552f7358SJed Brown {
3776552f7358SJed Brown   PetscFunctionBegin;
37779566063dSJacob Faibussowitsch   if (subdm) PetscCall(DMClone(dm, subdm));
37789566063dSJacob Faibussowitsch   PetscCall(DMCreateSectionSubDM(dm, numFields, fields, is, subdm));
3779c2939958SSatish Balay   if (subdm) {(*subdm)->useNatural = dm->useNatural;}
3780736995cdSBlaise Bourdin   if (dm->useNatural && dm->sfMigration) {
3781f94b4a02SBlaise Bourdin     PetscSF        sfMigrationInv,sfNatural;
3782f94b4a02SBlaise Bourdin     PetscSection   section, sectionSeq;
3783f94b4a02SBlaise Bourdin 
37843dcd263cSBlaise Bourdin     (*subdm)->sfMigration = dm->sfMigration;
37859566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject) dm->sfMigration));
37869566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection((*subdm), &section));
37879566063dSJacob Faibussowitsch     PetscCall(PetscSFCreateInverseSF((*subdm)->sfMigration, &sfMigrationInv));
37889566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject) (*subdm)), &sectionSeq));
37899566063dSJacob Faibussowitsch     PetscCall(PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq));
3790f94b4a02SBlaise Bourdin 
37919566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateGlobalToNaturalSF(*subdm, sectionSeq, (*subdm)->sfMigration, &sfNatural));
3792c40e9495SBlaise Bourdin     (*subdm)->sfNatural = sfNatural;
37939566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&sectionSeq));
37949566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfMigrationInv));
3795f94b4a02SBlaise Bourdin   }
3796552f7358SJed Brown   PetscFunctionReturn(0);
3797552f7358SJed Brown }
3798552f7358SJed Brown 
37992adcc780SMatthew G. Knepley PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm)
38002adcc780SMatthew G. Knepley {
38013dcd263cSBlaise Bourdin   PetscInt       i = 0;
38022adcc780SMatthew G. Knepley 
38032adcc780SMatthew G. Knepley   PetscFunctionBegin;
38049566063dSJacob Faibussowitsch   PetscCall(DMClone(dms[0], superdm));
38059566063dSJacob Faibussowitsch   PetscCall(DMCreateSectionSuperDM(dms, len, is, superdm));
3806c40e9495SBlaise Bourdin   (*superdm)->useNatural = PETSC_FALSE;
38073dcd263cSBlaise Bourdin   for (i = 0; i < len; i++) {
38083dcd263cSBlaise Bourdin     if (dms[i]->useNatural && dms[i]->sfMigration) {
38093dcd263cSBlaise Bourdin       PetscSF        sfMigrationInv,sfNatural;
38103dcd263cSBlaise Bourdin       PetscSection   section, sectionSeq;
38113dcd263cSBlaise Bourdin 
38123dcd263cSBlaise Bourdin       (*superdm)->sfMigration = dms[i]->sfMigration;
38139566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject) dms[i]->sfMigration));
3814c40e9495SBlaise Bourdin       (*superdm)->useNatural = PETSC_TRUE;
38159566063dSJacob Faibussowitsch       PetscCall(DMGetLocalSection((*superdm), &section));
38169566063dSJacob Faibussowitsch       PetscCall(PetscSFCreateInverseSF((*superdm)->sfMigration, &sfMigrationInv));
38179566063dSJacob Faibussowitsch       PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject) (*superdm)), &sectionSeq));
38189566063dSJacob Faibussowitsch       PetscCall(PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq));
38193dcd263cSBlaise Bourdin 
38209566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateGlobalToNaturalSF(*superdm, sectionSeq, (*superdm)->sfMigration, &sfNatural));
3821c40e9495SBlaise Bourdin       (*superdm)->sfNatural = sfNatural;
38229566063dSJacob Faibussowitsch       PetscCall(PetscSectionDestroy(&sectionSeq));
38239566063dSJacob Faibussowitsch       PetscCall(PetscSFDestroy(&sfMigrationInv));
38243dcd263cSBlaise Bourdin       break;
38253dcd263cSBlaise Bourdin     }
38263dcd263cSBlaise Bourdin   }
38272adcc780SMatthew G. Knepley   PetscFunctionReturn(0);
38282adcc780SMatthew G. Knepley }
38292adcc780SMatthew G. Knepley 
3830552f7358SJed Brown /*@
3831eaf898f9SPatrick Sanan   DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information
3832552f7358SJed Brown 
3833552f7358SJed Brown   Not collective
3834552f7358SJed Brown 
3835552f7358SJed Brown   Input Parameter:
3836552f7358SJed Brown . mesh - The DMPlex
3837552f7358SJed Brown 
3838552f7358SJed Brown   Output Parameter:
3839552f7358SJed Brown 
3840552f7358SJed Brown   Note:
3841552f7358SJed Brown   This should be called after all calls to DMPlexSetCone()
3842552f7358SJed Brown 
3843552f7358SJed Brown   Level: beginner
3844552f7358SJed Brown 
3845db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMPlexSetCone()`
3846552f7358SJed Brown @*/
3847552f7358SJed Brown PetscErrorCode DMPlexSymmetrize(DM dm)
3848552f7358SJed Brown {
3849552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3850552f7358SJed Brown   PetscInt      *offsets;
3851552f7358SJed Brown   PetscInt       supportSize;
3852552f7358SJed Brown   PetscInt       pStart, pEnd, p;
3853552f7358SJed Brown 
3854552f7358SJed Brown   PetscFunctionBegin;
3855552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
385628b400f6SJacob Faibussowitsch   PetscCheck(!mesh->supports,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex");
38579566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_Symmetrize,dm,0,0,0));
3858552f7358SJed Brown   /* Calculate support sizes */
38599566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
3860552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
3861552f7358SJed Brown     PetscInt dof, off, c;
3862552f7358SJed Brown 
38639566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
38649566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
3865552f7358SJed Brown     for (c = off; c < off+dof; ++c) {
38669566063dSJacob Faibussowitsch       PetscCall(PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1));
3867552f7358SJed Brown     }
3868552f7358SJed Brown   }
38699566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(mesh->supportSection));
3870552f7358SJed Brown   /* Calculate supports */
38719566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &supportSize));
38729566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(supportSize, &mesh->supports));
38739566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(pEnd - pStart, &offsets));
3874552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
3875552f7358SJed Brown     PetscInt dof, off, c;
3876552f7358SJed Brown 
38779566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
38789566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
3879552f7358SJed Brown     for (c = off; c < off+dof; ++c) {
3880552f7358SJed Brown       const PetscInt q = mesh->cones[c];
3881552f7358SJed Brown       PetscInt       offS;
3882552f7358SJed Brown 
38839566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->supportSection, q, &offS));
38840d644c17SKarl Rupp 
3885552f7358SJed Brown       mesh->supports[offS+offsets[q]] = p;
3886552f7358SJed Brown       ++offsets[q];
3887552f7358SJed Brown     }
3888552f7358SJed Brown   }
38899566063dSJacob Faibussowitsch   PetscCall(PetscFree(offsets));
38909566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_Symmetrize,dm,0,0,0));
3891552f7358SJed Brown   PetscFunctionReturn(0);
3892552f7358SJed Brown }
3893552f7358SJed Brown 
3894277ea44aSLisandro Dalcin static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd)
3895277ea44aSLisandro Dalcin {
3896277ea44aSLisandro Dalcin   IS             stratumIS;
3897277ea44aSLisandro Dalcin 
3898277ea44aSLisandro Dalcin   PetscFunctionBegin;
3899277ea44aSLisandro Dalcin   if (pStart >= pEnd) PetscFunctionReturn(0);
390076bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
3901277ea44aSLisandro Dalcin     PetscInt  qStart, qEnd, numLevels, level;
3902277ea44aSLisandro Dalcin     PetscBool overlap = PETSC_FALSE;
39039566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &numLevels));
3904277ea44aSLisandro Dalcin     for (level = 0; level < numLevels; level++) {
39059566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
3906277ea44aSLisandro Dalcin       if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) {overlap = PETSC_TRUE; break;}
3907277ea44aSLisandro Dalcin     }
390863a3b9bcSJacob 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);
3909277ea44aSLisandro Dalcin   }
39109566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd-pStart, pStart, 1, &stratumIS));
39119566063dSJacob Faibussowitsch   PetscCall(DMLabelSetStratumIS(label, depth, stratumIS));
39129566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&stratumIS));
3913277ea44aSLisandro Dalcin   PetscFunctionReturn(0);
3914277ea44aSLisandro Dalcin }
3915277ea44aSLisandro Dalcin 
3916552f7358SJed Brown /*@
3917a8d69d7bSBarry Smith   DMPlexStratify - The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and
39186dd80730SBarry Smith   can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the
3919552f7358SJed Brown   same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in
3920552f7358SJed Brown   the DAG.
3921552f7358SJed Brown 
3922bf4602e4SToby Isaac   Collective on dm
3923552f7358SJed Brown 
3924552f7358SJed Brown   Input Parameter:
3925552f7358SJed Brown . mesh - The DMPlex
3926552f7358SJed Brown 
3927552f7358SJed Brown   Output Parameter:
3928552f7358SJed Brown 
3929552f7358SJed Brown   Notes:
3930b1bb481bSMatthew Knepley   Concretely, DMPlexStratify() creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex
3931b1bb481bSMatthew 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
3932b1bb481bSMatthew Knepley   until cells have depth equal to the dimension of the mesh. The depth label can be accessed through DMPlexGetDepthLabel() or DMPlexGetDepthStratum(), or
3933c58f1c22SToby Isaac   manually via DMGetLabel().  The height is defined implicitly by height = maxDimension - depth, and can be accessed
3934150b719bSJed Brown   via DMPlexGetHeightStratum().  For example, cells have height 0 and faces have height 1.
3935552f7358SJed Brown 
3936b1bb481bSMatthew Knepley   The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results
3937b1bb481bSMatthew Knepley   if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that
3938b1bb481bSMatthew 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
3939b1bb481bSMatthew Knepley   to interpolate only that one (e0), so that
3940b1bb481bSMatthew Knepley $  cone(c0) = {e0, v2}
3941b1bb481bSMatthew Knepley $  cone(e0) = {v0, v1}
3942b1bb481bSMatthew Knepley   If DMPlexStratify() is run on this mesh, it will give depths
3943b1bb481bSMatthew Knepley $  depth 0 = {v0, v1, v2}
3944b1bb481bSMatthew Knepley $  depth 1 = {e0, c0}
3945b1bb481bSMatthew Knepley   where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2.
3946b1bb481bSMatthew Knepley 
3947150b719bSJed Brown   DMPlexStratify() should be called after all calls to DMPlexSymmetrize()
3948552f7358SJed Brown 
3949552f7358SJed Brown   Level: beginner
3950552f7358SJed Brown 
3951db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexComputeCellTypes()`
3952552f7358SJed Brown @*/
3953552f7358SJed Brown PetscErrorCode DMPlexStratify(DM dm)
3954552f7358SJed Brown {
3955df0420ecSMatthew G. Knepley   DM_Plex       *mesh = (DM_Plex*) dm->data;
3956aa50250dSMatthew G. Knepley   DMLabel        label;
3957552f7358SJed Brown   PetscInt       pStart, pEnd, p;
3958552f7358SJed Brown   PetscInt       numRoots = 0, numLeaves = 0;
3959552f7358SJed Brown 
3960552f7358SJed Brown   PetscFunctionBegin;
3961552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
39629566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0));
3963277ea44aSLisandro Dalcin 
3964277ea44aSLisandro Dalcin   /* Create depth label */
39659566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
39669566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "depth"));
39679566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
3968277ea44aSLisandro Dalcin 
3969277ea44aSLisandro Dalcin   {
3970552f7358SJed Brown     /* Initialize roots and count leaves */
3971277ea44aSLisandro Dalcin     PetscInt sMin = PETSC_MAX_INT;
3972277ea44aSLisandro Dalcin     PetscInt sMax = PETSC_MIN_INT;
3973552f7358SJed Brown     PetscInt coneSize, supportSize;
3974552f7358SJed Brown 
3975277ea44aSLisandro Dalcin     for (p = pStart; p < pEnd; ++p) {
39769566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
39779566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
3978552f7358SJed Brown       if (!coneSize && supportSize) {
3979277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
3980277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
3981552f7358SJed Brown         ++numRoots;
3982552f7358SJed Brown       } else if (!supportSize && coneSize) {
3983552f7358SJed Brown         ++numLeaves;
3984552f7358SJed Brown       } else if (!supportSize && !coneSize) {
3985552f7358SJed Brown         /* Isolated points */
3986277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
3987277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
3988552f7358SJed Brown       }
3989552f7358SJed Brown     }
39909566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax+1));
3991277ea44aSLisandro Dalcin   }
3992277ea44aSLisandro Dalcin 
3993552f7358SJed Brown   if (numRoots + numLeaves == (pEnd - pStart)) {
3994277ea44aSLisandro Dalcin     PetscInt sMin = PETSC_MAX_INT;
3995277ea44aSLisandro Dalcin     PetscInt sMax = PETSC_MIN_INT;
3996552f7358SJed Brown     PetscInt coneSize, supportSize;
3997552f7358SJed Brown 
3998277ea44aSLisandro Dalcin     for (p = pStart; p < pEnd; ++p) {
39999566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
40009566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
4001552f7358SJed Brown       if (!supportSize && coneSize) {
4002277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
4003277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
4004552f7358SJed Brown       }
4005552f7358SJed Brown     }
40069566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax+1));
4007552f7358SJed Brown   } else {
4008277ea44aSLisandro Dalcin     PetscInt level = 0;
4009277ea44aSLisandro Dalcin     PetscInt qStart, qEnd, q;
4010552f7358SJed Brown 
40119566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
4012277ea44aSLisandro Dalcin     while (qEnd > qStart) {
4013277ea44aSLisandro Dalcin       PetscInt sMin = PETSC_MAX_INT;
4014277ea44aSLisandro Dalcin       PetscInt sMax = PETSC_MIN_INT;
401574ef644bSMatthew G. Knepley 
4016277ea44aSLisandro Dalcin       for (q = qStart; q < qEnd; ++q) {
401774ef644bSMatthew G. Knepley         const PetscInt *support;
401874ef644bSMatthew G. Knepley         PetscInt        supportSize, s;
401974ef644bSMatthew G. Knepley 
40209566063dSJacob Faibussowitsch         PetscCall(DMPlexGetSupportSize(dm, q, &supportSize));
40219566063dSJacob Faibussowitsch         PetscCall(DMPlexGetSupport(dm, q, &support));
402274ef644bSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
4023277ea44aSLisandro Dalcin           sMin = PetscMin(support[s], sMin);
4024277ea44aSLisandro Dalcin           sMax = PetscMax(support[s], sMax);
4025552f7358SJed Brown         }
4026552f7358SJed Brown       }
40279566063dSJacob Faibussowitsch       PetscCall(DMLabelGetNumValues(label, &level));
40289566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateDepthStratum(dm, label, level, sMin, sMax+1));
40299566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
403074ef644bSMatthew G. Knepley     }
403174ef644bSMatthew G. Knepley   }
4032bf4602e4SToby Isaac   { /* just in case there is an empty process */
4033bf4602e4SToby Isaac     PetscInt numValues, maxValues = 0, v;
4034bf4602e4SToby Isaac 
40359566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &numValues));
40369566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(&numValues,&maxValues,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm)));
4037bf4602e4SToby Isaac     for (v = numValues; v < maxValues; v++) {
40389566063dSJacob Faibussowitsch       PetscCall(DMLabelAddStratum(label, v));
4039bf4602e4SToby Isaac     }
4040bf4602e4SToby Isaac   }
40419566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateGet((PetscObject) label, &mesh->depthState));
40429566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0));
4043552f7358SJed Brown   PetscFunctionReturn(0);
4044552f7358SJed Brown }
4045552f7358SJed Brown 
4046412e9a14SMatthew G. Knepley PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt)
4047ba2698f1SMatthew G. Knepley {
4048412e9a14SMatthew G. Knepley   DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
4049412e9a14SMatthew G. Knepley   PetscInt       dim, depth, pheight, coneSize;
4050ba2698f1SMatthew G. Knepley 
4051412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
40529566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
40539566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
40549566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
4055ba2698f1SMatthew G. Knepley   pheight = depth - pdepth;
4056ba2698f1SMatthew G. Knepley   if (depth <= 1) {
4057ba2698f1SMatthew G. Knepley     switch (pdepth) {
4058ba2698f1SMatthew G. Knepley       case 0: ct = DM_POLYTOPE_POINT;break;
4059ba2698f1SMatthew G. Knepley       case 1:
4060ba2698f1SMatthew G. Knepley         switch (coneSize) {
4061ba2698f1SMatthew G. Knepley           case 2: ct = DM_POLYTOPE_SEGMENT;break;
4062ba2698f1SMatthew G. Knepley           case 3: ct = DM_POLYTOPE_TRIANGLE;break;
4063ba2698f1SMatthew G. Knepley           case 4:
4064ba2698f1SMatthew G. Knepley           switch (dim) {
4065ba2698f1SMatthew G. Knepley             case 2: ct = DM_POLYTOPE_QUADRILATERAL;break;
4066ba2698f1SMatthew G. Knepley             case 3: ct = DM_POLYTOPE_TETRAHEDRON;break;
4067ba2698f1SMatthew G. Knepley             default: break;
4068ba2698f1SMatthew G. Knepley           }
4069ba2698f1SMatthew G. Knepley           break;
4070da9060c4SMatthew G. Knepley         case 5: ct = DM_POLYTOPE_PYRAMID;break;
4071ba2698f1SMatthew G. Knepley         case 6: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break;
4072ba2698f1SMatthew G. Knepley         case 8: ct = DM_POLYTOPE_HEXAHEDRON;break;
4073ba2698f1SMatthew G. Knepley         default: break;
4074ba2698f1SMatthew G. Knepley       }
4075ba2698f1SMatthew G. Knepley     }
4076ba2698f1SMatthew G. Knepley   } else {
4077ba2698f1SMatthew G. Knepley     if (pdepth == 0) {
4078ba2698f1SMatthew G. Knepley       ct = DM_POLYTOPE_POINT;
4079ba2698f1SMatthew G. Knepley     } else if (pheight == 0) {
4080ba2698f1SMatthew G. Knepley       switch (dim) {
4081ba2698f1SMatthew G. Knepley         case 1:
4082ba2698f1SMatthew G. Knepley           switch (coneSize) {
4083ba2698f1SMatthew G. Knepley             case 2: ct = DM_POLYTOPE_SEGMENT;break;
4084ba2698f1SMatthew G. Knepley             default: break;
4085ba2698f1SMatthew G. Knepley           }
4086ba2698f1SMatthew G. Knepley           break;
4087ba2698f1SMatthew G. Knepley         case 2:
4088ba2698f1SMatthew G. Knepley           switch (coneSize) {
4089ba2698f1SMatthew G. Knepley             case 3: ct = DM_POLYTOPE_TRIANGLE;break;
4090ba2698f1SMatthew G. Knepley             case 4: ct = DM_POLYTOPE_QUADRILATERAL;break;
4091ba2698f1SMatthew G. Knepley             default: break;
4092ba2698f1SMatthew G. Knepley           }
4093ba2698f1SMatthew G. Knepley           break;
4094ba2698f1SMatthew G. Knepley         case 3:
4095ba2698f1SMatthew G. Knepley           switch (coneSize) {
4096ba2698f1SMatthew G. Knepley             case 4: ct = DM_POLYTOPE_TETRAHEDRON;break;
4097da9060c4SMatthew G. Knepley             case 5:
4098da9060c4SMatthew G. Knepley             {
4099da9060c4SMatthew G. Knepley               const PetscInt *cone;
4100da9060c4SMatthew G. Knepley               PetscInt        faceConeSize;
4101da9060c4SMatthew G. Knepley 
41029566063dSJacob Faibussowitsch               PetscCall(DMPlexGetCone(dm, p, &cone));
41039566063dSJacob Faibussowitsch               PetscCall(DMPlexGetConeSize(dm, cone[0], &faceConeSize));
4104da9060c4SMatthew G. Knepley               switch (faceConeSize) {
4105da9060c4SMatthew G. Knepley                 case 3: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break;
4106da9060c4SMatthew G. Knepley                 case 4: ct = DM_POLYTOPE_PYRAMID;break;
4107da9060c4SMatthew G. Knepley               }
4108da9060c4SMatthew G. Knepley             }
4109da9060c4SMatthew G. Knepley             break;
4110ba2698f1SMatthew G. Knepley             case 6: ct = DM_POLYTOPE_HEXAHEDRON;break;
4111ba2698f1SMatthew G. Knepley             default: break;
4112ba2698f1SMatthew G. Knepley           }
4113ba2698f1SMatthew G. Knepley           break;
4114ba2698f1SMatthew G. Knepley         default: break;
4115ba2698f1SMatthew G. Knepley       }
4116ba2698f1SMatthew G. Knepley     } else if (pheight > 0) {
4117ba2698f1SMatthew G. Knepley       switch (coneSize) {
4118ba2698f1SMatthew G. Knepley         case 2: ct = DM_POLYTOPE_SEGMENT;break;
4119ba2698f1SMatthew G. Knepley         case 3: ct = DM_POLYTOPE_TRIANGLE;break;
4120ba2698f1SMatthew G. Knepley         case 4: ct = DM_POLYTOPE_QUADRILATERAL;break;
4121ba2698f1SMatthew G. Knepley         default: break;
4122ba2698f1SMatthew G. Knepley       }
4123ba2698f1SMatthew G. Knepley     }
4124ba2698f1SMatthew G. Knepley   }
4125412e9a14SMatthew G. Knepley   *pt = ct;
4126412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
4127ba2698f1SMatthew G. Knepley }
4128412e9a14SMatthew G. Knepley 
4129412e9a14SMatthew G. Knepley /*@
4130412e9a14SMatthew G. Knepley   DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size.
4131412e9a14SMatthew G. Knepley 
4132412e9a14SMatthew G. Knepley   Collective on dm
4133412e9a14SMatthew G. Knepley 
4134412e9a14SMatthew G. Knepley   Input Parameter:
4135412e9a14SMatthew G. Knepley . mesh - The DMPlex
4136412e9a14SMatthew G. Knepley 
4137412e9a14SMatthew G. Knepley   DMPlexComputeCellTypes() should be called after all calls to DMPlexSymmetrize() and DMPlexStratify()
4138412e9a14SMatthew G. Knepley 
4139412e9a14SMatthew G. Knepley   Level: developer
4140412e9a14SMatthew G. Knepley 
4141412e9a14SMatthew G. Knepley   Note: This function is normally called automatically by Plex when a cell type is requested. It creates an
4142412e9a14SMatthew G. Knepley   internal DMLabel named "celltype" which can be directly accessed using DMGetLabel(). A user may disable
4143412e9a14SMatthew G. Knepley   automatic creation by creating the label manually, using DMCreateLabel(dm, "celltype").
4144412e9a14SMatthew G. Knepley 
4145db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexStratify()`, `DMGetLabel()`, `DMCreateLabel()`
4146412e9a14SMatthew G. Knepley @*/
4147412e9a14SMatthew G. Knepley PetscErrorCode DMPlexComputeCellTypes(DM dm)
4148412e9a14SMatthew G. Knepley {
4149412e9a14SMatthew G. Knepley   DM_Plex       *mesh;
4150412e9a14SMatthew G. Knepley   DMLabel        ctLabel;
4151412e9a14SMatthew G. Knepley   PetscInt       pStart, pEnd, p;
4152412e9a14SMatthew G. Knepley 
4153412e9a14SMatthew G. Knepley   PetscFunctionBegin;
4154412e9a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4155412e9a14SMatthew G. Knepley   mesh = (DM_Plex *) dm->data;
41569566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "celltype"));
41579566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel));
41589566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
4159412e9a14SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
4160327c2912SStefano Zampini     DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
4161412e9a14SMatthew G. Knepley     PetscInt       pdepth;
4162412e9a14SMatthew G. Knepley 
41639566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPointDepth(dm, p, &pdepth));
41649566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellType_Internal(dm, p, pdepth, &ct));
416563a3b9bcSJacob Faibussowitsch     PetscCheck(ct != DM_POLYTOPE_UNKNOWN,PETSC_COMM_SELF, PETSC_ERR_SUP, "Point %" PetscInt_FMT " is screwed up", p);
41669566063dSJacob Faibussowitsch     PetscCall(DMLabelSetValue(ctLabel, p, ct));
4167412e9a14SMatthew G. Knepley   }
41689566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateGet((PetscObject) ctLabel, &mesh->celltypeState));
41699566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject) ctLabel, NULL, "-dm_plex_celltypes_view"));
4170ba2698f1SMatthew G. Knepley   PetscFunctionReturn(0);
4171ba2698f1SMatthew G. Knepley }
4172ba2698f1SMatthew G. Knepley 
4173552f7358SJed Brown /*@C
4174552f7358SJed Brown   DMPlexGetJoin - Get an array for the join of the set of points
4175552f7358SJed Brown 
4176552f7358SJed Brown   Not Collective
4177552f7358SJed Brown 
4178552f7358SJed Brown   Input Parameters:
4179552f7358SJed Brown + dm - The DMPlex object
4180552f7358SJed Brown . numPoints - The number of input points for the join
4181552f7358SJed Brown - points - The input points
4182552f7358SJed Brown 
4183552f7358SJed Brown   Output Parameters:
4184552f7358SJed Brown + numCoveredPoints - The number of points in the join
4185552f7358SJed Brown - coveredPoints - The points in the join
4186552f7358SJed Brown 
4187552f7358SJed Brown   Level: intermediate
4188552f7358SJed Brown 
4189552f7358SJed Brown   Note: Currently, this is restricted to a single level join
4190552f7358SJed Brown 
41913813dfbdSMatthew G Knepley   Fortran Notes:
41923813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
41933813dfbdSMatthew G Knepley   include petsc.h90 in your code.
41943813dfbdSMatthew G Knepley 
41953813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
41963813dfbdSMatthew G Knepley 
4197db781477SPatrick Sanan .seealso: `DMPlexRestoreJoin()`, `DMPlexGetMeet()`
4198552f7358SJed Brown @*/
4199552f7358SJed Brown PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4200552f7358SJed Brown {
4201552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
4202552f7358SJed Brown   PetscInt      *join[2];
4203552f7358SJed Brown   PetscInt       joinSize, i = 0;
4204552f7358SJed Brown   PetscInt       dof, off, p, c, m;
42056302a7fbSVaclav Hapla   PetscInt       maxSupportSize;
4206552f7358SJed Brown 
4207552f7358SJed Brown   PetscFunctionBegin;
4208552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
420948bb261cSVaclav Hapla   PetscValidIntPointer(points, 3);
421048bb261cSVaclav Hapla   PetscValidIntPointer(numCoveredPoints, 4);
421148bb261cSVaclav Hapla   PetscValidPointer(coveredPoints, 5);
42126302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize));
42136302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[0]));
42146302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[1]));
4215552f7358SJed Brown   /* Copy in support of first point */
42169566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, points[0], &dof));
42179566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, points[0], &off));
4218552f7358SJed Brown   for (joinSize = 0; joinSize < dof; ++joinSize) {
4219552f7358SJed Brown     join[i][joinSize] = mesh->supports[off+joinSize];
4220552f7358SJed Brown   }
4221552f7358SJed Brown   /* Check each successive support */
4222552f7358SJed Brown   for (p = 1; p < numPoints; ++p) {
4223552f7358SJed Brown     PetscInt newJoinSize = 0;
4224552f7358SJed Brown 
42259566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->supportSection, points[p], &dof));
42269566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->supportSection, points[p], &off));
4227552f7358SJed Brown     for (c = 0; c < dof; ++c) {
4228552f7358SJed Brown       const PetscInt point = mesh->supports[off+c];
4229552f7358SJed Brown 
4230552f7358SJed Brown       for (m = 0; m < joinSize; ++m) {
4231552f7358SJed Brown         if (point == join[i][m]) {
4232552f7358SJed Brown           join[1-i][newJoinSize++] = point;
4233552f7358SJed Brown           break;
4234552f7358SJed Brown         }
4235552f7358SJed Brown       }
4236552f7358SJed Brown     }
4237552f7358SJed Brown     joinSize = newJoinSize;
4238552f7358SJed Brown     i        = 1-i;
4239552f7358SJed Brown   }
4240552f7358SJed Brown   *numCoveredPoints = joinSize;
4241552f7358SJed Brown   *coveredPoints    = join[i];
42426302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, maxSupportSize, MPIU_INT, &join[1-i]));
4243552f7358SJed Brown   PetscFunctionReturn(0);
4244552f7358SJed Brown }
4245552f7358SJed Brown 
4246552f7358SJed Brown /*@C
4247552f7358SJed Brown   DMPlexRestoreJoin - Restore an array for the join of the set of points
4248552f7358SJed Brown 
4249552f7358SJed Brown   Not Collective
4250552f7358SJed Brown 
4251552f7358SJed Brown   Input Parameters:
4252552f7358SJed Brown + dm - The DMPlex object
4253552f7358SJed Brown . numPoints - The number of input points for the join
4254552f7358SJed Brown - points - The input points
4255552f7358SJed Brown 
4256552f7358SJed Brown   Output Parameters:
4257552f7358SJed Brown + numCoveredPoints - The number of points in the join
4258552f7358SJed Brown - coveredPoints - The points in the join
4259552f7358SJed Brown 
42603813dfbdSMatthew G Knepley   Fortran Notes:
42613813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
42623813dfbdSMatthew G Knepley   include petsc.h90 in your code.
42633813dfbdSMatthew G Knepley 
42643813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
42653813dfbdSMatthew G Knepley 
4266552f7358SJed Brown   Level: intermediate
4267552f7358SJed Brown 
4268db781477SPatrick Sanan .seealso: `DMPlexGetJoin()`, `DMPlexGetFullJoin()`, `DMPlexGetMeet()`
4269552f7358SJed Brown @*/
4270552f7358SJed Brown PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4271552f7358SJed Brown {
4272552f7358SJed Brown   PetscFunctionBegin;
4273552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4274d7902bd2SMatthew G. Knepley   if (points) PetscValidIntPointer(points,3);
4275d7902bd2SMatthew G. Knepley   if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4);
4276d7902bd2SMatthew G. Knepley   PetscValidPointer(coveredPoints, 5);
42779566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints));
4278d7902bd2SMatthew G. Knepley   if (numCoveredPoints) *numCoveredPoints = 0;
4279552f7358SJed Brown   PetscFunctionReturn(0);
4280552f7358SJed Brown }
4281552f7358SJed Brown 
4282552f7358SJed Brown /*@C
4283552f7358SJed Brown   DMPlexGetFullJoin - Get an array for the join of the set of points
4284552f7358SJed Brown 
4285552f7358SJed Brown   Not Collective
4286552f7358SJed Brown 
4287552f7358SJed Brown   Input Parameters:
4288552f7358SJed Brown + dm - The DMPlex object
4289552f7358SJed Brown . numPoints - The number of input points for the join
4290552f7358SJed Brown - points - The input points
4291552f7358SJed Brown 
4292552f7358SJed Brown   Output Parameters:
4293552f7358SJed Brown + numCoveredPoints - The number of points in the join
4294552f7358SJed Brown - coveredPoints - The points in the join
4295552f7358SJed Brown 
42963813dfbdSMatthew G Knepley   Fortran Notes:
42973813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
42983813dfbdSMatthew G Knepley   include petsc.h90 in your code.
42993813dfbdSMatthew G Knepley 
43003813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
43013813dfbdSMatthew G Knepley 
4302552f7358SJed Brown   Level: intermediate
4303552f7358SJed Brown 
4304db781477SPatrick Sanan .seealso: `DMPlexGetJoin()`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()`
4305552f7358SJed Brown @*/
4306552f7358SJed Brown PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4307552f7358SJed Brown {
4308552f7358SJed Brown   PetscInt      *offsets, **closures;
4309552f7358SJed Brown   PetscInt      *join[2];
4310552f7358SJed Brown   PetscInt       depth = 0, maxSize, joinSize = 0, i = 0;
431124c766afSToby Isaac   PetscInt       p, d, c, m, ms;
4312552f7358SJed Brown 
4313552f7358SJed Brown   PetscFunctionBegin;
4314552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
431548bb261cSVaclav Hapla   PetscValidIntPointer(points, 3);
431648bb261cSVaclav Hapla   PetscValidIntPointer(numCoveredPoints, 4);
431748bb261cSVaclav Hapla   PetscValidPointer(coveredPoints, 5);
4318552f7358SJed Brown 
43199566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
43209566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(numPoints, &closures));
43219566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets));
43226302a7fbSVaclav Hapla   PetscCall(DMPlexGetMaxSizes(dm, NULL, &ms));
432324c766afSToby Isaac   maxSize = (ms > 1) ? ((PetscPowInt(ms,depth+1)-1)/(ms-1)) : depth + 1;
43249566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0]));
43259566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1]));
4326552f7358SJed Brown 
4327552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
4328552f7358SJed Brown     PetscInt closureSize;
4329552f7358SJed Brown 
43309566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]));
43310d644c17SKarl Rupp 
4332552f7358SJed Brown     offsets[p*(depth+2)+0] = 0;
4333552f7358SJed Brown     for (d = 0; d < depth+1; ++d) {
4334552f7358SJed Brown       PetscInt pStart, pEnd, i;
4335552f7358SJed Brown 
43369566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
4337552f7358SJed Brown       for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) {
4338552f7358SJed Brown         if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) {
4339552f7358SJed Brown           offsets[p*(depth+2)+d+1] = i;
4340552f7358SJed Brown           break;
4341552f7358SJed Brown         }
4342552f7358SJed Brown       }
4343552f7358SJed Brown       if (i == closureSize) offsets[p*(depth+2)+d+1] = i;
4344552f7358SJed Brown     }
434563a3b9bcSJacob 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);
4346552f7358SJed Brown   }
4347552f7358SJed Brown   for (d = 0; d < depth+1; ++d) {
4348552f7358SJed Brown     PetscInt dof;
4349552f7358SJed Brown 
4350552f7358SJed Brown     /* Copy in support of first point */
4351552f7358SJed Brown     dof = offsets[d+1] - offsets[d];
4352552f7358SJed Brown     for (joinSize = 0; joinSize < dof; ++joinSize) {
4353552f7358SJed Brown       join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2];
4354552f7358SJed Brown     }
4355552f7358SJed Brown     /* Check each successive cone */
4356552f7358SJed Brown     for (p = 1; p < numPoints && joinSize; ++p) {
4357552f7358SJed Brown       PetscInt newJoinSize = 0;
4358552f7358SJed Brown 
4359552f7358SJed Brown       dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d];
4360552f7358SJed Brown       for (c = 0; c < dof; ++c) {
4361552f7358SJed Brown         const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2];
4362552f7358SJed Brown 
4363552f7358SJed Brown         for (m = 0; m < joinSize; ++m) {
4364552f7358SJed Brown           if (point == join[i][m]) {
4365552f7358SJed Brown             join[1-i][newJoinSize++] = point;
4366552f7358SJed Brown             break;
4367552f7358SJed Brown           }
4368552f7358SJed Brown         }
4369552f7358SJed Brown       }
4370552f7358SJed Brown       joinSize = newJoinSize;
4371552f7358SJed Brown       i        = 1-i;
4372552f7358SJed Brown     }
4373552f7358SJed Brown     if (joinSize) break;
4374552f7358SJed Brown   }
4375552f7358SJed Brown   *numCoveredPoints = joinSize;
4376552f7358SJed Brown   *coveredPoints    = join[i];
4377552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
43789566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]));
4379552f7358SJed Brown   }
43809566063dSJacob Faibussowitsch   PetscCall(PetscFree(closures));
43819566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets));
43826302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, ms, MPIU_INT, &join[1-i]));
4383552f7358SJed Brown   PetscFunctionReturn(0);
4384552f7358SJed Brown }
4385552f7358SJed Brown 
4386552f7358SJed Brown /*@C
4387552f7358SJed Brown   DMPlexGetMeet - Get an array for the meet of the set of points
4388552f7358SJed Brown 
4389552f7358SJed Brown   Not Collective
4390552f7358SJed Brown 
4391552f7358SJed Brown   Input Parameters:
4392552f7358SJed Brown + dm - The DMPlex object
4393552f7358SJed Brown . numPoints - The number of input points for the meet
4394552f7358SJed Brown - points - The input points
4395552f7358SJed Brown 
4396552f7358SJed Brown   Output Parameters:
4397552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4398552f7358SJed Brown - coveredPoints - The points in the meet
4399552f7358SJed Brown 
4400552f7358SJed Brown   Level: intermediate
4401552f7358SJed Brown 
4402552f7358SJed Brown   Note: Currently, this is restricted to a single level meet
4403552f7358SJed Brown 
44043813dfbdSMatthew G Knepley   Fortran Notes:
44053813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
44063813dfbdSMatthew G Knepley   include petsc.h90 in your code.
44073813dfbdSMatthew G Knepley 
44083813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
44093813dfbdSMatthew G Knepley 
4410db781477SPatrick Sanan .seealso: `DMPlexRestoreMeet()`, `DMPlexGetJoin()`
4411552f7358SJed Brown @*/
4412552f7358SJed Brown PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints)
4413552f7358SJed Brown {
4414552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
4415552f7358SJed Brown   PetscInt      *meet[2];
4416552f7358SJed Brown   PetscInt       meetSize, i = 0;
4417552f7358SJed Brown   PetscInt       dof, off, p, c, m;
44186302a7fbSVaclav Hapla   PetscInt       maxConeSize;
4419552f7358SJed Brown 
4420552f7358SJed Brown   PetscFunctionBegin;
4421552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4422dadcf809SJacob Faibussowitsch   PetscValidIntPointer(points, 3);
4423dadcf809SJacob Faibussowitsch   PetscValidIntPointer(numCoveringPoints, 4);
4424064a246eSJacob Faibussowitsch   PetscValidPointer(coveringPoints, 5);
44256302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->coneSection, &maxConeSize));
44266302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[0]));
44276302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[1]));
4428552f7358SJed Brown   /* Copy in cone of first point */
44299566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, points[0], &dof));
44309566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, points[0], &off));
4431552f7358SJed Brown   for (meetSize = 0; meetSize < dof; ++meetSize) {
4432552f7358SJed Brown     meet[i][meetSize] = mesh->cones[off+meetSize];
4433552f7358SJed Brown   }
4434552f7358SJed Brown   /* Check each successive cone */
4435552f7358SJed Brown   for (p = 1; p < numPoints; ++p) {
4436552f7358SJed Brown     PetscInt newMeetSize = 0;
4437552f7358SJed Brown 
44389566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, points[p], &dof));
44399566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, points[p], &off));
4440552f7358SJed Brown     for (c = 0; c < dof; ++c) {
4441552f7358SJed Brown       const PetscInt point = mesh->cones[off+c];
4442552f7358SJed Brown 
4443552f7358SJed Brown       for (m = 0; m < meetSize; ++m) {
4444552f7358SJed Brown         if (point == meet[i][m]) {
4445552f7358SJed Brown           meet[1-i][newMeetSize++] = point;
4446552f7358SJed Brown           break;
4447552f7358SJed Brown         }
4448552f7358SJed Brown       }
4449552f7358SJed Brown     }
4450552f7358SJed Brown     meetSize = newMeetSize;
4451552f7358SJed Brown     i        = 1-i;
4452552f7358SJed Brown   }
4453552f7358SJed Brown   *numCoveringPoints = meetSize;
4454552f7358SJed Brown   *coveringPoints    = meet[i];
44556302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, maxConeSize, MPIU_INT, &meet[1-i]));
4456552f7358SJed Brown   PetscFunctionReturn(0);
4457552f7358SJed Brown }
4458552f7358SJed Brown 
4459552f7358SJed Brown /*@C
4460552f7358SJed Brown   DMPlexRestoreMeet - Restore an array for the meet of the set of points
4461552f7358SJed Brown 
4462552f7358SJed Brown   Not Collective
4463552f7358SJed Brown 
4464552f7358SJed Brown   Input Parameters:
4465552f7358SJed Brown + dm - The DMPlex object
4466552f7358SJed Brown . numPoints - The number of input points for the meet
4467552f7358SJed Brown - points - The input points
4468552f7358SJed Brown 
4469552f7358SJed Brown   Output Parameters:
4470552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4471552f7358SJed Brown - coveredPoints - The points in the meet
4472552f7358SJed Brown 
4473552f7358SJed Brown   Level: intermediate
4474552f7358SJed Brown 
44753813dfbdSMatthew G Knepley   Fortran Notes:
44763813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
44773813dfbdSMatthew G Knepley   include petsc.h90 in your code.
44783813dfbdSMatthew G Knepley 
44793813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
44803813dfbdSMatthew G Knepley 
4481db781477SPatrick Sanan .seealso: `DMPlexGetMeet()`, `DMPlexGetFullMeet()`, `DMPlexGetJoin()`
4482552f7358SJed Brown @*/
4483552f7358SJed Brown PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4484552f7358SJed Brown {
4485552f7358SJed Brown   PetscFunctionBegin;
4486552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4487d7902bd2SMatthew G. Knepley   if (points) PetscValidIntPointer(points,3);
4488d7902bd2SMatthew G. Knepley   if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4);
4489d7902bd2SMatthew G. Knepley   PetscValidPointer(coveredPoints,5);
44909566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints));
4491d7902bd2SMatthew G. Knepley   if (numCoveredPoints) *numCoveredPoints = 0;
4492552f7358SJed Brown   PetscFunctionReturn(0);
4493552f7358SJed Brown }
4494552f7358SJed Brown 
4495552f7358SJed Brown /*@C
4496552f7358SJed Brown   DMPlexGetFullMeet - Get an array for the meet of the set of points
4497552f7358SJed Brown 
4498552f7358SJed Brown   Not Collective
4499552f7358SJed Brown 
4500552f7358SJed Brown   Input Parameters:
4501552f7358SJed Brown + dm - The DMPlex object
4502552f7358SJed Brown . numPoints - The number of input points for the meet
4503552f7358SJed Brown - points - The input points
4504552f7358SJed Brown 
4505552f7358SJed Brown   Output Parameters:
4506552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4507552f7358SJed Brown - coveredPoints - The points in the meet
4508552f7358SJed Brown 
4509552f7358SJed Brown   Level: intermediate
4510552f7358SJed Brown 
45113813dfbdSMatthew G Knepley   Fortran Notes:
45123813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
45133813dfbdSMatthew G Knepley   include petsc.h90 in your code.
45143813dfbdSMatthew G Knepley 
45153813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
45163813dfbdSMatthew G Knepley 
4517db781477SPatrick Sanan .seealso: `DMPlexGetMeet()`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()`
4518552f7358SJed Brown @*/
4519552f7358SJed Brown PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4520552f7358SJed Brown {
4521552f7358SJed Brown   PetscInt      *offsets, **closures;
4522552f7358SJed Brown   PetscInt      *meet[2];
4523552f7358SJed Brown   PetscInt       height = 0, maxSize, meetSize = 0, i = 0;
452424c766afSToby Isaac   PetscInt       p, h, c, m, mc;
4525552f7358SJed Brown 
4526552f7358SJed Brown   PetscFunctionBegin;
4527552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4528dadcf809SJacob Faibussowitsch   PetscValidIntPointer(points, 3);
4529dadcf809SJacob Faibussowitsch   PetscValidIntPointer(numCoveredPoints, 4);
4530064a246eSJacob Faibussowitsch   PetscValidPointer(coveredPoints, 5);
4531552f7358SJed Brown 
45329566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &height));
45339566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(numPoints, &closures));
45349566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets));
45356302a7fbSVaclav Hapla   PetscCall(DMPlexGetMaxSizes(dm, &mc, NULL));
453624c766afSToby Isaac   maxSize = (mc > 1) ? ((PetscPowInt(mc,height+1)-1)/(mc-1)) : height + 1;
45379566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0]));
45389566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1]));
4539552f7358SJed Brown 
4540552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
4541552f7358SJed Brown     PetscInt closureSize;
4542552f7358SJed Brown 
45439566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]));
45440d644c17SKarl Rupp 
4545552f7358SJed Brown     offsets[p*(height+2)+0] = 0;
4546552f7358SJed Brown     for (h = 0; h < height+1; ++h) {
4547552f7358SJed Brown       PetscInt pStart, pEnd, i;
4548552f7358SJed Brown 
45499566063dSJacob Faibussowitsch       PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd));
4550552f7358SJed Brown       for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) {
4551552f7358SJed Brown         if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) {
4552552f7358SJed Brown           offsets[p*(height+2)+h+1] = i;
4553552f7358SJed Brown           break;
4554552f7358SJed Brown         }
4555552f7358SJed Brown       }
4556552f7358SJed Brown       if (i == closureSize) offsets[p*(height+2)+h+1] = i;
4557552f7358SJed Brown     }
455863a3b9bcSJacob 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);
4559552f7358SJed Brown   }
4560552f7358SJed Brown   for (h = 0; h < height+1; ++h) {
4561552f7358SJed Brown     PetscInt dof;
4562552f7358SJed Brown 
4563552f7358SJed Brown     /* Copy in cone of first point */
4564552f7358SJed Brown     dof = offsets[h+1] - offsets[h];
4565552f7358SJed Brown     for (meetSize = 0; meetSize < dof; ++meetSize) {
4566552f7358SJed Brown       meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2];
4567552f7358SJed Brown     }
4568552f7358SJed Brown     /* Check each successive cone */
4569552f7358SJed Brown     for (p = 1; p < numPoints && meetSize; ++p) {
4570552f7358SJed Brown       PetscInt newMeetSize = 0;
4571552f7358SJed Brown 
4572552f7358SJed Brown       dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h];
4573552f7358SJed Brown       for (c = 0; c < dof; ++c) {
4574552f7358SJed Brown         const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2];
4575552f7358SJed Brown 
4576552f7358SJed Brown         for (m = 0; m < meetSize; ++m) {
4577552f7358SJed Brown           if (point == meet[i][m]) {
4578552f7358SJed Brown             meet[1-i][newMeetSize++] = point;
4579552f7358SJed Brown             break;
4580552f7358SJed Brown           }
4581552f7358SJed Brown         }
4582552f7358SJed Brown       }
4583552f7358SJed Brown       meetSize = newMeetSize;
4584552f7358SJed Brown       i        = 1-i;
4585552f7358SJed Brown     }
4586552f7358SJed Brown     if (meetSize) break;
4587552f7358SJed Brown   }
4588552f7358SJed Brown   *numCoveredPoints = meetSize;
4589552f7358SJed Brown   *coveredPoints    = meet[i];
4590552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
45919566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]));
4592552f7358SJed Brown   }
45939566063dSJacob Faibussowitsch   PetscCall(PetscFree(closures));
45949566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets));
45956302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, mc, MPIU_INT, &meet[1-i]));
4596552f7358SJed Brown   PetscFunctionReturn(0);
4597552f7358SJed Brown }
4598552f7358SJed Brown 
45994e3744c5SMatthew G. Knepley /*@C
46004e3744c5SMatthew G. Knepley   DMPlexEqual - Determine if two DMs have the same topology
46014e3744c5SMatthew G. Knepley 
46024e3744c5SMatthew G. Knepley   Not Collective
46034e3744c5SMatthew G. Knepley 
46044e3744c5SMatthew G. Knepley   Input Parameters:
46054e3744c5SMatthew G. Knepley + dmA - A DMPlex object
46064e3744c5SMatthew G. Knepley - dmB - A DMPlex object
46074e3744c5SMatthew G. Knepley 
46084e3744c5SMatthew G. Knepley   Output Parameters:
46094e3744c5SMatthew G. Knepley . equal - PETSC_TRUE if the topologies are identical
46104e3744c5SMatthew G. Knepley 
46114e3744c5SMatthew G. Knepley   Level: intermediate
46124e3744c5SMatthew G. Knepley 
46134e3744c5SMatthew G. Knepley   Notes:
46144e3744c5SMatthew G. Knepley   We are not solving graph isomorphism, so we do not permutation.
46154e3744c5SMatthew G. Knepley 
4616db781477SPatrick Sanan .seealso: `DMPlexGetCone()`
46174e3744c5SMatthew G. Knepley @*/
46184e3744c5SMatthew G. Knepley PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal)
46194e3744c5SMatthew G. Knepley {
46204e3744c5SMatthew G. Knepley   PetscInt       depth, depthB, pStart, pEnd, pStartB, pEndB, p;
46214e3744c5SMatthew G. Knepley 
46224e3744c5SMatthew G. Knepley   PetscFunctionBegin;
46234e3744c5SMatthew G. Knepley   PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
46244e3744c5SMatthew G. Knepley   PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
4625dadcf809SJacob Faibussowitsch   PetscValidBoolPointer(equal, 3);
46264e3744c5SMatthew G. Knepley 
46274e3744c5SMatthew G. Knepley   *equal = PETSC_FALSE;
46289566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmA, &depth));
46299566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmB, &depthB));
46304e3744c5SMatthew G. Knepley   if (depth != depthB) PetscFunctionReturn(0);
46319566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dmA, &pStart,  &pEnd));
46329566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dmB, &pStartB, &pEndB));
46334e3744c5SMatthew G. Knepley   if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(0);
46344e3744c5SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
46354e3744c5SMatthew G. Knepley     const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB;
46364e3744c5SMatthew G. Knepley     PetscInt        coneSize, coneSizeB, c, supportSize, supportSizeB, s;
46374e3744c5SMatthew G. Knepley 
46389566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dmA, p, &coneSize));
46399566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dmA, p, &cone));
46409566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dmA, p, &ornt));
46419566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dmB, p, &coneSizeB));
46429566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dmB, p, &coneB));
46439566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dmB, p, &orntB));
46444e3744c5SMatthew G. Knepley     if (coneSize != coneSizeB) PetscFunctionReturn(0);
46454e3744c5SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
46464e3744c5SMatthew G. Knepley       if (cone[c] != coneB[c]) PetscFunctionReturn(0);
46474e3744c5SMatthew G. Knepley       if (ornt[c] != orntB[c]) PetscFunctionReturn(0);
46484e3744c5SMatthew G. Knepley     }
46499566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dmA, p, &supportSize));
46509566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dmA, p, &support));
46519566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dmB, p, &supportSizeB));
46529566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dmB, p, &supportB));
46534e3744c5SMatthew G. Knepley     if (supportSize != supportSizeB) PetscFunctionReturn(0);
46544e3744c5SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
46554e3744c5SMatthew G. Knepley       if (support[s] != supportB[s]) PetscFunctionReturn(0);
46564e3744c5SMatthew G. Knepley     }
46574e3744c5SMatthew G. Knepley   }
46584e3744c5SMatthew G. Knepley   *equal = PETSC_TRUE;
46594e3744c5SMatthew G. Knepley   PetscFunctionReturn(0);
46604e3744c5SMatthew G. Knepley }
46614e3744c5SMatthew G. Knepley 
46627cd05799SMatthew G. Knepley /*@C
46637cd05799SMatthew G. Knepley   DMPlexGetNumFaceVertices - Returns the number of vertices on a face
46647cd05799SMatthew G. Knepley 
46657cd05799SMatthew G. Knepley   Not Collective
46667cd05799SMatthew G. Knepley 
46677cd05799SMatthew G. Knepley   Input Parameters:
46687cd05799SMatthew G. Knepley + dm         - The DMPlex
46697cd05799SMatthew G. Knepley . cellDim    - The cell dimension
46707cd05799SMatthew G. Knepley - numCorners - The number of vertices on a cell
46717cd05799SMatthew G. Knepley 
46727cd05799SMatthew G. Knepley   Output Parameters:
46737cd05799SMatthew G. Knepley . numFaceVertices - The number of vertices on a face
46747cd05799SMatthew G. Knepley 
46757cd05799SMatthew G. Knepley   Level: developer
46767cd05799SMatthew G. Knepley 
46777cd05799SMatthew G. Knepley   Notes:
46787cd05799SMatthew G. Knepley   Of course this can only work for a restricted set of symmetric shapes
46797cd05799SMatthew G. Knepley 
4680db781477SPatrick Sanan .seealso: `DMPlexGetCone()`
46817cd05799SMatthew G. Knepley @*/
468218ad9376SMatthew G. Knepley PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices)
4683a6dfd86eSKarl Rupp {
468482f516ccSBarry Smith   MPI_Comm       comm;
4685552f7358SJed Brown 
4686552f7358SJed Brown   PetscFunctionBegin;
46879566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm,&comm));
4688dadcf809SJacob Faibussowitsch   PetscValidIntPointer(numFaceVertices,4);
4689552f7358SJed Brown   switch (cellDim) {
4690552f7358SJed Brown   case 0:
4691552f7358SJed Brown     *numFaceVertices = 0;
4692552f7358SJed Brown     break;
4693552f7358SJed Brown   case 1:
4694552f7358SJed Brown     *numFaceVertices = 1;
4695552f7358SJed Brown     break;
4696552f7358SJed Brown   case 2:
4697552f7358SJed Brown     switch (numCorners) {
469819436ca2SJed Brown     case 3: /* triangle */
469919436ca2SJed Brown       *numFaceVertices = 2; /* Edge has 2 vertices */
4700552f7358SJed Brown       break;
470119436ca2SJed Brown     case 4: /* quadrilateral */
470219436ca2SJed Brown       *numFaceVertices = 2; /* Edge has 2 vertices */
4703552f7358SJed Brown       break;
470419436ca2SJed Brown     case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */
470519436ca2SJed Brown       *numFaceVertices = 3; /* Edge has 3 vertices */
4706552f7358SJed Brown       break;
470719436ca2SJed Brown     case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */
470819436ca2SJed Brown       *numFaceVertices = 3; /* Edge has 3 vertices */
4709552f7358SJed Brown       break;
4710552f7358SJed Brown     default:
471163a3b9bcSJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim);
4712552f7358SJed Brown     }
4713552f7358SJed Brown     break;
4714552f7358SJed Brown   case 3:
4715552f7358SJed Brown     switch (numCorners) {
471619436ca2SJed Brown     case 4: /* tetradehdron */
471719436ca2SJed Brown       *numFaceVertices = 3; /* Face has 3 vertices */
4718552f7358SJed Brown       break;
471919436ca2SJed Brown     case 6: /* tet cohesive cells */
472019436ca2SJed Brown       *numFaceVertices = 4; /* Face has 4 vertices */
4721552f7358SJed Brown       break;
472219436ca2SJed Brown     case 8: /* hexahedron */
472319436ca2SJed Brown       *numFaceVertices = 4; /* Face has 4 vertices */
4724552f7358SJed Brown       break;
472519436ca2SJed Brown     case 9: /* tet cohesive Lagrange cells */
472619436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4727552f7358SJed Brown       break;
472819436ca2SJed Brown     case 10: /* quadratic tetrahedron */
472919436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4730552f7358SJed Brown       break;
473119436ca2SJed Brown     case 12: /* hex cohesive Lagrange cells */
473219436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4733552f7358SJed Brown       break;
473419436ca2SJed Brown     case 18: /* quadratic tet cohesive Lagrange cells */
473519436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4736552f7358SJed Brown       break;
473719436ca2SJed Brown     case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */
473819436ca2SJed Brown       *numFaceVertices = 9; /* Face has 9 vertices */
4739552f7358SJed Brown       break;
4740552f7358SJed Brown     default:
474163a3b9bcSJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim);
4742552f7358SJed Brown     }
4743552f7358SJed Brown     break;
4744552f7358SJed Brown   default:
474563a3b9bcSJacob Faibussowitsch     SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %" PetscInt_FMT, cellDim);
4746552f7358SJed Brown   }
4747552f7358SJed Brown   PetscFunctionReturn(0);
4748552f7358SJed Brown }
4749552f7358SJed Brown 
4750552f7358SJed Brown /*@
4751aa50250dSMatthew G. Knepley   DMPlexGetDepthLabel - Get the DMLabel recording the depth of each point
4752552f7358SJed Brown 
4753552f7358SJed Brown   Not Collective
4754552f7358SJed Brown 
4755aa50250dSMatthew G. Knepley   Input Parameter:
4756552f7358SJed Brown . dm    - The DMPlex object
4757552f7358SJed Brown 
4758aa50250dSMatthew G. Knepley   Output Parameter:
4759aa50250dSMatthew G. Knepley . depthLabel - The DMLabel recording point depth
4760552f7358SJed Brown 
4761552f7358SJed Brown   Level: developer
4762552f7358SJed Brown 
4763db781477SPatrick Sanan .seealso: `DMPlexGetDepth()`, `DMPlexGetHeightStratum()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`,
4764aa50250dSMatthew G. Knepley @*/
4765aa50250dSMatthew G. Knepley PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel)
4766aa50250dSMatthew G. Knepley {
4767aa50250dSMatthew G. Knepley   PetscFunctionBegin;
4768aa50250dSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4769aa50250dSMatthew G. Knepley   PetscValidPointer(depthLabel, 2);
4770c58f1c22SToby Isaac   *depthLabel = dm->depthLabel;
4771aa50250dSMatthew G. Knepley   PetscFunctionReturn(0);
4772aa50250dSMatthew G. Knepley }
4773aa50250dSMatthew G. Knepley 
4774aa50250dSMatthew G. Knepley /*@
4775aa50250dSMatthew G. Knepley   DMPlexGetDepth - Get the depth of the DAG representing this mesh
4776aa50250dSMatthew G. Knepley 
4777aa50250dSMatthew G. Knepley   Not Collective
4778aa50250dSMatthew G. Knepley 
4779aa50250dSMatthew G. Knepley   Input Parameter:
4780aa50250dSMatthew G. Knepley . dm    - The DMPlex object
4781aa50250dSMatthew G. Knepley 
4782aa50250dSMatthew G. Knepley   Output Parameter:
4783aa50250dSMatthew G. Knepley . depth - The number of strata (breadth first levels) in the DAG
4784aa50250dSMatthew G. Knepley 
4785aa50250dSMatthew G. Knepley   Level: developer
4786552f7358SJed Brown 
4787b1bb481bSMatthew Knepley   Notes:
4788b1bb481bSMatthew Knepley   This returns maximum of point depths over all points, i.e. maximum value of the label returned by DMPlexGetDepthLabel().
4789dc287ab2SVaclav Hapla   The point depth is described more in detail in DMPlexGetDepthStratum().
4790dc287ab2SVaclav Hapla   An empty mesh gives -1.
4791b1bb481bSMatthew Knepley 
4792db781477SPatrick Sanan .seealso: `DMPlexGetDepthLabel()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`
4793552f7358SJed Brown @*/
4794552f7358SJed Brown PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth)
4795552f7358SJed Brown {
4796aa50250dSMatthew G. Knepley   DMLabel        label;
4797aa50250dSMatthew G. Knepley   PetscInt       d = 0;
4798552f7358SJed Brown 
4799552f7358SJed Brown   PetscFunctionBegin;
4800552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4801dadcf809SJacob Faibussowitsch   PetscValidIntPointer(depth, 2);
48029566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
48039566063dSJacob Faibussowitsch   if (label) PetscCall(DMLabelGetNumValues(label, &d));
4804552f7358SJed Brown   *depth = d-1;
4805552f7358SJed Brown   PetscFunctionReturn(0);
4806552f7358SJed Brown }
4807552f7358SJed Brown 
4808552f7358SJed Brown /*@
4809552f7358SJed Brown   DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth.
4810552f7358SJed Brown 
4811552f7358SJed Brown   Not Collective
4812552f7358SJed Brown 
4813552f7358SJed Brown   Input Parameters:
4814552f7358SJed Brown + dm    - The DMPlex object
4815570fa34dSVaclav Hapla - depth - The requested depth
4816552f7358SJed Brown 
4817552f7358SJed Brown   Output Parameters:
4818552f7358SJed Brown + start - The first point at this depth
4819552f7358SJed Brown - end   - One beyond the last point at this depth
4820552f7358SJed Brown 
4821647867b2SJed Brown   Notes:
4822647867b2SJed Brown   Depth indexing is related to topological dimension.  Depth stratum 0 contains the lowest topological dimension points,
4823647867b2SJed Brown   often "vertices".  If the mesh is "interpolated" (see DMPlexInterpolate()), then depth stratum 1 contains the next
4824647867b2SJed Brown   higher dimension, e.g., "edges".
4825647867b2SJed Brown 
4826552f7358SJed Brown   Level: developer
4827552f7358SJed Brown 
4828db781477SPatrick Sanan .seealso: `DMPlexGetHeightStratum()`, `DMPlexGetDepth()`, `DMPlexGetDepthLabel()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`, `DMPlexInterpolate()`
4829552f7358SJed Brown @*/
4830570fa34dSVaclav Hapla PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt depth, PetscInt *start, PetscInt *end)
48310adebc6cSBarry Smith {
4832aa50250dSMatthew G. Knepley   DMLabel        label;
483363d1a920SMatthew G. Knepley   PetscInt       pStart, pEnd;
4834552f7358SJed Brown 
4835552f7358SJed Brown   PetscFunctionBegin;
4836552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4837dadcf809SJacob Faibussowitsch   if (start) {PetscValidIntPointer(start, 3); *start = 0;}
4838dadcf809SJacob Faibussowitsch   if (end)   {PetscValidIntPointer(end,   4); *end   = 0;}
48399566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
48400d644c17SKarl Rupp   if (pStart == pEnd) PetscFunctionReturn(0);
4841570fa34dSVaclav Hapla   if (depth < 0) {
484263d1a920SMatthew G. Knepley     if (start) *start = pStart;
484363d1a920SMatthew G. Knepley     if (end)   *end   = pEnd;
484463d1a920SMatthew G. Knepley     PetscFunctionReturn(0);
4845552f7358SJed Brown   }
48469566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
484728b400f6SJacob Faibussowitsch   PetscCheck(label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");
4848570fa34dSVaclav Hapla   PetscCall(DMLabelGetStratumBounds(label, depth, start, end));
4849552f7358SJed Brown   PetscFunctionReturn(0);
4850552f7358SJed Brown }
4851552f7358SJed Brown 
4852552f7358SJed Brown /*@
4853552f7358SJed Brown   DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height.
4854552f7358SJed Brown 
4855552f7358SJed Brown   Not Collective
4856552f7358SJed Brown 
4857552f7358SJed Brown   Input Parameters:
4858552f7358SJed Brown + dm     - The DMPlex object
4859570fa34dSVaclav Hapla - height - The requested height
4860552f7358SJed Brown 
4861552f7358SJed Brown   Output Parameters:
4862552f7358SJed Brown + start - The first point at this height
4863552f7358SJed Brown - end   - One beyond the last point at this height
4864552f7358SJed Brown 
4865647867b2SJed Brown   Notes:
4866647867b2SJed Brown   Height indexing is related to topological codimension.  Height stratum 0 contains the highest topological dimension
4867647867b2SJed Brown   points, often called "cells" or "elements".  If the mesh is "interpolated" (see DMPlexInterpolate()), then height
4868647867b2SJed Brown   stratum 1 contains the boundary of these "cells", often called "faces" or "facets".
4869647867b2SJed Brown 
4870552f7358SJed Brown   Level: developer
4871552f7358SJed Brown 
4872db781477SPatrick Sanan .seealso: `DMPlexGetDepthStratum()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()`
4873552f7358SJed Brown @*/
4874570fa34dSVaclav Hapla PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt height, PetscInt *start, PetscInt *end)
48750adebc6cSBarry Smith {
4876aa50250dSMatthew G. Knepley   DMLabel        label;
487763d1a920SMatthew G. Knepley   PetscInt       depth, pStart, pEnd;
4878552f7358SJed Brown 
4879552f7358SJed Brown   PetscFunctionBegin;
4880552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4881dadcf809SJacob Faibussowitsch   if (start) {PetscValidIntPointer(start, 3); *start = 0;}
4882dadcf809SJacob Faibussowitsch   if (end)   {PetscValidIntPointer(end,   4); *end   = 0;}
48839566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
48840d644c17SKarl Rupp   if (pStart == pEnd) PetscFunctionReturn(0);
4885570fa34dSVaclav Hapla   if (height < 0) {
488663d1a920SMatthew G. Knepley     if (start) *start = pStart;
488763d1a920SMatthew G. Knepley     if (end)   *end   = pEnd;
488863d1a920SMatthew G. Knepley     PetscFunctionReturn(0);
4889552f7358SJed Brown   }
48909566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
489128b400f6SJacob Faibussowitsch   PetscCheck(label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");
48929566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(label, &depth));
4893570fa34dSVaclav Hapla   PetscCall(DMLabelGetStratumBounds(label, depth-1-height, start, end));
4894552f7358SJed Brown   PetscFunctionReturn(0);
4895552f7358SJed Brown }
4896552f7358SJed Brown 
4897ba2698f1SMatthew G. Knepley /*@
4898ba2698f1SMatthew G. Knepley   DMPlexGetPointDepth - Get the depth of a given point
4899ba2698f1SMatthew G. Knepley 
4900ba2698f1SMatthew G. Knepley   Not Collective
4901ba2698f1SMatthew G. Knepley 
4902d8d19677SJose E. Roman   Input Parameters:
4903ba2698f1SMatthew G. Knepley + dm    - The DMPlex object
4904ba2698f1SMatthew G. Knepley - point - The point
4905ba2698f1SMatthew G. Knepley 
4906ba2698f1SMatthew G. Knepley   Output Parameter:
4907ba2698f1SMatthew G. Knepley . depth - The depth of the point
4908ba2698f1SMatthew G. Knepley 
4909ba2698f1SMatthew G. Knepley   Level: intermediate
4910ba2698f1SMatthew G. Knepley 
4911db781477SPatrick Sanan .seealso: `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()`
4912ba2698f1SMatthew G. Knepley @*/
4913ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth)
4914ba2698f1SMatthew G. Knepley {
4915ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
4916ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
491740a2aa30SMatthew G. Knepley   PetscValidIntPointer(depth, 3);
49189566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(dm->depthLabel, point, depth));
4919ba2698f1SMatthew G. Knepley   PetscFunctionReturn(0);
4920ba2698f1SMatthew G. Knepley }
4921ba2698f1SMatthew G. Knepley 
4922ba2698f1SMatthew G. Knepley /*@
49230c0a32dcSVaclav Hapla   DMPlexGetPointHeight - Get the height of a given point
49240c0a32dcSVaclav Hapla 
49250c0a32dcSVaclav Hapla   Not Collective
49260c0a32dcSVaclav Hapla 
4927d8d19677SJose E. Roman   Input Parameters:
49280c0a32dcSVaclav Hapla + dm    - The DMPlex object
49290c0a32dcSVaclav Hapla - point - The point
49300c0a32dcSVaclav Hapla 
49310c0a32dcSVaclav Hapla   Output Parameter:
49320c0a32dcSVaclav Hapla . height - The height of the point
49330c0a32dcSVaclav Hapla 
49340c0a32dcSVaclav Hapla   Level: intermediate
49350c0a32dcSVaclav Hapla 
4936db781477SPatrick Sanan .seealso: `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointDepth()`
49370c0a32dcSVaclav Hapla @*/
49380c0a32dcSVaclav Hapla PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height)
49390c0a32dcSVaclav Hapla {
49400c0a32dcSVaclav Hapla   PetscInt       n, pDepth;
49410c0a32dcSVaclav Hapla 
49420c0a32dcSVaclav Hapla   PetscFunctionBegin;
49430c0a32dcSVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
49440c0a32dcSVaclav Hapla   PetscValidIntPointer(height, 3);
49459566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(dm->depthLabel, &n));
49469566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(dm->depthLabel, point, &pDepth));
49470c0a32dcSVaclav Hapla   *height = n - 1 - pDepth;  /* DAG depth is n-1 */
49480c0a32dcSVaclav Hapla   PetscFunctionReturn(0);
49490c0a32dcSVaclav Hapla }
49500c0a32dcSVaclav Hapla 
49510c0a32dcSVaclav Hapla /*@
4952ba2698f1SMatthew G. Knepley   DMPlexGetCellTypeLabel - Get the DMLabel recording the polytope type of each cell
4953ba2698f1SMatthew G. Knepley 
4954ba2698f1SMatthew G. Knepley   Not Collective
4955ba2698f1SMatthew G. Knepley 
4956ba2698f1SMatthew G. Knepley   Input Parameter:
4957ba2698f1SMatthew G. Knepley . dm - The DMPlex object
4958ba2698f1SMatthew G. Knepley 
4959ba2698f1SMatthew G. Knepley   Output Parameter:
4960ba2698f1SMatthew G. Knepley . celltypeLabel - The DMLabel recording cell polytope type
4961ba2698f1SMatthew G. Knepley 
4962412e9a14SMatthew G. Knepley   Note: This function will trigger automatica computation of cell types. This can be disabled by calling
4963412e9a14SMatthew G. Knepley   DMCreateLabel(dm, "celltype") beforehand.
4964412e9a14SMatthew G. Knepley 
4965ba2698f1SMatthew G. Knepley   Level: developer
4966ba2698f1SMatthew G. Knepley 
4967db781477SPatrick Sanan .seealso: `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMCreateLabel()`
4968ba2698f1SMatthew G. Knepley @*/
4969ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel)
4970ba2698f1SMatthew G. Knepley {
4971ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
4972ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4973ba2698f1SMatthew G. Knepley   PetscValidPointer(celltypeLabel, 2);
49749566063dSJacob Faibussowitsch   if (!dm->celltypeLabel) PetscCall(DMPlexComputeCellTypes(dm));
4975ba2698f1SMatthew G. Knepley   *celltypeLabel = dm->celltypeLabel;
4976ba2698f1SMatthew G. Knepley   PetscFunctionReturn(0);
4977ba2698f1SMatthew G. Knepley }
4978ba2698f1SMatthew G. Knepley 
4979ba2698f1SMatthew G. Knepley /*@
4980ba2698f1SMatthew G. Knepley   DMPlexGetCellType - Get the polytope type of a given cell
4981ba2698f1SMatthew G. Knepley 
4982ba2698f1SMatthew G. Knepley   Not Collective
4983ba2698f1SMatthew G. Knepley 
4984d8d19677SJose E. Roman   Input Parameters:
4985ba2698f1SMatthew G. Knepley + dm   - The DMPlex object
4986ba2698f1SMatthew G. Knepley - cell - The cell
4987ba2698f1SMatthew G. Knepley 
4988ba2698f1SMatthew G. Knepley   Output Parameter:
4989ba2698f1SMatthew G. Knepley . celltype - The polytope type of the cell
4990ba2698f1SMatthew G. Knepley 
4991ba2698f1SMatthew G. Knepley   Level: intermediate
4992ba2698f1SMatthew G. Knepley 
4993db781477SPatrick Sanan .seealso: `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`
4994ba2698f1SMatthew G. Knepley @*/
4995ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype)
4996ba2698f1SMatthew G. Knepley {
4997ba2698f1SMatthew G. Knepley   DMLabel        label;
4998ba2698f1SMatthew G. Knepley   PetscInt       ct;
4999ba2698f1SMatthew G. Knepley 
5000ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
5001ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5002ba2698f1SMatthew G. Knepley   PetscValidPointer(celltype, 3);
50039566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &label));
50049566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(label, cell, &ct));
500563a3b9bcSJacob Faibussowitsch   PetscCheck(ct >= 0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %" PetscInt_FMT " has not been assigned a cell type", cell);
5006ba2698f1SMatthew G. Knepley   *celltype = (DMPolytopeType) ct;
5007ba2698f1SMatthew G. Knepley   PetscFunctionReturn(0);
5008ba2698f1SMatthew G. Knepley }
5009ba2698f1SMatthew G. Knepley 
5010412e9a14SMatthew G. Knepley /*@
5011412e9a14SMatthew G. Knepley   DMPlexSetCellType - Set the polytope type of a given cell
5012412e9a14SMatthew G. Knepley 
5013412e9a14SMatthew G. Knepley   Not Collective
5014412e9a14SMatthew G. Knepley 
5015412e9a14SMatthew G. Knepley   Input Parameters:
5016412e9a14SMatthew G. Knepley + dm   - The DMPlex object
5017412e9a14SMatthew G. Knepley . cell - The cell
5018412e9a14SMatthew G. Knepley - celltype - The polytope type of the cell
5019412e9a14SMatthew G. Knepley 
5020412e9a14SMatthew G. Knepley   Note: By default, cell types will be automatically computed using DMPlexComputeCellTypes() before this function
5021412e9a14SMatthew G. Knepley   is executed. This function will override the computed type. However, if automatic classification will not succeed
5022412e9a14SMatthew G. Knepley   and a user wants to manually specify all types, the classification must be disabled by calling
5023412e9a14SMatthew G. Knepley   DMCreaateLabel(dm, "celltype") before getting or setting any cell types.
5024412e9a14SMatthew G. Knepley 
5025412e9a14SMatthew G. Knepley   Level: advanced
5026412e9a14SMatthew G. Knepley 
5027db781477SPatrick Sanan .seealso: `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexComputeCellTypes()`, `DMCreateLabel()`
5028412e9a14SMatthew G. Knepley @*/
5029412e9a14SMatthew G. Knepley PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype)
5030412e9a14SMatthew G. Knepley {
5031412e9a14SMatthew G. Knepley   DMLabel        label;
5032412e9a14SMatthew G. Knepley 
5033412e9a14SMatthew G. Knepley   PetscFunctionBegin;
5034412e9a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
50359566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &label));
50369566063dSJacob Faibussowitsch   PetscCall(DMLabelSetValue(label, cell, celltype));
5037412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
5038412e9a14SMatthew G. Knepley }
5039412e9a14SMatthew G. Knepley 
50400adebc6cSBarry Smith PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm)
50410adebc6cSBarry Smith {
5042efe440bfSMatthew G. Knepley   PetscSection   section, s;
5043efe440bfSMatthew G. Knepley   Mat            m;
50443e922f36SToby Isaac   PetscInt       maxHeight;
5045552f7358SJed Brown 
5046552f7358SJed Brown   PetscFunctionBegin;
50479566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, cdm));
50489566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxProjectionHeight(dm, &maxHeight));
50499566063dSJacob Faibussowitsch   PetscCall(DMPlexSetMaxProjectionHeight(*cdm, maxHeight));
50509566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section));
50519566063dSJacob Faibussowitsch   PetscCall(DMSetLocalSection(*cdm, section));
50529566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&section));
50539566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &s));
50549566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_SELF, &m));
50559566063dSJacob Faibussowitsch   PetscCall(DMSetDefaultConstraints(*cdm, s, m, NULL));
50569566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&s));
50579566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&m));
50588f4c458bSMatthew G. Knepley 
50599566063dSJacob Faibussowitsch   PetscCall(DMSetNumFields(*cdm, 1));
50609566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(*cdm));
5061552f7358SJed Brown   PetscFunctionReturn(0);
5062552f7358SJed Brown }
5063552f7358SJed Brown 
5064f19dbd58SToby Isaac PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field)
5065f19dbd58SToby Isaac {
50666858538eSMatthew G. Knepley   Vec coordsLocal, cellCoordsLocal;
50676858538eSMatthew G. Knepley   DM  coordsDM,    cellCoordsDM;
5068f19dbd58SToby Isaac 
5069f19dbd58SToby Isaac   PetscFunctionBegin;
5070f19dbd58SToby Isaac   *field = NULL;
50719566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal));
50729566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &coordsDM));
50736858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dm, &cellCoordsLocal));
50746858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dm, &cellCoordsDM));
5075f19dbd58SToby Isaac   if (coordsLocal && coordsDM) {
50766858538eSMatthew G. Knepley     if (cellCoordsLocal && cellCoordsDM) PetscCall(DMFieldCreateDSWithDG(coordsDM, cellCoordsDM, 0, coordsLocal, cellCoordsLocal, field));
50776858538eSMatthew G. Knepley     else                                 PetscCall(DMFieldCreateDS(coordsDM, 0, coordsLocal, field));
5078f19dbd58SToby Isaac   }
5079f19dbd58SToby Isaac   PetscFunctionReturn(0);
5080f19dbd58SToby Isaac }
5081f19dbd58SToby Isaac 
50827cd05799SMatthew G. Knepley /*@C
50837cd05799SMatthew G. Knepley   DMPlexGetConeSection - Return a section which describes the layout of cone data
50847cd05799SMatthew G. Knepley 
50857cd05799SMatthew G. Knepley   Not Collective
50867cd05799SMatthew G. Knepley 
50877cd05799SMatthew G. Knepley   Input Parameters:
50887cd05799SMatthew G. Knepley . dm        - The DMPlex object
50897cd05799SMatthew G. Knepley 
50907cd05799SMatthew G. Knepley   Output Parameter:
50917cd05799SMatthew G. Knepley . section - The PetscSection object
50927cd05799SMatthew G. Knepley 
50937cd05799SMatthew G. Knepley   Level: developer
50947cd05799SMatthew G. Knepley 
5095db781477SPatrick Sanan .seealso: `DMPlexGetSupportSection()`, `DMPlexGetCones()`, `DMPlexGetConeOrientations()`
50967cd05799SMatthew G. Knepley @*/
50970adebc6cSBarry Smith PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section)
50980adebc6cSBarry Smith {
5099552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
5100552f7358SJed Brown 
5101552f7358SJed Brown   PetscFunctionBegin;
5102552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5103552f7358SJed Brown   if (section) *section = mesh->coneSection;
5104552f7358SJed Brown   PetscFunctionReturn(0);
5105552f7358SJed Brown }
5106552f7358SJed Brown 
51077cd05799SMatthew G. Knepley /*@C
51087cd05799SMatthew G. Knepley   DMPlexGetSupportSection - Return a section which describes the layout of support data
51097cd05799SMatthew G. Knepley 
51107cd05799SMatthew G. Knepley   Not Collective
51117cd05799SMatthew G. Knepley 
51127cd05799SMatthew G. Knepley   Input Parameters:
51137cd05799SMatthew G. Knepley . dm        - The DMPlex object
51147cd05799SMatthew G. Knepley 
51157cd05799SMatthew G. Knepley   Output Parameter:
51167cd05799SMatthew G. Knepley . section - The PetscSection object
51177cd05799SMatthew G. Knepley 
51187cd05799SMatthew G. Knepley   Level: developer
51197cd05799SMatthew G. Knepley 
5120db781477SPatrick Sanan .seealso: `DMPlexGetConeSection()`
51217cd05799SMatthew G. Knepley @*/
51228cb4d582SMatthew G. Knepley PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section)
51238cb4d582SMatthew G. Knepley {
51248cb4d582SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
51258cb4d582SMatthew G. Knepley 
51268cb4d582SMatthew G. Knepley   PetscFunctionBegin;
51278cb4d582SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
51288cb4d582SMatthew G. Knepley   if (section) *section = mesh->supportSection;
51298cb4d582SMatthew G. Knepley   PetscFunctionReturn(0);
51308cb4d582SMatthew G. Knepley }
51318cb4d582SMatthew G. Knepley 
51327cd05799SMatthew G. Knepley /*@C
51337cd05799SMatthew G. Knepley   DMPlexGetCones - Return cone data
51347cd05799SMatthew G. Knepley 
51357cd05799SMatthew G. Knepley   Not Collective
51367cd05799SMatthew G. Knepley 
51377cd05799SMatthew G. Knepley   Input Parameters:
51387cd05799SMatthew G. Knepley . dm        - The DMPlex object
51397cd05799SMatthew G. Knepley 
51407cd05799SMatthew G. Knepley   Output Parameter:
51417cd05799SMatthew G. Knepley . cones - The cone for each point
51427cd05799SMatthew G. Knepley 
51437cd05799SMatthew G. Knepley   Level: developer
51447cd05799SMatthew G. Knepley 
5145db781477SPatrick Sanan .seealso: `DMPlexGetConeSection()`
51467cd05799SMatthew G. Knepley @*/
5147a6dfd86eSKarl Rupp PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[])
5148a6dfd86eSKarl Rupp {
5149552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
5150552f7358SJed Brown 
5151552f7358SJed Brown   PetscFunctionBegin;
5152552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5153552f7358SJed Brown   if (cones) *cones = mesh->cones;
5154552f7358SJed Brown   PetscFunctionReturn(0);
5155552f7358SJed Brown }
5156552f7358SJed Brown 
51577cd05799SMatthew G. Knepley /*@C
51587cd05799SMatthew G. Knepley   DMPlexGetConeOrientations - Return cone orientation data
51597cd05799SMatthew G. Knepley 
51607cd05799SMatthew G. Knepley   Not Collective
51617cd05799SMatthew G. Knepley 
51627cd05799SMatthew G. Knepley   Input Parameters:
51637cd05799SMatthew G. Knepley . dm        - The DMPlex object
51647cd05799SMatthew G. Knepley 
51657cd05799SMatthew G. Knepley   Output Parameter:
5166b5a892a1SMatthew G. Knepley . coneOrientations - The array of cone orientations for all points
51677cd05799SMatthew G. Knepley 
51687cd05799SMatthew G. Knepley   Level: developer
51697cd05799SMatthew G. Knepley 
5170b5a892a1SMatthew G. Knepley   Notes:
5171b5a892a1SMatthew G. Knepley   The PetscSection returned by DMPlexGetConeSection() partitions coneOrientations into cone orientations of particular points as returned by DMPlexGetConeOrientation().
5172b5a892a1SMatthew G. Knepley 
5173b5a892a1SMatthew G. Knepley   The meaning of coneOrientations values is detailed in DMPlexGetConeOrientation().
5174b5a892a1SMatthew G. Knepley 
5175db781477SPatrick Sanan .seealso: `DMPlexGetConeSection()`, `DMPlexGetConeOrientation()`
51767cd05799SMatthew G. Knepley @*/
5177a6dfd86eSKarl Rupp PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[])
5178a6dfd86eSKarl Rupp {
5179552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
5180552f7358SJed Brown 
5181552f7358SJed Brown   PetscFunctionBegin;
5182552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5183552f7358SJed Brown   if (coneOrientations) *coneOrientations = mesh->coneOrientations;
5184552f7358SJed Brown   PetscFunctionReturn(0);
5185552f7358SJed Brown }
5186552f7358SJed Brown 
5187552f7358SJed Brown /******************************** FEM Support **********************************/
5188552f7358SJed Brown 
51899e8305c2SJed Brown /*
51909e8305c2SJed Brown  Returns number of components and tensor degree for the field.  For interpolated meshes, line should be a point
51919e8305c2SJed Brown  representing a line in the section.
51929e8305c2SJed Brown */
51939e8305c2SJed Brown static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(PetscSection section,PetscInt field,PetscInt line,PetscBool vertexchart,PetscInt *Nc,PetscInt *k)
51949e8305c2SJed Brown {
51959e8305c2SJed Brown   PetscFunctionBeginHot;
51969566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldComponents(section, field, Nc));
5197a433471fSStefano Zampini   if (line < 0) {
5198a433471fSStefano Zampini     *k = 0;
5199a433471fSStefano Zampini     *Nc = 0;
5200a433471fSStefano Zampini   } else if (vertexchart) {            /* If we only have a vertex chart, we must have degree k=1 */
52019e8305c2SJed Brown     *k = 1;
52029e8305c2SJed Brown   } else {                      /* Assume the full interpolated mesh is in the chart; lines in particular */
52039e8305c2SJed Brown     /* An order k SEM disc has k-1 dofs on an edge */
52049566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, line, field, k));
52059e8305c2SJed Brown     *k = *k / *Nc + 1;
52069e8305c2SJed Brown   }
52079e8305c2SJed Brown   PetscFunctionReturn(0);
52089e8305c2SJed Brown }
52099e8305c2SJed Brown 
5210a4355906SMatthew Knepley /*@
5211bc1eb3faSJed Brown 
5212bc1eb3faSJed Brown   DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a
5213bc1eb3faSJed Brown   lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the
52141bb6d2a8SBarry Smith   section provided (or the section of the DM).
5215a4355906SMatthew Knepley 
5216a4355906SMatthew Knepley   Input Parameters:
5217a4355906SMatthew Knepley + dm      - The DM
5218a4355906SMatthew Knepley . point   - Either a cell (highest dim point) or an edge (dim 1 point), or PETSC_DETERMINE
5219a4355906SMatthew Knepley - section - The PetscSection to reorder, or NULL for the default section
5220a4355906SMatthew Knepley 
5221a4355906SMatthew Knepley   Note: The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial
5222a4355906SMatthew Knepley   degree of the basis.
5223a4355906SMatthew Knepley 
5224bc1eb3faSJed Brown   Example:
5225bc1eb3faSJed Brown   A typical interpolated single-quad mesh might order points as
5226bc1eb3faSJed Brown .vb
5227bc1eb3faSJed Brown   [c0, v1, v2, v3, v4, e5, e6, e7, e8]
5228bc1eb3faSJed Brown 
5229bc1eb3faSJed Brown   v4 -- e6 -- v3
5230bc1eb3faSJed Brown   |           |
5231bc1eb3faSJed Brown   e7    c0    e8
5232bc1eb3faSJed Brown   |           |
5233bc1eb3faSJed Brown   v1 -- e5 -- v2
5234bc1eb3faSJed Brown .ve
5235bc1eb3faSJed Brown 
5236bc1eb3faSJed Brown   (There is no significance to the ordering described here.)  The default section for a Q3 quad might typically assign
5237bc1eb3faSJed Brown   dofs in the order of points, e.g.,
5238bc1eb3faSJed Brown .vb
5239bc1eb3faSJed Brown     c0 -> [0,1,2,3]
5240bc1eb3faSJed Brown     v1 -> [4]
5241bc1eb3faSJed Brown     ...
5242bc1eb3faSJed Brown     e5 -> [8, 9]
5243bc1eb3faSJed Brown .ve
5244bc1eb3faSJed Brown 
5245bc1eb3faSJed Brown   which corresponds to the dofs
5246bc1eb3faSJed Brown .vb
5247bc1eb3faSJed Brown     6   10  11  7
5248bc1eb3faSJed Brown     13  2   3   15
5249bc1eb3faSJed Brown     12  0   1   14
5250bc1eb3faSJed Brown     4   8   9   5
5251bc1eb3faSJed Brown .ve
5252bc1eb3faSJed Brown 
5253bc1eb3faSJed Brown   The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering
5254bc1eb3faSJed Brown .vb
5255bc1eb3faSJed Brown   0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6
5256bc1eb3faSJed Brown .ve
5257bc1eb3faSJed Brown 
5258bc1eb3faSJed Brown   After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically,
5259bc1eb3faSJed Brown .vb
5260bc1eb3faSJed Brown    4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7
5261bc1eb3faSJed Brown .ve
5262bc1eb3faSJed Brown 
5263a4355906SMatthew Knepley   Level: developer
5264a4355906SMatthew Knepley 
5265db781477SPatrick Sanan .seealso: `DMGetLocalSection()`, `PetscSectionSetClosurePermutation()`, `DMSetGlobalSection()`
5266a4355906SMatthew Knepley @*/
5267bc1eb3faSJed Brown PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section)
52683194fc30SMatthew G. Knepley {
52697391a63aSMatthew G. Knepley   DMLabel        label;
5270bb197d40SJed Brown   PetscInt       dim, depth = -1, eStart = -1, Nf;
52719e8305c2SJed Brown   PetscBool      vertexchart;
52723194fc30SMatthew G. Knepley 
52733194fc30SMatthew G. Knepley   PetscFunctionBegin;
52749566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
5275a433471fSStefano Zampini   if (dim < 1) PetscFunctionReturn(0);
5276a433471fSStefano Zampini   if (point < 0) {
5277a433471fSStefano Zampini     PetscInt sStart,sEnd;
5278a433471fSStefano Zampini 
52799566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd));
5280a433471fSStefano Zampini     point = sEnd-sStart ? sStart : point;
5281a433471fSStefano Zampini   }
52829566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
52839566063dSJacob Faibussowitsch   if (point >= 0) PetscCall(DMLabelGetValue(label, point, &depth));
52849566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
52857391a63aSMatthew G. Knepley   if (depth == 1) {eStart = point;}
52867391a63aSMatthew G. Knepley   else if  (depth == dim) {
52877391a63aSMatthew G. Knepley     const PetscInt *cone;
52887391a63aSMatthew G. Knepley 
52899566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, point, &cone));
5290d4e6627bSStefano Zampini     if (dim == 2) eStart = cone[0];
5291d4e6627bSStefano Zampini     else if (dim == 3) {
5292d4e6627bSStefano Zampini       const PetscInt *cone2;
52939566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, cone[0], &cone2));
5294d4e6627bSStefano Zampini       eStart = cone2[0];
529563a3b9bcSJacob 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);
529663a3b9bcSJacob 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);
52979e8305c2SJed Brown   {                             /* Determine whether the chart covers all points or just vertices. */
52989e8305c2SJed Brown     PetscInt pStart,pEnd,cStart,cEnd;
52999566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm,0,&pStart,&pEnd));
53009566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(section,&cStart,&cEnd));
5301796d0a68SJed Brown     if (pStart == cStart && pEnd == cEnd) vertexchart = PETSC_TRUE;      /* Only vertices are in the chart */
5302796d0a68SJed Brown     else if (cStart <= point && point < cEnd) vertexchart = PETSC_FALSE; /* Some interpolated points exist in the chart */
5303796d0a68SJed Brown     else vertexchart = PETSC_TRUE;                                       /* Some interpolated points are not in chart; assume dofs only at cells and vertices */
53049e8305c2SJed Brown   }
53059566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &Nf));
5306bb197d40SJed Brown   for (PetscInt d=1; d<=dim; d++) {
5307bb197d40SJed Brown     PetscInt k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0;
5308bb197d40SJed Brown     PetscInt *perm;
5309bb197d40SJed Brown 
53103194fc30SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
53119566063dSJacob Faibussowitsch       PetscCall(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k));
5312bb197d40SJed Brown       size += PetscPowInt(k+1, d)*Nc;
53133194fc30SMatthew G. Knepley     }
53149566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(size, &perm));
53153194fc30SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
5316bb197d40SJed Brown       switch (d) {
5317babf31e0SJed Brown       case 1:
53189566063dSJacob Faibussowitsch         PetscCall(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k));
5319babf31e0SJed Brown         /*
5320babf31e0SJed Brown          Original ordering is [ edge of length k-1; vtx0; vtx1 ]
5321babf31e0SJed Brown          We want              [ vtx0; edge of length k-1; vtx1 ]
5322babf31e0SJed Brown          */
5323babf31e0SJed Brown         for (c=0; c<Nc; c++,offset++) perm[offset] = (k-1)*Nc + c + foffset;
5324babf31e0SJed Brown         for (i=0; i<k-1; i++) for (c=0; c<Nc; c++,offset++) perm[offset] = i*Nc + c + foffset;
5325babf31e0SJed Brown         for (c=0; c<Nc; c++,offset++) perm[offset] = k*Nc + c + foffset;
5326babf31e0SJed Brown         foffset = offset;
5327babf31e0SJed Brown         break;
532889eabcffSMatthew G. Knepley       case 2:
53293194fc30SMatthew 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} */
53309566063dSJacob Faibussowitsch         PetscCall(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k));
53313194fc30SMatthew G. Knepley         /* The SEM order is
53323194fc30SMatthew G. Knepley 
53333194fc30SMatthew G. Knepley          v_lb, {e_b}, v_rb,
533489eabcffSMatthew G. Knepley          e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r,
53353194fc30SMatthew G. Knepley          v_lt, reverse {e_t}, v_rt
53363194fc30SMatthew G. Knepley          */
53373194fc30SMatthew G. Knepley         {
53383194fc30SMatthew G. Knepley           const PetscInt of   = 0;
53393194fc30SMatthew G. Knepley           const PetscInt oeb  = of   + PetscSqr(k-1);
53403194fc30SMatthew G. Knepley           const PetscInt oer  = oeb  + (k-1);
53413194fc30SMatthew G. Knepley           const PetscInt oet  = oer  + (k-1);
53423194fc30SMatthew G. Knepley           const PetscInt oel  = oet  + (k-1);
53433194fc30SMatthew G. Knepley           const PetscInt ovlb = oel  + (k-1);
53443194fc30SMatthew G. Knepley           const PetscInt ovrb = ovlb + 1;
53453194fc30SMatthew G. Knepley           const PetscInt ovrt = ovrb + 1;
53463194fc30SMatthew G. Knepley           const PetscInt ovlt = ovrt + 1;
53473194fc30SMatthew G. Knepley           PetscInt       o;
53483194fc30SMatthew G. Knepley 
53493194fc30SMatthew G. Knepley           /* bottom */
53503194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb*Nc + c + foffset;
53513194fc30SMatthew G. Knepley           for (o = oeb; o < oer; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
53523194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb*Nc + c + foffset;
53533194fc30SMatthew G. Knepley           /* middle */
53543194fc30SMatthew G. Knepley           for (i = 0; i < k-1; ++i) {
53553194fc30SMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel+(k-2)-i)*Nc + c + foffset;
53563194fc30SMatthew 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;
53573194fc30SMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer+i)*Nc + c + foffset;
53583194fc30SMatthew G. Knepley           }
53593194fc30SMatthew G. Knepley           /* top */
53603194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt*Nc + c + foffset;
53613194fc30SMatthew G. Knepley           for (o = oel-1; o >= oet; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
53623194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt*Nc + c + foffset;
53633194fc30SMatthew G. Knepley           foffset = offset;
53643194fc30SMatthew G. Knepley         }
536589eabcffSMatthew G. Knepley         break;
536689eabcffSMatthew G. Knepley       case 3:
536789eabcffSMatthew G. Knepley         /* The original hex closure is
536889eabcffSMatthew G. Knepley 
536989eabcffSMatthew G. Knepley          {c,
537089eabcffSMatthew G. Knepley          f_b, f_t, f_f, f_b, f_r, f_l,
537189eabcffSMatthew 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,
537289eabcffSMatthew G. Knepley          v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb}
537389eabcffSMatthew G. Knepley          */
53749566063dSJacob Faibussowitsch         PetscCall(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k));
537589eabcffSMatthew G. Knepley         /* The SEM order is
537689eabcffSMatthew G. Knepley          Bottom Slice
537789eabcffSMatthew G. Knepley          v_blf, {e^{(k-1)-n}_bf}, v_brf,
537889eabcffSMatthew G. Knepley          e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br,
537989eabcffSMatthew G. Knepley          v_blb, {e_bb}, v_brb,
538089eabcffSMatthew G. Knepley 
538189eabcffSMatthew G. Knepley          Middle Slice (j)
538289eabcffSMatthew G. Knepley          {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf,
538389eabcffSMatthew G. Knepley          f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r,
538489eabcffSMatthew G. Knepley          e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb,
538589eabcffSMatthew G. Knepley 
538689eabcffSMatthew G. Knepley          Top Slice
538789eabcffSMatthew G. Knepley          v_tlf, {e_tf}, v_trf,
538889eabcffSMatthew G. Knepley          e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr,
538989eabcffSMatthew G. Knepley          v_tlb, {e^{(k-1)-n}_tb}, v_trb,
539089eabcffSMatthew G. Knepley          */
539189eabcffSMatthew G. Knepley         {
539289eabcffSMatthew G. Knepley           const PetscInt oc    = 0;
539389eabcffSMatthew G. Knepley           const PetscInt ofb   = oc    + PetscSqr(k-1)*(k-1);
539489eabcffSMatthew G. Knepley           const PetscInt oft   = ofb   + PetscSqr(k-1);
539589eabcffSMatthew G. Knepley           const PetscInt off   = oft   + PetscSqr(k-1);
539689eabcffSMatthew G. Knepley           const PetscInt ofk   = off   + PetscSqr(k-1);
539789eabcffSMatthew G. Knepley           const PetscInt ofr   = ofk   + PetscSqr(k-1);
539889eabcffSMatthew G. Knepley           const PetscInt ofl   = ofr   + PetscSqr(k-1);
539989eabcffSMatthew G. Knepley           const PetscInt oebl  = ofl   + PetscSqr(k-1);
540089eabcffSMatthew G. Knepley           const PetscInt oebb  = oebl  + (k-1);
540189eabcffSMatthew G. Knepley           const PetscInt oebr  = oebb  + (k-1);
540289eabcffSMatthew G. Knepley           const PetscInt oebf  = oebr  + (k-1);
540389eabcffSMatthew G. Knepley           const PetscInt oetf  = oebf  + (k-1);
540489eabcffSMatthew G. Knepley           const PetscInt oetr  = oetf  + (k-1);
540589eabcffSMatthew G. Knepley           const PetscInt oetb  = oetr  + (k-1);
540689eabcffSMatthew G. Knepley           const PetscInt oetl  = oetb  + (k-1);
540789eabcffSMatthew G. Knepley           const PetscInt oerf  = oetl  + (k-1);
540889eabcffSMatthew G. Knepley           const PetscInt oelf  = oerf  + (k-1);
540989eabcffSMatthew G. Knepley           const PetscInt oelb  = oelf  + (k-1);
541089eabcffSMatthew G. Knepley           const PetscInt oerb  = oelb  + (k-1);
541189eabcffSMatthew G. Knepley           const PetscInt ovblf = oerb  + (k-1);
541289eabcffSMatthew G. Knepley           const PetscInt ovblb = ovblf + 1;
541389eabcffSMatthew G. Knepley           const PetscInt ovbrb = ovblb + 1;
541489eabcffSMatthew G. Knepley           const PetscInt ovbrf = ovbrb + 1;
541589eabcffSMatthew G. Knepley           const PetscInt ovtlf = ovbrf + 1;
541689eabcffSMatthew G. Knepley           const PetscInt ovtrf = ovtlf + 1;
541789eabcffSMatthew G. Knepley           const PetscInt ovtrb = ovtrf + 1;
541889eabcffSMatthew G. Knepley           const PetscInt ovtlb = ovtrb + 1;
541989eabcffSMatthew G. Knepley           PetscInt       o, n;
542089eabcffSMatthew G. Knepley 
542189eabcffSMatthew G. Knepley           /* Bottom Slice */
542289eabcffSMatthew G. Knepley           /*   bottom */
542389eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf*Nc + c + foffset;
542489eabcffSMatthew G. Knepley           for (o = oetf-1; o >= oebf; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
542589eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf*Nc + c + foffset;
542689eabcffSMatthew G. Knepley           /*   middle */
542789eabcffSMatthew G. Knepley           for (i = 0; i < k-1; ++i) {
542889eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl+i)*Nc + c + foffset;
5429316b7f87SMax 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;}
543089eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr+(k-2)-i)*Nc + c + foffset;
54313194fc30SMatthew G. Knepley           }
543289eabcffSMatthew G. Knepley           /*   top */
543389eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb*Nc + c + foffset;
543489eabcffSMatthew G. Knepley           for (o = oebb; o < oebr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
543589eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb*Nc + c + foffset;
543689eabcffSMatthew G. Knepley 
543789eabcffSMatthew G. Knepley           /* Middle Slice */
543889eabcffSMatthew G. Knepley           for (j = 0; j < k-1; ++j) {
543989eabcffSMatthew G. Knepley             /*   bottom */
544089eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf+(k-2)-j)*Nc + c + foffset;
544189eabcffSMatthew 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;
544289eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf+j)*Nc + c + foffset;
544389eabcffSMatthew G. Knepley             /*   middle */
544489eabcffSMatthew G. Knepley             for (i = 0; i < k-1; ++i) {
544589eabcffSMatthew G. Knepley               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl+i*(k-1)+j)*Nc + c + foffset;
544689eabcffSMatthew 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;
544789eabcffSMatthew G. Knepley               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr+j*(k-1)+i)*Nc + c + foffset;
544889eabcffSMatthew G. Knepley             }
544989eabcffSMatthew G. Knepley             /*   top */
545089eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb+j)*Nc + c + foffset;
545189eabcffSMatthew 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;
545289eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb+(k-2)-j)*Nc + c + foffset;
545389eabcffSMatthew G. Knepley           }
545489eabcffSMatthew G. Knepley 
545589eabcffSMatthew G. Knepley           /* Top Slice */
545689eabcffSMatthew G. Knepley           /*   bottom */
545789eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf*Nc + c + foffset;
545889eabcffSMatthew G. Knepley           for (o = oetf; o < oetr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
545989eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf*Nc + c + foffset;
546089eabcffSMatthew G. Knepley           /*   middle */
546189eabcffSMatthew G. Knepley           for (i = 0; i < k-1; ++i) {
546289eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl+(k-2)-i)*Nc + c + foffset;
546389eabcffSMatthew 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;
546489eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr+i)*Nc + c + foffset;
546589eabcffSMatthew G. Knepley           }
546689eabcffSMatthew G. Knepley           /*   top */
546789eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb*Nc + c + foffset;
546889eabcffSMatthew G. Knepley           for (o = oetl-1; o >= oetb; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
546989eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb*Nc + c + foffset;
547089eabcffSMatthew G. Knepley 
547189eabcffSMatthew G. Knepley           foffset = offset;
547289eabcffSMatthew G. Knepley         }
547389eabcffSMatthew G. Knepley         break;
547463a3b9bcSJacob Faibussowitsch       default: SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %" PetscInt_FMT, d);
547589eabcffSMatthew G. Knepley       }
547689eabcffSMatthew G. Knepley     }
547763a3b9bcSJacob Faibussowitsch     PetscCheck(offset == size,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Number of permutation entries %" PetscInt_FMT " != %" PetscInt_FMT, offset, size);
54783194fc30SMatthew G. Knepley     /* Check permutation */
54793194fc30SMatthew G. Knepley     {
54803194fc30SMatthew G. Knepley       PetscInt *check;
54813194fc30SMatthew G. Knepley 
54829566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(size, &check));
54831dca8a05SBarry Smith       for (i = 0; i < size; ++i) {
54841dca8a05SBarry Smith         check[i] = -1;
54851dca8a05SBarry 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]);
54861dca8a05SBarry Smith       }
54873194fc30SMatthew G. Knepley       for (i = 0; i < size; ++i) check[perm[i]] = i;
54881dca8a05SBarry Smith       for (i = 0; i < size; ++i) PetscCheck(check[i] >= 0,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Missing permutation index %" PetscInt_FMT, i);
54899566063dSJacob Faibussowitsch       PetscCall(PetscFree(check));
54903194fc30SMatthew G. Knepley     }
54919566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size, PETSC_OWN_POINTER, perm));
5492a05c9aa3SJed Brown     if (d == dim) { // Add permutation for localized (in case this is a coordinate DM)
5493a05c9aa3SJed Brown       PetscInt *loc_perm;
54949566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(size*2, &loc_perm));
5495a05c9aa3SJed Brown       for (PetscInt i=0; i<size; i++) {
5496a05c9aa3SJed Brown         loc_perm[i] = perm[i];
5497a05c9aa3SJed Brown         loc_perm[size+i] = size + perm[i];
5498a05c9aa3SJed Brown       }
54999566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size*2, PETSC_OWN_POINTER, loc_perm));
5500a05c9aa3SJed Brown     }
5501bb197d40SJed Brown   }
55023194fc30SMatthew G. Knepley   PetscFunctionReturn(0);
55033194fc30SMatthew G. Knepley }
55043194fc30SMatthew G. Knepley 
5505e071409bSToby Isaac PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace)
5506e071409bSToby Isaac {
5507e071409bSToby Isaac   PetscDS        prob;
5508e071409bSToby Isaac   PetscInt       depth, Nf, h;
5509e071409bSToby Isaac   DMLabel        label;
5510e071409bSToby Isaac 
5511e071409bSToby Isaac   PetscFunctionBeginHot;
55129566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &prob));
5513e071409bSToby Isaac   Nf      = prob->Nf;
5514e071409bSToby Isaac   label   = dm->depthLabel;
5515e071409bSToby Isaac   *dspace = NULL;
5516e071409bSToby Isaac   if (field < Nf) {
5517e071409bSToby Isaac     PetscObject disc = prob->disc[field];
5518e071409bSToby Isaac 
5519e071409bSToby Isaac     if (disc->classid == PETSCFE_CLASSID) {
5520e071409bSToby Isaac       PetscDualSpace dsp;
5521e071409bSToby Isaac 
55229566063dSJacob Faibussowitsch       PetscCall(PetscFEGetDualSpace((PetscFE)disc,&dsp));
55239566063dSJacob Faibussowitsch       PetscCall(DMLabelGetNumValues(label,&depth));
55249566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(label,point,&h));
5525e071409bSToby Isaac       h    = depth - 1 - h;
5526e071409bSToby Isaac       if (h) {
55279566063dSJacob Faibussowitsch         PetscCall(PetscDualSpaceGetHeightSubspace(dsp,h,dspace));
5528e071409bSToby Isaac       } else {
5529e071409bSToby Isaac         *dspace = dsp;
5530e071409bSToby Isaac       }
5531e071409bSToby Isaac     }
5532e071409bSToby Isaac   }
5533e071409bSToby Isaac   PetscFunctionReturn(0);
5534e071409bSToby Isaac }
5535e071409bSToby Isaac 
55369fbee547SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
5537a6dfd86eSKarl Rupp {
553828351e22SJed Brown   PetscScalar    *array;
553928351e22SJed Brown   const PetscScalar *vArray;
5540d9917b9dSMatthew G. Knepley   const PetscInt *cone, *coneO;
55411a271a75SMatthew G. Knepley   PetscInt        pStart, pEnd, p, numPoints, size = 0, offset = 0;
5542552f7358SJed Brown 
55431b406b76SMatthew G. Knepley   PetscFunctionBeginHot;
55449566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
55459566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, point, &numPoints));
55469566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, point, &cone));
55479566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeOrientation(dm, point, &coneO));
55483f7cbbe7SMatthew G. Knepley   if (!values || !*values) {
55499df71ca4SMatthew G. Knepley     if ((point >= pStart) && (point < pEnd)) {
55509df71ca4SMatthew G. Knepley       PetscInt dof;
5551d9917b9dSMatthew G. Knepley 
55529566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, point, &dof));
55539df71ca4SMatthew G. Knepley       size += dof;
55549df71ca4SMatthew G. Knepley     }
55559df71ca4SMatthew G. Knepley     for (p = 0; p < numPoints; ++p) {
55569df71ca4SMatthew G. Knepley       const PetscInt cp = cone[p];
55572a3aaacfSMatthew G. Knepley       PetscInt       dof;
55585a1bb5cfSMatthew G. Knepley 
55595a1bb5cfSMatthew G. Knepley       if ((cp < pStart) || (cp >= pEnd)) continue;
55609566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, cp, &dof));
55615a1bb5cfSMatthew G. Knepley       size += dof;
55625a1bb5cfSMatthew G. Knepley     }
55633f7cbbe7SMatthew G. Knepley     if (!values) {
55643f7cbbe7SMatthew G. Knepley       if (csize) *csize = size;
55653f7cbbe7SMatthew G. Knepley       PetscFunctionReturn(0);
55663f7cbbe7SMatthew G. Knepley     }
55679566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, size, MPIU_SCALAR, &array));
5568982e9ed1SMatthew G. Knepley   } else {
5569982e9ed1SMatthew G. Knepley     array = *values;
5570982e9ed1SMatthew G. Knepley   }
55719df71ca4SMatthew G. Knepley   size = 0;
557228351e22SJed Brown   PetscCall(VecGetArrayRead(v, &vArray));
55739df71ca4SMatthew G. Knepley   if ((point >= pStart) && (point < pEnd)) {
55749df71ca4SMatthew G. Knepley     PetscInt     dof, off, d;
557528351e22SJed Brown     const PetscScalar *varr;
5576d9917b9dSMatthew G. Knepley 
55779566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, point, &dof));
55789566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, point, &off));
55799df71ca4SMatthew G. Knepley     varr = &vArray[off];
55801a271a75SMatthew G. Knepley     for (d = 0; d < dof; ++d, ++offset) {
55811a271a75SMatthew G. Knepley       array[offset] = varr[d];
55829df71ca4SMatthew G. Knepley     }
55839df71ca4SMatthew G. Knepley     size += dof;
55849df71ca4SMatthew G. Knepley   }
55859df71ca4SMatthew G. Knepley   for (p = 0; p < numPoints; ++p) {
55869df71ca4SMatthew G. Knepley     const PetscInt cp = cone[p];
55879df71ca4SMatthew G. Knepley     PetscInt       o  = coneO[p];
55885a1bb5cfSMatthew G. Knepley     PetscInt       dof, off, d;
558928351e22SJed Brown     const PetscScalar *varr;
55905a1bb5cfSMatthew G. Knepley 
559152ed52e8SMatthew G. Knepley     if ((cp < pStart) || (cp >= pEnd)) continue;
55929566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, cp, &dof));
55939566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, cp, &off));
55945a1bb5cfSMatthew G. Knepley     varr = &vArray[off];
55955a1bb5cfSMatthew G. Knepley     if (o >= 0) {
55961a271a75SMatthew G. Knepley       for (d = 0; d < dof; ++d, ++offset) {
55971a271a75SMatthew G. Knepley         array[offset] = varr[d];
55985a1bb5cfSMatthew G. Knepley       }
55995a1bb5cfSMatthew G. Knepley     } else {
56001a271a75SMatthew G. Knepley       for (d = dof-1; d >= 0; --d, ++offset) {
56011a271a75SMatthew G. Knepley         array[offset] = varr[d];
56025a1bb5cfSMatthew G. Knepley       }
56035a1bb5cfSMatthew G. Knepley     }
56049df71ca4SMatthew G. Knepley     size += dof;
56055a1bb5cfSMatthew G. Knepley   }
560628351e22SJed Brown   PetscCall(VecRestoreArrayRead(v, &vArray));
56079df71ca4SMatthew G. Knepley   if (!*values) {
56085a1bb5cfSMatthew G. Knepley     if (csize) *csize = size;
56095a1bb5cfSMatthew G. Knepley     *values = array;
56109df71ca4SMatthew G. Knepley   } else {
561163a3b9bcSJacob Faibussowitsch     PetscCheck(size <= *csize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size);
56128c312ff3SMatthew G. Knepley     *csize = size;
56139df71ca4SMatthew G. Knepley   }
56145a1bb5cfSMatthew G. Knepley   PetscFunctionReturn(0);
56155a1bb5cfSMatthew G. Knepley }
5616d9917b9dSMatthew G. Knepley 
561727f02ce8SMatthew G. Knepley /* Compress out points not in the section */
56189fbee547SJacob Faibussowitsch static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[])
561927f02ce8SMatthew G. Knepley {
562027f02ce8SMatthew G. Knepley   const PetscInt np = *numPoints;
562127f02ce8SMatthew G. Knepley   PetscInt       pStart, pEnd, p, q;
562227f02ce8SMatthew G. Knepley 
56239566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
562427f02ce8SMatthew G. Knepley   for (p = 0, q = 0; p < np; ++p) {
562527f02ce8SMatthew G. Knepley     const PetscInt r = points[p*2];
562627f02ce8SMatthew G. Knepley     if ((r >= pStart) && (r < pEnd)) {
562727f02ce8SMatthew G. Knepley       points[q*2]   = r;
562827f02ce8SMatthew G. Knepley       points[q*2+1] = points[p*2+1];
562927f02ce8SMatthew G. Knepley       ++q;
563027f02ce8SMatthew G. Knepley     }
563127f02ce8SMatthew G. Knepley   }
563227f02ce8SMatthew G. Knepley   *numPoints = q;
563327f02ce8SMatthew G. Knepley   return 0;
563427f02ce8SMatthew G. Knepley }
563527f02ce8SMatthew G. Knepley 
563697529cf3SJed Brown /* Compressed closure does not apply closure permutation */
56371dc59d61SMatthew G. Knepley PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp)
5638923c78e0SToby Isaac {
563927f02ce8SMatthew G. Knepley   const PetscInt *cla = NULL;
5640923c78e0SToby Isaac   PetscInt       np, *pts = NULL;
5641923c78e0SToby Isaac 
5642923c78e0SToby Isaac   PetscFunctionBeginHot;
56439566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureIndex(section, (PetscObject) dm, clSec, clPoints));
564427f02ce8SMatthew G. Knepley   if (*clPoints) {
5645923c78e0SToby Isaac     PetscInt dof, off;
5646923c78e0SToby Isaac 
56479566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(*clSec, point, &dof));
56489566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(*clSec, point, &off));
56499566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(*clPoints, &cla));
5650923c78e0SToby Isaac     np   = dof/2;
5651923c78e0SToby Isaac     pts  = (PetscInt *) &cla[off];
565227f02ce8SMatthew G. Knepley   } else {
56539566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &np, &pts));
56549566063dSJacob Faibussowitsch     PetscCall(CompressPoints_Private(section, &np, pts));
5655923c78e0SToby Isaac   }
5656923c78e0SToby Isaac   *numPoints = np;
5657923c78e0SToby Isaac   *points    = pts;
5658923c78e0SToby Isaac   *clp       = cla;
5659923c78e0SToby Isaac   PetscFunctionReturn(0);
5660923c78e0SToby Isaac }
5661923c78e0SToby Isaac 
56621dc59d61SMatthew G. Knepley PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp)
5663923c78e0SToby Isaac {
5664923c78e0SToby Isaac   PetscFunctionBeginHot;
5665923c78e0SToby Isaac   if (!*clPoints) {
56669566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points));
5667923c78e0SToby Isaac   } else {
56689566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(*clPoints, clp));
5669923c78e0SToby Isaac   }
5670923c78e0SToby Isaac   *numPoints = 0;
5671923c78e0SToby Isaac   *points    = NULL;
5672923c78e0SToby Isaac   *clSec     = NULL;
5673923c78e0SToby Isaac   *clPoints  = NULL;
5674923c78e0SToby Isaac   *clp       = NULL;
5675923c78e0SToby Isaac   PetscFunctionReturn(0);
5676923c78e0SToby Isaac }
5677923c78e0SToby Isaac 
56789fbee547SJacob 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[])
56791a271a75SMatthew G. Knepley {
56801a271a75SMatthew G. Knepley   PetscInt          offset = 0, p;
568197e99dd9SToby Isaac   const PetscInt    **perms = NULL;
568297e99dd9SToby Isaac   const PetscScalar **flips = NULL;
56831a271a75SMatthew G. Knepley 
56841a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
5685fe02ba77SJed Brown   *size = 0;
56869566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips));
568797e99dd9SToby Isaac   for (p = 0; p < numPoints; p++) {
568897e99dd9SToby Isaac     const PetscInt    point = points[2*p];
568997e99dd9SToby Isaac     const PetscInt    *perm = perms ? perms[p] : NULL;
569097e99dd9SToby Isaac     const PetscScalar *flip = flips ? flips[p] : NULL;
56911a271a75SMatthew G. Knepley     PetscInt          dof, off, d;
56921a271a75SMatthew G. Knepley     const PetscScalar *varr;
56931a271a75SMatthew G. Knepley 
56949566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, point, &dof));
56959566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, point, &off));
56961a271a75SMatthew G. Knepley     varr = &vArray[off];
569797e99dd9SToby Isaac     if (clperm) {
569897e99dd9SToby Isaac       if (perm) {
569997e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]]  = varr[d];
57001a271a75SMatthew G. Knepley       } else {
570197e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset +      d ]]  = varr[d];
570297e99dd9SToby Isaac       }
570397e99dd9SToby Isaac       if (flip) {
570497e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset +      d ]] *= flip[d];
570597e99dd9SToby Isaac       }
570697e99dd9SToby Isaac     } else {
570797e99dd9SToby Isaac       if (perm) {
570897e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset + perm[d]]  = varr[d];
570997e99dd9SToby Isaac       } else {
571097e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset +      d ]  = varr[d];
571197e99dd9SToby Isaac       }
571297e99dd9SToby Isaac       if (flip) {
571397e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset +      d ] *= flip[d];
57141a271a75SMatthew G. Knepley       }
57151a271a75SMatthew G. Knepley     }
571697e99dd9SToby Isaac     offset += dof;
571797e99dd9SToby Isaac   }
57189566063dSJacob Faibussowitsch   PetscCall(PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips));
57191a271a75SMatthew G. Knepley   *size = offset;
57201a271a75SMatthew G. Knepley   PetscFunctionReturn(0);
57211a271a75SMatthew G. Knepley }
57221a271a75SMatthew G. Knepley 
57239fbee547SJacob 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[])
57241a271a75SMatthew G. Knepley {
57251a271a75SMatthew G. Knepley   PetscInt          offset = 0, f;
57261a271a75SMatthew G. Knepley 
57271a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
5728fe02ba77SJed Brown   *size = 0;
57291a271a75SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
573097e99dd9SToby Isaac     PetscInt          p;
573197e99dd9SToby Isaac     const PetscInt    **perms = NULL;
573297e99dd9SToby Isaac     const PetscScalar **flips = NULL;
57331a271a75SMatthew G. Knepley 
57349566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips));
573597e99dd9SToby Isaac     for (p = 0; p < numPoints; p++) {
573697e99dd9SToby Isaac       const PetscInt    point = points[2*p];
573797e99dd9SToby Isaac       PetscInt          fdof, foff, b;
57381a271a75SMatthew G. Knepley       const PetscScalar *varr;
573997e99dd9SToby Isaac       const PetscInt    *perm = perms ? perms[p] : NULL;
574097e99dd9SToby Isaac       const PetscScalar *flip = flips ? flips[p] : NULL;
57411a271a75SMatthew G. Knepley 
57429566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
57439566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
57441a271a75SMatthew G. Knepley       varr = &vArray[foff];
574597e99dd9SToby Isaac       if (clperm) {
574697e99dd9SToby Isaac         if (perm) {for (b = 0; b < fdof; b++) {array[clperm[offset + perm[b]]]  = varr[b];}}
574797e99dd9SToby Isaac         else      {for (b = 0; b < fdof; b++) {array[clperm[offset +      b ]]  = varr[b];}}
574897e99dd9SToby Isaac         if (flip) {for (b = 0; b < fdof; b++) {array[clperm[offset +      b ]] *= flip[b];}}
57491a271a75SMatthew G. Knepley       } else {
575097e99dd9SToby Isaac         if (perm) {for (b = 0; b < fdof; b++) {array[offset + perm[b]]  = varr[b];}}
575197e99dd9SToby Isaac         else      {for (b = 0; b < fdof; b++) {array[offset +      b ]  = varr[b];}}
575297e99dd9SToby Isaac         if (flip) {for (b = 0; b < fdof; b++) {array[offset +      b ] *= flip[b];}}
57531a271a75SMatthew G. Knepley       }
575497e99dd9SToby Isaac       offset += fdof;
57551a271a75SMatthew G. Knepley     }
57569566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips));
57571a271a75SMatthew G. Knepley   }
57581a271a75SMatthew G. Knepley   *size = offset;
57591a271a75SMatthew G. Knepley   PetscFunctionReturn(0);
57601a271a75SMatthew G. Knepley }
57611a271a75SMatthew G. Knepley 
5762552f7358SJed Brown /*@C
5763552f7358SJed Brown   DMPlexVecGetClosure - Get an array of the values on the closure of 'point'
5764552f7358SJed Brown 
5765552f7358SJed Brown   Not collective
5766552f7358SJed Brown 
5767552f7358SJed Brown   Input Parameters:
5768552f7358SJed Brown + dm - The DM
5769552f7358SJed Brown . section - The section describing the layout in v, or NULL to use the default section
5770552f7358SJed Brown . v - The local vector
57716b867d5aSJose E. Roman - point - The point in the DM
5772552f7358SJed Brown 
57736b867d5aSJose E. Roman   Input/Output Parameters:
57746b867d5aSJose E. Roman + csize  - The size of the input values array, or NULL; on output the number of values in the closure
57756b867d5aSJose E. Roman - values - An array to use for the values, or NULL to have it allocated automatically;
57766b867d5aSJose E. Roman            if the user provided NULL, it is a borrowed array and should not be freed
577722c1ee49SMatthew G. Knepley 
577822c1ee49SMatthew G. Knepley $ Note that DMPlexVecGetClosure/DMPlexVecRestoreClosure only allocates the values array if it set to NULL in the
577922c1ee49SMatthew G. Knepley $ calling function. This is because DMPlexVecGetClosure() is typically called in the inner loop of a Vec or Mat
578022c1ee49SMatthew G. Knepley $ assembly function, and a user may already have allocated storage for this operation.
578122c1ee49SMatthew G. Knepley $
578222c1ee49SMatthew G. Knepley $ A typical use could be
578322c1ee49SMatthew G. Knepley $
578422c1ee49SMatthew G. Knepley $  values = NULL;
57859566063dSJacob Faibussowitsch $  PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values));
578622c1ee49SMatthew G. Knepley $  for (cl = 0; cl < clSize; ++cl) {
578722c1ee49SMatthew G. Knepley $    <Compute on closure>
578822c1ee49SMatthew G. Knepley $  }
57899566063dSJacob Faibussowitsch $  PetscCall(DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values));
579022c1ee49SMatthew G. Knepley $
579122c1ee49SMatthew G. Knepley $ or
579222c1ee49SMatthew G. Knepley $
579322c1ee49SMatthew G. Knepley $  PetscMalloc1(clMaxSize, &values);
579422c1ee49SMatthew G. Knepley $  for (p = pStart; p < pEnd; ++p) {
579522c1ee49SMatthew G. Knepley $    clSize = clMaxSize;
57969566063dSJacob Faibussowitsch $    PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values));
579722c1ee49SMatthew G. Knepley $    for (cl = 0; cl < clSize; ++cl) {
579822c1ee49SMatthew G. Knepley $      <Compute on closure>
579922c1ee49SMatthew G. Knepley $    }
580022c1ee49SMatthew G. Knepley $  }
580122c1ee49SMatthew G. Knepley $  PetscFree(values);
5802552f7358SJed Brown 
5803552f7358SJed Brown   Fortran Notes:
5804552f7358SJed Brown   Since it returns an array, this routine is only available in Fortran 90, and you must
5805552f7358SJed Brown   include petsc.h90 in your code.
5806552f7358SJed Brown 
5807552f7358SJed Brown   The csize argument is not present in the Fortran 90 binding since it is internal to the array.
5808552f7358SJed Brown 
5809552f7358SJed Brown   Level: intermediate
5810552f7358SJed Brown 
5811db781477SPatrick Sanan .seealso `DMPlexVecRestoreClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()`
5812552f7358SJed Brown @*/
5813552f7358SJed Brown PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
5814552f7358SJed Brown {
5815552f7358SJed Brown   PetscSection       clSection;
5816d9917b9dSMatthew G. Knepley   IS                 clPoints;
5817552f7358SJed Brown   PetscInt          *points = NULL;
5818c459fbc1SJed Brown   const PetscInt    *clp, *perm;
5819c459fbc1SJed Brown   PetscInt           depth, numFields, numPoints, asize;
5820552f7358SJed Brown 
5821d9917b9dSMatthew G. Knepley   PetscFunctionBeginHot;
5822552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
58239566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
58241a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
58251a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
58269566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
58279566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
5828552f7358SJed Brown   if (depth == 1 && numFields < 2) {
58299566063dSJacob Faibussowitsch     PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values));
5830552f7358SJed Brown     PetscFunctionReturn(0);
5831552f7358SJed Brown   }
58321a271a75SMatthew G. Knepley   /* Get points */
58339566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
5834c459fbc1SJed Brown   /* Get sizes */
5835c459fbc1SJed Brown   asize = 0;
5836c459fbc1SJed Brown   for (PetscInt p = 0; p < numPoints*2; p += 2) {
5837c459fbc1SJed Brown     PetscInt dof;
58389566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[p], &dof));
58391a271a75SMatthew G. Knepley     asize += dof;
5840552f7358SJed Brown   }
5841c459fbc1SJed Brown   if (values) {
5842c459fbc1SJed Brown     const PetscScalar *vArray;
5843c459fbc1SJed Brown     PetscInt          size;
5844c459fbc1SJed Brown 
5845c459fbc1SJed Brown     if (*values) {
584663a3b9bcSJacob 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);
58479566063dSJacob Faibussowitsch     } else PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, values));
58489566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, asize, &perm));
58499566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(v, &vArray));
58501a271a75SMatthew G. Knepley     /* Get values */
58519566063dSJacob Faibussowitsch     if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values));
58529566063dSJacob Faibussowitsch     else               PetscCall(DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values));
585363a3b9bcSJacob Faibussowitsch     PetscCheck(asize == size,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Section size %" PetscInt_FMT " does not match Vec closure size %" PetscInt_FMT, asize, size);
58541a271a75SMatthew G. Knepley     /* Cleanup array */
58559566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(v, &vArray));
5856d0f6b257SMatthew G. Knepley   }
5857c459fbc1SJed Brown   if (csize) *csize = asize;
5858c459fbc1SJed Brown   /* Cleanup points */
58599566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
5860552f7358SJed Brown   PetscFunctionReturn(0);
5861552f7358SJed Brown }
5862552f7358SJed Brown 
5863e5c487bfSMatthew G. Knepley PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[])
5864e5c487bfSMatthew G. Knepley {
5865e5c487bfSMatthew G. Knepley   DMLabel            depthLabel;
5866e5c487bfSMatthew G. Knepley   PetscSection       clSection;
5867e5c487bfSMatthew G. Knepley   IS                 clPoints;
5868e5c487bfSMatthew G. Knepley   PetscScalar       *array;
5869e5c487bfSMatthew G. Knepley   const PetscScalar *vArray;
5870e5c487bfSMatthew G. Knepley   PetscInt          *points = NULL;
5871c459fbc1SJed Brown   const PetscInt    *clp, *perm = NULL;
5872c459fbc1SJed Brown   PetscInt           mdepth, numFields, numPoints, Np = 0, p, clsize, size;
5873e5c487bfSMatthew G. Knepley 
5874e5c487bfSMatthew G. Knepley   PetscFunctionBeginHot;
5875e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
58769566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
5877e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
5878e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
58799566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &mdepth));
58809566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
58819566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
5882e5c487bfSMatthew G. Knepley   if (mdepth == 1 && numFields < 2) {
58839566063dSJacob Faibussowitsch     PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values));
5884e5c487bfSMatthew G. Knepley     PetscFunctionReturn(0);
5885e5c487bfSMatthew G. Knepley   }
5886e5c487bfSMatthew G. Knepley   /* Get points */
58879566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
5888c459fbc1SJed Brown   for (clsize=0,p=0; p<Np; p++) {
5889c459fbc1SJed Brown     PetscInt dof;
58909566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[2*p], &dof));
5891c459fbc1SJed Brown     clsize += dof;
5892c459fbc1SJed Brown   }
58939566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &perm));
5894e5c487bfSMatthew G. Knepley   /* Filter points */
5895e5c487bfSMatthew G. Knepley   for (p = 0; p < numPoints*2; p += 2) {
5896e5c487bfSMatthew G. Knepley     PetscInt dep;
5897e5c487bfSMatthew G. Knepley 
58989566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(depthLabel, points[p], &dep));
5899e5c487bfSMatthew G. Knepley     if (dep != depth) continue;
5900e5c487bfSMatthew G. Knepley     points[Np*2+0] = points[p];
5901e5c487bfSMatthew G. Knepley     points[Np*2+1] = points[p+1];
5902e5c487bfSMatthew G. Knepley     ++Np;
5903e5c487bfSMatthew G. Knepley   }
5904e5c487bfSMatthew G. Knepley   /* Get array */
5905e5c487bfSMatthew G. Knepley   if (!values || !*values) {
5906e5c487bfSMatthew G. Knepley     PetscInt asize = 0, dof;
5907e5c487bfSMatthew G. Knepley 
5908e5c487bfSMatthew G. Knepley     for (p = 0; p < Np*2; p += 2) {
59099566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, points[p], &dof));
5910e5c487bfSMatthew G. Knepley       asize += dof;
5911e5c487bfSMatthew G. Knepley     }
5912e5c487bfSMatthew G. Knepley     if (!values) {
59139566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
5914e5c487bfSMatthew G. Knepley       if (csize) *csize = asize;
5915e5c487bfSMatthew G. Knepley       PetscFunctionReturn(0);
5916e5c487bfSMatthew G. Knepley     }
59179566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, &array));
5918e5c487bfSMatthew G. Knepley   } else {
5919e5c487bfSMatthew G. Knepley     array = *values;
5920e5c487bfSMatthew G. Knepley   }
59219566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(v, &vArray));
5922e5c487bfSMatthew G. Knepley   /* Get values */
59239566063dSJacob Faibussowitsch   if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array));
59249566063dSJacob Faibussowitsch   else               PetscCall(DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array));
5925e5c487bfSMatthew G. Knepley   /* Cleanup points */
59269566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
5927e5c487bfSMatthew G. Knepley   /* Cleanup array */
59289566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(v, &vArray));
5929e5c487bfSMatthew G. Knepley   if (!*values) {
5930e5c487bfSMatthew G. Knepley     if (csize) *csize = size;
5931e5c487bfSMatthew G. Knepley     *values = array;
5932e5c487bfSMatthew G. Knepley   } else {
593363a3b9bcSJacob Faibussowitsch     PetscCheck(size <= *csize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size);
5934e5c487bfSMatthew G. Knepley     *csize = size;
5935e5c487bfSMatthew G. Knepley   }
5936e5c487bfSMatthew G. Knepley   PetscFunctionReturn(0);
5937e5c487bfSMatthew G. Knepley }
5938e5c487bfSMatthew G. Knepley 
5939552f7358SJed Brown /*@C
5940552f7358SJed Brown   DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point'
5941552f7358SJed Brown 
5942552f7358SJed Brown   Not collective
5943552f7358SJed Brown 
5944552f7358SJed Brown   Input Parameters:
5945552f7358SJed Brown + dm - The DM
59460298fd71SBarry Smith . section - The section describing the layout in v, or NULL to use the default section
5947552f7358SJed Brown . v - The local vector
5948eaf898f9SPatrick Sanan . point - The point in the DM
59490298fd71SBarry Smith . csize - The number of values in the closure, or NULL
5950552f7358SJed Brown - values - The array of values, which is a borrowed array and should not be freed
5951552f7358SJed Brown 
595222c1ee49SMatthew 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()
595322c1ee49SMatthew G. Knepley 
59543813dfbdSMatthew G Knepley   Fortran Notes:
59553813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
59563813dfbdSMatthew G Knepley   include petsc.h90 in your code.
59573813dfbdSMatthew G Knepley 
59583813dfbdSMatthew G Knepley   The csize argument is not present in the Fortran 90 binding since it is internal to the array.
59593813dfbdSMatthew G Knepley 
5960552f7358SJed Brown   Level: intermediate
5961552f7358SJed Brown 
5962db781477SPatrick Sanan .seealso `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()`
5963552f7358SJed Brown @*/
59647c1f9639SMatthew G Knepley PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
5965a6dfd86eSKarl Rupp {
5966552f7358SJed Brown   PetscInt       size = 0;
5967552f7358SJed Brown 
5968552f7358SJed Brown   PetscFunctionBegin;
5969552f7358SJed Brown   /* Should work without recalculating size */
59709566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void*) values));
5971c9fdaa05SMatthew G. Knepley   *values = NULL;
5972552f7358SJed Brown   PetscFunctionReturn(0);
5973552f7358SJed Brown }
5974552f7358SJed Brown 
59759fbee547SJacob Faibussowitsch static inline void add   (PetscScalar *x, PetscScalar y) {*x += y;}
59769fbee547SJacob Faibussowitsch static inline void insert(PetscScalar *x, PetscScalar y) {*x  = y;}
5977552f7358SJed Brown 
59789fbee547SJacob 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[])
5979552f7358SJed Brown {
5980552f7358SJed Brown   PetscInt        cdof;   /* The number of constraints on this point */
5981552f7358SJed Brown   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
5982552f7358SJed Brown   PetscScalar    *a;
5983552f7358SJed Brown   PetscInt        off, cind = 0, k;
5984552f7358SJed Brown 
5985552f7358SJed Brown   PetscFunctionBegin;
59869566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
59879566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(section, point, &off));
5988552f7358SJed Brown   a    = &array[off];
5989552f7358SJed Brown   if (!cdof || setBC) {
599097e99dd9SToby Isaac     if (clperm) {
599197e99dd9SToby Isaac       if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));}}
599297e99dd9SToby Isaac       else      {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+     k ]] * (flip ? flip[     k ] : 1.));}}
5993552f7358SJed Brown     } else {
599497e99dd9SToby Isaac       if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));}}
599597e99dd9SToby Isaac       else      {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+     k ] * (flip ? flip[     k ] : 1.));}}
5996552f7358SJed Brown     }
5997552f7358SJed Brown   } else {
59989566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
599997e99dd9SToby Isaac     if (clperm) {
600097e99dd9SToby Isaac       if (perm) {for (k = 0; k < dof; ++k) {
6001552f7358SJed Brown           if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
600297e99dd9SToby Isaac           fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));
6003552f7358SJed Brown         }
6004552f7358SJed Brown       } else {
6005552f7358SJed Brown         for (k = 0; k < dof; ++k) {
6006552f7358SJed Brown           if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
600797e99dd9SToby Isaac           fuse(&a[k], values[clperm[offset+     k ]] * (flip ? flip[     k ] : 1.));
600897e99dd9SToby Isaac         }
600997e99dd9SToby Isaac       }
601097e99dd9SToby Isaac     } else {
601197e99dd9SToby Isaac       if (perm) {
601297e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
601397e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
601497e99dd9SToby Isaac           fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));
601597e99dd9SToby Isaac         }
601697e99dd9SToby Isaac       } else {
601797e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
601897e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
601997e99dd9SToby Isaac           fuse(&a[k], values[offset+     k ] * (flip ? flip[     k ] : 1.));
602097e99dd9SToby Isaac         }
6021552f7358SJed Brown       }
6022552f7358SJed Brown     }
6023552f7358SJed Brown   }
6024552f7358SJed Brown   PetscFunctionReturn(0);
6025552f7358SJed Brown }
6026552f7358SJed Brown 
60279fbee547SJacob 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[])
6028a5e93ea8SMatthew G. Knepley {
6029a5e93ea8SMatthew G. Knepley   PetscInt        cdof;   /* The number of constraints on this point */
6030a5e93ea8SMatthew G. Knepley   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6031a5e93ea8SMatthew G. Knepley   PetscScalar    *a;
6032a5e93ea8SMatthew G. Knepley   PetscInt        off, cind = 0, k;
6033a5e93ea8SMatthew G. Knepley 
6034a5e93ea8SMatthew G. Knepley   PetscFunctionBegin;
60359566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
60369566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(section, point, &off));
6037a5e93ea8SMatthew G. Knepley   a    = &array[off];
6038a5e93ea8SMatthew G. Knepley   if (cdof) {
60399566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
604097e99dd9SToby Isaac     if (clperm) {
604197e99dd9SToby Isaac       if (perm) {
6042a5e93ea8SMatthew G. Knepley         for (k = 0; k < dof; ++k) {
6043a5e93ea8SMatthew G. Knepley           if ((cind < cdof) && (k == cdofs[cind])) {
604497e99dd9SToby Isaac             fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));
604597e99dd9SToby Isaac             cind++;
6046a5e93ea8SMatthew G. Knepley           }
6047a5e93ea8SMatthew G. Knepley         }
6048a5e93ea8SMatthew G. Knepley       } else {
6049a5e93ea8SMatthew G. Knepley         for (k = 0; k < dof; ++k) {
6050a5e93ea8SMatthew G. Knepley           if ((cind < cdof) && (k == cdofs[cind])) {
605197e99dd9SToby Isaac             fuse(&a[k], values[clperm[offset+     k ]] * (flip ? flip[     k ] : 1.));
605297e99dd9SToby Isaac             cind++;
605397e99dd9SToby Isaac           }
605497e99dd9SToby Isaac         }
605597e99dd9SToby Isaac       }
605697e99dd9SToby Isaac     } else {
605797e99dd9SToby Isaac       if (perm) {
605897e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
605997e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {
606097e99dd9SToby Isaac             fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));
606197e99dd9SToby Isaac             cind++;
606297e99dd9SToby Isaac           }
606397e99dd9SToby Isaac         }
606497e99dd9SToby Isaac       } else {
606597e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
606697e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {
606797e99dd9SToby Isaac             fuse(&a[k], values[offset+     k ] * (flip ? flip[     k ] : 1.));
606897e99dd9SToby Isaac             cind++;
606997e99dd9SToby Isaac           }
6070a5e93ea8SMatthew G. Knepley         }
6071a5e93ea8SMatthew G. Knepley       }
6072a5e93ea8SMatthew G. Knepley     }
6073a5e93ea8SMatthew G. Knepley   }
6074a5e93ea8SMatthew G. Knepley   PetscFunctionReturn(0);
6075a5e93ea8SMatthew G. Knepley }
6076a5e93ea8SMatthew G. Knepley 
60779fbee547SJacob 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[])
6078a6dfd86eSKarl Rupp {
6079552f7358SJed Brown   PetscScalar    *a;
60801a271a75SMatthew G. Knepley   PetscInt        fdof, foff, fcdof, foffset = *offset;
60811a271a75SMatthew G. Knepley   const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
608297e99dd9SToby Isaac   PetscInt        cind = 0, b;
6083552f7358SJed Brown 
6084552f7358SJed Brown   PetscFunctionBegin;
60859566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
60869566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof));
60879566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
60881a271a75SMatthew G. Knepley   a    = &array[foff];
6089552f7358SJed Brown   if (!fcdof || setBC) {
609097e99dd9SToby Isaac     if (clperm) {
609197e99dd9SToby Isaac       if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));}}
609297e99dd9SToby Isaac       else      {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+     b ]] * (flip ? flip[     b ] : 1.));}}
6093552f7358SJed Brown     } else {
609497e99dd9SToby Isaac       if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));}}
609597e99dd9SToby Isaac       else      {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+     b ] * (flip ? flip[     b ] : 1.));}}
6096552f7358SJed Brown     }
6097552f7358SJed Brown   } else {
60989566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
609997e99dd9SToby Isaac     if (clperm) {
610097e99dd9SToby Isaac       if (perm) {
610197e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
610297e99dd9SToby Isaac           if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;}
610397e99dd9SToby Isaac           fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));
6104552f7358SJed Brown         }
6105552f7358SJed Brown       } else {
610697e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
610797e99dd9SToby Isaac           if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;}
610897e99dd9SToby Isaac           fuse(&a[b], values[clperm[foffset+     b ]] * (flip ? flip[     b ] : 1.));
610997e99dd9SToby Isaac         }
611097e99dd9SToby Isaac       }
611197e99dd9SToby Isaac     } else {
611297e99dd9SToby Isaac       if (perm) {
611397e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
611497e99dd9SToby Isaac           if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;}
611597e99dd9SToby Isaac           fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));
611697e99dd9SToby Isaac         }
611797e99dd9SToby Isaac       } else {
611897e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
611997e99dd9SToby Isaac           if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;}
612097e99dd9SToby Isaac           fuse(&a[b], values[foffset+     b ] * (flip ? flip[     b ] : 1.));
6121552f7358SJed Brown         }
6122552f7358SJed Brown       }
6123552f7358SJed Brown     }
6124552f7358SJed Brown   }
61251a271a75SMatthew G. Knepley   *offset += fdof;
6126552f7358SJed Brown   PetscFunctionReturn(0);
6127552f7358SJed Brown }
6128552f7358SJed Brown 
61299fbee547SJacob 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[])
6130a5e93ea8SMatthew G. Knepley {
6131a5e93ea8SMatthew G. Knepley   PetscScalar    *a;
61321a271a75SMatthew G. Knepley   PetscInt        fdof, foff, fcdof, foffset = *offset;
61331a271a75SMatthew G. Knepley   const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
61345da9d227SMatthew G. Knepley   PetscInt        Nc, cind = 0, ncind = 0, b;
6135ba322698SMatthew G. Knepley   PetscBool       ncSet, fcSet;
6136a5e93ea8SMatthew G. Knepley 
6137a5e93ea8SMatthew G. Knepley   PetscFunctionBegin;
61389566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldComponents(section, f, &Nc));
61399566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
61409566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof));
61419566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
61421a271a75SMatthew G. Knepley   a    = &array[foff];
6143a5e93ea8SMatthew G. Knepley   if (fcdof) {
6144ba322698SMatthew G. Knepley     /* We just override fcdof and fcdofs with Ncc and comps */
61459566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
614697e99dd9SToby Isaac     if (clperm) {
614797e99dd9SToby Isaac       if (perm) {
6148ba322698SMatthew G. Knepley         if (comps) {
6149ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6150ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
61515da9d227SMatthew G. Knepley             if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;}
6152ba322698SMatthew G. Knepley             if ((cind < fcdof) && (b == fcdofs[cind])) {++cind;  fcSet = PETSC_TRUE;}
6153ba322698SMatthew G. Knepley             if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));}
6154ba322698SMatthew G. Knepley           }
6155ba322698SMatthew G. Knepley         } else {
615697e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
615797e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
615897e99dd9SToby Isaac               fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));
6159a5e93ea8SMatthew G. Knepley               ++cind;
6160a5e93ea8SMatthew G. Knepley             }
6161a5e93ea8SMatthew G. Knepley           }
6162ba322698SMatthew G. Knepley         }
6163ba322698SMatthew G. Knepley       } else {
6164ba322698SMatthew G. Knepley         if (comps) {
6165ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6166ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
61675da9d227SMatthew G. Knepley             if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;}
6168ba322698SMatthew G. Knepley             if ((cind < fcdof) && (b == fcdofs[cind])) {++cind;  fcSet = PETSC_TRUE;}
6169ba322698SMatthew G. Knepley             if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+     b ]] * (flip ? flip[     b ] : 1.));}
6170ba322698SMatthew G. Knepley           }
6171a5e93ea8SMatthew G. Knepley         } else {
617297e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
617397e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
617497e99dd9SToby Isaac               fuse(&a[b], values[clperm[foffset+     b ]] * (flip ? flip[     b ] : 1.));
617597e99dd9SToby Isaac               ++cind;
617697e99dd9SToby Isaac             }
617797e99dd9SToby Isaac           }
617897e99dd9SToby Isaac         }
6179ba322698SMatthew G. Knepley       }
618097e99dd9SToby Isaac     } else {
618197e99dd9SToby Isaac       if (perm) {
6182ba322698SMatthew G. Knepley         if (comps) {
6183ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6184ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
61855da9d227SMatthew G. Knepley             if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;}
6186ba322698SMatthew G. Knepley             if ((cind < fcdof) && (b == fcdofs[cind])) {++cind;  fcSet = PETSC_TRUE;}
6187ba322698SMatthew G. Knepley             if (ncSet && fcSet) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));}
6188ba322698SMatthew G. Knepley           }
6189ba322698SMatthew G. Knepley         } else {
619097e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
619197e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
619297e99dd9SToby Isaac               fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));
619397e99dd9SToby Isaac               ++cind;
619497e99dd9SToby Isaac             }
619597e99dd9SToby Isaac           }
6196ba322698SMatthew G. Knepley         }
6197ba322698SMatthew G. Knepley       } else {
6198ba322698SMatthew G. Knepley         if (comps) {
6199ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6200ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
62015da9d227SMatthew G. Knepley             if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;}
6202ba322698SMatthew G. Knepley             if ((cind < fcdof) && (b == fcdofs[cind])) {++cind;  fcSet = PETSC_TRUE;}
6203ba322698SMatthew G. Knepley             if (ncSet && fcSet) {fuse(&a[b], values[foffset+     b ] * (flip ? flip[     b ] : 1.));}
6204ba322698SMatthew G. Knepley           }
620597e99dd9SToby Isaac         } else {
620697e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
620797e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
620897e99dd9SToby Isaac               fuse(&a[b], values[foffset+     b ] * (flip ? flip[     b ] : 1.));
6209a5e93ea8SMatthew G. Knepley               ++cind;
6210a5e93ea8SMatthew G. Knepley             }
6211a5e93ea8SMatthew G. Knepley           }
6212a5e93ea8SMatthew G. Knepley         }
6213a5e93ea8SMatthew G. Knepley       }
6214a5e93ea8SMatthew G. Knepley     }
6215ba322698SMatthew G. Knepley   }
62161a271a75SMatthew G. Knepley   *offset += fdof;
6217a5e93ea8SMatthew G. Knepley   PetscFunctionReturn(0);
6218a5e93ea8SMatthew G. Knepley }
6219a5e93ea8SMatthew G. Knepley 
62209fbee547SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode)
6221a6dfd86eSKarl Rupp {
6222552f7358SJed Brown   PetscScalar    *array;
62231b406b76SMatthew G. Knepley   const PetscInt *cone, *coneO;
62241b406b76SMatthew G. Knepley   PetscInt        pStart, pEnd, p, numPoints, off, dof;
6225552f7358SJed Brown 
62261b406b76SMatthew G. Knepley   PetscFunctionBeginHot;
62279566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
62289566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, point, &numPoints));
62299566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, point, &cone));
62309566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeOrientation(dm, point, &coneO));
62319566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
6232b6ebb6e6SMatthew G. Knepley   for (p = 0, off = 0; p <= numPoints; ++p, off += dof) {
6233b6ebb6e6SMatthew G. Knepley     const PetscInt cp = !p ? point : cone[p-1];
6234b6ebb6e6SMatthew G. Knepley     const PetscInt o  = !p ? 0     : coneO[p-1];
6235b6ebb6e6SMatthew G. Knepley 
6236b6ebb6e6SMatthew G. Knepley     if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;}
62379566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, cp, &dof));
6238b6ebb6e6SMatthew G. Knepley     /* ADD_VALUES */
6239b6ebb6e6SMatthew G. Knepley     {
6240b6ebb6e6SMatthew G. Knepley       const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6241b6ebb6e6SMatthew G. Knepley       PetscScalar    *a;
6242b6ebb6e6SMatthew G. Knepley       PetscInt        cdof, coff, cind = 0, k;
6243b6ebb6e6SMatthew G. Knepley 
62449566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetConstraintDof(section, cp, &cdof));
62459566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(section, cp, &coff));
6246b6ebb6e6SMatthew G. Knepley       a    = &array[coff];
6247b6ebb6e6SMatthew G. Knepley       if (!cdof) {
6248b6ebb6e6SMatthew G. Knepley         if (o >= 0) {
6249b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
6250b6ebb6e6SMatthew G. Knepley             a[k] += values[off+k];
6251b6ebb6e6SMatthew G. Knepley           }
6252b6ebb6e6SMatthew G. Knepley         } else {
6253b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
6254b6ebb6e6SMatthew G. Knepley             a[k] += values[off+dof-k-1];
6255b6ebb6e6SMatthew G. Knepley           }
6256b6ebb6e6SMatthew G. Knepley         }
6257b6ebb6e6SMatthew G. Knepley       } else {
62589566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintIndices(section, cp, &cdofs));
6259b6ebb6e6SMatthew G. Knepley         if (o >= 0) {
6260b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
6261b6ebb6e6SMatthew G. Knepley             if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
6262b6ebb6e6SMatthew G. Knepley             a[k] += values[off+k];
6263b6ebb6e6SMatthew G. Knepley           }
6264b6ebb6e6SMatthew G. Knepley         } else {
6265b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
6266b6ebb6e6SMatthew G. Knepley             if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
6267b6ebb6e6SMatthew G. Knepley             a[k] += values[off+dof-k-1];
6268b6ebb6e6SMatthew G. Knepley           }
6269b6ebb6e6SMatthew G. Knepley         }
6270b6ebb6e6SMatthew G. Knepley       }
6271b6ebb6e6SMatthew G. Knepley     }
6272b6ebb6e6SMatthew G. Knepley   }
62739566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
6274b6ebb6e6SMatthew G. Knepley   PetscFunctionReturn(0);
6275b6ebb6e6SMatthew G. Knepley }
62761b406b76SMatthew G. Knepley 
62771b406b76SMatthew G. Knepley /*@C
62781b406b76SMatthew G. Knepley   DMPlexVecSetClosure - Set an array of the values on the closure of 'point'
62791b406b76SMatthew G. Knepley 
62801b406b76SMatthew G. Knepley   Not collective
62811b406b76SMatthew G. Knepley 
62821b406b76SMatthew G. Knepley   Input Parameters:
62831b406b76SMatthew G. Knepley + dm - The DM
62841b406b76SMatthew G. Knepley . section - The section describing the layout in v, or NULL to use the default section
62851b406b76SMatthew G. Knepley . v - The local vector
6286eaf898f9SPatrick Sanan . point - The point in the DM
62871b406b76SMatthew G. Knepley . values - The array of values
628822c1ee49SMatthew 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,
628922c1ee49SMatthew G. Knepley          where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions.
62901b406b76SMatthew G. Knepley 
62911b406b76SMatthew G. Knepley   Fortran Notes:
62921b406b76SMatthew G. Knepley   This routine is only available in Fortran 90, and you must include petsc.h90 in your code.
62931b406b76SMatthew G. Knepley 
62941b406b76SMatthew G. Knepley   Level: intermediate
62951b406b76SMatthew G. Knepley 
6296db781477SPatrick Sanan .seealso `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`
62971b406b76SMatthew G. Knepley @*/
62981b406b76SMatthew G. Knepley PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode)
62991b406b76SMatthew G. Knepley {
63001b406b76SMatthew G. Knepley   PetscSection    clSection;
63011b406b76SMatthew G. Knepley   IS              clPoints;
63021b406b76SMatthew G. Knepley   PetscScalar    *array;
63031b406b76SMatthew G. Knepley   PetscInt       *points = NULL;
630427f02ce8SMatthew G. Knepley   const PetscInt *clp, *clperm = NULL;
6305c459fbc1SJed Brown   PetscInt        depth, numFields, numPoints, p, clsize;
63061b406b76SMatthew G. Knepley 
63071a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
63081b406b76SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
63099566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
63101a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
63111a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
63129566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
63139566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
63141b406b76SMatthew G. Knepley   if (depth == 1 && numFields < 2 && mode == ADD_VALUES) {
63159566063dSJacob Faibussowitsch     PetscCall(DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode));
63161b406b76SMatthew G. Knepley     PetscFunctionReturn(0);
63171b406b76SMatthew G. Knepley   }
63181a271a75SMatthew G. Knepley   /* Get points */
63199566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
6320c459fbc1SJed Brown   for (clsize=0,p=0; p<numPoints; p++) {
6321c459fbc1SJed Brown     PetscInt dof;
63229566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[2*p], &dof));
6323c459fbc1SJed Brown     clsize += dof;
6324c459fbc1SJed Brown   }
63259566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm));
63261a271a75SMatthew G. Knepley   /* Get array */
63279566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
63281a271a75SMatthew G. Knepley   /* Get values */
6329ef90cfe2SMatthew G. Knepley   if (numFields > 0) {
633097e99dd9SToby Isaac     PetscInt offset = 0, f;
6331552f7358SJed Brown     for (f = 0; f < numFields; ++f) {
633297e99dd9SToby Isaac       const PetscInt    **perms = NULL;
633397e99dd9SToby Isaac       const PetscScalar **flips = NULL;
633497e99dd9SToby Isaac 
63359566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips));
6336552f7358SJed Brown       switch (mode) {
6337552f7358SJed Brown       case INSERT_VALUES:
633897e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
633997e99dd9SToby Isaac           const PetscInt    point = points[2*p];
634097e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
634197e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
634297e99dd9SToby Isaac           updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array);
6343552f7358SJed Brown         } break;
6344552f7358SJed Brown       case INSERT_ALL_VALUES:
634597e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
634697e99dd9SToby Isaac           const PetscInt    point = points[2*p];
634797e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
634897e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
634997e99dd9SToby Isaac           updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array);
6350552f7358SJed Brown         } break;
6351a5e93ea8SMatthew G. Knepley       case INSERT_BC_VALUES:
635297e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
635397e99dd9SToby Isaac           const PetscInt    point = points[2*p];
635497e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
635597e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
6356ba322698SMatthew G. Knepley           updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array);
6357a5e93ea8SMatthew G. Knepley         } break;
6358552f7358SJed Brown       case ADD_VALUES:
635997e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
636097e99dd9SToby Isaac           const PetscInt    point = points[2*p];
636197e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
636297e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
636397e99dd9SToby Isaac           updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array);
6364552f7358SJed Brown         } break;
6365552f7358SJed Brown       case ADD_ALL_VALUES:
636697e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
636797e99dd9SToby Isaac           const PetscInt    point = points[2*p];
636897e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
636997e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
637097e99dd9SToby Isaac           updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array);
6371552f7358SJed Brown         } break;
6372304ab55fSMatthew G. Knepley       case ADD_BC_VALUES:
637397e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
637497e99dd9SToby Isaac           const PetscInt    point = points[2*p];
637597e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
637697e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
6377ba322698SMatthew G. Knepley           updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array);
6378304ab55fSMatthew G. Knepley         } break;
6379552f7358SJed Brown       default:
638098921bdaSJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
6381552f7358SJed Brown       }
63829566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips));
63831a271a75SMatthew G. Knepley     }
6384552f7358SJed Brown   } else {
63851a271a75SMatthew G. Knepley     PetscInt dof, off;
638697e99dd9SToby Isaac     const PetscInt    **perms = NULL;
638797e99dd9SToby Isaac     const PetscScalar **flips = NULL;
63881a271a75SMatthew G. Knepley 
63899566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips));
6390552f7358SJed Brown     switch (mode) {
6391552f7358SJed Brown     case INSERT_VALUES:
639297e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
639397e99dd9SToby Isaac         const PetscInt    point = points[2*p];
639497e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
639597e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
63969566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
639797e99dd9SToby Isaac         updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array);
6398552f7358SJed Brown       } break;
6399552f7358SJed Brown     case INSERT_ALL_VALUES:
640097e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
640197e99dd9SToby Isaac         const PetscInt    point = points[2*p];
640297e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
640397e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
64049566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
640597e99dd9SToby Isaac         updatePoint_private(section, point, dof, insert, PETSC_TRUE,  perm, flip, clperm, values, off, array);
6406552f7358SJed Brown       } break;
6407a5e93ea8SMatthew G. Knepley     case INSERT_BC_VALUES:
640897e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
640997e99dd9SToby Isaac         const PetscInt    point = points[2*p];
641097e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
641197e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
64129566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
641397e99dd9SToby Isaac         updatePointBC_private(section, point, dof, insert,  perm, flip, clperm, values, off, array);
6414a5e93ea8SMatthew G. Knepley       } break;
6415552f7358SJed Brown     case ADD_VALUES:
641697e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
641797e99dd9SToby Isaac         const PetscInt    point = points[2*p];
641897e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
641997e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
64209566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
642197e99dd9SToby Isaac         updatePoint_private(section, point, dof, add,    PETSC_FALSE, perm, flip, clperm, values, off, array);
6422552f7358SJed Brown       } break;
6423552f7358SJed Brown     case ADD_ALL_VALUES:
642497e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
642597e99dd9SToby Isaac         const PetscInt    point = points[2*p];
642697e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
642797e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
64289566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
642997e99dd9SToby Isaac         updatePoint_private(section, point, dof, add,    PETSC_TRUE,  perm, flip, clperm, values, off, array);
6430552f7358SJed Brown       } break;
6431304ab55fSMatthew G. Knepley     case ADD_BC_VALUES:
643297e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
643397e99dd9SToby Isaac         const PetscInt    point = points[2*p];
643497e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
643597e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
64369566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
643797e99dd9SToby Isaac         updatePointBC_private(section, point, dof, add,  perm, flip, clperm, values, off, array);
6438304ab55fSMatthew G. Knepley       } break;
6439552f7358SJed Brown     default:
644098921bdaSJacob Faibussowitsch       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
6441552f7358SJed Brown     }
64429566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips));
6443552f7358SJed Brown   }
64441a271a75SMatthew G. Knepley   /* Cleanup points */
64459566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
64461a271a75SMatthew G. Knepley   /* Cleanup array */
64479566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
6448552f7358SJed Brown   PetscFunctionReturn(0);
6449552f7358SJed Brown }
6450552f7358SJed Brown 
64515f790a90SMatthew G. Knepley /* Check whether the given point is in the label. If not, update the offset to skip this point */
64529fbee547SJacob Faibussowitsch static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset)
64535f790a90SMatthew G. Knepley {
64545f790a90SMatthew G. Knepley   PetscFunctionBegin;
64555f790a90SMatthew G. Knepley   if (label) {
6456d6177c40SToby Isaac     PetscBool contains;
6457d6177c40SToby Isaac     PetscInt  fdof;
64585f790a90SMatthew G. Knepley 
6459d6177c40SToby Isaac     PetscCall(DMLabelStratumHasPoint(label, labelId, point, &contains));
6460d6177c40SToby Isaac     if (!contains) {
64619566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
64625f790a90SMatthew G. Knepley       *offset += fdof;
64635f790a90SMatthew G. Knepley       PetscFunctionReturn(1);
64645f790a90SMatthew G. Knepley     }
64655f790a90SMatthew G. Knepley   }
64665f790a90SMatthew G. Knepley   PetscFunctionReturn(0);
64675f790a90SMatthew G. Knepley }
64685f790a90SMatthew G. Knepley 
646997529cf3SJed Brown /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */
64705f790a90SMatthew 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)
6471e07394fbSMatthew G. Knepley {
6472e07394fbSMatthew G. Knepley   PetscSection    clSection;
6473e07394fbSMatthew G. Knepley   IS              clPoints;
6474e07394fbSMatthew G. Knepley   PetscScalar    *array;
6475e07394fbSMatthew G. Knepley   PetscInt       *points = NULL;
647697529cf3SJed Brown   const PetscInt *clp;
6477e07394fbSMatthew G. Knepley   PetscInt        numFields, numPoints, p;
647897e99dd9SToby Isaac   PetscInt        offset = 0, f;
6479e07394fbSMatthew G. Knepley 
6480e07394fbSMatthew G. Knepley   PetscFunctionBeginHot;
6481e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
64829566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
6483e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
6484e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
64859566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
6486e07394fbSMatthew G. Knepley   /* Get points */
64879566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
6488e07394fbSMatthew G. Knepley   /* Get array */
64899566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
6490e07394fbSMatthew G. Knepley   /* Get values */
6491e07394fbSMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
649297e99dd9SToby Isaac     const PetscInt    **perms = NULL;
649397e99dd9SToby Isaac     const PetscScalar **flips = NULL;
649497e99dd9SToby Isaac 
6495e07394fbSMatthew G. Knepley     if (!fieldActive[f]) {
6496e07394fbSMatthew G. Knepley       for (p = 0; p < numPoints*2; p += 2) {
6497e07394fbSMatthew G. Knepley         PetscInt fdof;
64989566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof));
6499e07394fbSMatthew G. Knepley         offset += fdof;
6500e07394fbSMatthew G. Knepley       }
6501e07394fbSMatthew G. Knepley       continue;
6502e07394fbSMatthew G. Knepley     }
65039566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips));
6504e07394fbSMatthew G. Knepley     switch (mode) {
6505e07394fbSMatthew G. Knepley     case INSERT_VALUES:
650697e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
650797e99dd9SToby Isaac         const PetscInt    point = points[2*p];
650897e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
650997e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
65105f80ce2aSJacob Faibussowitsch         if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue;
65119566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array));
6512e07394fbSMatthew G. Knepley       } break;
6513e07394fbSMatthew G. Knepley     case INSERT_ALL_VALUES:
651497e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
651597e99dd9SToby Isaac         const PetscInt    point = points[2*p];
651697e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
651797e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
65185f80ce2aSJacob Faibussowitsch         if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue;
65199566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array));
6520e07394fbSMatthew G. Knepley       } break;
6521e07394fbSMatthew G. Knepley     case INSERT_BC_VALUES:
652297e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
652397e99dd9SToby Isaac         const PetscInt    point = points[2*p];
652497e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
652597e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
65265f80ce2aSJacob Faibussowitsch         if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue;
65279566063dSJacob Faibussowitsch         PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array));
6528e07394fbSMatthew G. Knepley       } break;
6529e07394fbSMatthew G. Knepley     case ADD_VALUES:
653097e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
653197e99dd9SToby Isaac         const PetscInt    point = points[2*p];
653297e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
653397e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
65345f80ce2aSJacob Faibussowitsch         if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue;
65359566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array));
6536e07394fbSMatthew G. Knepley       } break;
6537e07394fbSMatthew G. Knepley     case ADD_ALL_VALUES:
653897e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
653997e99dd9SToby Isaac         const PetscInt    point = points[2*p];
654097e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
654197e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
65425f80ce2aSJacob Faibussowitsch         if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue;
65439566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array));
6544e07394fbSMatthew G. Knepley       } break;
6545e07394fbSMatthew G. Knepley     default:
654698921bdaSJacob Faibussowitsch       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
6547e07394fbSMatthew G. Knepley     }
65489566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips));
6549e07394fbSMatthew G. Knepley   }
6550e07394fbSMatthew G. Knepley   /* Cleanup points */
65519566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
6552e07394fbSMatthew G. Knepley   /* Cleanup array */
65539566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
6554e07394fbSMatthew G. Knepley   PetscFunctionReturn(0);
6555e07394fbSMatthew G. Knepley }
6556e07394fbSMatthew G. Knepley 
65577cd05799SMatthew G. Knepley static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[])
6558552f7358SJed Brown {
6559552f7358SJed Brown   PetscMPIInt    rank;
6560552f7358SJed Brown   PetscInt       i, j;
6561552f7358SJed Brown 
6562552f7358SJed Brown   PetscFunctionBegin;
65639566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
656463a3b9bcSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat for point %" PetscInt_FMT "\n", rank, point));
656563a3b9bcSJacob Faibussowitsch   for (i = 0; i < numRIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, rindices[i]));
656663a3b9bcSJacob Faibussowitsch   for (i = 0; i < numCIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, cindices[i]));
6567b0ecff45SMatthew G. Knepley   numCIndices = numCIndices ? numCIndices : numRIndices;
6568557cf195SMatthew G. Knepley   if (!values) PetscFunctionReturn(0);
6569b0ecff45SMatthew G. Knepley   for (i = 0; i < numRIndices; i++) {
65709566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]", rank));
6571b0ecff45SMatthew G. Knepley     for (j = 0; j < numCIndices; j++) {
6572519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX)
65739566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j])));
6574552f7358SJed Brown #else
65759566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j]));
6576552f7358SJed Brown #endif
6577552f7358SJed Brown     }
65789566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
6579552f7358SJed Brown   }
6580552f7358SJed Brown   PetscFunctionReturn(0);
6581552f7358SJed Brown }
6582552f7358SJed Brown 
658305586334SMatthew G. Knepley /*
658405586334SMatthew G. Knepley   DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array
658505586334SMatthew G. Knepley 
658605586334SMatthew G. Knepley   Input Parameters:
658705586334SMatthew G. Knepley + section - The section for this data layout
658836fa2b79SJed Brown . islocal - Is the section (and thus indices being requested) local or global?
658905586334SMatthew G. Knepley . point   - The point contributing dofs with these indices
659005586334SMatthew G. Knepley . off     - The global offset of this point
659105586334SMatthew G. Knepley . loff    - The local offset of each field
6592a5b23f4aSJose E. Roman . setBC   - The flag determining whether to include indices of boundary values
659305586334SMatthew G. Knepley . perm    - A permutation of the dofs on this point, or NULL
659405586334SMatthew G. Knepley - indperm - A permutation of the entire indices array, or NULL
659505586334SMatthew G. Knepley 
659605586334SMatthew G. Knepley   Output Parameter:
659705586334SMatthew G. Knepley . indices - Indices for dofs on this point
659805586334SMatthew G. Knepley 
659905586334SMatthew G. Knepley   Level: developer
660005586334SMatthew G. Knepley 
660105586334SMatthew G. Knepley   Note: The indices could be local or global, depending on the value of 'off'.
660205586334SMatthew G. Knepley */
660336fa2b79SJed Brown PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal,PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[])
6604a6dfd86eSKarl Rupp {
6605e6ccafaeSMatthew G Knepley   PetscInt        dof;   /* The number of unknowns on this point */
6606552f7358SJed Brown   PetscInt        cdof;  /* The number of constraints on this point */
6607552f7358SJed Brown   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6608552f7358SJed Brown   PetscInt        cind = 0, k;
6609552f7358SJed Brown 
6610552f7358SJed Brown   PetscFunctionBegin;
661108401ef6SPierre Jolivet   PetscCheck(islocal || !setBC,PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC");
66129566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(section, point, &dof));
66139566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
6614552f7358SJed Brown   if (!cdof || setBC) {
661505586334SMatthew G. Knepley     for (k = 0; k < dof; ++k) {
661605586334SMatthew G. Knepley       const PetscInt preind = perm ? *loff+perm[k] : *loff+k;
661705586334SMatthew G. Knepley       const PetscInt ind    = indperm ? indperm[preind] : preind;
661805586334SMatthew G. Knepley 
661905586334SMatthew G. Knepley       indices[ind] = off + k;
6620552f7358SJed Brown     }
6621552f7358SJed Brown   } else {
66229566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
66234acb8e1eSToby Isaac     for (k = 0; k < dof; ++k) {
662405586334SMatthew G. Knepley       const PetscInt preind = perm ? *loff+perm[k] : *loff+k;
662505586334SMatthew G. Knepley       const PetscInt ind    = indperm ? indperm[preind] : preind;
662605586334SMatthew G. Knepley 
66274acb8e1eSToby Isaac       if ((cind < cdof) && (k == cdofs[cind])) {
66284acb8e1eSToby Isaac         /* Insert check for returning constrained indices */
662905586334SMatthew G. Knepley         indices[ind] = -(off+k+1);
66304acb8e1eSToby Isaac         ++cind;
66314acb8e1eSToby Isaac       } else {
663236fa2b79SJed Brown         indices[ind] = off + k - (islocal ? 0 : cind);
6633552f7358SJed Brown       }
6634552f7358SJed Brown     }
6635552f7358SJed Brown   }
6636e6ccafaeSMatthew G Knepley   *loff += dof;
6637552f7358SJed Brown   PetscFunctionReturn(0);
6638552f7358SJed Brown }
6639552f7358SJed Brown 
66407e29afd2SMatthew G. Knepley /*
664136fa2b79SJed Brown  DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering.
66427e29afd2SMatthew G. Knepley 
664336fa2b79SJed Brown  Input Parameters:
664436fa2b79SJed Brown + section - a section (global or local)
664536fa2b79SJed Brown - islocal - PETSC_TRUE if requesting local indices (i.e., section is local); PETSC_FALSE for global
664636fa2b79SJed Brown . point - point within section
664736fa2b79SJed Brown . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section
664836fa2b79SJed Brown . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field
664936fa2b79SJed Brown . setBC - identify constrained (boundary condition) points via involution.
665036fa2b79SJed Brown . perms - perms[f][permsoff][:] is a permutation of dofs within each field
665136fa2b79SJed Brown . permsoff - offset
665236fa2b79SJed Brown - indperm - index permutation
665336fa2b79SJed Brown 
665436fa2b79SJed Brown  Output Parameter:
665536fa2b79SJed Brown . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field
665636fa2b79SJed Brown . indices - array to hold indices (as defined by section) of each dof associated with point
665736fa2b79SJed Brown 
665836fa2b79SJed Brown  Notes:
665936fa2b79SJed Brown  If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs.
666036fa2b79SJed Brown  If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position
666136fa2b79SJed Brown  in the local vector.
666236fa2b79SJed Brown 
666336fa2b79SJed Brown  If section is global and setBC=false, the indices for constrained points are negative (and their value is not
666436fa2b79SJed Brown  significant).  It is invalid to call with a global section and setBC=true.
666536fa2b79SJed Brown 
666636fa2b79SJed Brown  Developer Note:
666736fa2b79SJed Brown  The section is only used for field layout, so islocal is technically a statement about the offset (off).  At some point
666836fa2b79SJed Brown  in the future, global sections may have fields set, in which case we could pass the global section and obtain the
666936fa2b79SJed Brown  offset could be obtained from the section instead of passing it explicitly as we do now.
667036fa2b79SJed Brown 
667136fa2b79SJed Brown  Example:
667236fa2b79SJed Brown  Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}.
667336fa2b79SJed Brown  When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE).
667436fa2b79SJed Brown  Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices.
667536fa2b79SJed 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.
667636fa2b79SJed Brown 
667736fa2b79SJed Brown  Level: developer
66787e29afd2SMatthew G. Knepley */
667936fa2b79SJed 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[])
6680a6dfd86eSKarl Rupp {
6681552f7358SJed Brown   PetscInt       numFields, foff, f;
6682552f7358SJed Brown 
6683552f7358SJed Brown   PetscFunctionBegin;
668408401ef6SPierre Jolivet   PetscCheck(islocal || !setBC,PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC");
66859566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
6686552f7358SJed Brown   for (f = 0, foff = 0; f < numFields; ++f) {
66874acb8e1eSToby Isaac     PetscInt        fdof, cfdof;
6688552f7358SJed Brown     const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
66894acb8e1eSToby Isaac     PetscInt        cind = 0, b;
66904acb8e1eSToby Isaac     const PetscInt  *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL;
6691552f7358SJed Brown 
66929566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
66939566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof));
6694552f7358SJed Brown     if (!cfdof || setBC) {
669505586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
669605586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b;
669705586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
669805586334SMatthew G. Knepley 
669905586334SMatthew G. Knepley         indices[ind] = off+foff+b;
670005586334SMatthew G. Knepley       }
6701552f7358SJed Brown     } else {
67029566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
670305586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
670405586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b;
670505586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
670605586334SMatthew G. Knepley 
67074acb8e1eSToby Isaac         if ((cind < cfdof) && (b == fcdofs[cind])) {
670805586334SMatthew G. Knepley           indices[ind] = -(off+foff+b+1);
6709552f7358SJed Brown           ++cind;
6710552f7358SJed Brown         } else {
671136fa2b79SJed Brown           indices[ind] = off + foff + b - (islocal ? 0 : cind);
6712552f7358SJed Brown         }
6713552f7358SJed Brown       }
6714552f7358SJed Brown     }
671536fa2b79SJed Brown     foff     += (setBC || islocal ? fdof : (fdof - cfdof));
6716552f7358SJed Brown     foffs[f] += fdof;
6717552f7358SJed Brown   }
6718552f7358SJed Brown   PetscFunctionReturn(0);
6719552f7358SJed Brown }
6720552f7358SJed Brown 
67217e29afd2SMatthew G. Knepley /*
67227e29afd2SMatthew G. Knepley   This version believes the globalSection offsets for each field, rather than just the point offset
67237e29afd2SMatthew G. Knepley 
67247e29afd2SMatthew G. Knepley  . foffs - The offset into 'indices' for each field, since it is segregated by field
6725645102dcSJed Brown 
6726645102dcSJed Brown  Notes:
6727645102dcSJed Brown  The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal.
6728645102dcSJed Brown  Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists.
67297e29afd2SMatthew G. Knepley */
6730645102dcSJed Brown static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[])
67317e29afd2SMatthew G. Knepley {
67327e29afd2SMatthew G. Knepley   PetscInt       numFields, foff, f;
67337e29afd2SMatthew G. Knepley 
67347e29afd2SMatthew G. Knepley   PetscFunctionBegin;
67359566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
67367e29afd2SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
67377e29afd2SMatthew G. Knepley     PetscInt        fdof, cfdof;
67387e29afd2SMatthew G. Knepley     const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
67397e29afd2SMatthew G. Knepley     PetscInt        cind = 0, b;
67407e29afd2SMatthew G. Knepley     const PetscInt  *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL;
67417e29afd2SMatthew G. Knepley 
67429566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
67439566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof));
67449566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldOffset(globalSection, point, f, &foff));
6745645102dcSJed Brown     if (!cfdof) {
674605586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
674705586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b;
674805586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
674905586334SMatthew G. Knepley 
675005586334SMatthew G. Knepley         indices[ind] = foff+b;
675105586334SMatthew G. Knepley       }
67527e29afd2SMatthew G. Knepley     } else {
67539566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
675405586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
675505586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b;
675605586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
675705586334SMatthew G. Knepley 
67587e29afd2SMatthew G. Knepley         if ((cind < cfdof) && (b == fcdofs[cind])) {
675905586334SMatthew G. Knepley           indices[ind] = -(foff+b+1);
67607e29afd2SMatthew G. Knepley           ++cind;
67617e29afd2SMatthew G. Knepley         } else {
676205586334SMatthew G. Knepley           indices[ind] = foff+b-cind;
67637e29afd2SMatthew G. Knepley         }
67647e29afd2SMatthew G. Knepley       }
67657e29afd2SMatthew G. Knepley     }
67667e29afd2SMatthew G. Knepley     foffs[f] += fdof;
67677e29afd2SMatthew G. Knepley   }
67687e29afd2SMatthew G. Knepley   PetscFunctionReturn(0);
67697e29afd2SMatthew G. Knepley }
67707e29afd2SMatthew G. Knepley 
67714acb8e1eSToby 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)
6772d3d1a6afSToby Isaac {
6773d3d1a6afSToby Isaac   Mat             cMat;
6774d3d1a6afSToby Isaac   PetscSection    aSec, cSec;
6775d3d1a6afSToby Isaac   IS              aIS;
6776d3d1a6afSToby Isaac   PetscInt        aStart = -1, aEnd = -1;
6777d3d1a6afSToby Isaac   const PetscInt  *anchors;
6778e17c06e0SMatthew G. Knepley   PetscInt        numFields, f, p, q, newP = 0;
6779d3d1a6afSToby Isaac   PetscInt        newNumPoints = 0, newNumIndices = 0;
6780d3d1a6afSToby Isaac   PetscInt        *newPoints, *indices, *newIndices;
6781d3d1a6afSToby Isaac   PetscInt        maxAnchor, maxDof;
6782d3d1a6afSToby Isaac   PetscInt        newOffsets[32];
6783d3d1a6afSToby Isaac   PetscInt        *pointMatOffsets[32];
6784d3d1a6afSToby Isaac   PetscInt        *newPointOffsets[32];
6785d3d1a6afSToby Isaac   PetscScalar     *pointMat[32];
67866ecaa68aSToby Isaac   PetscScalar     *newValues=NULL,*tmpValues;
6787d3d1a6afSToby Isaac   PetscBool       anyConstrained = PETSC_FALSE;
6788d3d1a6afSToby Isaac 
6789d3d1a6afSToby Isaac   PetscFunctionBegin;
6790d3d1a6afSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6791d3d1a6afSToby Isaac   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
67929566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
6793d3d1a6afSToby Isaac 
67949566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm,&aSec,&aIS));
6795d3d1a6afSToby Isaac   /* if there are point-to-point constraints */
6796d3d1a6afSToby Isaac   if (aSec) {
67979566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(newOffsets, 32));
67989566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(aIS,&anchors));
67999566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(aSec,&aStart,&aEnd));
6800d3d1a6afSToby Isaac     /* figure out how many points are going to be in the new element matrix
6801d3d1a6afSToby Isaac      * (we allow double counting, because it's all just going to be summed
6802d3d1a6afSToby Isaac      * into the global matrix anyway) */
6803d3d1a6afSToby Isaac     for (p = 0; p < 2*numPoints; p+=2) {
6804d3d1a6afSToby Isaac       PetscInt b    = points[p];
68054b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
6806d3d1a6afSToby Isaac 
68079566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section,b,&bSecDof));
68084b2f2278SToby Isaac       if (!bSecDof) {
68094b2f2278SToby Isaac         continue;
68104b2f2278SToby Isaac       }
6811d3d1a6afSToby Isaac       if (b >= aStart && b < aEnd) {
68129566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(aSec,b,&bDof));
6813d3d1a6afSToby Isaac       }
6814d3d1a6afSToby Isaac       if (bDof) {
6815d3d1a6afSToby Isaac         /* this point is constrained */
6816d3d1a6afSToby Isaac         /* it is going to be replaced by its anchors */
6817d3d1a6afSToby Isaac         PetscInt bOff, q;
6818d3d1a6afSToby Isaac 
6819d3d1a6afSToby Isaac         anyConstrained = PETSC_TRUE;
6820d3d1a6afSToby Isaac         newNumPoints  += bDof;
68219566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec,b,&bOff));
6822d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
6823d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q];
6824d3d1a6afSToby Isaac           PetscInt aDof;
6825d3d1a6afSToby Isaac 
68269566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section,a,&aDof));
6827d3d1a6afSToby Isaac           newNumIndices += aDof;
6828d3d1a6afSToby Isaac           for (f = 0; f < numFields; ++f) {
6829d3d1a6afSToby Isaac             PetscInt fDof;
6830d3d1a6afSToby Isaac 
68319566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, a, f, &fDof));
6832d3d1a6afSToby Isaac             newOffsets[f+1] += fDof;
6833d3d1a6afSToby Isaac           }
6834d3d1a6afSToby Isaac         }
6835d3d1a6afSToby Isaac       }
6836d3d1a6afSToby Isaac       else {
6837d3d1a6afSToby Isaac         /* this point is not constrained */
6838d3d1a6afSToby Isaac         newNumPoints++;
68394b2f2278SToby Isaac         newNumIndices += bSecDof;
6840d3d1a6afSToby Isaac         for (f = 0; f < numFields; ++f) {
6841d3d1a6afSToby Isaac           PetscInt fDof;
6842d3d1a6afSToby Isaac 
68439566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
6844d3d1a6afSToby Isaac           newOffsets[f+1] += fDof;
6845d3d1a6afSToby Isaac         }
6846d3d1a6afSToby Isaac       }
6847d3d1a6afSToby Isaac     }
6848d3d1a6afSToby Isaac   }
6849d3d1a6afSToby Isaac   if (!anyConstrained) {
685072b80496SMatthew G. Knepley     if (outNumPoints)  *outNumPoints  = 0;
685172b80496SMatthew G. Knepley     if (outNumIndices) *outNumIndices = 0;
685272b80496SMatthew G. Knepley     if (outPoints)     *outPoints     = NULL;
685372b80496SMatthew G. Knepley     if (outValues)     *outValues     = NULL;
68549566063dSJacob Faibussowitsch     if (aSec) PetscCall(ISRestoreIndices(aIS,&anchors));
6855d3d1a6afSToby Isaac     PetscFunctionReturn(0);
6856d3d1a6afSToby Isaac   }
6857d3d1a6afSToby Isaac 
68586ecaa68aSToby Isaac   if (outNumPoints)  *outNumPoints  = newNumPoints;
68596ecaa68aSToby Isaac   if (outNumIndices) *outNumIndices = newNumIndices;
68606ecaa68aSToby Isaac 
6861f13f9184SToby Isaac   for (f = 0; f < numFields; ++f) newOffsets[f+1] += newOffsets[f];
6862d3d1a6afSToby Isaac 
68636ecaa68aSToby Isaac   if (!outPoints && !outValues) {
68646ecaa68aSToby Isaac     if (offsets) {
68656ecaa68aSToby Isaac       for (f = 0; f <= numFields; f++) {
68666ecaa68aSToby Isaac         offsets[f] = newOffsets[f];
68676ecaa68aSToby Isaac       }
68686ecaa68aSToby Isaac     }
68699566063dSJacob Faibussowitsch     if (aSec) PetscCall(ISRestoreIndices(aIS,&anchors));
68706ecaa68aSToby Isaac     PetscFunctionReturn(0);
68716ecaa68aSToby Isaac   }
68726ecaa68aSToby Isaac 
68731dca8a05SBarry 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);
6874d3d1a6afSToby Isaac 
68759566063dSJacob Faibussowitsch   PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, NULL));
6876d3d1a6afSToby Isaac 
6877d3d1a6afSToby Isaac   /* workspaces */
6878d3d1a6afSToby Isaac   if (numFields) {
6879d3d1a6afSToby Isaac     for (f = 0; f < numFields; f++) {
68809566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]));
68819566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]));
6882d3d1a6afSToby Isaac     }
6883d3d1a6afSToby Isaac   }
6884d3d1a6afSToby Isaac   else {
68859566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]));
68869566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm,numPoints,MPIU_INT,&newPointOffsets[0]));
6887d3d1a6afSToby Isaac   }
6888d3d1a6afSToby Isaac 
6889d3d1a6afSToby Isaac   /* get workspaces for the point-to-point matrices */
6890d3d1a6afSToby Isaac   if (numFields) {
68914b2f2278SToby Isaac     PetscInt totalOffset, totalMatOffset;
68924b2f2278SToby Isaac 
6893d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
6894d3d1a6afSToby Isaac       PetscInt b    = points[2*p];
68954b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
6896d3d1a6afSToby Isaac 
68979566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section,b,&bSecDof));
68984b2f2278SToby Isaac       if (!bSecDof) {
68994b2f2278SToby Isaac         for (f = 0; f < numFields; f++) {
69004b2f2278SToby Isaac           newPointOffsets[f][p + 1] = 0;
69014b2f2278SToby Isaac           pointMatOffsets[f][p + 1] = 0;
69024b2f2278SToby Isaac         }
69034b2f2278SToby Isaac         continue;
69044b2f2278SToby Isaac       }
6905d3d1a6afSToby Isaac       if (b >= aStart && b < aEnd) {
69069566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(aSec, b, &bDof));
6907d3d1a6afSToby Isaac       }
6908d3d1a6afSToby Isaac       if (bDof) {
6909d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
6910d3d1a6afSToby Isaac           PetscInt fDof, q, bOff, allFDof = 0;
6911d3d1a6afSToby Isaac 
69129566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
69139566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
6914d3d1a6afSToby Isaac           for (q = 0; q < bDof; q++) {
6915d3d1a6afSToby Isaac             PetscInt a = anchors[bOff + q];
6916d3d1a6afSToby Isaac             PetscInt aFDof;
6917d3d1a6afSToby Isaac 
69189566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, a, f, &aFDof));
6919d3d1a6afSToby Isaac             allFDof += aFDof;
6920d3d1a6afSToby Isaac           }
6921d3d1a6afSToby Isaac           newPointOffsets[f][p+1] = allFDof;
6922d3d1a6afSToby Isaac           pointMatOffsets[f][p+1] = fDof * allFDof;
6923d3d1a6afSToby Isaac         }
6924d3d1a6afSToby Isaac       }
6925d3d1a6afSToby Isaac       else {
6926d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
6927d3d1a6afSToby Isaac           PetscInt fDof;
6928d3d1a6afSToby Isaac 
69299566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
6930d3d1a6afSToby Isaac           newPointOffsets[f][p+1] = fDof;
6931d3d1a6afSToby Isaac           pointMatOffsets[f][p+1] = 0;
6932d3d1a6afSToby Isaac         }
6933d3d1a6afSToby Isaac       }
6934d3d1a6afSToby Isaac     }
69354b2f2278SToby Isaac     for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) {
69364b2f2278SToby Isaac       newPointOffsets[f][0] = totalOffset;
69374b2f2278SToby Isaac       pointMatOffsets[f][0] = totalMatOffset;
6938d3d1a6afSToby Isaac       for (p = 0; p < numPoints; p++) {
6939d3d1a6afSToby Isaac         newPointOffsets[f][p+1] += newPointOffsets[f][p];
6940d3d1a6afSToby Isaac         pointMatOffsets[f][p+1] += pointMatOffsets[f][p];
6941d3d1a6afSToby Isaac       }
694219f70fd5SToby Isaac       totalOffset    = newPointOffsets[f][numPoints];
694319f70fd5SToby Isaac       totalMatOffset = pointMatOffsets[f][numPoints];
69449566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]));
6945d3d1a6afSToby Isaac     }
6946d3d1a6afSToby Isaac   }
6947d3d1a6afSToby Isaac   else {
6948d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
6949d3d1a6afSToby Isaac       PetscInt b    = points[2*p];
69504b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
6951d3d1a6afSToby Isaac 
69529566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section,b,&bSecDof));
69534b2f2278SToby Isaac       if (!bSecDof) {
69544b2f2278SToby Isaac         newPointOffsets[0][p + 1] = 0;
69554b2f2278SToby Isaac         pointMatOffsets[0][p + 1] = 0;
69564b2f2278SToby Isaac         continue;
69574b2f2278SToby Isaac       }
6958d3d1a6afSToby Isaac       if (b >= aStart && b < aEnd) {
69599566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(aSec, b, &bDof));
6960d3d1a6afSToby Isaac       }
6961d3d1a6afSToby Isaac       if (bDof) {
69624b2f2278SToby Isaac         PetscInt bOff, q, allDof = 0;
6963d3d1a6afSToby Isaac 
69649566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
6965d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
6966d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aDof;
6967d3d1a6afSToby Isaac 
69689566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section, a, &aDof));
6969d3d1a6afSToby Isaac           allDof += aDof;
6970d3d1a6afSToby Isaac         }
6971d3d1a6afSToby Isaac         newPointOffsets[0][p+1] = allDof;
69724b2f2278SToby Isaac         pointMatOffsets[0][p+1] = bSecDof * allDof;
6973d3d1a6afSToby Isaac       }
6974d3d1a6afSToby Isaac       else {
69754b2f2278SToby Isaac         newPointOffsets[0][p+1] = bSecDof;
6976d3d1a6afSToby Isaac         pointMatOffsets[0][p+1] = 0;
6977d3d1a6afSToby Isaac       }
6978d3d1a6afSToby Isaac     }
6979d3d1a6afSToby Isaac     newPointOffsets[0][0] = 0;
6980d3d1a6afSToby Isaac     pointMatOffsets[0][0] = 0;
6981d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
6982d3d1a6afSToby Isaac       newPointOffsets[0][p+1] += newPointOffsets[0][p];
6983d3d1a6afSToby Isaac       pointMatOffsets[0][p+1] += pointMatOffsets[0][p];
6984d3d1a6afSToby Isaac     }
69859566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]));
6986d3d1a6afSToby Isaac   }
6987d3d1a6afSToby Isaac 
69886ecaa68aSToby Isaac   /* output arrays */
69899566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints));
69906ecaa68aSToby Isaac 
6991d3d1a6afSToby Isaac   /* get the point-to-point matrices; construct newPoints */
69929566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetMaxDof(aSec, &maxAnchor));
69939566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetMaxDof(section, &maxDof));
69949566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm,maxDof,MPIU_INT,&indices));
69959566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices));
6996d3d1a6afSToby Isaac   if (numFields) {
6997d3d1a6afSToby Isaac     for (p = 0, newP = 0; p < numPoints; p++) {
6998d3d1a6afSToby Isaac       PetscInt b    = points[2*p];
6999d3d1a6afSToby Isaac       PetscInt o    = points[2*p+1];
70004b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7001d3d1a6afSToby Isaac 
70029566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
70034b2f2278SToby Isaac       if (!bSecDof) {
70044b2f2278SToby Isaac         continue;
70054b2f2278SToby Isaac       }
7006d3d1a6afSToby Isaac       if (b >= aStart && b < aEnd) {
70079566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7008d3d1a6afSToby Isaac       }
7009d3d1a6afSToby Isaac       if (bDof) {
7010d3d1a6afSToby Isaac         PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q;
7011d3d1a6afSToby Isaac 
7012d3d1a6afSToby Isaac         fStart[0] = 0;
7013d3d1a6afSToby Isaac         fEnd[0]   = 0;
7014d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7015d3d1a6afSToby Isaac           PetscInt fDof;
7016d3d1a6afSToby Isaac 
70179566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(cSec, b, f, &fDof));
7018d3d1a6afSToby Isaac           fStart[f+1] = fStart[f] + fDof;
7019d3d1a6afSToby Isaac           fEnd[f+1]   = fStart[f+1];
7020d3d1a6afSToby Isaac         }
70219566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(cSec, b, &bOff));
70229566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices));
7023d3d1a6afSToby Isaac 
7024d3d1a6afSToby Isaac         fAnchorStart[0] = 0;
7025d3d1a6afSToby Isaac         fAnchorEnd[0]   = 0;
7026d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7027d3d1a6afSToby Isaac           PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p];
7028d3d1a6afSToby Isaac 
7029d3d1a6afSToby Isaac           fAnchorStart[f+1] = fAnchorStart[f] + fDof;
7030d3d1a6afSToby Isaac           fAnchorEnd[f+1]   = fAnchorStart[f + 1];
7031d3d1a6afSToby Isaac         }
70329566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7033d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7034d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aOff;
7035d3d1a6afSToby Isaac 
7036d3d1a6afSToby 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 */
7037d3d1a6afSToby Isaac           newPoints[2*(newP + q)]     = a;
7038d3d1a6afSToby Isaac           newPoints[2*(newP + q) + 1] = 0;
70399566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(section, a, &aOff));
70409566063dSJacob Faibussowitsch           PetscCall(DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices));
7041d3d1a6afSToby Isaac         }
7042d3d1a6afSToby Isaac         newP += bDof;
7043d3d1a6afSToby Isaac 
70446ecaa68aSToby Isaac         if (outValues) {
7045d3d1a6afSToby Isaac           /* get the point-to-point submatrix */
7046d3d1a6afSToby Isaac           for (f = 0; f < numFields; f++) {
70479566063dSJacob Faibussowitsch             PetscCall(MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p]));
7048d3d1a6afSToby Isaac           }
7049d3d1a6afSToby Isaac         }
70506ecaa68aSToby Isaac       }
7051d3d1a6afSToby Isaac       else {
7052d3d1a6afSToby Isaac         newPoints[2 * newP]     = b;
7053d3d1a6afSToby Isaac         newPoints[2 * newP + 1] = o;
7054d3d1a6afSToby Isaac         newP++;
7055d3d1a6afSToby Isaac       }
7056d3d1a6afSToby Isaac     }
7057d3d1a6afSToby Isaac   } else {
7058d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
7059d3d1a6afSToby Isaac       PetscInt b    = points[2*p];
7060d3d1a6afSToby Isaac       PetscInt o    = points[2*p+1];
70614b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7062d3d1a6afSToby Isaac 
70639566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
70644b2f2278SToby Isaac       if (!bSecDof) {
70654b2f2278SToby Isaac         continue;
70664b2f2278SToby Isaac       }
7067d3d1a6afSToby Isaac       if (b >= aStart && b < aEnd) {
70689566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7069d3d1a6afSToby Isaac       }
7070d3d1a6afSToby Isaac       if (bDof) {
7071d3d1a6afSToby Isaac         PetscInt bEnd = 0, bAnchorEnd = 0, bOff;
7072d3d1a6afSToby Isaac 
70739566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(cSec, b, &bOff));
70749566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices));
7075d3d1a6afSToby Isaac 
70769566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset (aSec, b, &bOff));
7077d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7078d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aOff;
7079d3d1a6afSToby Isaac 
7080d3d1a6afSToby 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 */
7081d3d1a6afSToby Isaac 
7082d3d1a6afSToby Isaac           newPoints[2*(newP + q)]     = a;
7083d3d1a6afSToby Isaac           newPoints[2*(newP + q) + 1] = 0;
70849566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(section, a, &aOff));
70859566063dSJacob Faibussowitsch           PetscCall(DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices));
7086d3d1a6afSToby Isaac         }
7087d3d1a6afSToby Isaac         newP += bDof;
7088d3d1a6afSToby Isaac 
7089d3d1a6afSToby Isaac         /* get the point-to-point submatrix */
70906ecaa68aSToby Isaac         if (outValues) {
70919566063dSJacob Faibussowitsch           PetscCall(MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p]));
7092d3d1a6afSToby Isaac         }
70936ecaa68aSToby Isaac       }
7094d3d1a6afSToby Isaac       else {
7095d3d1a6afSToby Isaac         newPoints[2 * newP]     = b;
7096d3d1a6afSToby Isaac         newPoints[2 * newP + 1] = o;
7097d3d1a6afSToby Isaac         newP++;
7098d3d1a6afSToby Isaac       }
7099d3d1a6afSToby Isaac     }
7100d3d1a6afSToby Isaac   }
7101d3d1a6afSToby Isaac 
71026ecaa68aSToby Isaac   if (outValues) {
71039566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues));
71049566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(tmpValues,newNumIndices*numIndices));
7105d3d1a6afSToby Isaac     /* multiply constraints on the right */
7106d3d1a6afSToby Isaac     if (numFields) {
7107d3d1a6afSToby Isaac       for (f = 0; f < numFields; f++) {
7108d3d1a6afSToby Isaac         PetscInt oldOff = offsets[f];
7109d3d1a6afSToby Isaac 
7110d3d1a6afSToby Isaac         for (p = 0; p < numPoints; p++) {
7111d3d1a6afSToby Isaac           PetscInt cStart = newPointOffsets[f][p];
7112d3d1a6afSToby Isaac           PetscInt b      = points[2 * p];
7113d3d1a6afSToby Isaac           PetscInt c, r, k;
7114d3d1a6afSToby Isaac           PetscInt dof;
7115d3d1a6afSToby Isaac 
71169566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section,b,f,&dof));
71174b2f2278SToby Isaac           if (!dof) {
71184b2f2278SToby Isaac             continue;
71194b2f2278SToby Isaac           }
7120d3d1a6afSToby Isaac           if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) {
7121d3d1a6afSToby Isaac             PetscInt nCols         = newPointOffsets[f][p+1]-cStart;
7122d3d1a6afSToby Isaac             const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p];
7123d3d1a6afSToby Isaac 
7124d3d1a6afSToby Isaac             for (r = 0; r < numIndices; r++) {
7125d3d1a6afSToby Isaac               for (c = 0; c < nCols; c++) {
7126d3d1a6afSToby Isaac                 for (k = 0; k < dof; k++) {
71274acb8e1eSToby Isaac                   tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c];
7128d3d1a6afSToby Isaac                 }
7129d3d1a6afSToby Isaac               }
7130d3d1a6afSToby Isaac             }
7131d3d1a6afSToby Isaac           }
7132d3d1a6afSToby Isaac           else {
7133d3d1a6afSToby Isaac             /* copy this column as is */
7134d3d1a6afSToby Isaac             for (r = 0; r < numIndices; r++) {
7135d3d1a6afSToby Isaac               for (c = 0; c < dof; c++) {
7136d3d1a6afSToby Isaac                 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c];
7137d3d1a6afSToby Isaac               }
7138d3d1a6afSToby Isaac             }
7139d3d1a6afSToby Isaac           }
7140d3d1a6afSToby Isaac           oldOff += dof;
7141d3d1a6afSToby Isaac         }
7142d3d1a6afSToby Isaac       }
7143d3d1a6afSToby Isaac     }
7144d3d1a6afSToby Isaac     else {
7145d3d1a6afSToby Isaac       PetscInt oldOff = 0;
7146d3d1a6afSToby Isaac       for (p = 0; p < numPoints; p++) {
7147d3d1a6afSToby Isaac         PetscInt cStart = newPointOffsets[0][p];
7148d3d1a6afSToby Isaac         PetscInt b      = points[2 * p];
7149d3d1a6afSToby Isaac         PetscInt c, r, k;
7150d3d1a6afSToby Isaac         PetscInt dof;
7151d3d1a6afSToby Isaac 
71529566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section,b,&dof));
71534b2f2278SToby Isaac         if (!dof) {
71544b2f2278SToby Isaac           continue;
71554b2f2278SToby Isaac         }
7156d3d1a6afSToby Isaac         if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) {
7157d3d1a6afSToby Isaac           PetscInt nCols         = newPointOffsets[0][p+1]-cStart;
7158d3d1a6afSToby Isaac           const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p];
7159d3d1a6afSToby Isaac 
7160d3d1a6afSToby Isaac           for (r = 0; r < numIndices; r++) {
7161d3d1a6afSToby Isaac             for (c = 0; c < nCols; c++) {
7162d3d1a6afSToby Isaac               for (k = 0; k < dof; k++) {
7163d3d1a6afSToby Isaac                 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k];
7164d3d1a6afSToby Isaac               }
7165d3d1a6afSToby Isaac             }
7166d3d1a6afSToby Isaac           }
7167d3d1a6afSToby Isaac         }
7168d3d1a6afSToby Isaac         else {
7169d3d1a6afSToby Isaac           /* copy this column as is */
7170d3d1a6afSToby Isaac           for (r = 0; r < numIndices; r++) {
7171d3d1a6afSToby Isaac             for (c = 0; c < dof; c++) {
7172d3d1a6afSToby Isaac               tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c];
7173d3d1a6afSToby Isaac             }
7174d3d1a6afSToby Isaac           }
7175d3d1a6afSToby Isaac         }
7176d3d1a6afSToby Isaac         oldOff += dof;
7177d3d1a6afSToby Isaac       }
7178d3d1a6afSToby Isaac     }
7179d3d1a6afSToby Isaac 
71806ecaa68aSToby Isaac     if (multiplyLeft) {
71819566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm,newNumIndices*newNumIndices,MPIU_SCALAR,&newValues));
71829566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(newValues,newNumIndices*newNumIndices));
7183d3d1a6afSToby Isaac       /* multiply constraints transpose on the left */
7184d3d1a6afSToby Isaac       if (numFields) {
7185d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7186d3d1a6afSToby Isaac           PetscInt oldOff = offsets[f];
7187d3d1a6afSToby Isaac 
7188d3d1a6afSToby Isaac           for (p = 0; p < numPoints; p++) {
7189d3d1a6afSToby Isaac             PetscInt rStart = newPointOffsets[f][p];
7190d3d1a6afSToby Isaac             PetscInt b      = points[2 * p];
7191d3d1a6afSToby Isaac             PetscInt c, r, k;
7192d3d1a6afSToby Isaac             PetscInt dof;
7193d3d1a6afSToby Isaac 
71949566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section,b,f,&dof));
7195d3d1a6afSToby Isaac             if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) {
7196d3d1a6afSToby Isaac               PetscInt nRows                        = newPointOffsets[f][p+1]-rStart;
7197d3d1a6afSToby Isaac               const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p];
7198d3d1a6afSToby Isaac 
7199d3d1a6afSToby Isaac               for (r = 0; r < nRows; r++) {
7200d3d1a6afSToby Isaac                 for (c = 0; c < newNumIndices; c++) {
7201d3d1a6afSToby Isaac                   for (k = 0; k < dof; k++) {
7202d3d1a6afSToby Isaac                     newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c];
7203d3d1a6afSToby Isaac                   }
7204d3d1a6afSToby Isaac                 }
7205d3d1a6afSToby Isaac               }
7206d3d1a6afSToby Isaac             }
7207d3d1a6afSToby Isaac             else {
7208d3d1a6afSToby Isaac               /* copy this row as is */
7209d3d1a6afSToby Isaac               for (r = 0; r < dof; r++) {
7210d3d1a6afSToby Isaac                 for (c = 0; c < newNumIndices; c++) {
7211d3d1a6afSToby Isaac                   newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c];
7212d3d1a6afSToby Isaac                 }
7213d3d1a6afSToby Isaac               }
7214d3d1a6afSToby Isaac             }
7215d3d1a6afSToby Isaac             oldOff += dof;
7216d3d1a6afSToby Isaac           }
7217d3d1a6afSToby Isaac         }
7218d3d1a6afSToby Isaac       }
7219d3d1a6afSToby Isaac       else {
7220d3d1a6afSToby Isaac         PetscInt oldOff = 0;
7221d3d1a6afSToby Isaac 
7222d3d1a6afSToby Isaac         for (p = 0; p < numPoints; p++) {
7223d3d1a6afSToby Isaac           PetscInt rStart = newPointOffsets[0][p];
7224d3d1a6afSToby Isaac           PetscInt b      = points[2 * p];
7225d3d1a6afSToby Isaac           PetscInt c, r, k;
7226d3d1a6afSToby Isaac           PetscInt dof;
7227d3d1a6afSToby Isaac 
72289566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section,b,&dof));
7229d3d1a6afSToby Isaac           if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) {
7230d3d1a6afSToby Isaac             PetscInt nRows                        = newPointOffsets[0][p+1]-rStart;
7231d3d1a6afSToby Isaac             const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p];
7232d3d1a6afSToby Isaac 
7233d3d1a6afSToby Isaac             for (r = 0; r < nRows; r++) {
7234d3d1a6afSToby Isaac               for (c = 0; c < newNumIndices; c++) {
7235d3d1a6afSToby Isaac                 for (k = 0; k < dof; k++) {
7236d3d1a6afSToby Isaac                   newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c];
7237d3d1a6afSToby Isaac                 }
7238d3d1a6afSToby Isaac               }
7239d3d1a6afSToby Isaac             }
7240d3d1a6afSToby Isaac           }
7241d3d1a6afSToby Isaac           else {
7242d3d1a6afSToby Isaac             /* copy this row as is */
72439fc93327SToby Isaac             for (r = 0; r < dof; r++) {
7244d3d1a6afSToby Isaac               for (c = 0; c < newNumIndices; c++) {
7245d3d1a6afSToby Isaac                 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c];
7246d3d1a6afSToby Isaac               }
7247d3d1a6afSToby Isaac             }
7248d3d1a6afSToby Isaac           }
7249d3d1a6afSToby Isaac           oldOff += dof;
7250d3d1a6afSToby Isaac         }
7251d3d1a6afSToby Isaac       }
7252d3d1a6afSToby Isaac 
72539566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues));
72546ecaa68aSToby Isaac     }
72556ecaa68aSToby Isaac     else {
72566ecaa68aSToby Isaac       newValues = tmpValues;
72576ecaa68aSToby Isaac     }
72586ecaa68aSToby Isaac   }
72596ecaa68aSToby Isaac 
7260d3d1a6afSToby Isaac   /* clean up */
72619566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm,maxDof,MPIU_INT,&indices));
72629566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices));
72636ecaa68aSToby Isaac 
7264d3d1a6afSToby Isaac   if (numFields) {
7265d3d1a6afSToby Isaac     for (f = 0; f < numFields; f++) {
72669566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]));
72679566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]));
72689566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]));
7269d3d1a6afSToby Isaac     }
7270d3d1a6afSToby Isaac   }
7271d3d1a6afSToby Isaac   else {
72729566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]));
72739566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]));
72749566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[0]));
7275d3d1a6afSToby Isaac   }
72769566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(aIS,&anchors));
7277d3d1a6afSToby Isaac 
7278d3d1a6afSToby Isaac   /* output */
72796ecaa68aSToby Isaac   if (outPoints) {
7280d3d1a6afSToby Isaac     *outPoints = newPoints;
72816ecaa68aSToby Isaac   }
72826ecaa68aSToby Isaac   else {
72839566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints));
72846ecaa68aSToby Isaac   }
728531620726SToby Isaac   if (outValues) {
7286d3d1a6afSToby Isaac     *outValues = newValues;
72876ecaa68aSToby Isaac   }
72886ecaa68aSToby Isaac   for (f = 0; f <= numFields; f++) {
7289d3d1a6afSToby Isaac     offsets[f] = newOffsets[f];
7290d3d1a6afSToby Isaac   }
7291d3d1a6afSToby Isaac   PetscFunctionReturn(0);
7292d3d1a6afSToby Isaac }
7293d3d1a6afSToby Isaac 
72944a1e0b3eSMatthew G. Knepley /*@C
729571f0bbf9SMatthew G. Knepley   DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections.
72967cd05799SMatthew G. Knepley 
72977cd05799SMatthew G. Knepley   Not collective
72987cd05799SMatthew G. Knepley 
72997cd05799SMatthew G. Knepley   Input Parameters:
73007cd05799SMatthew G. Knepley + dm         - The DM
730171f0bbf9SMatthew G. Knepley . section    - The PetscSection describing the points (a local section)
730271f0bbf9SMatthew G. Knepley . idxSection - The PetscSection from which to obtain indices (may be local or global)
730371f0bbf9SMatthew G. Knepley . point      - The point defining the closure
730471f0bbf9SMatthew G. Knepley - useClPerm  - Use the closure point permutation if available
73057cd05799SMatthew G. Knepley 
730671f0bbf9SMatthew G. Knepley   Output Parameters:
730771f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections
730871f0bbf9SMatthew G. Knepley . indices    - The dof indices
730971f0bbf9SMatthew G. Knepley . outOffsets - Array to write the field offsets into, or NULL
731071f0bbf9SMatthew G. Knepley - values     - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL
73117cd05799SMatthew G. Knepley 
731236fa2b79SJed Brown   Notes:
731336fa2b79SJed Brown   Must call DMPlexRestoreClosureIndices() to free allocated memory
731436fa2b79SJed Brown 
731536fa2b79SJed Brown   If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices.  The value
731636fa2b79SJed Brown   of those indices is not significant.  If idxSection is local, the constrained dofs will yield the involution -(idx+1)
731736fa2b79SJed Brown   of their index in a local vector.  A caller who does not wish to distinguish those points may recover the nonnegative
731836fa2b79SJed Brown   indices via involution, -(-(idx+1)+1)==idx.  Local indices are provided when idxSection == section, otherwise global
731936fa2b79SJed Brown   indices (with the above semantics) are implied.
73207cd05799SMatthew G. Knepley 
73217cd05799SMatthew G. Knepley   Level: advanced
73227cd05799SMatthew G. Knepley 
7323db781477SPatrick Sanan .seealso `DMPlexRestoreClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()`
73244a1e0b3eSMatthew G. Knepley @*/
732571f0bbf9SMatthew G. Knepley PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm,
732671f0bbf9SMatthew G. Knepley                                        PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[])
73277773e69fSMatthew G. Knepley {
732871f0bbf9SMatthew G. Knepley   /* Closure ordering */
73297773e69fSMatthew G. Knepley   PetscSection        clSection;
73307773e69fSMatthew G. Knepley   IS                  clPoints;
733171f0bbf9SMatthew G. Knepley   const PetscInt     *clp;
733271f0bbf9SMatthew G. Knepley   PetscInt           *points;
733371f0bbf9SMatthew G. Knepley   const PetscInt     *clperm = NULL;
733471f0bbf9SMatthew G. Knepley   /* Dof permutation and sign flips */
73354acb8e1eSToby Isaac   const PetscInt    **perms[32] = {NULL};
733671f0bbf9SMatthew G. Knepley   const PetscScalar **flips[32] = {NULL};
733771f0bbf9SMatthew G. Knepley   PetscScalar        *valCopy   = NULL;
733871f0bbf9SMatthew G. Knepley   /* Hanging node constraints */
733971f0bbf9SMatthew G. Knepley   PetscInt           *pointsC = NULL;
734071f0bbf9SMatthew G. Knepley   PetscScalar        *valuesC = NULL;
734171f0bbf9SMatthew G. Knepley   PetscInt            NclC, NiC;
734271f0bbf9SMatthew G. Knepley 
734371f0bbf9SMatthew G. Knepley   PetscInt           *idx;
734471f0bbf9SMatthew G. Knepley   PetscInt            Nf, Ncl, Ni = 0, offsets[32], p, f;
734571f0bbf9SMatthew G. Knepley   PetscBool           isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE;
73467773e69fSMatthew G. Knepley 
734771f0bbf9SMatthew G. Knepley   PetscFunctionBeginHot;
73487773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
73497773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
735036fa2b79SJed Brown   PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3);
7351dadcf809SJacob Faibussowitsch   if (numIndices) PetscValidIntPointer(numIndices, 6);
735271f0bbf9SMatthew G. Knepley   if (indices)    PetscValidPointer(indices, 7);
7353dadcf809SJacob Faibussowitsch   if (outOffsets) PetscValidIntPointer(outOffsets, 8);
735471f0bbf9SMatthew G. Knepley   if (values)     PetscValidPointer(values, 9);
73559566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &Nf));
735663a3b9bcSJacob Faibussowitsch   PetscCheck(Nf <= 31,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", Nf);
73579566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(offsets, 32));
735871f0bbf9SMatthew G. Knepley   /* 1) Get points in closure */
73599566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
7360c459fbc1SJed Brown   if (useClPerm) {
7361c459fbc1SJed Brown     PetscInt depth, clsize;
73629566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPointDepth(dm, point, &depth));
7363c459fbc1SJed Brown     for (clsize=0,p=0; p<Ncl; p++) {
7364c459fbc1SJed Brown       PetscInt dof;
73659566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, points[2*p], &dof));
7366c459fbc1SJed Brown       clsize += dof;
7367c459fbc1SJed Brown     }
73689566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm));
7369c459fbc1SJed Brown   }
737071f0bbf9SMatthew G. Knepley   /* 2) Get number of indices on these points and field offsets from section */
737171f0bbf9SMatthew G. Knepley   for (p = 0; p < Ncl*2; p += 2) {
73727773e69fSMatthew G. Knepley     PetscInt dof, fdof;
73737773e69fSMatthew G. Knepley 
73749566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[p], &dof));
73757773e69fSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
73769566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof));
73777773e69fSMatthew G. Knepley       offsets[f+1] += fdof;
73787773e69fSMatthew G. Knepley     }
737971f0bbf9SMatthew G. Knepley     Ni += dof;
73807773e69fSMatthew G. Knepley   }
73817773e69fSMatthew G. Knepley   for (f = 1; f < Nf; ++f) offsets[f+1] += offsets[f];
73821dca8a05SBarry 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);
738371f0bbf9SMatthew G. Knepley   /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */
738471f0bbf9SMatthew G. Knepley   for (f = 0; f < PetscMax(1, Nf); ++f) {
73859566063dSJacob Faibussowitsch     if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
73869566063dSJacob Faibussowitsch     else    PetscCall(PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f]));
738771f0bbf9SMatthew G. Knepley     /* may need to apply sign changes to the element matrix */
738871f0bbf9SMatthew G. Knepley     if (values && flips[f]) {
738971f0bbf9SMatthew G. Knepley       PetscInt foffset = offsets[f];
73906ecaa68aSToby Isaac 
739171f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
739271f0bbf9SMatthew G. Knepley         PetscInt           pnt  = points[2*p], fdof;
739371f0bbf9SMatthew G. Knepley         const PetscScalar *flip = flips[f] ? flips[f][p] : NULL;
739471f0bbf9SMatthew G. Knepley 
73959566063dSJacob Faibussowitsch         if (!Nf) PetscCall(PetscSectionGetDof(section, pnt, &fdof));
73969566063dSJacob Faibussowitsch         else     PetscCall(PetscSectionGetFieldDof(section, pnt, f, &fdof));
739771f0bbf9SMatthew G. Knepley         if (flip) {
739871f0bbf9SMatthew G. Knepley           PetscInt i, j, k;
739971f0bbf9SMatthew G. Knepley 
740071f0bbf9SMatthew G. Knepley           if (!valCopy) {
74019566063dSJacob Faibussowitsch             PetscCall(DMGetWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy));
740271f0bbf9SMatthew G. Knepley             for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j];
740371f0bbf9SMatthew G. Knepley             *values = valCopy;
740471f0bbf9SMatthew G. Knepley           }
740571f0bbf9SMatthew G. Knepley           for (i = 0; i < fdof; ++i) {
740671f0bbf9SMatthew G. Knepley             PetscScalar fval = flip[i];
740771f0bbf9SMatthew G. Knepley 
740871f0bbf9SMatthew G. Knepley             for (k = 0; k < Ni; ++k) {
740971f0bbf9SMatthew G. Knepley               valCopy[Ni * (foffset + i) + k] *= fval;
741071f0bbf9SMatthew G. Knepley               valCopy[Ni * k + (foffset + i)] *= fval;
74116ecaa68aSToby Isaac             }
74126ecaa68aSToby Isaac           }
741371f0bbf9SMatthew G. Knepley         }
741471f0bbf9SMatthew G. Knepley         foffset += fdof;
741571f0bbf9SMatthew G. Knepley       }
741671f0bbf9SMatthew G. Knepley     }
741771f0bbf9SMatthew G. Knepley   }
741871f0bbf9SMatthew G. Knepley   /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */
74199566063dSJacob Faibussowitsch   PetscCall(DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE));
742071f0bbf9SMatthew G. Knepley   if (NclC) {
74219566063dSJacob Faibussowitsch     if (valCopy) PetscCall(DMRestoreWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy));
742271f0bbf9SMatthew G. Knepley     for (f = 0; f < PetscMax(1, Nf); ++f) {
74239566063dSJacob Faibussowitsch       if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
74249566063dSJacob Faibussowitsch       else    PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]));
742571f0bbf9SMatthew G. Knepley     }
742671f0bbf9SMatthew G. Knepley     for (f = 0; f < PetscMax(1, Nf); ++f) {
74279566063dSJacob Faibussowitsch       if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f]));
74289566063dSJacob Faibussowitsch       else    PetscCall(PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f]));
742971f0bbf9SMatthew G. Knepley     }
74309566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
743171f0bbf9SMatthew G. Knepley     Ncl     = NclC;
743271f0bbf9SMatthew G. Knepley     Ni      = NiC;
743371f0bbf9SMatthew G. Knepley     points  = pointsC;
743471f0bbf9SMatthew G. Knepley     if (values) *values = valuesC;
743571f0bbf9SMatthew G. Knepley   }
743671f0bbf9SMatthew G. Knepley   /* 5) Calculate indices */
74379566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, Ni, MPIU_INT, &idx));
743871f0bbf9SMatthew G. Knepley   if (Nf) {
743971f0bbf9SMatthew G. Knepley     PetscInt  idxOff;
744071f0bbf9SMatthew G. Knepley     PetscBool useFieldOffsets;
744171f0bbf9SMatthew G. Knepley 
744271f0bbf9SMatthew G. Knepley     if (outOffsets) {for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f];}
74439566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets));
744471f0bbf9SMatthew G. Knepley     if (useFieldOffsets) {
744571f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
744671f0bbf9SMatthew G. Knepley         const PetscInt pnt = points[p*2];
744771f0bbf9SMatthew G. Knepley 
74489566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx));
74497773e69fSMatthew G. Knepley       }
74507773e69fSMatthew G. Knepley     } else {
745171f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
745271f0bbf9SMatthew G. Knepley         const PetscInt pnt = points[p*2];
745371f0bbf9SMatthew G. Knepley 
74549566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff));
745571f0bbf9SMatthew G. Knepley         /* Note that we pass a local section even though we're using global offsets.  This is because global sections do
745671f0bbf9SMatthew G. Knepley          * not (at the time of this writing) have fields set. They probably should, in which case we would pass the
745771f0bbf9SMatthew G. Knepley          * global section. */
74589566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx));
745971f0bbf9SMatthew G. Knepley       }
746071f0bbf9SMatthew G. Knepley     }
746171f0bbf9SMatthew G. Knepley   } else {
746271f0bbf9SMatthew G. Knepley     PetscInt off = 0, idxOff;
746371f0bbf9SMatthew G. Knepley 
746471f0bbf9SMatthew G. Knepley     for (p = 0; p < Ncl; ++p) {
746571f0bbf9SMatthew G. Knepley       const PetscInt  pnt  = points[p*2];
74664acb8e1eSToby Isaac       const PetscInt *perm = perms[0] ? perms[0][p] : NULL;
74674acb8e1eSToby Isaac 
74689566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff));
746971f0bbf9SMatthew G. Knepley       /* Note that we pass a local section even though we're using global offsets.  This is because global sections do
747071f0bbf9SMatthew G. Knepley        * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */
74719566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx));
74727773e69fSMatthew G. Knepley     }
74737773e69fSMatthew G. Knepley   }
747471f0bbf9SMatthew G. Knepley   /* 6) Cleanup */
747571f0bbf9SMatthew G. Knepley   for (f = 0; f < PetscMax(1, Nf); ++f) {
74769566063dSJacob Faibussowitsch     if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
74779566063dSJacob Faibussowitsch     else    PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]));
74784acb8e1eSToby Isaac   }
747971f0bbf9SMatthew G. Knepley   if (NclC) {
74809566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, NclC*2, MPIU_INT, &pointsC));
74817773e69fSMatthew G. Knepley   } else {
74829566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
74837773e69fSMatthew G. Knepley   }
748471f0bbf9SMatthew G. Knepley 
748571f0bbf9SMatthew G. Knepley   if (numIndices) *numIndices = Ni;
748671f0bbf9SMatthew G. Knepley   if (indices)    *indices    = idx;
74877773e69fSMatthew G. Knepley   PetscFunctionReturn(0);
74887773e69fSMatthew G. Knepley }
74897773e69fSMatthew G. Knepley 
74907cd05799SMatthew G. Knepley /*@C
749171f0bbf9SMatthew G. Knepley   DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections.
74927cd05799SMatthew G. Knepley 
74937cd05799SMatthew G. Knepley   Not collective
74947cd05799SMatthew G. Knepley 
74957cd05799SMatthew G. Knepley   Input Parameters:
74967cd05799SMatthew G. Knepley + dm         - The DM
749771f0bbf9SMatthew G. Knepley . section    - The PetscSection describing the points (a local section)
749871f0bbf9SMatthew G. Knepley . idxSection - The PetscSection from which to obtain indices (may be local or global)
749971f0bbf9SMatthew G. Knepley . point      - The point defining the closure
750071f0bbf9SMatthew G. Knepley - useClPerm  - Use the closure point permutation if available
750171f0bbf9SMatthew G. Knepley 
750271f0bbf9SMatthew G. Knepley   Output Parameters:
750371f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections
750471f0bbf9SMatthew G. Knepley . indices    - The dof indices
750571f0bbf9SMatthew G. Knepley . outOffsets - Array to write the field offsets into, or NULL
750671f0bbf9SMatthew G. Knepley - values     - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL
750771f0bbf9SMatthew G. Knepley 
750871f0bbf9SMatthew G. Knepley   Notes:
750971f0bbf9SMatthew G. Knepley   If values were modified, the user is responsible for calling DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values).
751071f0bbf9SMatthew G. Knepley 
751171f0bbf9SMatthew G. Knepley   If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices.  The value
751271f0bbf9SMatthew G. Knepley   of those indices is not significant.  If idxSection is local, the constrained dofs will yield the involution -(idx+1)
751371f0bbf9SMatthew G. Knepley   of their index in a local vector.  A caller who does not wish to distinguish those points may recover the nonnegative
751471f0bbf9SMatthew G. Knepley   indices via involution, -(-(idx+1)+1)==idx.  Local indices are provided when idxSection == section, otherwise global
751571f0bbf9SMatthew G. Knepley   indices (with the above semantics) are implied.
75167cd05799SMatthew G. Knepley 
75177cd05799SMatthew G. Knepley   Level: advanced
75187cd05799SMatthew G. Knepley 
7519db781477SPatrick Sanan .seealso `DMPlexGetClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()`
75207cd05799SMatthew G. Knepley @*/
752171f0bbf9SMatthew G. Knepley PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm,
752271f0bbf9SMatthew G. Knepley                                            PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[])
75237773e69fSMatthew G. Knepley {
75247773e69fSMatthew G. Knepley   PetscFunctionBegin;
75257773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7526064a246eSJacob Faibussowitsch   PetscValidPointer(indices, 7);
75279566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, indices));
75287773e69fSMatthew G. Knepley   PetscFunctionReturn(0);
75297773e69fSMatthew G. Knepley }
75307773e69fSMatthew G. Knepley 
75317f5d1fdeSMatthew G. Knepley /*@C
75327f5d1fdeSMatthew G. Knepley   DMPlexMatSetClosure - Set an array of the values on the closure of 'point'
75337f5d1fdeSMatthew G. Knepley 
75347f5d1fdeSMatthew G. Knepley   Not collective
75357f5d1fdeSMatthew G. Knepley 
75367f5d1fdeSMatthew G. Knepley   Input Parameters:
75377f5d1fdeSMatthew G. Knepley + dm - The DM
7538ebd6d717SJed Brown . section - The section describing the layout in v, or NULL to use the default section
7539ebd6d717SJed Brown . globalSection - The section describing the layout in v, or NULL to use the default global section
75407f5d1fdeSMatthew G. Knepley . A - The matrix
7541eaf898f9SPatrick Sanan . point - The point in the DM
75427f5d1fdeSMatthew G. Knepley . values - The array of values
75437f5d1fdeSMatthew G. Knepley - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions
75447f5d1fdeSMatthew G. Knepley 
75457f5d1fdeSMatthew G. Knepley   Fortran Notes:
75467f5d1fdeSMatthew G. Knepley   This routine is only available in Fortran 90, and you must include petsc.h90 in your code.
75477f5d1fdeSMatthew G. Knepley 
75487f5d1fdeSMatthew G. Knepley   Level: intermediate
75497f5d1fdeSMatthew G. Knepley 
7550db781477SPatrick Sanan .seealso `DMPlexMatSetClosureGeneral()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`
75517f5d1fdeSMatthew G. Knepley @*/
75527c1f9639SMatthew G Knepley PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
7553552f7358SJed Brown {
7554552f7358SJed Brown   DM_Plex           *mesh = (DM_Plex*) dm->data;
7555552f7358SJed Brown   PetscInt          *indices;
755671f0bbf9SMatthew G. Knepley   PetscInt           numIndices;
755771f0bbf9SMatthew G. Knepley   const PetscScalar *valuesOrig = values;
7558552f7358SJed Brown   PetscErrorCode     ierr;
7559552f7358SJed Brown 
7560552f7358SJed Brown   PetscFunctionBegin;
7561552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
75629566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
75633dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
75649566063dSJacob Faibussowitsch   if (!globalSection) PetscCall(DMGetGlobalSection(dm, &globalSection));
75653dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3);
75663dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 4);
7567552f7358SJed Brown 
75689566063dSJacob Faibussowitsch   PetscCall(DMPlexGetClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values));
75690d644c17SKarl Rupp 
75709566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values));
7571d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
75724a1e0b3eSMatthew G. Knepley   ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode);
7573552f7358SJed Brown   if (ierr) {
7574552f7358SJed Brown     PetscMPIInt    rank;
7575552f7358SJed Brown 
75769566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
75779566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
75789566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values));
75799566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values));
75809566063dSJacob Faibussowitsch     if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values));
7581c3e24edfSBarry Smith     SETERRQ(PetscObjectComm((PetscObject)dm),ierr,"Not possible to set matrix values");
7582552f7358SJed Brown   }
75834a1e0b3eSMatthew G. Knepley   if (mesh->printFEM > 1) {
75844a1e0b3eSMatthew G. Knepley     PetscInt i;
75859566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "  Indices:"));
758663a3b9bcSJacob Faibussowitsch     for (i = 0; i < numIndices; ++i) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, indices[i]));
75879566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
75884a1e0b3eSMatthew G. Knepley   }
758971f0bbf9SMatthew G. Knepley 
75909566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values));
75919566063dSJacob Faibussowitsch   if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values));
759271f0bbf9SMatthew G. Knepley   PetscFunctionReturn(0);
75934acb8e1eSToby Isaac }
759471f0bbf9SMatthew G. Knepley 
75954a1e0b3eSMatthew G. Knepley /*@C
75964a1e0b3eSMatthew G. Knepley   DMPlexMatSetClosure - Set an array of the values on the closure of 'point' using a different row and column section
75974a1e0b3eSMatthew G. Knepley 
75984a1e0b3eSMatthew G. Knepley   Not collective
75994a1e0b3eSMatthew G. Knepley 
76004a1e0b3eSMatthew G. Knepley   Input Parameters:
76014a1e0b3eSMatthew G. Knepley + dmRow - The DM for the row fields
76024a1e0b3eSMatthew G. Knepley . sectionRow - The section describing the layout, or NULL to use the default section in dmRow
76034a1e0b3eSMatthew G. Knepley . globalSectionRow - The section describing the layout, or NULL to use the default global section in dmRow
76044a1e0b3eSMatthew G. Knepley . dmCol - The DM for the column fields
76054a1e0b3eSMatthew G. Knepley . sectionCol - The section describing the layout, or NULL to use the default section in dmCol
76064a1e0b3eSMatthew G. Knepley . globalSectionCol - The section describing the layout, or NULL to use the default global section in dmCol
76074a1e0b3eSMatthew G. Knepley . A - The matrix
76084a1e0b3eSMatthew G. Knepley . point - The point in the DMs
76094a1e0b3eSMatthew G. Knepley . values - The array of values
76104a1e0b3eSMatthew G. Knepley - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions
76114a1e0b3eSMatthew G. Knepley 
76124a1e0b3eSMatthew G. Knepley   Level: intermediate
76134a1e0b3eSMatthew G. Knepley 
7614db781477SPatrick Sanan .seealso `DMPlexMatSetClosure()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`
76154a1e0b3eSMatthew G. Knepley @*/
761671f0bbf9SMatthew 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)
761771f0bbf9SMatthew G. Knepley {
761871f0bbf9SMatthew G. Knepley   DM_Plex           *mesh = (DM_Plex*) dmRow->data;
761971f0bbf9SMatthew G. Knepley   PetscInt          *indicesRow, *indicesCol;
762071f0bbf9SMatthew G. Knepley   PetscInt           numIndicesRow, numIndicesCol;
762171f0bbf9SMatthew G. Knepley   const PetscScalar *valuesOrig = values;
762271f0bbf9SMatthew G. Knepley   PetscErrorCode     ierr;
762371f0bbf9SMatthew G. Knepley 
762471f0bbf9SMatthew G. Knepley   PetscFunctionBegin;
762571f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1);
76269566063dSJacob Faibussowitsch   if (!sectionRow) PetscCall(DMGetLocalSection(dmRow, &sectionRow));
762771f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2);
76289566063dSJacob Faibussowitsch   if (!globalSectionRow) PetscCall(DMGetGlobalSection(dmRow, &globalSectionRow));
762971f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3);
763071f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(dmCol, DM_CLASSID, 4);
76319566063dSJacob Faibussowitsch   if (!sectionCol) PetscCall(DMGetLocalSection(dmCol, &sectionCol));
763271f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 5);
76339566063dSJacob Faibussowitsch   if (!globalSectionCol) PetscCall(DMGetGlobalSection(dmCol, &globalSectionCol));
763471f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 6);
763571f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 7);
763671f0bbf9SMatthew G. Knepley 
76379566063dSJacob Faibussowitsch   PetscCall(DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values));
76389566063dSJacob Faibussowitsch   PetscCall(DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values));
763971f0bbf9SMatthew G. Knepley 
76409566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values));
7641d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
76424a1e0b3eSMatthew G. Knepley   ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode);
764371f0bbf9SMatthew G. Knepley   if (ierr) {
764471f0bbf9SMatthew G. Knepley     PetscMPIInt    rank;
764571f0bbf9SMatthew G. Knepley 
76469566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
76479566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
76489566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values));
76499566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values));
76509566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **) &values));
76519566063dSJacob Faibussowitsch     if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values));
7652d3d1a6afSToby Isaac   }
765371f0bbf9SMatthew G. Knepley 
76549566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values));
76559566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values));
76569566063dSJacob Faibussowitsch   if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values));
7657552f7358SJed Brown   PetscFunctionReturn(0);
7658552f7358SJed Brown }
7659552f7358SJed Brown 
7660de41b84cSMatthew 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)
7661de41b84cSMatthew G. Knepley {
7662de41b84cSMatthew G. Knepley   DM_Plex        *mesh   = (DM_Plex*) dmf->data;
7663de41b84cSMatthew G. Knepley   PetscInt       *fpoints = NULL, *ftotpoints = NULL;
7664de41b84cSMatthew G. Knepley   PetscInt       *cpoints = NULL;
7665de41b84cSMatthew G. Knepley   PetscInt       *findices, *cindices;
766617c0192bSMatthew G. Knepley   const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */
7667de41b84cSMatthew G. Knepley   PetscInt        foffsets[32], coffsets[32];
7668412e9a14SMatthew G. Knepley   DMPolytopeType  ct;
76694ca5e9f5SMatthew G. Knepley   PetscInt        numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f;
7670de41b84cSMatthew G. Knepley   PetscErrorCode  ierr;
7671de41b84cSMatthew G. Knepley 
7672de41b84cSMatthew G. Knepley   PetscFunctionBegin;
7673de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 1);
7674de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 4);
76759566063dSJacob Faibussowitsch   if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection));
7676de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2);
76779566063dSJacob Faibussowitsch   if (!csection) PetscCall(DMGetLocalSection(dmc, &csection));
7678de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5);
76799566063dSJacob Faibussowitsch   if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection));
7680de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3);
76819566063dSJacob Faibussowitsch   if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection));
7682de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6);
7683de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 7);
76849566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(fsection, &numFields));
768563a3b9bcSJacob Faibussowitsch   PetscCheck(numFields <= 31,PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields);
76869566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(foffsets, 32));
76879566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(coffsets, 32));
7688de41b84cSMatthew G. Knepley   /* Column indices */
76899566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
76904ca5e9f5SMatthew G. Knepley   maxFPoints = numCPoints;
7691de41b84cSMatthew G. Knepley   /* Compress out points not in the section */
7692de41b84cSMatthew G. Knepley   /*   TODO: Squeeze out points with 0 dof as well */
76939566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd));
7694de41b84cSMatthew G. Knepley   for (p = 0, q = 0; p < numCPoints*2; p += 2) {
7695de41b84cSMatthew G. Knepley     if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) {
7696de41b84cSMatthew G. Knepley       cpoints[q*2]   = cpoints[p];
7697de41b84cSMatthew G. Knepley       cpoints[q*2+1] = cpoints[p+1];
7698de41b84cSMatthew G. Knepley       ++q;
7699de41b84cSMatthew G. Knepley     }
7700de41b84cSMatthew G. Knepley   }
7701de41b84cSMatthew G. Knepley   numCPoints = q;
7702de41b84cSMatthew G. Knepley   for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) {
7703de41b84cSMatthew G. Knepley     PetscInt fdof;
7704de41b84cSMatthew G. Knepley 
77059566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof));
77064ca5e9f5SMatthew G. Knepley     if (!dof) continue;
7707de41b84cSMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
77089566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof));
7709de41b84cSMatthew G. Knepley       coffsets[f+1] += fdof;
7710de41b84cSMatthew G. Knepley     }
7711de41b84cSMatthew G. Knepley     numCIndices += dof;
7712de41b84cSMatthew G. Knepley   }
7713de41b84cSMatthew G. Knepley   for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f];
7714de41b84cSMatthew G. Knepley   /* Row indices */
77159566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dmc, point, &ct));
7716412e9a14SMatthew G. Knepley   {
7717012bc364SMatthew G. Knepley     DMPlexTransform tr;
7718012bc364SMatthew G. Knepley     DMPolytopeType *rct;
7719012bc364SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt, Nt;
7720012bc364SMatthew G. Knepley 
77219566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr));
77229566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR));
77239566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt));
7724012bc364SMatthew G. Knepley     numSubcells = rsize[Nt-1];
77259566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformDestroy(&tr));
7726412e9a14SMatthew G. Knepley   }
77279566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints));
7728de41b84cSMatthew G. Knepley   for (r = 0, q = 0; r < numSubcells; ++r) {
7729de41b84cSMatthew G. Knepley     /* TODO Map from coarse to fine cells */
77309566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints));
7731de41b84cSMatthew G. Knepley     /* Compress out points not in the section */
77329566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd));
7733de41b84cSMatthew G. Knepley     for (p = 0; p < numFPoints*2; p += 2) {
7734de41b84cSMatthew G. Knepley       if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) {
77359566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof));
77364ca5e9f5SMatthew G. Knepley         if (!dof) continue;
77374ca5e9f5SMatthew G. Knepley         for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break;
77384ca5e9f5SMatthew G. Knepley         if (s < q) continue;
7739de41b84cSMatthew G. Knepley         ftotpoints[q*2]   = fpoints[p];
7740de41b84cSMatthew G. Knepley         ftotpoints[q*2+1] = fpoints[p+1];
7741de41b84cSMatthew G. Knepley         ++q;
7742de41b84cSMatthew G. Knepley       }
7743de41b84cSMatthew G. Knepley     }
77449566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints));
7745de41b84cSMatthew G. Knepley   }
7746de41b84cSMatthew G. Knepley   numFPoints = q;
7747de41b84cSMatthew G. Knepley   for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) {
7748de41b84cSMatthew G. Knepley     PetscInt fdof;
7749de41b84cSMatthew G. Knepley 
77509566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof));
77514ca5e9f5SMatthew G. Knepley     if (!dof) continue;
7752de41b84cSMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
77539566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof));
7754de41b84cSMatthew G. Knepley       foffsets[f+1] += fdof;
7755de41b84cSMatthew G. Knepley     }
7756de41b84cSMatthew G. Knepley     numFIndices += dof;
7757de41b84cSMatthew G. Knepley   }
7758de41b84cSMatthew G. Knepley   for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f];
7759de41b84cSMatthew G. Knepley 
77601dca8a05SBarry 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);
77611dca8a05SBarry 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);
77629566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices));
77639566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
7764de41b84cSMatthew G. Knepley   if (numFields) {
77654acb8e1eSToby Isaac     const PetscInt **permsF[32] = {NULL};
77664acb8e1eSToby Isaac     const PetscInt **permsC[32] = {NULL};
77674acb8e1eSToby Isaac 
77684acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
77699566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL));
77709566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL));
7771de41b84cSMatthew G. Knepley     }
77724acb8e1eSToby Isaac     for (p = 0; p < numFPoints; p++) {
77739566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff));
77749566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices));
77754acb8e1eSToby Isaac     }
77764acb8e1eSToby Isaac     for (p = 0; p < numCPoints; p++) {
77779566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff));
77789566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices));
77794acb8e1eSToby Isaac     }
77804acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
77819566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL));
77829566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL));
7783de41b84cSMatthew G. Knepley     }
7784de41b84cSMatthew G. Knepley   } else {
77854acb8e1eSToby Isaac     const PetscInt **permsF = NULL;
77864acb8e1eSToby Isaac     const PetscInt **permsC = NULL;
77874acb8e1eSToby Isaac 
77889566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL));
77899566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL));
77904acb8e1eSToby Isaac     for (p = 0, off = 0; p < numFPoints; p++) {
77914acb8e1eSToby Isaac       const PetscInt *perm = permsF ? permsF[p] : NULL;
77924acb8e1eSToby Isaac 
77939566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff));
77949566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices));
7795de41b84cSMatthew G. Knepley     }
77964acb8e1eSToby Isaac     for (p = 0, off = 0; p < numCPoints; p++) {
77974acb8e1eSToby Isaac       const PetscInt *perm = permsC ? permsC[p] : NULL;
77984acb8e1eSToby Isaac 
77999566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff));
78009566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices));
7801de41b84cSMatthew G. Knepley     }
78029566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL));
78039566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL));
7804de41b84cSMatthew G. Knepley   }
78059566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values));
78064acb8e1eSToby Isaac   /* TODO: flips */
7807d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
7808de41b84cSMatthew G. Knepley   ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode);
7809de41b84cSMatthew G. Knepley   if (ierr) {
7810de41b84cSMatthew G. Knepley     PetscMPIInt    rank;
7811de41b84cSMatthew G. Knepley 
78129566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
78139566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
78149566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values));
78159566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices));
78169566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
7817de41b84cSMatthew G. Knepley   }
78189566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints));
78199566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
78209566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices));
78219566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
7822de41b84cSMatthew G. Knepley   PetscFunctionReturn(0);
7823de41b84cSMatthew G. Knepley }
7824de41b84cSMatthew G. Knepley 
78257c927364SMatthew G. Knepley PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[])
78267c927364SMatthew G. Knepley {
78277c927364SMatthew G. Knepley   PetscInt      *fpoints = NULL, *ftotpoints = NULL;
78287c927364SMatthew G. Knepley   PetscInt      *cpoints = NULL;
78297c927364SMatthew G. Knepley   PetscInt       foffsets[32], coffsets[32];
783017c0192bSMatthew G. Knepley   const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */
7831412e9a14SMatthew G. Knepley   DMPolytopeType ct;
78327c927364SMatthew G. Knepley   PetscInt       numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f;
78337c927364SMatthew G. Knepley 
78347c927364SMatthew G. Knepley   PetscFunctionBegin;
78357c927364SMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 1);
78367c927364SMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 4);
78379566063dSJacob Faibussowitsch   if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection));
78387c927364SMatthew G. Knepley   PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2);
78399566063dSJacob Faibussowitsch   if (!csection) PetscCall(DMGetLocalSection(dmc, &csection));
78407c927364SMatthew G. Knepley   PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5);
78419566063dSJacob Faibussowitsch   if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection));
78427c927364SMatthew G. Knepley   PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3);
78439566063dSJacob Faibussowitsch   if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection));
78447c927364SMatthew G. Knepley   PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6);
78459566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(fsection, &numFields));
784663a3b9bcSJacob Faibussowitsch   PetscCheck(numFields <= 31,PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields);
78479566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(foffsets, 32));
78489566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(coffsets, 32));
78497c927364SMatthew G. Knepley   /* Column indices */
78509566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
78517c927364SMatthew G. Knepley   maxFPoints = numCPoints;
78527c927364SMatthew G. Knepley   /* Compress out points not in the section */
78537c927364SMatthew G. Knepley   /*   TODO: Squeeze out points with 0 dof as well */
78549566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd));
78557c927364SMatthew G. Knepley   for (p = 0, q = 0; p < numCPoints*2; p += 2) {
78567c927364SMatthew G. Knepley     if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) {
78577c927364SMatthew G. Knepley       cpoints[q*2]   = cpoints[p];
78587c927364SMatthew G. Knepley       cpoints[q*2+1] = cpoints[p+1];
78597c927364SMatthew G. Knepley       ++q;
78607c927364SMatthew G. Knepley     }
78617c927364SMatthew G. Knepley   }
78627c927364SMatthew G. Knepley   numCPoints = q;
78637c927364SMatthew G. Knepley   for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) {
78647c927364SMatthew G. Knepley     PetscInt fdof;
78657c927364SMatthew G. Knepley 
78669566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof));
78677c927364SMatthew G. Knepley     if (!dof) continue;
78687c927364SMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
78699566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof));
78707c927364SMatthew G. Knepley       coffsets[f+1] += fdof;
78717c927364SMatthew G. Knepley     }
78727c927364SMatthew G. Knepley     numCIndices += dof;
78737c927364SMatthew G. Knepley   }
78747c927364SMatthew G. Knepley   for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f];
78757c927364SMatthew G. Knepley   /* Row indices */
78769566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dmc, point, &ct));
7877412e9a14SMatthew G. Knepley   {
7878012bc364SMatthew G. Knepley     DMPlexTransform tr;
7879012bc364SMatthew G. Knepley     DMPolytopeType *rct;
7880012bc364SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt, Nt;
7881012bc364SMatthew G. Knepley 
78829566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr));
78839566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR));
78849566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt));
7885012bc364SMatthew G. Knepley     numSubcells = rsize[Nt-1];
78869566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformDestroy(&tr));
7887412e9a14SMatthew G. Knepley   }
78889566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints));
78897c927364SMatthew G. Knepley   for (r = 0, q = 0; r < numSubcells; ++r) {
78907c927364SMatthew G. Knepley     /* TODO Map from coarse to fine cells */
78919566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints));
78927c927364SMatthew G. Knepley     /* Compress out points not in the section */
78939566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd));
78947c927364SMatthew G. Knepley     for (p = 0; p < numFPoints*2; p += 2) {
78957c927364SMatthew G. Knepley       if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) {
78969566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof));
78977c927364SMatthew G. Knepley         if (!dof) continue;
78987c927364SMatthew G. Knepley         for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break;
78997c927364SMatthew G. Knepley         if (s < q) continue;
79007c927364SMatthew G. Knepley         ftotpoints[q*2]   = fpoints[p];
79017c927364SMatthew G. Knepley         ftotpoints[q*2+1] = fpoints[p+1];
79027c927364SMatthew G. Knepley         ++q;
79037c927364SMatthew G. Knepley       }
79047c927364SMatthew G. Knepley     }
79059566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints));
79067c927364SMatthew G. Knepley   }
79077c927364SMatthew G. Knepley   numFPoints = q;
79087c927364SMatthew G. Knepley   for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) {
79097c927364SMatthew G. Knepley     PetscInt fdof;
79107c927364SMatthew G. Knepley 
79119566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof));
79127c927364SMatthew G. Knepley     if (!dof) continue;
79137c927364SMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
79149566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof));
79157c927364SMatthew G. Knepley       foffsets[f+1] += fdof;
79167c927364SMatthew G. Knepley     }
79177c927364SMatthew G. Knepley     numFIndices += dof;
79187c927364SMatthew G. Knepley   }
79197c927364SMatthew G. Knepley   for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f];
79207c927364SMatthew G. Knepley 
79211dca8a05SBarry 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);
79221dca8a05SBarry 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);
79237c927364SMatthew G. Knepley   if (numFields) {
79244acb8e1eSToby Isaac     const PetscInt **permsF[32] = {NULL};
79254acb8e1eSToby Isaac     const PetscInt **permsC[32] = {NULL};
79264acb8e1eSToby Isaac 
79274acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
79289566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL));
79299566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL));
79307c927364SMatthew G. Knepley     }
79314acb8e1eSToby Isaac     for (p = 0; p < numFPoints; p++) {
79329566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff));
79339566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices));
79344acb8e1eSToby Isaac     }
79354acb8e1eSToby Isaac     for (p = 0; p < numCPoints; p++) {
79369566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff));
79379566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices));
79384acb8e1eSToby Isaac     }
79394acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
79409566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL));
79419566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL));
79427c927364SMatthew G. Knepley     }
79437c927364SMatthew G. Knepley   } else {
79444acb8e1eSToby Isaac     const PetscInt **permsF = NULL;
79454acb8e1eSToby Isaac     const PetscInt **permsC = NULL;
79464acb8e1eSToby Isaac 
79479566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL));
79489566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL));
79494acb8e1eSToby Isaac     for (p = 0, off = 0; p < numFPoints; p++) {
79504acb8e1eSToby Isaac       const PetscInt *perm = permsF ? permsF[p] : NULL;
79514acb8e1eSToby Isaac 
79529566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff));
79539566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices));
79547c927364SMatthew G. Knepley     }
79554acb8e1eSToby Isaac     for (p = 0, off = 0; p < numCPoints; p++) {
79564acb8e1eSToby Isaac       const PetscInt *perm = permsC ? permsC[p] : NULL;
79574acb8e1eSToby Isaac 
79589566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff));
79599566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices));
79607c927364SMatthew G. Knepley     }
79619566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL));
79629566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL));
79637c927364SMatthew G. Knepley   }
79649566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints));
79659566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
79667c927364SMatthew G. Knepley   PetscFunctionReturn(0);
79677c927364SMatthew G. Knepley }
79687c927364SMatthew G. Knepley 
79697cd05799SMatthew G. Knepley /*@C
79707cd05799SMatthew G. Knepley   DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0)
79717cd05799SMatthew G. Knepley 
79727cd05799SMatthew G. Knepley   Input Parameter:
79737cd05799SMatthew G. Knepley . dm   - The DMPlex object
79747cd05799SMatthew G. Knepley 
79757cd05799SMatthew G. Knepley   Output Parameter:
79767cd05799SMatthew G. Knepley . cellHeight - The height of a cell
79777cd05799SMatthew G. Knepley 
79787cd05799SMatthew G. Knepley   Level: developer
79797cd05799SMatthew G. Knepley 
7980db781477SPatrick Sanan .seealso `DMPlexSetVTKCellHeight()`
79817cd05799SMatthew G. Knepley @*/
7982552f7358SJed Brown PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight)
7983552f7358SJed Brown {
7984552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
7985552f7358SJed Brown 
7986552f7358SJed Brown   PetscFunctionBegin;
7987552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7988dadcf809SJacob Faibussowitsch   PetscValidIntPointer(cellHeight, 2);
7989552f7358SJed Brown   *cellHeight = mesh->vtkCellHeight;
7990552f7358SJed Brown   PetscFunctionReturn(0);
7991552f7358SJed Brown }
7992552f7358SJed Brown 
79937cd05799SMatthew G. Knepley /*@C
79947cd05799SMatthew G. Knepley   DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0)
79957cd05799SMatthew G. Knepley 
79967cd05799SMatthew G. Knepley   Input Parameters:
79977cd05799SMatthew G. Knepley + dm   - The DMPlex object
79987cd05799SMatthew G. Knepley - cellHeight - The height of a cell
79997cd05799SMatthew G. Knepley 
80007cd05799SMatthew G. Knepley   Level: developer
80017cd05799SMatthew G. Knepley 
8002db781477SPatrick Sanan .seealso `DMPlexGetVTKCellHeight()`
80037cd05799SMatthew G. Knepley @*/
8004552f7358SJed Brown PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight)
8005552f7358SJed Brown {
8006552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
8007552f7358SJed Brown 
8008552f7358SJed Brown   PetscFunctionBegin;
8009552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8010552f7358SJed Brown   mesh->vtkCellHeight = cellHeight;
8011552f7358SJed Brown   PetscFunctionReturn(0);
8012552f7358SJed Brown }
8013552f7358SJed Brown 
8014e6139122SMatthew G. Knepley /*@
8015e6139122SMatthew G. Knepley   DMPlexGetGhostCellStratum - Get the range of cells which are used to enforce FV boundary conditions
8016e6139122SMatthew G. Knepley 
8017e6139122SMatthew G. Knepley   Input Parameter:
8018e6139122SMatthew G. Knepley . dm - The DMPlex object
8019e6139122SMatthew G. Knepley 
8020e6139122SMatthew G. Knepley   Output Parameters:
80212a9f31c0SMatthew G. Knepley + gcStart - The first ghost cell, or NULL
80222a9f31c0SMatthew G. Knepley - gcEnd   - The upper bound on ghost cells, or NULL
8023e6139122SMatthew G. Knepley 
80242a9f31c0SMatthew G. Knepley   Level: advanced
8025e6139122SMatthew G. Knepley 
8026db781477SPatrick Sanan .seealso `DMPlexConstructGhostCells()`, `DMPlexGetGhostCellStratum()`
8027e6139122SMatthew G. Knepley @*/
8028e6139122SMatthew G. Knepley PetscErrorCode DMPlexGetGhostCellStratum(DM dm, PetscInt *gcStart, PetscInt *gcEnd)
8029e6139122SMatthew G. Knepley {
8030412e9a14SMatthew G. Knepley   DMLabel        ctLabel;
8031e6139122SMatthew G. Knepley 
8032e6139122SMatthew G. Knepley   PetscFunctionBegin;
8033e6139122SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
80349566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel));
80359566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_FV_GHOST, gcStart, gcEnd));
8036695799ffSMatthew G. Knepley   // Reset label for fast lookup
8037695799ffSMatthew G. Knepley   PetscCall(DMLabelMakeAllInvalid_Internal(ctLabel));
8038e6139122SMatthew G. Knepley   PetscFunctionReturn(0);
8039e6139122SMatthew G. Knepley }
8040e6139122SMatthew G. Knepley 
80419886b8cfSStefano Zampini PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering)
8042552f7358SJed Brown {
8043552f7358SJed Brown   PetscSection   section, globalSection;
8044552f7358SJed Brown   PetscInt      *numbers, p;
8045552f7358SJed Brown 
8046552f7358SJed Brown   PetscFunctionBegin;
80476c1ef331SVaclav Hapla   if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf));
80489566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section));
80499566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(section, pStart, pEnd));
8050552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
80519566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(section, p, 1));
8052552f7358SJed Brown   }
80539566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(section));
80549566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection));
80559566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(pEnd - pStart, &numbers));
8056552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
80579566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]));
8058ef48cebcSMatthew G. Knepley     if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift;
8059ef48cebcSMatthew G. Knepley     else                       numbers[p-pStart] += shift;
8060552f7358SJed Brown   }
80619566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering));
8062ef48cebcSMatthew G. Knepley   if (globalSize) {
8063ef48cebcSMatthew G. Knepley     PetscLayout layout;
80649566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout));
80659566063dSJacob Faibussowitsch     PetscCall(PetscLayoutGetSize(layout, globalSize));
80669566063dSJacob Faibussowitsch     PetscCall(PetscLayoutDestroy(&layout));
8067ef48cebcSMatthew G. Knepley   }
80689566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&section));
80699566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&globalSection));
8070552f7358SJed Brown   PetscFunctionReturn(0);
8071552f7358SJed Brown }
8072552f7358SJed Brown 
807381ed3555SMatthew G. Knepley PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers)
8074552f7358SJed Brown {
8075412e9a14SMatthew G. Knepley   PetscInt       cellHeight, cStart, cEnd;
8076552f7358SJed Brown 
8077552f7358SJed Brown   PetscFunctionBegin;
80789566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
80799566063dSJacob Faibussowitsch   if (includeHybrid) PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
80809566063dSJacob Faibussowitsch   else               PetscCall(DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd));
80819566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers));
808281ed3555SMatthew G. Knepley   PetscFunctionReturn(0);
8083552f7358SJed Brown }
808481ed3555SMatthew G. Knepley 
80858dab3259SMatthew G. Knepley /*@
80867cd05799SMatthew G. Knepley   DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process
80877cd05799SMatthew G. Knepley 
80887cd05799SMatthew G. Knepley   Input Parameter:
80897cd05799SMatthew G. Knepley . dm   - The DMPlex object
80907cd05799SMatthew G. Knepley 
80917cd05799SMatthew G. Knepley   Output Parameter:
80927cd05799SMatthew G. Knepley . globalCellNumbers - Global cell numbers for all cells on this process
80937cd05799SMatthew G. Knepley 
80947cd05799SMatthew G. Knepley   Level: developer
80957cd05799SMatthew G. Knepley 
8096db781477SPatrick Sanan .seealso `DMPlexGetVertexNumbering()`
80977cd05799SMatthew G. Knepley @*/
809881ed3555SMatthew G. Knepley PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers)
809981ed3555SMatthew G. Knepley {
810081ed3555SMatthew G. Knepley   DM_Plex       *mesh = (DM_Plex*) dm->data;
810181ed3555SMatthew G. Knepley 
810281ed3555SMatthew G. Knepley   PetscFunctionBegin;
810381ed3555SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
81049566063dSJacob Faibussowitsch   if (!mesh->globalCellNumbers) PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers));
8105552f7358SJed Brown   *globalCellNumbers = mesh->globalCellNumbers;
8106552f7358SJed Brown   PetscFunctionReturn(0);
8107552f7358SJed Brown }
8108552f7358SJed Brown 
810981ed3555SMatthew G. Knepley PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers)
811081ed3555SMatthew G. Knepley {
8111412e9a14SMatthew G. Knepley   PetscInt       vStart, vEnd;
811281ed3555SMatthew G. Knepley 
811381ed3555SMatthew G. Knepley   PetscFunctionBegin;
811481ed3555SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
81159566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
81169566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers));
811781ed3555SMatthew G. Knepley   PetscFunctionReturn(0);
811881ed3555SMatthew G. Knepley }
811981ed3555SMatthew G. Knepley 
81208dab3259SMatthew G. Knepley /*@
81216aa51ba9SJacob Faibussowitsch   DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process
81227cd05799SMatthew G. Knepley 
81237cd05799SMatthew G. Knepley   Input Parameter:
81247cd05799SMatthew G. Knepley . dm   - The DMPlex object
81257cd05799SMatthew G. Knepley 
81267cd05799SMatthew G. Knepley   Output Parameter:
81277cd05799SMatthew G. Knepley . globalVertexNumbers - Global vertex numbers for all vertices on this process
81287cd05799SMatthew G. Knepley 
81297cd05799SMatthew G. Knepley   Level: developer
81307cd05799SMatthew G. Knepley 
8131db781477SPatrick Sanan .seealso `DMPlexGetCellNumbering()`
81327cd05799SMatthew G. Knepley @*/
8133552f7358SJed Brown PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers)
8134552f7358SJed Brown {
8135552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
8136552f7358SJed Brown 
8137552f7358SJed Brown   PetscFunctionBegin;
8138552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
81399566063dSJacob Faibussowitsch   if (!mesh->globalVertexNumbers) PetscCall(DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers));
8140552f7358SJed Brown   *globalVertexNumbers = mesh->globalVertexNumbers;
8141552f7358SJed Brown   PetscFunctionReturn(0);
8142552f7358SJed Brown }
8143552f7358SJed Brown 
81448dab3259SMatthew G. Knepley /*@
8145966484cfSJed Brown   DMPlexCreatePointNumbering - Create a global numbering for all points.
8146966484cfSJed Brown 
8147966484cfSJed Brown   Collective on dm
81487cd05799SMatthew G. Knepley 
81497cd05799SMatthew G. Knepley   Input Parameter:
81507cd05799SMatthew G. Knepley . dm   - The DMPlex object
81517cd05799SMatthew G. Knepley 
81527cd05799SMatthew G. Knepley   Output Parameter:
81537cd05799SMatthew G. Knepley . globalPointNumbers - Global numbers for all points on this process
81547cd05799SMatthew G. Knepley 
8155966484cfSJed Brown   Notes:
8156966484cfSJed Brown 
8157966484cfSJed Brown   The point numbering IS is parallel, with local portion indexed by local points (see `DMGetLocalSection()`). The global
8158966484cfSJed Brown   points are taken as stratified, with each MPI rank owning a contiguous subset of each stratum. In the IS, owned points
8159966484cfSJed Brown   will have their non-negative value while points owned by different ranks will be involuted -(idx+1). As an example,
8160966484cfSJed Brown   consider a parallel mesh in which the first two elements and first two vertices are owned by rank 0.
8161966484cfSJed Brown 
8162966484cfSJed Brown   The partitioned mesh is
8163966484cfSJed Brown ```
8164966484cfSJed Brown  (2)--0--(3)--1--(4)    (1)--0--(2)
8165966484cfSJed Brown ```
8166966484cfSJed Brown   and its global numbering is
8167966484cfSJed Brown ```
8168966484cfSJed Brown   (3)--0--(4)--1--(5)--2--(6)
8169966484cfSJed Brown ```
8170966484cfSJed Brown   Then the global numbering is provided as
8171966484cfSJed Brown ```
8172966484cfSJed Brown [0] Number of indices in set 5
8173966484cfSJed Brown [0] 0 0
8174966484cfSJed Brown [0] 1 1
8175966484cfSJed Brown [0] 2 3
8176966484cfSJed Brown [0] 3 4
8177966484cfSJed Brown [0] 4 -6
8178966484cfSJed Brown [1] Number of indices in set 3
8179966484cfSJed Brown [1] 0 2
8180966484cfSJed Brown [1] 1 5
8181966484cfSJed Brown [1] 2 6
8182966484cfSJed Brown ```
8183966484cfSJed Brown 
81847cd05799SMatthew G. Knepley   Level: developer
81857cd05799SMatthew G. Knepley 
8186db781477SPatrick Sanan .seealso `DMPlexGetCellNumbering()`
81877cd05799SMatthew G. Knepley @*/
8188ef48cebcSMatthew G. Knepley PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers)
8189ef48cebcSMatthew G. Knepley {
8190ef48cebcSMatthew G. Knepley   IS             nums[4];
8191862913ffSStefano Zampini   PetscInt       depths[4], gdepths[4], starts[4];
8192ef48cebcSMatthew G. Knepley   PetscInt       depth, d, shift = 0;
8193ef48cebcSMatthew G. Knepley 
8194ef48cebcSMatthew G. Knepley   PetscFunctionBegin;
8195ef48cebcSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
81969566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
81978abc87a0SMichael Lange   /* For unstratified meshes use dim instead of depth */
81989566063dSJacob Faibussowitsch   if (depth < 0) PetscCall(DMGetDimension(dm, &depth));
8199862913ffSStefano Zampini   for (d = 0; d <= depth; ++d) {
8200862913ffSStefano Zampini     PetscInt end;
8201862913ffSStefano Zampini 
8202862913ffSStefano Zampini     depths[d] = depth-d;
82039566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end));
8204862913ffSStefano Zampini     if (!(starts[d]-end)) { starts[d] = depths[d] = -1; }
8205862913ffSStefano Zampini   }
82069566063dSJacob Faibussowitsch   PetscCall(PetscSortIntWithArray(depth+1, starts, depths));
82071c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(depths, gdepths, depth+1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject) dm)));
8208862913ffSStefano Zampini   for (d = 0; d <= depth; ++d) {
82091dca8a05SBarry 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]);
8210862913ffSStefano Zampini   }
8211ef48cebcSMatthew G. Knepley   for (d = 0; d <= depth; ++d) {
8212ef48cebcSMatthew G. Knepley     PetscInt pStart, pEnd, gsize;
8213ef48cebcSMatthew G. Knepley 
82149566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd));
82159566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]));
8216ef48cebcSMatthew G. Knepley     shift += gsize;
8217ef48cebcSMatthew G. Knepley   }
82189566063dSJacob Faibussowitsch   PetscCall(ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers));
82199566063dSJacob Faibussowitsch   for (d = 0; d <= depth; ++d) PetscCall(ISDestroy(&nums[d]));
8220ef48cebcSMatthew G. Knepley   PetscFunctionReturn(0);
8221ef48cebcSMatthew G. Knepley }
8222ef48cebcSMatthew G. Knepley 
822308a22f4bSMatthew G. Knepley /*@
822408a22f4bSMatthew G. Knepley   DMPlexCreateRankField - Create a cell field whose value is the rank of the owner
822508a22f4bSMatthew G. Knepley 
822608a22f4bSMatthew G. Knepley   Input Parameter:
822708a22f4bSMatthew G. Knepley . dm - The DMPlex object
822808a22f4bSMatthew G. Knepley 
822908a22f4bSMatthew G. Knepley   Output Parameter:
823008a22f4bSMatthew G. Knepley . ranks - The rank field
823108a22f4bSMatthew G. Knepley 
823208a22f4bSMatthew G. Knepley   Options Database Keys:
823308a22f4bSMatthew G. Knepley . -dm_partition_view - Adds the rank field into the DM output from -dm_view using the same viewer
823408a22f4bSMatthew G. Knepley 
823508a22f4bSMatthew G. Knepley   Level: intermediate
823608a22f4bSMatthew G. Knepley 
8237db781477SPatrick Sanan .seealso: `DMView()`
823808a22f4bSMatthew G. Knepley @*/
823908a22f4bSMatthew G. Knepley PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks)
824008a22f4bSMatthew G. Knepley {
824108a22f4bSMatthew G. Knepley   DM             rdm;
824208a22f4bSMatthew G. Knepley   PetscFE        fe;
824308a22f4bSMatthew G. Knepley   PetscScalar   *r;
824408a22f4bSMatthew G. Knepley   PetscMPIInt    rank;
8245a55f9a55SMatthew G. Knepley   DMPolytopeType ct;
824608a22f4bSMatthew G. Knepley   PetscInt       dim, cStart, cEnd, c;
8247a55f9a55SMatthew G. Knepley   PetscBool      simplex;
824808a22f4bSMatthew G. Knepley 
824908a22f4bSMatthew G. Knepley   PetscFunctionBeginUser;
8250f95ace6aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8251f95ace6aSMatthew G. Knepley   PetscValidPointer(ranks, 2);
82529566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank));
82539566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &rdm));
82549566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(rdm, &dim));
82559566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd));
82569566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cStart, &ct));
8257a55f9a55SMatthew G. Knepley   simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE;
82589566063dSJacob Faibussowitsch   PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe));
82599566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject) fe, "rank"));
82609566063dSJacob Faibussowitsch   PetscCall(DMSetField(rdm, 0, NULL, (PetscObject) fe));
82619566063dSJacob Faibussowitsch   PetscCall(PetscFEDestroy(&fe));
82629566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(rdm));
82639566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(rdm, ranks));
82649566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject) *ranks, "partition"));
82659566063dSJacob Faibussowitsch   PetscCall(VecGetArray(*ranks, &r));
826608a22f4bSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
826708a22f4bSMatthew G. Knepley     PetscScalar *lr;
826808a22f4bSMatthew G. Knepley 
82699566063dSJacob Faibussowitsch     PetscCall(DMPlexPointGlobalRef(rdm, c, r, &lr));
827071f09efeSPierre Jolivet     if (lr) *lr = rank;
827108a22f4bSMatthew G. Knepley   }
82729566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(*ranks, &r));
82739566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&rdm));
827408a22f4bSMatthew G. Knepley   PetscFunctionReturn(0);
827508a22f4bSMatthew G. Knepley }
827608a22f4bSMatthew G. Knepley 
8277ca8062c8SMatthew G. Knepley /*@
827818e14f0cSMatthew G. Knepley   DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell
827918e14f0cSMatthew G. Knepley 
828018e14f0cSMatthew G. Knepley   Input Parameters:
828118e14f0cSMatthew G. Knepley + dm    - The DMPlex
828218e14f0cSMatthew G. Knepley - label - The DMLabel
828318e14f0cSMatthew G. Knepley 
828418e14f0cSMatthew G. Knepley   Output Parameter:
828518e14f0cSMatthew G. Knepley . val - The label value field
828618e14f0cSMatthew G. Knepley 
828718e14f0cSMatthew G. Knepley   Options Database Keys:
828818e14f0cSMatthew G. Knepley . -dm_label_view - Adds the label value field into the DM output from -dm_view using the same viewer
828918e14f0cSMatthew G. Knepley 
829018e14f0cSMatthew G. Knepley   Level: intermediate
829118e14f0cSMatthew G. Knepley 
8292db781477SPatrick Sanan .seealso: `DMView()`
829318e14f0cSMatthew G. Knepley @*/
829418e14f0cSMatthew G. Knepley PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val)
829518e14f0cSMatthew G. Knepley {
829618e14f0cSMatthew G. Knepley   DM             rdm;
829718e14f0cSMatthew G. Knepley   PetscFE        fe;
829818e14f0cSMatthew G. Knepley   PetscScalar   *v;
829918e14f0cSMatthew G. Knepley   PetscInt       dim, cStart, cEnd, c;
830018e14f0cSMatthew G. Knepley 
830118e14f0cSMatthew G. Knepley   PetscFunctionBeginUser;
830218e14f0cSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
830318e14f0cSMatthew G. Knepley   PetscValidPointer(label, 2);
830418e14f0cSMatthew G. Knepley   PetscValidPointer(val, 3);
83059566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &rdm));
83069566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(rdm, &dim));
83079566063dSJacob Faibussowitsch   PetscCall(PetscFECreateDefault(PetscObjectComm((PetscObject) rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe));
83089566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject) fe, "label_value"));
83099566063dSJacob Faibussowitsch   PetscCall(DMSetField(rdm, 0, NULL, (PetscObject) fe));
83109566063dSJacob Faibussowitsch   PetscCall(PetscFEDestroy(&fe));
83119566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(rdm));
83129566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd));
83139566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(rdm, val));
83149566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject) *val, "label_value"));
83159566063dSJacob Faibussowitsch   PetscCall(VecGetArray(*val, &v));
831618e14f0cSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
831718e14f0cSMatthew G. Knepley     PetscScalar *lv;
831818e14f0cSMatthew G. Knepley     PetscInt     cval;
831918e14f0cSMatthew G. Knepley 
83209566063dSJacob Faibussowitsch     PetscCall(DMPlexPointGlobalRef(rdm, c, v, &lv));
83219566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(label, c, &cval));
832218e14f0cSMatthew G. Knepley     *lv = cval;
832318e14f0cSMatthew G. Knepley   }
83249566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(*val, &v));
83259566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&rdm));
832618e14f0cSMatthew G. Knepley   PetscFunctionReturn(0);
832718e14f0cSMatthew G. Knepley }
832818e14f0cSMatthew G. Knepley 
832918e14f0cSMatthew G. Knepley /*@
8330ca8062c8SMatthew G. Knepley   DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric.
8331ca8062c8SMatthew G. Knepley 
833269916449SMatthew G. Knepley   Input Parameter:
833369916449SMatthew G. Knepley . dm - The DMPlex object
8334ca8062c8SMatthew G. Knepley 
833595eb5ee5SVaclav Hapla   Notes:
833695eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
833795eb5ee5SVaclav Hapla 
833895eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
8339ca8062c8SMatthew G. Knepley 
8340ca8062c8SMatthew G. Knepley   Level: developer
8341ca8062c8SMatthew G. Knepley 
8342db781477SPatrick Sanan .seealso: `DMCreate()`, `DMSetFromOptions()`
8343ca8062c8SMatthew G. Knepley @*/
8344ca8062c8SMatthew G. Knepley PetscErrorCode DMPlexCheckSymmetry(DM dm)
8345ca8062c8SMatthew G. Knepley {
8346ca8062c8SMatthew G. Knepley   PetscSection    coneSection, supportSection;
8347ca8062c8SMatthew G. Knepley   const PetscInt *cone, *support;
8348ca8062c8SMatthew G. Knepley   PetscInt        coneSize, c, supportSize, s;
834957beb4faSStefano Zampini   PetscInt        pStart, pEnd, p, pp, csize, ssize;
835057beb4faSStefano Zampini   PetscBool       storagecheck = PETSC_TRUE;
8351ca8062c8SMatthew G. Knepley 
8352ca8062c8SMatthew G. Knepley   PetscFunctionBegin;
8353ca8062c8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
83549566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(dm, NULL, "-sym_dm_view"));
83559566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSection(dm, &coneSection));
83569566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSupportSection(dm, &supportSection));
8357ca8062c8SMatthew G. Knepley   /* Check that point p is found in the support of its cone points, and vice versa */
83589566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
8359ca8062c8SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
83609566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
83619566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
8362ca8062c8SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
836342e66dfaSMatthew G. Knepley       PetscBool dup = PETSC_FALSE;
836442e66dfaSMatthew G. Knepley       PetscInt  d;
836542e66dfaSMatthew G. Knepley       for (d = c-1; d >= 0; --d) {
836642e66dfaSMatthew G. Knepley         if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;}
836742e66dfaSMatthew G. Knepley       }
83689566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, cone[c], &supportSize));
83699566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupport(dm, cone[c], &support));
8370ca8062c8SMatthew G. Knepley       for (s = 0; s < supportSize; ++s) {
8371ca8062c8SMatthew G. Knepley         if (support[s] == p) break;
8372ca8062c8SMatthew G. Knepley       }
837342e66dfaSMatthew G. Knepley       if ((s >= supportSize) || (dup && (support[s+1] != p))) {
837463a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", p));
8375ca8062c8SMatthew G. Knepley         for (s = 0; s < coneSize; ++s) {
837663a3b9bcSJacob Faibussowitsch           PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[s]));
8377ca8062c8SMatthew G. Knepley         }
83789566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
837963a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", cone[c]));
8380ca8062c8SMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
838163a3b9bcSJacob Faibussowitsch           PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[s]));
8382ca8062c8SMatthew G. Knepley         }
83839566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
838463a3b9bcSJacob 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]);
8385f7d195e4SLawrence Mitchell         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in support of cone point %" PetscInt_FMT, p, cone[c]);
8386ca8062c8SMatthew G. Knepley       }
838742e66dfaSMatthew G. Knepley     }
83889566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTreeParent(dm, p, &pp, NULL));
838957beb4faSStefano Zampini     if (p != pp) { storagecheck = PETSC_FALSE; continue; }
83909566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
83919566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dm, p, &support));
8392ca8062c8SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
83939566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, support[s], &coneSize));
83949566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, support[s], &cone));
8395ca8062c8SMatthew G. Knepley       for (c = 0; c < coneSize; ++c) {
83969566063dSJacob Faibussowitsch         PetscCall(DMPlexGetTreeParent(dm, cone[c], &pp, NULL));
839757beb4faSStefano Zampini         if (cone[c] != pp) { c = 0; break; }
8398ca8062c8SMatthew G. Knepley         if (cone[c] == p) break;
8399ca8062c8SMatthew G. Knepley       }
8400ca8062c8SMatthew G. Knepley       if (c >= coneSize) {
840163a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", p));
8402ca8062c8SMatthew G. Knepley         for (c = 0; c < supportSize; ++c) {
840363a3b9bcSJacob Faibussowitsch           PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[c]));
8404ca8062c8SMatthew G. Knepley         }
84059566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
840663a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", support[s]));
8407ca8062c8SMatthew G. Knepley         for (c = 0; c < coneSize; ++c) {
840863a3b9bcSJacob Faibussowitsch           PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[c]));
8409ca8062c8SMatthew G. Knepley         }
84109566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
841163a3b9bcSJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in cone of support point %" PetscInt_FMT, p, support[s]);
8412ca8062c8SMatthew G. Knepley       }
8413ca8062c8SMatthew G. Knepley     }
8414ca8062c8SMatthew G. Knepley   }
841557beb4faSStefano Zampini   if (storagecheck) {
84169566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coneSection, &csize));
84179566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(supportSection, &ssize));
841863a3b9bcSJacob Faibussowitsch     PetscCheck(csize == ssize,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %" PetscInt_FMT " != Total support size %" PetscInt_FMT, csize, ssize);
841957beb4faSStefano Zampini   }
8420ca8062c8SMatthew G. Knepley   PetscFunctionReturn(0);
8421ca8062c8SMatthew G. Knepley }
8422ca8062c8SMatthew G. Knepley 
8423412e9a14SMatthew G. Knepley /*
8424412e9a14SMatthew 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.
8425412e9a14SMatthew G. Knepley */
8426412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit)
8427412e9a14SMatthew G. Knepley {
8428412e9a14SMatthew G. Knepley   DMPolytopeType  cct;
8429412e9a14SMatthew G. Knepley   PetscInt        ptpoints[4];
8430412e9a14SMatthew G. Knepley   const PetscInt *cone, *ccone, *ptcone;
8431412e9a14SMatthew G. Knepley   PetscInt        coneSize, cp, cconeSize, ccp, npt = 0, pt;
8432412e9a14SMatthew G. Knepley 
8433412e9a14SMatthew G. Knepley   PetscFunctionBegin;
8434412e9a14SMatthew G. Knepley   *unsplit = 0;
8435412e9a14SMatthew G. Knepley   switch (ct) {
8436b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_POINT_PRISM_TENSOR:
8437b5a892a1SMatthew G. Knepley       ptpoints[npt++] = c;
8438b5a892a1SMatthew G. Knepley       break;
8439412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEG_PRISM_TENSOR:
84409566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, c, &cone));
84419566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
8442412e9a14SMatthew G. Knepley       for (cp = 0; cp < coneSize; ++cp) {
84439566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, cone[cp], &cct));
8444412e9a14SMatthew G. Knepley         if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp];
8445412e9a14SMatthew G. Knepley       }
8446412e9a14SMatthew G. Knepley       break;
8447412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:
8448412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
84499566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, c, &cone));
84509566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
8451412e9a14SMatthew G. Knepley       for (cp = 0; cp < coneSize; ++cp) {
84529566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, cone[cp], &ccone));
84539566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, cone[cp], &cconeSize));
8454412e9a14SMatthew G. Knepley         for (ccp = 0; ccp < cconeSize; ++ccp) {
84559566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCellType(dm, ccone[ccp], &cct));
8456412e9a14SMatthew G. Knepley           if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) {
8457412e9a14SMatthew G. Knepley             PetscInt p;
8458412e9a14SMatthew G. Knepley             for (p = 0; p < npt; ++p) if (ptpoints[p] == ccone[ccp]) break;
8459412e9a14SMatthew G. Knepley             if (p == npt) ptpoints[npt++] = ccone[ccp];
8460412e9a14SMatthew G. Knepley           }
8461412e9a14SMatthew G. Knepley         }
8462412e9a14SMatthew G. Knepley       }
8463412e9a14SMatthew G. Knepley       break;
8464412e9a14SMatthew G. Knepley     default: break;
8465412e9a14SMatthew G. Knepley   }
8466412e9a14SMatthew G. Knepley   for (pt = 0; pt < npt; ++pt) {
84679566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, ptpoints[pt], &ptcone));
8468412e9a14SMatthew G. Knepley     if (ptcone[0] == ptcone[1]) ++(*unsplit);
8469412e9a14SMatthew G. Knepley   }
8470412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
8471412e9a14SMatthew G. Knepley }
8472412e9a14SMatthew G. Knepley 
8473ca8062c8SMatthew G. Knepley /*@
8474ca8062c8SMatthew G. Knepley   DMPlexCheckSkeleton - Check that each cell has the correct number of vertices
8475ca8062c8SMatthew G. Knepley 
8476ca8062c8SMatthew G. Knepley   Input Parameters:
8477ca8062c8SMatthew G. Knepley + dm - The DMPlex object
847858723a97SMatthew G. Knepley - cellHeight - Normally 0
8479ca8062c8SMatthew G. Knepley 
848095eb5ee5SVaclav Hapla   Notes:
848195eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
848225c50c26SVaclav Hapla   Currently applicable only to homogeneous simplex or tensor meshes.
8483ca8062c8SMatthew G. Knepley 
848495eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
848595eb5ee5SVaclav Hapla 
8486ca8062c8SMatthew G. Knepley   Level: developer
8487ca8062c8SMatthew G. Knepley 
8488db781477SPatrick Sanan .seealso: `DMCreate()`, `DMSetFromOptions()`
8489ca8062c8SMatthew G. Knepley @*/
849025c50c26SVaclav Hapla PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight)
8491ca8062c8SMatthew G. Knepley {
8492412e9a14SMatthew G. Knepley   DMPlexInterpolatedFlag interp;
8493412e9a14SMatthew G. Knepley   DMPolytopeType         ct;
8494412e9a14SMatthew G. Knepley   PetscInt               vStart, vEnd, cStart, cEnd, c;
8495ca8062c8SMatthew G. Knepley 
8496ca8062c8SMatthew G. Knepley   PetscFunctionBegin;
8497ca8062c8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
84989566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolated(dm, &interp));
84999566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
85009566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
8501412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
8502412e9a14SMatthew G. Knepley     PetscInt *closure = NULL;
8503412e9a14SMatthew G. Knepley     PetscInt  coneSize, closureSize, cl, Nv = 0;
850458723a97SMatthew G. Knepley 
85059566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
850663a3b9bcSJacob Faibussowitsch     PetscCheck((PetscInt) ct >= 0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " has no cell type", c);
8507412e9a14SMatthew G. Knepley     if (ct == DM_POLYTOPE_UNKNOWN) continue;
8508412e9a14SMatthew G. Knepley     if (interp == DMPLEX_INTERPOLATED_FULL) {
85099566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
851063a3b9bcSJacob 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));
8511412e9a14SMatthew G. Knepley     }
85129566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
851358723a97SMatthew G. Knepley     for (cl = 0; cl < closureSize*2; cl += 2) {
851458723a97SMatthew G. Knepley       const PetscInt p = closure[cl];
8515412e9a14SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) ++Nv;
851658723a97SMatthew G. Knepley     }
85179566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
8518412e9a14SMatthew G. Knepley     /* Special Case: Tensor faces with identified vertices */
8519412e9a14SMatthew G. Knepley     if (Nv < DMPolytopeTypeGetNumVertices(ct)) {
8520412e9a14SMatthew G. Knepley       PetscInt unsplit;
852142363296SMatthew G. Knepley 
85229566063dSJacob Faibussowitsch       PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
8523412e9a14SMatthew G. Knepley       if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue;
852442363296SMatthew G. Knepley     }
852563a3b9bcSJacob 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));
852642363296SMatthew G. Knepley   }
8527ca8062c8SMatthew G. Knepley   PetscFunctionReturn(0);
8528ca8062c8SMatthew G. Knepley }
85299bf0dad6SMatthew G. Knepley 
85309bf0dad6SMatthew G. Knepley /*@
85319bf0dad6SMatthew 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
85329bf0dad6SMatthew G. Knepley 
85338f6815adSVaclav Hapla   Collective
8534899ea2b8SJacob Faibussowitsch 
85359bf0dad6SMatthew G. Knepley   Input Parameters:
85369bf0dad6SMatthew G. Knepley + dm - The DMPlex object
85379bf0dad6SMatthew G. Knepley - cellHeight - Normally 0
85389bf0dad6SMatthew G. Knepley 
853945da879fSVaclav Hapla   Notes:
854045da879fSVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
854145da879fSVaclav Hapla   This routine is only relevant for meshes that are fully interpolated across all ranks.
854245da879fSVaclav Hapla   It will error out if a partially interpolated mesh is given on some rank.
854345da879fSVaclav Hapla   It will do nothing for locally uninterpolated mesh (as there is nothing to check).
85449bf0dad6SMatthew G. Knepley 
854595eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
854695eb5ee5SVaclav Hapla 
85479bf0dad6SMatthew G. Knepley   Level: developer
85489bf0dad6SMatthew G. Knepley 
8549db781477SPatrick Sanan .seealso: `DMCreate()`, `DMPlexGetVTKCellHeight()`, `DMSetFromOptions()`
85509bf0dad6SMatthew G. Knepley @*/
855125c50c26SVaclav Hapla PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight)
85529bf0dad6SMatthew G. Knepley {
8553ab91121cSMatthew G. Knepley   PetscInt       dim, depth, vStart, vEnd, cStart, cEnd, c, h;
8554899ea2b8SJacob Faibussowitsch   DMPlexInterpolatedFlag interpEnum;
85559bf0dad6SMatthew G. Knepley 
85569bf0dad6SMatthew G. Knepley   PetscFunctionBegin;
85579bf0dad6SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
85588f6815adSVaclav Hapla   PetscCall(DMPlexIsInterpolatedCollective(dm, &interpEnum));
855945da879fSVaclav Hapla   if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(0);
85608f6815adSVaclav Hapla   if (interpEnum != DMPLEX_INTERPOLATED_FULL) {
85618f6815adSVaclav Hapla     PetscPrintf(PetscObjectComm((PetscObject)dm), "DMPlexCheckFaces() warning: Mesh is only partially interpolated, this is currently not supported");
85628f6815adSVaclav Hapla     PetscFunctionReturn(0);
8563899ea2b8SJacob Faibussowitsch   }
8564899ea2b8SJacob Faibussowitsch 
85659566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
85669566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
85679566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
8568ab91121cSMatthew G. Knepley   for (h = cellHeight; h < PetscMin(depth, dim); ++h) {
85699566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, h, &cStart, &cEnd));
85703554e41dSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
8571412e9a14SMatthew G. Knepley       const PetscInt      *cone, *ornt, *faceSizes, *faces;
8572412e9a14SMatthew G. Knepley       const DMPolytopeType *faceTypes;
8573ba2698f1SMatthew G. Knepley       DMPolytopeType        ct;
8574412e9a14SMatthew G. Knepley       PetscInt              numFaces, coneSize, f;
8575412e9a14SMatthew G. Knepley       PetscInt             *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit;
85769bf0dad6SMatthew G. Knepley 
85779566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, c, &ct));
85789566063dSJacob Faibussowitsch       PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
8579412e9a14SMatthew G. Knepley       if (unsplit) continue;
85809566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
85819566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, c, &cone));
85829566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeOrientation(dm, c, &ornt));
85839566063dSJacob Faibussowitsch       PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
85849bf0dad6SMatthew G. Knepley       for (cl = 0; cl < closureSize*2; cl += 2) {
85859bf0dad6SMatthew G. Knepley         const PetscInt p = closure[cl];
85869bf0dad6SMatthew G. Knepley         if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p;
85879bf0dad6SMatthew G. Knepley       }
85889566063dSJacob Faibussowitsch       PetscCall(DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces));
858963a3b9bcSJacob 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);
85909bf0dad6SMatthew G. Knepley       for (f = 0; f < numFaces; ++f) {
8591d4961f80SStefano Zampini         DMPolytopeType fct;
85929bf0dad6SMatthew G. Knepley         PetscInt       *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v;
85939bf0dad6SMatthew G. Knepley 
85949566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, cone[f], &fct));
85959566063dSJacob Faibussowitsch         PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure));
85969bf0dad6SMatthew G. Knepley         for (cl = 0; cl < fclosureSize*2; cl += 2) {
85979bf0dad6SMatthew G. Knepley           const PetscInt p = fclosure[cl];
85989bf0dad6SMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p;
85999bf0dad6SMatthew G. Knepley         }
860063a3b9bcSJacob 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]);
86019bf0dad6SMatthew G. Knepley         for (v = 0; v < fnumCorners; ++v) {
8602b5a892a1SMatthew G. Knepley           if (fclosure[v] != faces[fOff+v]) {
8603b5a892a1SMatthew G. Knepley             PetscInt v1;
8604b5a892a1SMatthew G. Knepley 
86059566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "face closure:"));
860663a3b9bcSJacob Faibussowitsch             for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, fclosure[v1]));
86079566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "\ncell face:"));
860863a3b9bcSJacob Faibussowitsch             for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, faces[fOff+v1]));
86099566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
861063a3b9bcSJacob 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]);
8611b5a892a1SMatthew G. Knepley           }
86129bf0dad6SMatthew G. Knepley         }
86139566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure));
8614412e9a14SMatthew G. Knepley         fOff += faceSizes[f];
86159bf0dad6SMatthew G. Knepley       }
86169566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces));
86179566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
86189bf0dad6SMatthew G. Knepley     }
86193554e41dSMatthew G. Knepley   }
8620552f7358SJed Brown   PetscFunctionReturn(0);
8621552f7358SJed Brown }
86223913d7c8SMatthew G. Knepley 
8623bb6a34a8SMatthew G. Knepley /*@
8624bb6a34a8SMatthew G. Knepley   DMPlexCheckGeometry - Check the geometry of mesh cells
8625bb6a34a8SMatthew G. Knepley 
8626bb6a34a8SMatthew G. Knepley   Input Parameter:
8627bb6a34a8SMatthew G. Knepley . dm - The DMPlex object
8628bb6a34a8SMatthew G. Knepley 
862995eb5ee5SVaclav Hapla   Notes:
863095eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
863195eb5ee5SVaclav Hapla 
863295eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
8633bb6a34a8SMatthew G. Knepley 
8634bb6a34a8SMatthew G. Knepley   Level: developer
8635bb6a34a8SMatthew G. Knepley 
8636db781477SPatrick Sanan .seealso: `DMCreate()`, `DMSetFromOptions()`
8637bb6a34a8SMatthew G. Knepley @*/
8638bb6a34a8SMatthew G. Knepley PetscErrorCode DMPlexCheckGeometry(DM dm)
8639bb6a34a8SMatthew G. Knepley {
8640a2a9e04cSMatthew G. Knepley   Vec       coordinates;
8641bb6a34a8SMatthew G. Knepley   PetscReal detJ, J[9], refVol = 1.0;
8642bb6a34a8SMatthew G. Knepley   PetscReal vol;
864351a74b61SMatthew G. Knepley   PetscInt  dim, depth, dE, d, cStart, cEnd, c;
8644bb6a34a8SMatthew G. Knepley 
8645bb6a34a8SMatthew G. Knepley   PetscFunctionBegin;
86469566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
86479566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dE));
864851a74b61SMatthew G. Knepley   if (dim != dE) PetscFunctionReturn(0);
86499566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
8650bb6a34a8SMatthew G. Knepley   for (d = 0; d < dim; ++d) refVol *= 2.0;
86519566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
8652a2a9e04cSMatthew G. Knepley   /* Make sure local coordinates are created, because that step is collective */
86539566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
8654412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
8655412e9a14SMatthew G. Knepley     DMPolytopeType ct;
8656412e9a14SMatthew G. Knepley     PetscInt       unsplit;
8657412e9a14SMatthew G. Knepley     PetscBool      ignoreZeroVol = PETSC_FALSE;
8658412e9a14SMatthew G. Knepley 
86599566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
8660412e9a14SMatthew G. Knepley     switch (ct) {
8661412e9a14SMatthew G. Knepley       case DM_POLYTOPE_SEG_PRISM_TENSOR:
8662412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM_TENSOR:
8663412e9a14SMatthew G. Knepley       case DM_POLYTOPE_QUAD_PRISM_TENSOR:
8664412e9a14SMatthew G. Knepley         ignoreZeroVol = PETSC_TRUE; break;
8665412e9a14SMatthew G. Knepley       default: break;
8666412e9a14SMatthew G. Knepley     }
8667412e9a14SMatthew G. Knepley     switch (ct) {
8668412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM:
8669412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM_TENSOR:
8670412e9a14SMatthew G. Knepley       case DM_POLYTOPE_QUAD_PRISM_TENSOR:
8671a2a9e04cSMatthew G. Knepley       case DM_POLYTOPE_PYRAMID:
8672412e9a14SMatthew G. Knepley         continue;
8673412e9a14SMatthew G. Knepley       default: break;
8674412e9a14SMatthew G. Knepley     }
86759566063dSJacob Faibussowitsch     PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
8676412e9a14SMatthew G. Knepley     if (unsplit) continue;
86779566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ));
86781dca8a05SBarry 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);
867963a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FEM Volume %g\n", c, (double)(detJ*refVol)));
86806858538eSMatthew G. Knepley     /* This should work with periodicity since DG coordinates should be used */
86816858538eSMatthew G. Knepley     if (depth > 1) {
86829566063dSJacob Faibussowitsch       PetscCall(DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL));
86831dca8a05SBarry 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);
868463a3b9bcSJacob Faibussowitsch       PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FVM Volume %g\n", c, (double) vol));
8685bb6a34a8SMatthew G. Knepley     }
8686bb6a34a8SMatthew G. Knepley   }
8687bb6a34a8SMatthew G. Knepley   PetscFunctionReturn(0);
8688bb6a34a8SMatthew G. Knepley }
8689bb6a34a8SMatthew G. Knepley 
869003da9461SVaclav Hapla /*@
86917726db96SVaclav Hapla   DMPlexCheckPointSF - Check that several necessary conditions are met for the Point SF of this plex.
86927726db96SVaclav Hapla 
86937726db96SVaclav Hapla   Collective
869403da9461SVaclav Hapla 
869503da9461SVaclav Hapla   Input Parameters:
86967726db96SVaclav Hapla + dm - The DMPlex object
86977726db96SVaclav Hapla - pointSF - The Point SF, or NULL for Point SF attached to DM
869803da9461SVaclav Hapla 
8699e83a0d2dSVaclav Hapla   Notes:
8700e83a0d2dSVaclav Hapla   This is mainly intended for debugging/testing purposes.
870103da9461SVaclav Hapla 
870295eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
870395eb5ee5SVaclav Hapla 
870403da9461SVaclav Hapla   Level: developer
870503da9461SVaclav Hapla 
8706db781477SPatrick Sanan .seealso: `DMGetPointSF()`, `DMSetFromOptions()`
870703da9461SVaclav Hapla @*/
87087726db96SVaclav Hapla PetscErrorCode DMPlexCheckPointSF(DM dm, PetscSF pointSF)
870903da9461SVaclav Hapla {
87107726db96SVaclav Hapla   PetscInt        l, nleaves, nroots, overlap;
87117726db96SVaclav Hapla   const PetscInt *locals;
87127726db96SVaclav Hapla   const PetscSFNode *remotes;
8713f0cfc026SVaclav Hapla   PetscBool       distributed;
87147726db96SVaclav Hapla   MPI_Comm        comm;
87157726db96SVaclav Hapla   PetscMPIInt     rank;
871603da9461SVaclav Hapla 
871703da9461SVaclav Hapla   PetscFunctionBegin;
871803da9461SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
87197726db96SVaclav Hapla   if (pointSF) PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2);
87207726db96SVaclav Hapla   else         pointSF = dm->sf;
87217726db96SVaclav Hapla   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
87227726db96SVaclav Hapla   PetscCheck(pointSF, comm, PETSC_ERR_ARG_WRONGSTATE, "DMPlex must have Point SF attached");
87237726db96SVaclav Hapla   PetscCallMPI(MPI_Comm_rank(comm, &rank));
87247726db96SVaclav Hapla   {
87257726db96SVaclav Hapla     PetscMPIInt    mpiFlag;
87267726db96SVaclav Hapla 
87277726db96SVaclav Hapla     PetscCallMPI(MPI_Comm_compare(comm, PetscObjectComm((PetscObject)pointSF),&mpiFlag));
87287726db96SVaclav 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);
87297726db96SVaclav Hapla   }
87307726db96SVaclav Hapla   PetscCall(PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, &remotes));
87319566063dSJacob Faibussowitsch   PetscCall(DMPlexIsDistributed(dm, &distributed));
87327726db96SVaclav Hapla   if (!distributed) {
87337726db96SVaclav 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);
87348918e3e2SVaclav Hapla     PetscFunctionReturn(0);
87358918e3e2SVaclav Hapla   }
87367726db96SVaclav 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);
87377726db96SVaclav Hapla   PetscCall(DMPlexGetOverlap(dm, &overlap));
873803da9461SVaclav Hapla 
87397726db96SVaclav Hapla   /* Check SF graph is compatible with DMPlex chart */
87407726db96SVaclav Hapla   {
87417726db96SVaclav Hapla     PetscInt pStart, pEnd, maxLeaf;
87427726db96SVaclav Hapla 
87437726db96SVaclav Hapla     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
87447726db96SVaclav Hapla     PetscCall(PetscSFGetLeafRange(pointSF, NULL, &maxLeaf));
87457726db96SVaclav Hapla     PetscCheck(pEnd - pStart == nroots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "pEnd - pStart = %" PetscInt_FMT " != nroots = %" PetscInt_FMT, pEnd-pStart, nroots);
87467726db96SVaclav Hapla     PetscCheck(maxLeaf < pEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "maxLeaf = %" PetscInt_FMT " >= pEnd = %" PetscInt_FMT, maxLeaf, pEnd);
87477726db96SVaclav Hapla   }
87487726db96SVaclav Hapla 
87497726db96SVaclav Hapla   /* Check Point SF has no local points referenced */
87507726db96SVaclav Hapla   for (l = 0; l < nleaves; l++) {
87517726db96SVaclav 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);
87527726db96SVaclav Hapla   }
87537726db96SVaclav Hapla 
87547726db96SVaclav Hapla   /* Check there are no cells in interface */
87557726db96SVaclav Hapla   if (!overlap) {
87567726db96SVaclav Hapla     PetscInt cellHeight, cStart, cEnd;
87577726db96SVaclav Hapla 
87589566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
87599566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
8760f5869d18SMatthew G. Knepley     for (l = 0; l < nleaves; ++l) {
87617726db96SVaclav Hapla       const PetscInt point = locals ? locals[l] : l;
8762f5869d18SMatthew G. Knepley 
87637726db96SVaclav Hapla       PetscCheck(point < cStart || point >= cEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %" PetscInt_FMT " which is a cell", point);
87647726db96SVaclav Hapla     }
876503da9461SVaclav Hapla   }
8766ece87651SVaclav Hapla 
87677726db96SVaclav Hapla   /* If some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */
87687726db96SVaclav Hapla   {
87697726db96SVaclav Hapla     const PetscInt *rootdegree;
87707726db96SVaclav Hapla 
87717726db96SVaclav Hapla     PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree));
87727726db96SVaclav Hapla     PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree));
8773f5869d18SMatthew G. Knepley     for (l = 0; l < nleaves; ++l) {
87747726db96SVaclav Hapla       const PetscInt  point = locals ? locals[l] : l;
8775f5869d18SMatthew G. Knepley       const PetscInt *cone;
8776f5869d18SMatthew G. Knepley       PetscInt        coneSize, c, idx;
8777f5869d18SMatthew G. Knepley 
87789566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, point, &coneSize));
87799566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, point, &cone));
8780f5869d18SMatthew G. Knepley       for (c = 0; c < coneSize; ++c) {
8781f5869d18SMatthew G. Knepley         if (!rootdegree[cone[c]]) {
87827726db96SVaclav Hapla           if (locals) {
87839566063dSJacob Faibussowitsch             PetscCall(PetscFindInt(cone[c], nleaves, locals, &idx));
87847726db96SVaclav Hapla           } else {
87857726db96SVaclav Hapla             idx = (cone[c] < nleaves) ? cone[c] : -1;
87867726db96SVaclav Hapla           }
878763a3b9bcSJacob 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]);
8788f5869d18SMatthew G. Knepley         }
8789f5869d18SMatthew G. Knepley       }
8790ece87651SVaclav Hapla     }
87917726db96SVaclav Hapla   }
879203da9461SVaclav Hapla   PetscFunctionReturn(0);
879303da9461SVaclav Hapla }
879403da9461SVaclav Hapla 
87957f9d8d6cSVaclav Hapla /*@
87967f9d8d6cSVaclav Hapla   DMPlexCheck - Perform various checks of Plex sanity
87977f9d8d6cSVaclav Hapla 
87987f9d8d6cSVaclav Hapla   Input Parameter:
87997f9d8d6cSVaclav Hapla . dm - The DMPlex object
88007f9d8d6cSVaclav Hapla 
88017f9d8d6cSVaclav Hapla   Notes:
88027f9d8d6cSVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
88037f9d8d6cSVaclav Hapla 
88047f9d8d6cSVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
88057f9d8d6cSVaclav Hapla 
88067f9d8d6cSVaclav Hapla   Currently does not include DMPlexCheckCellShape().
88077f9d8d6cSVaclav Hapla 
88087f9d8d6cSVaclav Hapla   Level: developer
88097f9d8d6cSVaclav Hapla 
88107f9d8d6cSVaclav Hapla .seealso: DMCreate(), DMSetFromOptions()
88117f9d8d6cSVaclav Hapla @*/
88127f9d8d6cSVaclav Hapla PetscErrorCode DMPlexCheck(DM dm)
8813b5a892a1SMatthew G. Knepley {
88147f9d8d6cSVaclav Hapla   PetscInt cellHeight;
88157f9d8d6cSVaclav Hapla 
8816b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
88177f9d8d6cSVaclav Hapla   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
88189566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckSymmetry(dm));
88199566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckSkeleton(dm, cellHeight));
88209566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckFaces(dm, cellHeight));
88219566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckGeometry(dm));
88227726db96SVaclav Hapla   PetscCall(DMPlexCheckPointSF(dm, NULL));
88239566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckInterfaceCones(dm));
8824b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
8825b5a892a1SMatthew G. Knepley }
8826b5a892a1SMatthew G. Knepley 
8827068a5610SStefano Zampini typedef struct cell_stats
8828068a5610SStefano Zampini {
8829068a5610SStefano Zampini   PetscReal min, max, sum, squaresum;
8830068a5610SStefano Zampini   PetscInt  count;
8831068a5610SStefano Zampini } cell_stats_t;
8832068a5610SStefano Zampini 
883325befc3bSSatish Balay static void MPIAPI cell_stats_reduce(void *a, void *b, int * len, MPI_Datatype *datatype)
8834068a5610SStefano Zampini {
8835068a5610SStefano Zampini   PetscInt i, N = *len;
8836068a5610SStefano Zampini 
8837068a5610SStefano Zampini   for (i = 0; i < N; i++) {
8838068a5610SStefano Zampini     cell_stats_t *A = (cell_stats_t *) a;
8839068a5610SStefano Zampini     cell_stats_t *B = (cell_stats_t *) b;
8840068a5610SStefano Zampini 
8841068a5610SStefano Zampini     B->min = PetscMin(A->min,B->min);
8842068a5610SStefano Zampini     B->max = PetscMax(A->max,B->max);
8843068a5610SStefano Zampini     B->sum += A->sum;
8844068a5610SStefano Zampini     B->squaresum += A->squaresum;
8845068a5610SStefano Zampini     B->count += A->count;
8846068a5610SStefano Zampini   }
8847068a5610SStefano Zampini }
8848068a5610SStefano Zampini 
8849068a5610SStefano Zampini /*@
885043fa8764SMatthew G. Knepley   DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics.
8851068a5610SStefano Zampini 
88528261a58bSMatthew G. Knepley   Collective on dm
88538261a58bSMatthew G. Knepley 
8854068a5610SStefano Zampini   Input Parameters:
8855068a5610SStefano Zampini + dm        - The DMPlex object
885643fa8764SMatthew G. Knepley . output    - If true, statistics will be displayed on stdout
885743fa8764SMatthew G. Knepley - condLimit - Display all cells above this condition number, or PETSC_DETERMINE for no cell output
8858068a5610SStefano Zampini 
885995eb5ee5SVaclav Hapla   Notes:
886095eb5ee5SVaclav Hapla   This is mainly intended for debugging/testing purposes.
886195eb5ee5SVaclav Hapla 
886295eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
8863068a5610SStefano Zampini 
8864068a5610SStefano Zampini   Level: developer
8865068a5610SStefano Zampini 
8866db781477SPatrick Sanan .seealso: `DMSetFromOptions()`, `DMPlexComputeOrthogonalQuality()`
8867068a5610SStefano Zampini @*/
886843fa8764SMatthew G. Knepley PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit)
8869068a5610SStefano Zampini {
8870068a5610SStefano Zampini   DM             dmCoarse;
887143fa8764SMatthew G. Knepley   cell_stats_t   stats, globalStats;
887243fa8764SMatthew G. Knepley   MPI_Comm       comm = PetscObjectComm((PetscObject)dm);
887343fa8764SMatthew G. Knepley   PetscReal      *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0;
887443fa8764SMatthew G. Knepley   PetscReal      limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL;
8875412e9a14SMatthew G. Knepley   PetscInt       cdim, cStart, cEnd, c, eStart, eEnd, count = 0;
887643fa8764SMatthew G. Knepley   PetscMPIInt    rank,size;
8877068a5610SStefano Zampini 
8878068a5610SStefano Zampini   PetscFunctionBegin;
8879068a5610SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8880068a5610SStefano Zampini   stats.min   = PETSC_MAX_REAL;
8881068a5610SStefano Zampini   stats.max   = PETSC_MIN_REAL;
8882068a5610SStefano Zampini   stats.sum   = stats.squaresum = 0.;
8883068a5610SStefano Zampini   stats.count = 0;
8884068a5610SStefano Zampini 
88859566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
88869566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
88879566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm,&cdim));
88889566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ));
88899566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSimplexOrBoxCells(dm,0,&cStart,&cEnd));
88909566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm,1,&eStart,&eEnd));
8891412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; c++) {
8892068a5610SStefano Zampini     PetscInt  i;
8893068a5610SStefano Zampini     PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ;
8894068a5610SStefano Zampini 
88959566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellGeometryAffineFEM(dm,c,NULL,J,invJ,&detJ));
889663a3b9bcSJacob Faibussowitsch     PetscCheck(detJ >= 0.0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " is inverted", c);
889743fa8764SMatthew G. Knepley     for (i = 0; i < PetscSqr(cdim); ++i) {
8898068a5610SStefano Zampini       frobJ    += J[i] * J[i];
8899068a5610SStefano Zampini       frobInvJ += invJ[i] * invJ[i];
8900068a5610SStefano Zampini     }
8901068a5610SStefano Zampini     cond2 = frobJ * frobInvJ;
8902068a5610SStefano Zampini     cond  = PetscSqrtReal(cond2);
8903068a5610SStefano Zampini 
8904068a5610SStefano Zampini     stats.min        = PetscMin(stats.min,cond);
8905068a5610SStefano Zampini     stats.max        = PetscMax(stats.max,cond);
8906068a5610SStefano Zampini     stats.sum       += cond;
8907068a5610SStefano Zampini     stats.squaresum += cond2;
8908068a5610SStefano Zampini     stats.count++;
89098261a58bSMatthew G. Knepley     if (output && cond > limit) {
891043fa8764SMatthew G. Knepley       PetscSection coordSection;
891143fa8764SMatthew G. Knepley       Vec          coordsLocal;
891243fa8764SMatthew G. Knepley       PetscScalar *coords = NULL;
891343fa8764SMatthew G. Knepley       PetscInt     Nv, d, clSize, cl, *closure = NULL;
891443fa8764SMatthew G. Knepley 
89159566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal));
89169566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinateSection(dm, &coordSection));
89179566063dSJacob Faibussowitsch       PetscCall(DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords));
891863a3b9bcSJacob Faibussowitsch       PetscCall(PetscSynchronizedPrintf(comm, "[%d] Cell %" PetscInt_FMT " cond %g\n", rank, c, (double) cond));
891943fa8764SMatthew G. Knepley       for (i = 0; i < Nv/cdim; ++i) {
892063a3b9bcSJacob Faibussowitsch         PetscCall(PetscSynchronizedPrintf(comm, "  Vertex %" PetscInt_FMT ": (", i));
892143fa8764SMatthew G. Knepley         for (d = 0; d < cdim; ++d) {
89229566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscSynchronizedPrintf(comm, ", "));
89239566063dSJacob Faibussowitsch           PetscCall(PetscSynchronizedPrintf(comm, "%g", (double) PetscRealPart(coords[i*cdim+d])));
892443fa8764SMatthew G. Knepley         }
89259566063dSJacob Faibussowitsch         PetscCall(PetscSynchronizedPrintf(comm, ")\n"));
892643fa8764SMatthew G. Knepley       }
89279566063dSJacob Faibussowitsch       PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure));
892843fa8764SMatthew G. Knepley       for (cl = 0; cl < clSize*2; cl += 2) {
892943fa8764SMatthew G. Knepley         const PetscInt edge = closure[cl];
893043fa8764SMatthew G. Knepley 
893143fa8764SMatthew G. Knepley         if ((edge >= eStart) && (edge < eEnd)) {
893243fa8764SMatthew G. Knepley           PetscReal len;
893343fa8764SMatthew G. Knepley 
89349566063dSJacob Faibussowitsch           PetscCall(DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL));
893563a3b9bcSJacob Faibussowitsch           PetscCall(PetscSynchronizedPrintf(comm, "  Edge %" PetscInt_FMT ": length %g\n", edge, (double) len));
893643fa8764SMatthew G. Knepley         }
893743fa8764SMatthew G. Knepley       }
89389566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure));
89399566063dSJacob Faibussowitsch       PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords));
894043fa8764SMatthew G. Knepley     }
8941068a5610SStefano Zampini   }
89429566063dSJacob Faibussowitsch   if (output) PetscCall(PetscSynchronizedFlush(comm, NULL));
8943068a5610SStefano Zampini 
8944068a5610SStefano Zampini   if (size > 1) {
8945068a5610SStefano Zampini     PetscMPIInt   blockLengths[2] = {4,1};
8946068a5610SStefano Zampini     MPI_Aint      blockOffsets[2] = {offsetof(cell_stats_t,min),offsetof(cell_stats_t,count)};
8947068a5610SStefano Zampini     MPI_Datatype  blockTypes[2]   = {MPIU_REAL,MPIU_INT}, statType;
8948068a5610SStefano Zampini     MPI_Op        statReduce;
8949068a5610SStefano Zampini 
89509566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_create_struct(2,blockLengths,blockOffsets,blockTypes,&statType));
89519566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_commit(&statType));
89529566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce));
89539566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&stats,&globalStats,1,statType,statReduce,0,comm));
89549566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Op_free(&statReduce));
89559566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_free(&statType));
8956068a5610SStefano Zampini   } else {
89579566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(&globalStats,&stats,1));
8958068a5610SStefano Zampini   }
8959dd400576SPatrick Sanan   if (rank == 0) {
8960068a5610SStefano Zampini     count = globalStats.count;
8961068a5610SStefano Zampini     min   = globalStats.min;
8962068a5610SStefano Zampini     max   = globalStats.max;
8963068a5610SStefano Zampini     mean  = globalStats.sum / globalStats.count;
8964068a5610SStefano Zampini     stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1),0)) : 0.0;
8965068a5610SStefano Zampini   }
8966068a5610SStefano Zampini 
8967068a5610SStefano Zampini   if (output) {
896863a3b9bcSJacob 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));
8969068a5610SStefano Zampini   }
89709566063dSJacob Faibussowitsch   PetscCall(PetscFree2(J,invJ));
8971068a5610SStefano Zampini 
89729566063dSJacob Faibussowitsch   PetscCall(DMGetCoarseDM(dm,&dmCoarse));
8973068a5610SStefano Zampini   if (dmCoarse) {
8974068a5610SStefano Zampini     PetscBool isplex;
8975068a5610SStefano Zampini 
89769566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)dmCoarse,DMPLEX,&isplex));
89771baa6e33SBarry Smith     if (isplex) PetscCall(DMPlexCheckCellShape(dmCoarse,output,condLimit));
8978068a5610SStefano Zampini   }
8979068a5610SStefano Zampini   PetscFunctionReturn(0);
8980068a5610SStefano Zampini }
8981068a5610SStefano Zampini 
8982f108dbd7SJacob Faibussowitsch /*@
8983f108dbd7SJacob Faibussowitsch   DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with
8984f108dbd7SJacob Faibussowitsch   orthogonal quality below given tolerance.
8985f108dbd7SJacob Faibussowitsch 
89866ed19f2fSJacob Faibussowitsch   Collective on dm
8987f108dbd7SJacob Faibussowitsch 
8988f108dbd7SJacob Faibussowitsch   Input Parameters:
8989f108dbd7SJacob Faibussowitsch + dm   - The DMPlex object
8990f108dbd7SJacob Faibussowitsch . fv   - Optional PetscFV object for pre-computed cell/face centroid information
8991f108dbd7SJacob Faibussowitsch - atol - [0, 1] Absolute tolerance for tagging cells.
8992f108dbd7SJacob Faibussowitsch 
8993f108dbd7SJacob Faibussowitsch   Output Parameters:
8994f108dbd7SJacob Faibussowitsch + OrthQual      - Vec containing orthogonal quality per cell
8995f108dbd7SJacob Faibussowitsch - OrthQualLabel - DMLabel tagging cells below atol with DM_ADAPT_REFINE
8996f108dbd7SJacob Faibussowitsch 
8997f108dbd7SJacob Faibussowitsch   Options Database Keys:
8998f108dbd7SJacob Faibussowitsch + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only PETSCVIEWERASCII is
8999f108dbd7SJacob Faibussowitsch supported.
9000f108dbd7SJacob Faibussowitsch - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector.
9001f108dbd7SJacob Faibussowitsch 
9002f108dbd7SJacob Faibussowitsch   Notes:
9003f108dbd7SJacob Faibussowitsch   Orthogonal quality is given by the following formula:
9004f108dbd7SJacob Faibussowitsch 
9005f108dbd7SJacob Faibussowitsch   \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right]
9006f108dbd7SJacob Faibussowitsch 
9007f108dbd7SJacob 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
9008f108dbd7SJacob Faibussowitsch   is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the
9009f108dbd7SJacob Faibussowitsch   current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by
9010f108dbd7SJacob Faibussowitsch   calculating the cosine of the angle between these vectors.
9011f108dbd7SJacob Faibussowitsch 
9012f108dbd7SJacob Faibussowitsch   Orthogonal quality ranges from 1 (best) to 0 (worst).
9013f108dbd7SJacob Faibussowitsch 
9014f108dbd7SJacob Faibussowitsch   This routine is mainly useful for FVM, however is not restricted to only FVM. The PetscFV object is optionally used to check for
9015f108dbd7SJacob Faibussowitsch   pre-computed FVM cell data, but if it is not passed in then this data will be computed.
9016f108dbd7SJacob Faibussowitsch 
9017f108dbd7SJacob Faibussowitsch   Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance.
9018f108dbd7SJacob Faibussowitsch 
9019f108dbd7SJacob Faibussowitsch   Level: intermediate
9020f108dbd7SJacob Faibussowitsch 
9021db781477SPatrick Sanan .seealso: `DMPlexCheckCellShape()`, `DMCreateLabel()`
9022f108dbd7SJacob Faibussowitsch @*/
9023f108dbd7SJacob Faibussowitsch PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel)
9024f108dbd7SJacob Faibussowitsch {
90256ed19f2fSJacob Faibussowitsch   PetscInt                nc, cellHeight, cStart, cEnd, cell, cellIter = 0;
90266ed19f2fSJacob Faibussowitsch   PetscInt                *idx;
90276ed19f2fSJacob Faibussowitsch   PetscScalar             *oqVals;
9028f108dbd7SJacob Faibussowitsch   const PetscScalar       *cellGeomArr, *faceGeomArr;
90296ed19f2fSJacob Faibussowitsch   PetscReal               *ci, *fi, *Ai;
9030f108dbd7SJacob Faibussowitsch   MPI_Comm                comm;
9031f108dbd7SJacob Faibussowitsch   Vec                     cellgeom, facegeom;
9032f108dbd7SJacob Faibussowitsch   DM                      dmFace, dmCell;
9033f108dbd7SJacob Faibussowitsch   IS                      glob;
9034f108dbd7SJacob Faibussowitsch   ISLocalToGlobalMapping  ltog;
9035f108dbd7SJacob Faibussowitsch   PetscViewer             vwr;
9036f108dbd7SJacob Faibussowitsch 
9037f108dbd7SJacob Faibussowitsch   PetscFunctionBegin;
9038f108dbd7SJacob Faibussowitsch   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
90396ed19f2fSJacob Faibussowitsch   if (fv) {PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2);}
9040f108dbd7SJacob Faibussowitsch   PetscValidPointer(OrthQual, 4);
90416bdcaf15SBarry Smith   PetscCheck(atol >= 0.0 && atol <= 1.0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Absolute tolerance %g not in [0,1]",(double)atol);
90429566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject) dm, &comm));
90439566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &nc));
904463a3b9bcSJacob Faibussowitsch   PetscCheck(nc >= 2,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %" PetscInt_FMT ")", nc);
90456ed19f2fSJacob Faibussowitsch   {
90466ed19f2fSJacob Faibussowitsch     DMPlexInterpolatedFlag interpFlag;
90476ed19f2fSJacob Faibussowitsch 
90489566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated(dm, &interpFlag));
9049f108dbd7SJacob Faibussowitsch     if (interpFlag != DMPLEX_INTERPOLATED_FULL) {
9050f108dbd7SJacob Faibussowitsch       PetscMPIInt rank;
9051f108dbd7SJacob Faibussowitsch 
90529566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(comm, &rank));
905398921bdaSJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank);
9054f108dbd7SJacob Faibussowitsch     }
90556ed19f2fSJacob Faibussowitsch   }
9056f108dbd7SJacob Faibussowitsch   if (OrthQualLabel) {
9057f108dbd7SJacob Faibussowitsch     PetscValidPointer(OrthQualLabel, 5);
90589566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(dm, "Orthogonal_Quality"));
90599566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel));
90606ed19f2fSJacob Faibussowitsch   } else {*OrthQualLabel = NULL;}
90619566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
90629566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
90639566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob));
90649566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreateIS(glob, &ltog));
90659566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH));
90669566063dSJacob Faibussowitsch   PetscCall(VecCreate(comm, OrthQual));
90679566063dSJacob Faibussowitsch   PetscCall(VecSetType(*OrthQual, VECSTANDARD));
90689566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(*OrthQual, cEnd-cStart, PETSC_DETERMINE));
90699566063dSJacob Faibussowitsch   PetscCall(VecSetLocalToGlobalMapping(*OrthQual, ltog));
90709566063dSJacob Faibussowitsch   PetscCall(VecSetUp(*OrthQual));
90719566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&glob));
90729566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&ltog));
90739566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL));
90749566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(cellgeom, &cellGeomArr));
90759566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(facegeom, &faceGeomArr));
90769566063dSJacob Faibussowitsch   PetscCall(VecGetDM(cellgeom, &dmCell));
90779566063dSJacob Faibussowitsch   PetscCall(VecGetDM(facegeom, &dmFace));
90789566063dSJacob Faibussowitsch   PetscCall(PetscMalloc5(cEnd-cStart, &idx, cEnd-cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai));
90796ed19f2fSJacob Faibussowitsch   for (cell = cStart; cell < cEnd; cellIter++,cell++) {
90806ed19f2fSJacob Faibussowitsch     PetscInt           cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE;
9081f108dbd7SJacob Faibussowitsch     PetscInt           cellarr[2], *adj = NULL;
9082f108dbd7SJacob Faibussowitsch     PetscScalar        *cArr, *fArr;
9083898cd552SSatish Balay     PetscReal          minvalc = 1.0, minvalf = 1.0;
9084f108dbd7SJacob Faibussowitsch     PetscFVCellGeom    *cg;
9085f108dbd7SJacob Faibussowitsch 
90866ed19f2fSJacob Faibussowitsch     idx[cellIter] = cell-cStart;
9087f108dbd7SJacob Faibussowitsch     cellarr[0] = cell;
9088f108dbd7SJacob Faibussowitsch     /* Make indexing into cellGeom easier */
90899566063dSJacob Faibussowitsch     PetscCall(DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg));
90909566063dSJacob Faibussowitsch     PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj));
9091f108dbd7SJacob Faibussowitsch     /* Technically 1 too big, but easier than fiddling with empty adjacency array */
90929566063dSJacob Faibussowitsch     PetscCall(PetscCalloc2(adjSize, &cArr, adjSize, &fArr));
90936ed19f2fSJacob Faibussowitsch     for (cellneigh = 0; cellneigh < adjSize; cellneighiter++,cellneigh++) {
90946ed19f2fSJacob Faibussowitsch       PetscInt         i;
90956ed19f2fSJacob Faibussowitsch       const PetscInt   neigh = adj[cellneigh];
9096f108dbd7SJacob Faibussowitsch       PetscReal        normci = 0, normfi = 0, normai = 0;
9097f108dbd7SJacob Faibussowitsch       PetscFVCellGeom  *cgneigh;
9098f108dbd7SJacob Faibussowitsch       PetscFVFaceGeom  *fg;
9099f108dbd7SJacob Faibussowitsch 
9100f108dbd7SJacob Faibussowitsch       /* Don't count ourselves in the neighbor list */
9101f108dbd7SJacob Faibussowitsch       if (neigh == cell) continue;
91029566063dSJacob Faibussowitsch       PetscCall(DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh));
9103f108dbd7SJacob Faibussowitsch       cellarr[1] = neigh;
91046ed19f2fSJacob Faibussowitsch       {
91056ed19f2fSJacob Faibussowitsch         PetscInt       numcovpts;
91066ed19f2fSJacob Faibussowitsch         const PetscInt *covpts;
91076ed19f2fSJacob Faibussowitsch 
91089566063dSJacob Faibussowitsch         PetscCall(DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts));
91099566063dSJacob Faibussowitsch         PetscCall(DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg));
91109566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts));
91116ed19f2fSJacob Faibussowitsch       }
9112f108dbd7SJacob Faibussowitsch 
9113f108dbd7SJacob Faibussowitsch       /* Compute c_i, f_i and their norms */
9114f108dbd7SJacob Faibussowitsch       for (i = 0; i < nc; i++) {
9115f108dbd7SJacob Faibussowitsch         ci[i] = cgneigh->centroid[i] - cg->centroid[i];
9116f108dbd7SJacob Faibussowitsch         fi[i] = fg->centroid[i] - cg->centroid[i];
9117f108dbd7SJacob Faibussowitsch         Ai[i] = fg->normal[i];
9118addd1e01SJunchao Zhang         normci += PetscPowReal(ci[i], 2);
9119addd1e01SJunchao Zhang         normfi += PetscPowReal(fi[i], 2);
9120addd1e01SJunchao Zhang         normai += PetscPowReal(Ai[i], 2);
9121f108dbd7SJacob Faibussowitsch       }
9122addd1e01SJunchao Zhang       normci = PetscSqrtReal(normci);
9123addd1e01SJunchao Zhang       normfi = PetscSqrtReal(normfi);
9124addd1e01SJunchao Zhang       normai = PetscSqrtReal(normai);
9125f108dbd7SJacob Faibussowitsch 
9126f108dbd7SJacob Faibussowitsch       /* Normalize and compute for each face-cell-normal pair */
9127f108dbd7SJacob Faibussowitsch       for (i = 0; i < nc; i++) {
9128f108dbd7SJacob Faibussowitsch         ci[i] = ci[i]/normci;
9129f108dbd7SJacob Faibussowitsch         fi[i] = fi[i]/normfi;
9130f108dbd7SJacob Faibussowitsch         Ai[i] = Ai[i]/normai;
9131f108dbd7SJacob Faibussowitsch         /* PetscAbs because I don't know if normals are guaranteed to point out */
9132f108dbd7SJacob Faibussowitsch         cArr[cellneighiter] += PetscAbs(Ai[i]*ci[i]);
9133f108dbd7SJacob Faibussowitsch         fArr[cellneighiter] += PetscAbs(Ai[i]*fi[i]);
9134f108dbd7SJacob Faibussowitsch       }
9135f108dbd7SJacob Faibussowitsch       if (PetscRealPart(cArr[cellneighiter]) < minvalc) {
9136f108dbd7SJacob Faibussowitsch         minvalc = PetscRealPart(cArr[cellneighiter]);
9137f108dbd7SJacob Faibussowitsch       }
9138f108dbd7SJacob Faibussowitsch       if (PetscRealPart(fArr[cellneighiter]) < minvalf) {
9139f108dbd7SJacob Faibussowitsch         minvalf = PetscRealPart(fArr[cellneighiter]);
9140f108dbd7SJacob Faibussowitsch       }
9141f108dbd7SJacob Faibussowitsch     }
91429566063dSJacob Faibussowitsch     PetscCall(PetscFree(adj));
91439566063dSJacob Faibussowitsch     PetscCall(PetscFree2(cArr, fArr));
9144f108dbd7SJacob Faibussowitsch     /* Defer to cell if they're equal */
91456ed19f2fSJacob Faibussowitsch     oqVals[cellIter] = PetscMin(minvalf, minvalc);
9146f108dbd7SJacob Faibussowitsch     if (OrthQualLabel) {
91479566063dSJacob Faibussowitsch       if (PetscRealPart(oqVals[cellIter]) <= atol) PetscCall(DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE));
9148f108dbd7SJacob Faibussowitsch     }
9149f108dbd7SJacob Faibussowitsch   }
91509566063dSJacob Faibussowitsch   PetscCall(VecSetValuesLocal(*OrthQual, cEnd-cStart, idx, oqVals, INSERT_VALUES));
91519566063dSJacob Faibussowitsch   PetscCall(VecAssemblyBegin(*OrthQual));
91529566063dSJacob Faibussowitsch   PetscCall(VecAssemblyEnd(*OrthQual));
91539566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(cellgeom, &cellGeomArr));
91549566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(facegeom, &faceGeomArr));
91559566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL));
9156f108dbd7SJacob Faibussowitsch   if (OrthQualLabel) {
91579566063dSJacob Faibussowitsch     if (vwr) PetscCall(DMLabelView(*OrthQualLabel, vwr));
9158f108dbd7SJacob Faibussowitsch   }
91599566063dSJacob Faibussowitsch   PetscCall(PetscFree5(idx, oqVals, ci, fi, Ai));
91609566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(&vwr));
91619566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view"));
9162f108dbd7SJacob Faibussowitsch   PetscFunctionReturn(0);
9163f108dbd7SJacob Faibussowitsch }
9164f108dbd7SJacob Faibussowitsch 
91651eb70e55SToby Isaac /* this is here insead of DMGetOutputDM because output DM still has constraints in the local indices that affect
91661eb70e55SToby Isaac  * interpolator construction */
91671eb70e55SToby Isaac static PetscErrorCode DMGetFullDM(DM dm, DM *odm)
91681eb70e55SToby Isaac {
91691eb70e55SToby Isaac   PetscSection   section, newSection, gsection;
91701eb70e55SToby Isaac   PetscSF        sf;
91711eb70e55SToby Isaac   PetscBool      hasConstraints, ghasConstraints;
91721eb70e55SToby Isaac 
91731eb70e55SToby Isaac   PetscFunctionBegin;
91741eb70e55SToby Isaac   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
91751eb70e55SToby Isaac   PetscValidPointer(odm,2);
91769566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
91779566063dSJacob Faibussowitsch   PetscCall(PetscSectionHasConstraints(section, &hasConstraints));
91789566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm)));
91791eb70e55SToby Isaac   if (!ghasConstraints) {
91809566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm));
91811eb70e55SToby Isaac     *odm = dm;
91821eb70e55SToby Isaac     PetscFunctionReturn(0);
91831eb70e55SToby Isaac   }
91849566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, odm));
91859566063dSJacob Faibussowitsch   PetscCall(DMCopyFields(dm, *odm));
91869566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(*odm, &newSection));
91879566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(*odm, &sf));
91889566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_FALSE, &gsection));
91899566063dSJacob Faibussowitsch   PetscCall(DMSetGlobalSection(*odm, gsection));
91909566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&gsection));
91911eb70e55SToby Isaac   PetscFunctionReturn(0);
91921eb70e55SToby Isaac }
91931eb70e55SToby Isaac 
91941eb70e55SToby Isaac static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift)
91951eb70e55SToby Isaac {
91961eb70e55SToby Isaac   DM             dmco, dmfo;
91971eb70e55SToby Isaac   Mat            interpo;
91981eb70e55SToby Isaac   Vec            rscale;
91991eb70e55SToby Isaac   Vec            cglobalo, clocal;
92001eb70e55SToby Isaac   Vec            fglobal, fglobalo, flocal;
92011eb70e55SToby Isaac   PetscBool      regular;
92021eb70e55SToby Isaac 
92031eb70e55SToby Isaac   PetscFunctionBegin;
92049566063dSJacob Faibussowitsch   PetscCall(DMGetFullDM(dmc, &dmco));
92059566063dSJacob Faibussowitsch   PetscCall(DMGetFullDM(dmf, &dmfo));
92069566063dSJacob Faibussowitsch   PetscCall(DMSetCoarseDM(dmfo, dmco));
92079566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRegularRefinement(dmf, &regular));
92089566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRegularRefinement(dmfo, regular));
92099566063dSJacob Faibussowitsch   PetscCall(DMCreateInterpolation(dmco, dmfo, &interpo, &rscale));
92109566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmco, &cglobalo));
92119566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dmc, &clocal));
92129566063dSJacob Faibussowitsch   PetscCall(VecSet(cglobalo, 0.));
92139566063dSJacob Faibussowitsch   PetscCall(VecSet(clocal, 0.));
92149566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmf, &fglobal));
92159566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmfo, &fglobalo));
92169566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dmf, &flocal));
92179566063dSJacob Faibussowitsch   PetscCall(VecSet(fglobal, 0.));
92189566063dSJacob Faibussowitsch   PetscCall(VecSet(fglobalo, 0.));
92199566063dSJacob Faibussowitsch   PetscCall(VecSet(flocal, 0.));
92209566063dSJacob Faibussowitsch   PetscCall(DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL));
92219566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo));
92229566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo));
92239566063dSJacob Faibussowitsch   PetscCall(MatMult(interpo, cglobalo, fglobalo));
92249566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal));
92259566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal));
92269566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal));
92279566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal));
92281eb70e55SToby Isaac   *shift = fglobal;
92299566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&flocal));
92309566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&fglobalo));
92319566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&clocal));
92329566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&cglobalo));
92339566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&rscale));
92349566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&interpo));
92359566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmfo));
92369566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmco));
92371eb70e55SToby Isaac   PetscFunctionReturn(0);
92381eb70e55SToby Isaac }
92391eb70e55SToby Isaac 
92401eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol)
92411eb70e55SToby Isaac {
92421eb70e55SToby Isaac   PetscObject    shifto;
92431eb70e55SToby Isaac   Vec            shift;
92441eb70e55SToby Isaac 
92451eb70e55SToby Isaac   PetscFunctionBegin;
92461eb70e55SToby Isaac   if (!interp) {
92471eb70e55SToby Isaac     Vec rscale;
92481eb70e55SToby Isaac 
92499566063dSJacob Faibussowitsch     PetscCall(DMCreateInterpolation(coarse, fine, &interp, &rscale));
92509566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&rscale));
92511eb70e55SToby Isaac   } else {
92529566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)interp));
92531eb70e55SToby Isaac   }
92549566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto));
92551eb70e55SToby Isaac   if (!shifto) {
92569566063dSJacob Faibussowitsch     PetscCall(DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift));
92579566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject) shift));
92581eb70e55SToby Isaac     shifto = (PetscObject) shift;
92599566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&shift));
92601eb70e55SToby Isaac   }
92611eb70e55SToby Isaac   shift = (Vec) shifto;
92629566063dSJacob Faibussowitsch   PetscCall(MatInterpolate(interp, coarseSol, fineSol));
92639566063dSJacob Faibussowitsch   PetscCall(VecAXPY(fineSol, 1.0, shift));
92649566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&interp));
92651eb70e55SToby Isaac   PetscFunctionReturn(0);
92661eb70e55SToby Isaac }
92671eb70e55SToby Isaac 
9268bceba477SMatthew G. Knepley /* Pointwise interpolation
9269bceba477SMatthew G. Knepley      Just code FEM for now
9270bceba477SMatthew G. Knepley      u^f = I u^c
92714ca5e9f5SMatthew G. Knepley      sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j
92724ca5e9f5SMatthew G. Knepley      u^f_i = sum_j psi^f_i I phi^c_j u^c_j
92734ca5e9f5SMatthew G. Knepley      I_{ij} = psi^f_i phi^c_j
9274bceba477SMatthew G. Knepley */
9275bceba477SMatthew G. Knepley PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling)
9276bceba477SMatthew G. Knepley {
9277bceba477SMatthew G. Knepley   PetscSection   gsc, gsf;
9278bceba477SMatthew G. Knepley   PetscInt       m, n;
9279a063dac3SMatthew G. Knepley   void          *ctx;
928068132eb9SMatthew G. Knepley   DM             cdm;
9281cf51de39SMatthew G. Knepley   PetscBool      regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE;
9282bceba477SMatthew G. Knepley 
9283bceba477SMatthew G. Knepley   PetscFunctionBegin;
92849566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmFine, &gsf));
92859566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m));
92869566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmCoarse, &gsc));
92879566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n));
928868132eb9SMatthew G. Knepley 
92899566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis));
92909566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation));
92919566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE));
92929566063dSJacob Faibussowitsch   PetscCall(MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype));
92939566063dSJacob Faibussowitsch   PetscCall(DMGetApplicationContext(dmFine, &ctx));
929468132eb9SMatthew G. Knepley 
92959566063dSJacob Faibussowitsch   PetscCall(DMGetCoarseDM(dmFine, &cdm));
92969566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRegularRefinement(dmFine, &regular));
92979566063dSJacob Faibussowitsch   if (!isRefined || (regular && cdm == dmCoarse)) PetscCall(DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx));
92989566063dSJacob Faibussowitsch   else                                            PetscCall(DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx));
92999566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view"));
93004db47ee9SStefano Zampini   if (scaling) {
93015d1c2e58SMatthew G. Knepley     /* Use naive scaling */
93029566063dSJacob Faibussowitsch     PetscCall(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling));
93034db47ee9SStefano Zampini   }
9304a063dac3SMatthew G. Knepley   PetscFunctionReturn(0);
9305a063dac3SMatthew G. Knepley }
9306bceba477SMatthew G. Knepley 
93076dbf9973SLawrence Mitchell PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat)
9308a063dac3SMatthew G. Knepley {
93096dbf9973SLawrence Mitchell   VecScatter     ctx;
931090748bafSMatthew G. Knepley 
9311a063dac3SMatthew G. Knepley   PetscFunctionBegin;
93129566063dSJacob Faibussowitsch   PetscCall(DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL));
93139566063dSJacob Faibussowitsch   PetscCall(MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat));
93149566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&ctx));
9315bceba477SMatthew G. Knepley   PetscFunctionReturn(0);
9316bceba477SMatthew G. Knepley }
9317bceba477SMatthew G. Knepley 
93183e9753d6SMatthew G. Knepley static void g0_identity_private(PetscInt dim, PetscInt Nf, PetscInt NfAux,
93193e9753d6SMatthew G. Knepley                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
93203e9753d6SMatthew G. Knepley                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
93213e9753d6SMatthew G. Knepley                                 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[])
93223e9753d6SMatthew G. Knepley {
932300635df3SMatthew G. Knepley   const PetscInt Nc = uOff[1] - uOff[0];
932400635df3SMatthew G. Knepley   PetscInt       c;
932500635df3SMatthew G. Knepley   for (c = 0; c < Nc; ++c) g0[c*Nc+c] = 1.0;
93263e9753d6SMatthew G. Knepley }
93273e9753d6SMatthew G. Knepley 
9328b4937a87SMatthew G. Knepley PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *mass)
9329b4937a87SMatthew G. Knepley {
9330b4937a87SMatthew G. Knepley   DM             dmc;
9331b4937a87SMatthew G. Knepley   PetscDS        ds;
9332b4937a87SMatthew G. Knepley   Vec            ones, locmass;
9333b4937a87SMatthew G. Knepley   IS             cellIS;
9334b4937a87SMatthew G. Knepley   PetscFormKey   key;
9335b4937a87SMatthew G. Knepley   PetscInt       depth;
9336b4937a87SMatthew G. Knepley 
9337b4937a87SMatthew G. Knepley   PetscFunctionBegin;
93389566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &dmc));
93399566063dSJacob Faibussowitsch   PetscCall(DMCopyDisc(dm, dmc));
93409566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dmc, &ds));
93419566063dSJacob Faibussowitsch   PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL));
93429566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmc, mass));
93439566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dmc, &ones));
93449566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dmc, &locmass));
93459566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmc, &depth));
93469566063dSJacob Faibussowitsch   PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS));
93479566063dSJacob Faibussowitsch   PetscCall(VecSet(locmass, 0.0));
93489566063dSJacob Faibussowitsch   PetscCall(VecSet(ones, 1.0));
9349b4937a87SMatthew G. Knepley   key.label = NULL;
9350b4937a87SMatthew G. Knepley   key.value = 0;
9351b4937a87SMatthew G. Knepley   key.field = 0;
9352b4937a87SMatthew G. Knepley   key.part  = 0;
93539566063dSJacob Faibussowitsch   PetscCall(DMPlexComputeJacobian_Action_Internal(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL));
93549566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&cellIS));
93559566063dSJacob Faibussowitsch   PetscCall(VecSet(*mass, 0.0));
93569566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmc, locmass, ADD_VALUES, *mass));
93579566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmc, locmass, ADD_VALUES, *mass));
93589566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dmc, &ones));
93599566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dmc, &locmass));
93609566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmc));
9361b4937a87SMatthew G. Knepley   PetscFunctionReturn(0);
9362b4937a87SMatthew G. Knepley }
9363b4937a87SMatthew G. Knepley 
9364bd041c0cSMatthew G. Knepley PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass)
9365bd041c0cSMatthew G. Knepley {
9366bd041c0cSMatthew G. Knepley   PetscSection   gsc, gsf;
9367bd041c0cSMatthew G. Knepley   PetscInt       m, n;
9368bd041c0cSMatthew G. Knepley   void          *ctx;
9369bd041c0cSMatthew G. Knepley   DM             cdm;
9370bd041c0cSMatthew G. Knepley   PetscBool      regular;
9371bd041c0cSMatthew G. Knepley 
9372bd041c0cSMatthew G. Knepley   PetscFunctionBegin;
93733e9753d6SMatthew G. Knepley   if (dmFine == dmCoarse) {
93743e9753d6SMatthew G. Knepley     DM            dmc;
93753e9753d6SMatthew G. Knepley     PetscDS       ds;
9376b4937a87SMatthew G. Knepley     PetscWeakForm wf;
93773e9753d6SMatthew G. Knepley     Vec           u;
93783e9753d6SMatthew G. Knepley     IS            cellIS;
937906ad1575SMatthew G. Knepley     PetscFormKey  key;
93803e9753d6SMatthew G. Knepley     PetscInt      depth;
93813e9753d6SMatthew G. Knepley 
93829566063dSJacob Faibussowitsch     PetscCall(DMClone(dmFine, &dmc));
93839566063dSJacob Faibussowitsch     PetscCall(DMCopyDisc(dmFine, dmc));
93849566063dSJacob Faibussowitsch     PetscCall(DMGetDS(dmc, &ds));
93859566063dSJacob Faibussowitsch     PetscCall(PetscDSGetWeakForm(ds, &wf));
93869566063dSJacob Faibussowitsch     PetscCall(PetscWeakFormClear(wf));
93879566063dSJacob Faibussowitsch     PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL));
93889566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(dmc, mass));
93898d94ca23SJed Brown     PetscCall(DMGetLocalVector(dmc, &u));
93909566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dmc, &depth));
93919566063dSJacob Faibussowitsch     PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS));
93929566063dSJacob Faibussowitsch     PetscCall(MatZeroEntries(*mass));
93936528b96dSMatthew G. Knepley     key.label = NULL;
93946528b96dSMatthew G. Knepley     key.value = 0;
93956528b96dSMatthew G. Knepley     key.field = 0;
939606ad1575SMatthew G. Knepley     key.part  = 0;
93979566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL));
93989566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&cellIS));
93998d94ca23SJed Brown     PetscCall(DMRestoreLocalVector(dmc, &u));
94009566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&dmc));
94013e9753d6SMatthew G. Knepley   } else {
94029566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dmFine, &gsf));
94039566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m));
94049566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dmCoarse, &gsc));
94059566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n));
9406bd041c0cSMatthew G. Knepley 
94079566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass));
94089566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE));
94099566063dSJacob Faibussowitsch     PetscCall(MatSetType(*mass, dmCoarse->mattype));
94109566063dSJacob Faibussowitsch     PetscCall(DMGetApplicationContext(dmFine, &ctx));
9411bd041c0cSMatthew G. Knepley 
94129566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dmFine, &cdm));
94139566063dSJacob Faibussowitsch     PetscCall(DMPlexGetRegularRefinement(dmFine, &regular));
94149566063dSJacob Faibussowitsch     if (regular && cdm == dmCoarse) PetscCall(DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx));
94159566063dSJacob Faibussowitsch     else                            PetscCall(DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx));
94163e9753d6SMatthew G. Knepley   }
94179566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view"));
9418bd041c0cSMatthew G. Knepley   PetscFunctionReturn(0);
9419bd041c0cSMatthew G. Knepley }
9420bd041c0cSMatthew G. Knepley 
94210aef6b92SMatthew G. Knepley /*@
94220aef6b92SMatthew G. Knepley   DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh
94230aef6b92SMatthew G. Knepley 
94240aef6b92SMatthew G. Knepley   Input Parameter:
94250aef6b92SMatthew G. Knepley . dm - The DMPlex object
94260aef6b92SMatthew G. Knepley 
94270aef6b92SMatthew G. Knepley   Output Parameter:
94280aef6b92SMatthew G. Knepley . regular - The flag
94290aef6b92SMatthew G. Knepley 
94300aef6b92SMatthew G. Knepley   Level: intermediate
94310aef6b92SMatthew G. Knepley 
9432db781477SPatrick Sanan .seealso: `DMPlexSetRegularRefinement()`
94330aef6b92SMatthew G. Knepley @*/
94340aef6b92SMatthew G. Knepley PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular)
94350aef6b92SMatthew G. Knepley {
94360aef6b92SMatthew G. Knepley   PetscFunctionBegin;
94370aef6b92SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9438dadcf809SJacob Faibussowitsch   PetscValidBoolPointer(regular, 2);
94390aef6b92SMatthew G. Knepley   *regular = ((DM_Plex *) dm->data)->regularRefinement;
94400aef6b92SMatthew G. Knepley   PetscFunctionReturn(0);
94410aef6b92SMatthew G. Knepley }
94420aef6b92SMatthew G. Knepley 
94430aef6b92SMatthew G. Knepley /*@
94440aef6b92SMatthew G. Knepley   DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh
94450aef6b92SMatthew G. Knepley 
94460aef6b92SMatthew G. Knepley   Input Parameters:
94470aef6b92SMatthew G. Knepley + dm - The DMPlex object
94480aef6b92SMatthew G. Knepley - regular - The flag
94490aef6b92SMatthew G. Knepley 
94500aef6b92SMatthew G. Knepley   Level: intermediate
94510aef6b92SMatthew G. Knepley 
9452db781477SPatrick Sanan .seealso: `DMPlexGetRegularRefinement()`
94530aef6b92SMatthew G. Knepley @*/
94540aef6b92SMatthew G. Knepley PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular)
94550aef6b92SMatthew G. Knepley {
94560aef6b92SMatthew G. Knepley   PetscFunctionBegin;
94570aef6b92SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
94580aef6b92SMatthew G. Knepley   ((DM_Plex *) dm->data)->regularRefinement = regular;
94590aef6b92SMatthew G. Knepley   PetscFunctionReturn(0);
94600aef6b92SMatthew G. Knepley }
94610aef6b92SMatthew G. Knepley 
9462f7c74593SToby Isaac /* anchors */
9463a68b90caSToby Isaac /*@
9464f7c74593SToby Isaac   DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints.  Typically, the user will not have to
9465ebdb1bfaSJed Brown   call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetDefaultConstraints().
9466a68b90caSToby Isaac 
9467e228b242SToby Isaac   not collective
9468a68b90caSToby Isaac 
9469f899ff85SJose E. Roman   Input Parameter:
9470a68b90caSToby Isaac . dm - The DMPlex object
9471a68b90caSToby Isaac 
9472a68b90caSToby Isaac   Output Parameters:
9473a68b90caSToby Isaac + anchorSection - If not NULL, set to the section describing which points anchor the constrained points.
9474a68b90caSToby Isaac - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection
9475a68b90caSToby Isaac 
9476a68b90caSToby Isaac   Level: intermediate
9477a68b90caSToby Isaac 
9478db781477SPatrick Sanan .seealso: `DMPlexSetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()`
9479a68b90caSToby Isaac @*/
9480a17985deSToby Isaac PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS)
9481a68b90caSToby Isaac {
9482a68b90caSToby Isaac   DM_Plex *plex = (DM_Plex *)dm->data;
9483a68b90caSToby Isaac 
9484a68b90caSToby Isaac   PetscFunctionBegin;
9485a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
94869566063dSJacob Faibussowitsch   if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) PetscCall((*plex->createanchors)(dm));
9487a68b90caSToby Isaac   if (anchorSection) *anchorSection = plex->anchorSection;
9488a68b90caSToby Isaac   if (anchorIS) *anchorIS = plex->anchorIS;
9489a68b90caSToby Isaac   PetscFunctionReturn(0);
9490a68b90caSToby Isaac }
9491a68b90caSToby Isaac 
9492a68b90caSToby Isaac /*@
9493f7c74593SToby Isaac   DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints.  Unlike boundary conditions,
9494f7c74593SToby Isaac   when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a
9495a68b90caSToby Isaac   point's degrees of freedom to be a linear combination of other points' degrees of freedom.
9496a68b90caSToby Isaac 
9497a17985deSToby Isaac   After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling
9498ebdb1bfaSJed Brown   DMGetDefaultConstraints() and filling in the entries in the constraint matrix.
9499a68b90caSToby Isaac 
9500e228b242SToby Isaac   collective on dm
9501a68b90caSToby Isaac 
9502a68b90caSToby Isaac   Input Parameters:
9503a68b90caSToby Isaac + dm - The DMPlex object
9504e228b242SToby 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).
9505e228b242SToby Isaac - anchorIS - The list of all anchor points.  Must have a local communicator (PETSC_COMM_SELF or derivative).
9506a68b90caSToby Isaac 
9507a68b90caSToby Isaac   The reference counts of anchorSection and anchorIS are incremented.
9508a68b90caSToby Isaac 
9509a68b90caSToby Isaac   Level: intermediate
9510a68b90caSToby Isaac 
9511db781477SPatrick Sanan .seealso: `DMPlexGetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()`
9512a68b90caSToby Isaac @*/
9513a17985deSToby Isaac PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS)
9514a68b90caSToby Isaac {
9515a68b90caSToby Isaac   DM_Plex        *plex = (DM_Plex *)dm->data;
9516e228b242SToby Isaac   PetscMPIInt    result;
9517a68b90caSToby Isaac 
9518a68b90caSToby Isaac   PetscFunctionBegin;
9519a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9520e228b242SToby Isaac   if (anchorSection) {
9521e228b242SToby Isaac     PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2);
95229566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result));
95231dca8a05SBarry Smith     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator");
9524e228b242SToby Isaac   }
9525e228b242SToby Isaac   if (anchorIS) {
9526e228b242SToby Isaac     PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3);
95279566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result));
95281dca8a05SBarry Smith     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator");
9529e228b242SToby Isaac   }
9530a68b90caSToby Isaac 
95319566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)anchorSection));
95329566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&plex->anchorSection));
9533a68b90caSToby Isaac   plex->anchorSection = anchorSection;
9534a68b90caSToby Isaac 
95359566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)anchorIS));
95369566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&plex->anchorIS));
9537a68b90caSToby Isaac   plex->anchorIS = anchorIS;
9538a68b90caSToby Isaac 
9539cf9c20a2SJed Brown   if (PetscUnlikelyDebug(anchorIS && anchorSection)) {
9540a68b90caSToby Isaac     PetscInt size, a, pStart, pEnd;
9541a68b90caSToby Isaac     const PetscInt *anchors;
9542a68b90caSToby Isaac 
95439566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(anchorSection,&pStart,&pEnd));
95449566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(anchorIS,&size));
95459566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(anchorIS,&anchors));
9546a68b90caSToby Isaac     for (a = 0; a < size; a++) {
9547a68b90caSToby Isaac       PetscInt p;
9548a68b90caSToby Isaac 
9549a68b90caSToby Isaac       p = anchors[a];
9550a68b90caSToby Isaac       if (p >= pStart && p < pEnd) {
9551a68b90caSToby Isaac         PetscInt dof;
9552a68b90caSToby Isaac 
95539566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(anchorSection,p,&dof));
9554a68b90caSToby Isaac         if (dof) {
9555a68b90caSToby Isaac 
95569566063dSJacob Faibussowitsch           PetscCall(ISRestoreIndices(anchorIS,&anchors));
955763a3b9bcSJacob Faibussowitsch           SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %" PetscInt_FMT " cannot be constrained and an anchor",p);
9558a68b90caSToby Isaac         }
9559a68b90caSToby Isaac       }
9560a68b90caSToby Isaac     }
95619566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(anchorIS,&anchors));
9562a68b90caSToby Isaac   }
9563f7c74593SToby Isaac   /* reset the generic constraints */
95649566063dSJacob Faibussowitsch   PetscCall(DMSetDefaultConstraints(dm,NULL,NULL,NULL));
9565a68b90caSToby Isaac   PetscFunctionReturn(0);
9566a68b90caSToby Isaac }
9567a68b90caSToby Isaac 
9568f7c74593SToby Isaac static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec)
9569a68b90caSToby Isaac {
9570f7c74593SToby Isaac   PetscSection anchorSection;
95716995de1eSToby Isaac   PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f;
9572a68b90caSToby Isaac 
9573a68b90caSToby Isaac   PetscFunctionBegin;
9574a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
95759566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm,&anchorSection,NULL));
95769566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF,cSec));
95779566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section,&numFields));
95786995de1eSToby Isaac   if (numFields) {
9579719ab38cSToby Isaac     PetscInt f;
95809566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(*cSec,numFields));
9581719ab38cSToby Isaac 
9582719ab38cSToby Isaac     for (f = 0; f < numFields; f++) {
9583719ab38cSToby Isaac       PetscInt numComp;
9584719ab38cSToby Isaac 
95859566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldComponents(section,f,&numComp));
95869566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldComponents(*cSec,f,numComp));
9587719ab38cSToby Isaac     }
95886995de1eSToby Isaac   }
95899566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(anchorSection,&pStart,&pEnd));
95909566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section,&sStart,&sEnd));
95916995de1eSToby Isaac   pStart = PetscMax(pStart,sStart);
95926995de1eSToby Isaac   pEnd   = PetscMin(pEnd,sEnd);
95936995de1eSToby Isaac   pEnd   = PetscMax(pStart,pEnd);
95949566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*cSec,pStart,pEnd));
9595a68b90caSToby Isaac   for (p = pStart; p < pEnd; p++) {
95969566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(anchorSection,p,&dof));
9597a68b90caSToby Isaac     if (dof) {
95989566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section,p,&dof));
95999566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(*cSec,p,dof));
9600a68b90caSToby Isaac       for (f = 0; f < numFields; f++) {
96019566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(section,p,f,&dof));
96029566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetFieldDof(*cSec,p,f,dof));
9603a68b90caSToby Isaac       }
9604a68b90caSToby Isaac     }
9605a68b90caSToby Isaac   }
96069566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(*cSec));
96079566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject) *cSec, "Constraint Section"));
9608a68b90caSToby Isaac   PetscFunctionReturn(0);
9609a68b90caSToby Isaac }
9610a68b90caSToby Isaac 
9611f7c74593SToby Isaac static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat)
9612a68b90caSToby Isaac {
9613f7c74593SToby Isaac   PetscSection   aSec;
9614ae65431dSMatthew G. Knepley   PetscInt       pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j;
96150ac89760SToby Isaac   const PetscInt *anchors;
96160ac89760SToby Isaac   PetscInt       numFields, f;
961766ad2231SToby Isaac   IS             aIS;
9618e19f7ee6SMark Adams   MatType        mtype;
9619e19f7ee6SMark Adams   PetscBool      iscuda,iskokkos;
96200ac89760SToby Isaac 
96210ac89760SToby Isaac   PetscFunctionBegin;
96220ac89760SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
96239566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(cSec, &m));
96249566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(section, &n));
96259566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_SELF,cMat));
96269566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*cMat,m,n,m,n));
96279566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dm->mattype,MATSEQAIJCUSPARSE,&iscuda));
96289566063dSJacob Faibussowitsch   if (!iscuda) PetscCall(PetscStrcmp(dm->mattype,MATMPIAIJCUSPARSE,&iscuda));
96299566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dm->mattype,MATSEQAIJKOKKOS,&iskokkos));
96309566063dSJacob Faibussowitsch   if (!iskokkos) PetscCall(PetscStrcmp(dm->mattype,MATMPIAIJKOKKOS,&iskokkos));
9631e19f7ee6SMark Adams   if (iscuda) mtype = MATSEQAIJCUSPARSE;
9632e19f7ee6SMark Adams   else if (iskokkos) mtype = MATSEQAIJKOKKOS;
9633e19f7ee6SMark Adams   else mtype = MATSEQAIJ;
96349566063dSJacob Faibussowitsch   PetscCall(MatSetType(*cMat,mtype));
96359566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm,&aSec,&aIS));
96369566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(aIS,&anchors));
96376995de1eSToby Isaac   /* cSec will be a subset of aSec and section */
96389566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(cSec,&pStart,&pEnd));
96399566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section,&sStart,&sEnd));
96409566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m+1,&i));
96410ac89760SToby Isaac   i[0] = 0;
96429566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section,&numFields));
96430ac89760SToby Isaac   for (p = pStart; p < pEnd; p++) {
9644f19733c5SToby Isaac     PetscInt rDof, rOff, r;
9645f19733c5SToby Isaac 
96469566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(aSec,p,&rDof));
9647f19733c5SToby Isaac     if (!rDof) continue;
96489566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(aSec,p,&rOff));
96490ac89760SToby Isaac     if (numFields) {
96500ac89760SToby Isaac       for (f = 0; f < numFields; f++) {
96510ac89760SToby Isaac         annz = 0;
9652f19733c5SToby Isaac         for (r = 0; r < rDof; r++) {
9653f19733c5SToby Isaac           a = anchors[rOff + r];
9654ae65431dSMatthew G. Knepley           if (a < sStart || a >= sEnd) continue;
96559566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section,a,f,&aDof));
96560ac89760SToby Isaac           annz += aDof;
96570ac89760SToby Isaac         }
96589566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(cSec,p,f,&dof));
96599566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldOffset(cSec,p,f,&off));
96600ac89760SToby Isaac         for (q = 0; q < dof; q++) {
96610ac89760SToby Isaac           i[off + q + 1] = i[off + q] + annz;
96620ac89760SToby Isaac         }
96630ac89760SToby Isaac       }
96642f7452b8SBarry Smith     } else {
96650ac89760SToby Isaac       annz = 0;
96669566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec,p,&dof));
96670ac89760SToby Isaac       for (q = 0; q < dof; q++) {
9668ae65431dSMatthew G. Knepley         a = anchors[rOff + q];
9669ae65431dSMatthew G. Knepley         if (a < sStart || a >= sEnd) continue;
96709566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section,a,&aDof));
96710ac89760SToby Isaac         annz += aDof;
96720ac89760SToby Isaac       }
96739566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec,p,&dof));
96749566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(cSec,p,&off));
96750ac89760SToby Isaac       for (q = 0; q < dof; q++) {
96760ac89760SToby Isaac         i[off + q + 1] = i[off + q] + annz;
96770ac89760SToby Isaac       }
96780ac89760SToby Isaac     }
96790ac89760SToby Isaac   }
96800ac89760SToby Isaac   nnz = i[m];
96819566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nnz,&j));
96820ac89760SToby Isaac   offset = 0;
96830ac89760SToby Isaac   for (p = pStart; p < pEnd; p++) {
96840ac89760SToby Isaac     if (numFields) {
96850ac89760SToby Isaac       for (f = 0; f < numFields; f++) {
96869566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(cSec,p,f,&dof));
96870ac89760SToby Isaac         for (q = 0; q < dof; q++) {
96880ac89760SToby Isaac           PetscInt rDof, rOff, r;
96899566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(aSec,p,&rDof));
96909566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(aSec,p,&rOff));
96910ac89760SToby Isaac           for (r = 0; r < rDof; r++) {
96920ac89760SToby Isaac             PetscInt s;
96930ac89760SToby Isaac 
96940ac89760SToby Isaac             a = anchors[rOff + r];
9695ae65431dSMatthew G. Knepley             if (a < sStart || a >= sEnd) continue;
96969566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section,a,f,&aDof));
96979566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldOffset(section,a,f,&aOff));
96980ac89760SToby Isaac             for (s = 0; s < aDof; s++) {
96990ac89760SToby Isaac               j[offset++] = aOff + s;
97000ac89760SToby Isaac             }
97010ac89760SToby Isaac           }
97020ac89760SToby Isaac         }
97030ac89760SToby Isaac       }
97042f7452b8SBarry Smith     } else {
97059566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec,p,&dof));
97060ac89760SToby Isaac       for (q = 0; q < dof; q++) {
97070ac89760SToby Isaac         PetscInt rDof, rOff, r;
97089566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(aSec,p,&rDof));
97099566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec,p,&rOff));
97100ac89760SToby Isaac         for (r = 0; r < rDof; r++) {
97110ac89760SToby Isaac           PetscInt s;
97120ac89760SToby Isaac 
97130ac89760SToby Isaac           a = anchors[rOff + r];
9714ae65431dSMatthew G. Knepley           if (a < sStart || a >= sEnd) continue;
97159566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section,a,&aDof));
97169566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(section,a,&aOff));
97170ac89760SToby Isaac           for (s = 0; s < aDof; s++) {
97180ac89760SToby Isaac             j[offset++] = aOff + s;
97190ac89760SToby Isaac           }
97200ac89760SToby Isaac         }
97210ac89760SToby Isaac       }
97220ac89760SToby Isaac     }
97230ac89760SToby Isaac   }
97249566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL));
97259566063dSJacob Faibussowitsch   PetscCall(PetscFree(i));
97269566063dSJacob Faibussowitsch   PetscCall(PetscFree(j));
97279566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(aIS,&anchors));
97280ac89760SToby Isaac   PetscFunctionReturn(0);
97290ac89760SToby Isaac }
97300ac89760SToby Isaac 
973166ad2231SToby Isaac PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm)
973266ad2231SToby Isaac {
9733f7c74593SToby Isaac   DM_Plex        *plex = (DM_Plex *)dm->data;
9734f7c74593SToby Isaac   PetscSection   anchorSection, section, cSec;
973566ad2231SToby Isaac   Mat            cMat;
973666ad2231SToby Isaac 
973766ad2231SToby Isaac   PetscFunctionBegin;
973866ad2231SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
97399566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm,&anchorSection,NULL));
974066ad2231SToby Isaac   if (anchorSection) {
974144a7f3ddSMatthew G. Knepley     PetscInt Nf;
9742e228b242SToby Isaac 
97439566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm,&section));
97449566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateConstraintSection_Anchors(dm,section,&cSec));
97459566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat));
97469566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm,&Nf));
97479566063dSJacob Faibussowitsch     if (Nf && plex->computeanchormatrix) PetscCall((*plex->computeanchormatrix)(dm,section,cSec,cMat));
97489566063dSJacob Faibussowitsch     PetscCall(DMSetDefaultConstraints(dm,cSec,cMat,NULL));
97499566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&cSec));
97509566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&cMat));
975166ad2231SToby Isaac   }
975266ad2231SToby Isaac   PetscFunctionReturn(0);
975366ad2231SToby Isaac }
9754a93c429eSMatthew G. Knepley 
9755a93c429eSMatthew G. Knepley PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm)
9756a93c429eSMatthew G. Knepley {
9757a93c429eSMatthew G. Knepley   IS             subis;
9758a93c429eSMatthew G. Knepley   PetscSection   section, subsection;
9759a93c429eSMatthew G. Knepley 
9760a93c429eSMatthew G. Knepley   PetscFunctionBegin;
97619566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
976228b400f6SJacob Faibussowitsch   PetscCheck(section,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain");
976328b400f6SJacob Faibussowitsch   PetscCheck(subdm,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain");
9764a93c429eSMatthew G. Knepley   /* Create subdomain */
97659566063dSJacob Faibussowitsch   PetscCall(DMPlexFilter(dm, label, value, subdm));
9766a93c429eSMatthew G. Knepley   /* Create submodel */
97679566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSubpointIS(*subdm, &subis));
97689566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreateSubmeshSection(section, subis, &subsection));
97699566063dSJacob Faibussowitsch   PetscCall(DMSetLocalSection(*subdm, subsection));
97709566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&subsection));
97719566063dSJacob Faibussowitsch   PetscCall(DMCopyDisc(dm, *subdm));
9772a93c429eSMatthew G. Knepley   /* Create map from submodel to global model */
9773a93c429eSMatthew G. Knepley   if (is) {
9774a93c429eSMatthew G. Knepley     PetscSection    sectionGlobal, subsectionGlobal;
9775a93c429eSMatthew G. Knepley     IS              spIS;
9776a93c429eSMatthew G. Knepley     const PetscInt *spmap;
9777a93c429eSMatthew G. Knepley     PetscInt       *subIndices;
9778a93c429eSMatthew G. Knepley     PetscInt        subSize = 0, subOff = 0, pStart, pEnd, p;
9779a93c429eSMatthew G. Knepley     PetscInt        Nf, f, bs = -1, bsLocal[2], bsMinMax[2];
9780a93c429eSMatthew G. Knepley 
97819566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSubpointIS(*subdm, &spIS));
97829566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(spIS, &spmap));
97839566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetNumFields(section, &Nf));
97849566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dm, &sectionGlobal));
97859566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(*subdm, &subsectionGlobal));
97869566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(subsection, &pStart, &pEnd));
9787a93c429eSMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
9788a93c429eSMatthew G. Knepley       PetscInt gdof, pSubSize  = 0;
9789a93c429eSMatthew G. Knepley 
97909566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof));
9791a93c429eSMatthew G. Knepley       if (gdof > 0) {
9792a93c429eSMatthew G. Knepley         for (f = 0; f < Nf; ++f) {
9793a93c429eSMatthew G. Knepley           PetscInt fdof, fcdof;
9794a93c429eSMatthew G. Knepley 
97959566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(subsection, p, f, &fdof));
97969566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof));
9797a93c429eSMatthew G. Knepley           pSubSize += fdof-fcdof;
9798a93c429eSMatthew G. Knepley         }
9799a93c429eSMatthew G. Knepley         subSize += pSubSize;
9800a93c429eSMatthew G. Knepley         if (pSubSize) {
9801a93c429eSMatthew G. Knepley           if (bs < 0) {
9802a93c429eSMatthew G. Knepley             bs = pSubSize;
9803a93c429eSMatthew G. Knepley           } else if (bs != pSubSize) {
9804a93c429eSMatthew G. Knepley             /* Layout does not admit a pointwise block size */
9805a93c429eSMatthew G. Knepley             bs = 1;
9806a93c429eSMatthew G. Knepley           }
9807a93c429eSMatthew G. Knepley         }
9808a93c429eSMatthew G. Knepley       }
9809a93c429eSMatthew G. Knepley     }
9810a93c429eSMatthew G. Knepley     /* Must have same blocksize on all procs (some might have no points) */
9811a93c429eSMatthew G. Knepley     bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs;
98129566063dSJacob Faibussowitsch     PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax));
9813a93c429eSMatthew G. Knepley     if (bsMinMax[0] != bsMinMax[1]) {bs = 1;}
9814a93c429eSMatthew G. Knepley     else                            {bs = bsMinMax[0];}
98159566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(subSize, &subIndices));
9816a93c429eSMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
9817a93c429eSMatthew G. Knepley       PetscInt gdof, goff;
9818a93c429eSMatthew G. Knepley 
98199566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(subsectionGlobal, p, &gdof));
9820a93c429eSMatthew G. Knepley       if (gdof > 0) {
9821a93c429eSMatthew G. Knepley         const PetscInt point = spmap[p];
9822a93c429eSMatthew G. Knepley 
98239566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(sectionGlobal, point, &goff));
9824a93c429eSMatthew G. Knepley         for (f = 0; f < Nf; ++f) {
9825a93c429eSMatthew G. Knepley           PetscInt fdof, fcdof, fc, f2, poff = 0;
9826a93c429eSMatthew G. Knepley 
9827a93c429eSMatthew G. Knepley           /* Can get rid of this loop by storing field information in the global section */
9828a93c429eSMatthew G. Knepley           for (f2 = 0; f2 < f; ++f2) {
98299566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, p, f2, &fdof));
98309566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof));
9831a93c429eSMatthew G. Knepley             poff += fdof-fcdof;
9832a93c429eSMatthew G. Knepley           }
98339566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof));
98349566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof));
9835a93c429eSMatthew G. Knepley           for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) {
9836a93c429eSMatthew G. Knepley             subIndices[subOff] = goff+poff+fc;
9837a93c429eSMatthew G. Knepley           }
9838a93c429eSMatthew G. Knepley         }
9839a93c429eSMatthew G. Knepley       }
9840a93c429eSMatthew G. Knepley     }
98419566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(spIS, &spmap));
98429566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is));
9843a93c429eSMatthew G. Knepley     if (bs > 1) {
9844a93c429eSMatthew G. Knepley       /* We need to check that the block size does not come from non-contiguous fields */
9845a93c429eSMatthew G. Knepley       PetscInt i, j, set = 1;
9846a93c429eSMatthew G. Knepley       for (i = 0; i < subSize; i += bs) {
9847a93c429eSMatthew G. Knepley         for (j = 0; j < bs; ++j) {
9848a93c429eSMatthew G. Knepley           if (subIndices[i+j] != subIndices[i]+j) {set = 0; break;}
9849a93c429eSMatthew G. Knepley         }
9850a93c429eSMatthew G. Knepley       }
98519566063dSJacob Faibussowitsch       if (set) PetscCall(ISSetBlockSize(*is, bs));
9852a93c429eSMatthew G. Knepley     }
9853a93c429eSMatthew G. Knepley     /* Attach nullspace */
9854a93c429eSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
9855a93c429eSMatthew G. Knepley       (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f];
9856a93c429eSMatthew G. Knepley       if ((*subdm)->nullspaceConstructors[f]) break;
9857a93c429eSMatthew G. Knepley     }
9858a93c429eSMatthew G. Knepley     if (f < Nf) {
9859a93c429eSMatthew G. Knepley       MatNullSpace nullSpace;
98609566063dSJacob Faibussowitsch       PetscCall((*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace));
98616823f3c5SBlaise Bourdin 
98629566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace));
98639566063dSJacob Faibussowitsch       PetscCall(MatNullSpaceDestroy(&nullSpace));
9864a93c429eSMatthew G. Knepley     }
9865a93c429eSMatthew G. Knepley   }
9866a93c429eSMatthew G. Knepley   PetscFunctionReturn(0);
9867a93c429eSMatthew G. Knepley }
9868c0f0dcc3SMatthew G. Knepley 
9869c0f0dcc3SMatthew G. Knepley /*@
9870c0f0dcc3SMatthew G. Knepley   DMPlexMonitorThroughput - Report the cell throughput of FE integration
9871c0f0dcc3SMatthew G. Knepley 
9872c0f0dcc3SMatthew G. Knepley   Input Parameter:
9873c0f0dcc3SMatthew G. Knepley - dm - The DM
9874c0f0dcc3SMatthew G. Knepley 
9875c0f0dcc3SMatthew G. Knepley   Level: developer
9876c0f0dcc3SMatthew G. Knepley 
9877c0f0dcc3SMatthew G. Knepley   Options Database Keys:
9878c0f0dcc3SMatthew G. Knepley . -dm_plex_monitor_throughput - Activate the monitor
9879c0f0dcc3SMatthew G. Knepley 
9880db781477SPatrick Sanan .seealso: `DMSetFromOptions()`, `DMPlexCreate()`
9881c0f0dcc3SMatthew G. Knepley @*/
9882c0f0dcc3SMatthew G. Knepley PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy)
9883c0f0dcc3SMatthew G. Knepley {
9884e5ed2c37SJose E. Roman #if defined(PETSC_USE_LOG)
9885c0f0dcc3SMatthew G. Knepley   PetscStageLog      stageLog;
9886c0f0dcc3SMatthew G. Knepley   PetscLogEvent      event;
9887c0f0dcc3SMatthew G. Knepley   PetscLogStage      stage;
9888c0f0dcc3SMatthew G. Knepley   PetscEventPerfInfo eventInfo;
9889c0f0dcc3SMatthew G. Knepley   PetscReal          cellRate, flopRate;
9890c0f0dcc3SMatthew G. Knepley   PetscInt           cStart, cEnd, Nf, N;
9891c0f0dcc3SMatthew G. Knepley   const char        *name;
9892e5ed2c37SJose E. Roman #endif
9893c0f0dcc3SMatthew G. Knepley 
9894c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
9895c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9896c0f0dcc3SMatthew G. Knepley #if defined(PETSC_USE_LOG)
98979566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject) dm, &name));
98989566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
98999566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
99009566063dSJacob Faibussowitsch   PetscCall(PetscLogGetStageLog(&stageLog));
99019566063dSJacob Faibussowitsch   PetscCall(PetscStageLogGetCurrent(stageLog, &stage));
99029566063dSJacob Faibussowitsch   PetscCall(PetscLogEventGetId("DMPlexResidualFE", &event));
99039566063dSJacob Faibussowitsch   PetscCall(PetscLogEventGetPerfInfo(stage, event, &eventInfo));
9904c0f0dcc3SMatthew G. Knepley   N        = (cEnd - cStart)*Nf*eventInfo.count;
9905c0f0dcc3SMatthew G. Knepley   flopRate = eventInfo.flops/eventInfo.time;
9906c0f0dcc3SMatthew G. Knepley   cellRate = N/eventInfo.time;
990763a3b9bcSJacob 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)));
9908c0f0dcc3SMatthew G. Knepley #else
9909c0f0dcc3SMatthew G. Knepley   SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Plex Throughput Monitor is not supported if logging is turned off. Reconfigure using --with-log.");
9910c0f0dcc3SMatthew G. Knepley #endif
9911c0f0dcc3SMatthew G. Knepley   PetscFunctionReturn(0);
9912c0f0dcc3SMatthew G. Knepley }
9913