xref: /petsc/src/dm/impls/plex/plex.c (revision fe28d2976a9630dae544ebe0f11bc53acbfacbfa)
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 @*/
349371c9d4SSatish Balay PetscErrorCode DMPlexIsSimplex(DM dm, PetscBool *simplex) {
359318fe57SMatthew G. Knepley   DMPolytopeType ct;
369318fe57SMatthew G. Knepley   PetscInt       cStart, cEnd;
379318fe57SMatthew G. Knepley 
389318fe57SMatthew G. Knepley   PetscFunctionBegin;
399566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
409371c9d4SSatish Balay   if (cEnd <= cStart) {
419371c9d4SSatish Balay     *simplex = PETSC_FALSE;
429371c9d4SSatish Balay     PetscFunctionReturn(0);
439371c9d4SSatish Balay   }
449566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cStart, &ct));
459318fe57SMatthew G. Knepley   *simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE;
469318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
479318fe57SMatthew G. Knepley }
489318fe57SMatthew G. Knepley 
499318fe57SMatthew G. Knepley /*@
50412e9a14SMatthew G. Knepley   DMPlexGetSimplexOrBoxCells - Get the range of cells which are neither prisms nor ghost FV cells
51e5337592SStefano Zampini 
52d8d19677SJose E. Roman   Input Parameters:
53412e9a14SMatthew G. Knepley + dm     - The DMPlex object
54412e9a14SMatthew G. Knepley - height - The cell height in the Plex, 0 is the default
55e5337592SStefano Zampini 
56e5337592SStefano Zampini   Output Parameters:
57412e9a14SMatthew G. Knepley + cStart - The first "normal" cell
58412e9a14SMatthew G. Knepley - cEnd   - The upper bound on "normal"" cells
59e5337592SStefano Zampini 
60412e9a14SMatthew 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.
61e5337592SStefano Zampini 
62412e9a14SMatthew G. Knepley   Level: developer
63e5337592SStefano Zampini 
64db781477SPatrick Sanan .seealso `DMPlexConstructGhostCells()`, `DMPlexGetGhostCellStratum()`
65e5337592SStefano Zampini @*/
669371c9d4SSatish Balay PetscErrorCode DMPlexGetSimplexOrBoxCells(DM dm, PetscInt height, PetscInt *cStart, PetscInt *cEnd) {
67412e9a14SMatthew G. Knepley   DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
68412e9a14SMatthew G. Knepley   PetscInt       cS, cE, c;
69e5337592SStefano Zampini 
70e5337592SStefano Zampini   PetscFunctionBegin;
719566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, PetscMax(height, 0), &cS, &cE));
72412e9a14SMatthew G. Knepley   for (c = cS; c < cE; ++c) {
73412e9a14SMatthew G. Knepley     DMPolytopeType cct;
74412e9a14SMatthew G. Knepley 
759566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &cct));
76412e9a14SMatthew G. Knepley     if ((PetscInt)cct < 0) break;
77412e9a14SMatthew G. Knepley     switch (cct) {
78ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_POINT:
79ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:
80ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:
81ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:
82ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_TETRAHEDRON:
839371c9d4SSatish Balay     case DM_POLYTOPE_HEXAHEDRON: ct = cct; break;
84412e9a14SMatthew G. Knepley     default: break;
85e5337592SStefano Zampini     }
86412e9a14SMatthew G. Knepley     if (ct != DM_POLYTOPE_UNKNOWN) break;
87e5337592SStefano Zampini   }
88412e9a14SMatthew G. Knepley   if (ct != DM_POLYTOPE_UNKNOWN) {
89412e9a14SMatthew G. Knepley     DMLabel ctLabel;
90412e9a14SMatthew G. Knepley 
919566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel));
929566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumBounds(ctLabel, ct, &cS, &cE));
93695799ffSMatthew G. Knepley     // Reset label for fast lookup
94695799ffSMatthew G. Knepley     PetscCall(DMLabelMakeAllInvalid_Internal(ctLabel));
95e5337592SStefano Zampini   }
96412e9a14SMatthew G. Knepley   if (cStart) *cStart = cS;
97412e9a14SMatthew G. Knepley   if (cEnd) *cEnd = cE;
98e5337592SStefano Zampini   PetscFunctionReturn(0);
99e5337592SStefano Zampini }
100e5337592SStefano Zampini 
1019371c9d4SSatish Balay PetscErrorCode DMPlexGetFieldType_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *sStart, PetscInt *sEnd, PetscViewerVTKFieldType *ft) {
102412e9a14SMatthew G. Knepley   PetscInt cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd;
103a99a26bcSAdrian Croucher   PetscInt vcdof[2] = {0, 0}, globalvcdof[2];
1047e42fee7SMatthew G. Knepley 
1057e42fee7SMatthew G. Knepley   PetscFunctionBegin;
106e630c359SToby Isaac   *ft = PETSC_VTK_INVALID;
1079566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
1089566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
1099566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd));
1109566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
1117e42fee7SMatthew G. Knepley   if (field >= 0) {
1129566063dSJacob Faibussowitsch     if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, vStart, field, &vcdof[0]));
1139566063dSJacob Faibussowitsch     if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, cStart, field, &vcdof[1]));
1147e42fee7SMatthew G. Knepley   } else {
1159566063dSJacob Faibussowitsch     if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetDof(section, vStart, &vcdof[0]));
1169566063dSJacob Faibussowitsch     if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetDof(section, cStart, &vcdof[1]));
1177e42fee7SMatthew G. Knepley   }
1189566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allreduce(vcdof, globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
119a99a26bcSAdrian Croucher   if (globalvcdof[0]) {
1207e42fee7SMatthew G. Knepley     *sStart = vStart;
1217e42fee7SMatthew G. Knepley     *sEnd   = vEnd;
122f094498dSMatthew G. Knepley     if (globalvcdof[0] == cdim) *ft = PETSC_VTK_POINT_VECTOR_FIELD;
1237e42fee7SMatthew G. Knepley     else *ft = PETSC_VTK_POINT_FIELD;
124a99a26bcSAdrian Croucher   } else if (globalvcdof[1]) {
1257e42fee7SMatthew G. Knepley     *sStart = cStart;
1267e42fee7SMatthew G. Knepley     *sEnd   = cEnd;
127f094498dSMatthew G. Knepley     if (globalvcdof[1] == cdim) *ft = PETSC_VTK_CELL_VECTOR_FIELD;
1287e42fee7SMatthew G. Knepley     else *ft = PETSC_VTK_CELL_FIELD;
129e630c359SToby Isaac   } else {
130e630c359SToby Isaac     if (field >= 0) {
131e630c359SToby Isaac       const char *fieldname;
132e630c359SToby Isaac 
1339566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldName(section, field, &fieldname));
13463a3b9bcSJacob Faibussowitsch       PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section field %" PetscInt_FMT " \"%s\"\n", field, fieldname));
135e630c359SToby Isaac     } else {
13663a3b9bcSJacob Faibussowitsch       PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section\n"));
137e630c359SToby Isaac     }
138e630c359SToby Isaac   }
1397e42fee7SMatthew G. Knepley   PetscFunctionReturn(0);
1407e42fee7SMatthew G. Knepley }
1417e42fee7SMatthew G. Knepley 
1426913077dSMatthew G. Knepley /*@
1436913077dSMatthew G. Knepley   DMPlexVecView1D - Plot many 1D solutions on the same line graph
1446913077dSMatthew G. Knepley 
1456913077dSMatthew G. Knepley   Collective on dm
1466913077dSMatthew G. Knepley 
1476913077dSMatthew G. Knepley   Input Parameters:
1486913077dSMatthew G. Knepley + dm - The DMPlex
1496913077dSMatthew G. Knepley . n  - The number of vectors
1506913077dSMatthew G. Knepley . u  - The array of local vectors
1516913077dSMatthew G. Knepley - viewer - The Draw viewer
1526913077dSMatthew G. Knepley 
1536913077dSMatthew G. Knepley   Level: advanced
1546913077dSMatthew G. Knepley 
155db781477SPatrick Sanan .seealso: `VecViewFromOptions()`, `VecView()`
1566913077dSMatthew G. Knepley @*/
1579371c9d4SSatish Balay PetscErrorCode DMPlexVecView1D(DM dm, PetscInt n, Vec u[], PetscViewer viewer) {
1586913077dSMatthew G. Knepley   PetscDS            ds;
1596913077dSMatthew G. Knepley   PetscDraw          draw = NULL;
1606913077dSMatthew G. Knepley   PetscDrawLG        lg;
1616913077dSMatthew G. Knepley   Vec                coordinates;
1626913077dSMatthew G. Knepley   const PetscScalar *coords, **sol;
1636913077dSMatthew G. Knepley   PetscReal         *vals;
1646913077dSMatthew G. Knepley   PetscInt          *Nc;
1656913077dSMatthew G. Knepley   PetscInt           Nf, f, c, Nl, l, i, vStart, vEnd, v;
1666913077dSMatthew G. Knepley   char             **names;
1676913077dSMatthew G. Knepley 
1686913077dSMatthew G. Knepley   PetscFunctionBegin;
1699566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &ds));
1709566063dSJacob Faibussowitsch   PetscCall(PetscDSGetNumFields(ds, &Nf));
1719566063dSJacob Faibussowitsch   PetscCall(PetscDSGetTotalComponents(ds, &Nl));
1729566063dSJacob Faibussowitsch   PetscCall(PetscDSGetComponents(ds, &Nc));
1736913077dSMatthew G. Knepley 
1749566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
1756913077dSMatthew G. Knepley   if (!draw) PetscFunctionReturn(0);
1769566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGCreate(draw, n * Nl, &lg));
1776913077dSMatthew G. Knepley 
1789566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(n, &sol, n * Nl, &names, n * Nl, &vals));
1796913077dSMatthew G. Knepley   for (i = 0, l = 0; i < n; ++i) {
1806913077dSMatthew G. Knepley     const char *vname;
1816913077dSMatthew G. Knepley 
1829566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)u[i], &vname));
1836913077dSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
1846913077dSMatthew G. Knepley       PetscObject disc;
1856913077dSMatthew G. Knepley       const char *fname;
1866913077dSMatthew G. Knepley       char        tmpname[PETSC_MAX_PATH_LEN];
1876913077dSMatthew G. Knepley 
1889566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(ds, f, &disc));
1896913077dSMatthew G. Knepley       /* TODO Create names for components */
1906913077dSMatthew G. Knepley       for (c = 0; c < Nc[f]; ++c, ++l) {
1919566063dSJacob Faibussowitsch         PetscCall(PetscObjectGetName(disc, &fname));
1929566063dSJacob Faibussowitsch         PetscCall(PetscStrcpy(tmpname, vname));
1939566063dSJacob Faibussowitsch         PetscCall(PetscStrlcat(tmpname, ":", PETSC_MAX_PATH_LEN));
1949566063dSJacob Faibussowitsch         PetscCall(PetscStrlcat(tmpname, fname, PETSC_MAX_PATH_LEN));
1959566063dSJacob Faibussowitsch         PetscCall(PetscStrallocpy(tmpname, &names[l]));
1966913077dSMatthew G. Knepley       }
1976913077dSMatthew G. Knepley     }
1986913077dSMatthew G. Knepley   }
1999566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGSetLegend(lg, (const char *const *)names));
2006913077dSMatthew G. Knepley   /* Just add P_1 support for now */
2019566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
2029566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
2039566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(coordinates, &coords));
2049566063dSJacob Faibussowitsch   for (i = 0; i < n; ++i) PetscCall(VecGetArrayRead(u[i], &sol[i]));
2056913077dSMatthew G. Knepley   for (v = vStart; v < vEnd; ++v) {
2066913077dSMatthew G. Knepley     PetscScalar *x, *svals;
2076913077dSMatthew G. Knepley 
2089566063dSJacob Faibussowitsch     PetscCall(DMPlexPointLocalRead(dm, v, coords, &x));
2096913077dSMatthew G. Knepley     for (i = 0; i < n; ++i) {
2109566063dSJacob Faibussowitsch       PetscCall(DMPlexPointLocalRead(dm, v, sol[i], &svals));
2116913077dSMatthew G. Knepley       for (l = 0; l < Nl; ++l) vals[i * Nl + l] = PetscRealPart(svals[l]);
2126913077dSMatthew G. Knepley     }
2139566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGAddCommonPoint(lg, PetscRealPart(x[0]), vals));
2146913077dSMatthew G. Knepley   }
2159566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(coordinates, &coords));
2169566063dSJacob Faibussowitsch   for (i = 0; i < n; ++i) PetscCall(VecRestoreArrayRead(u[i], &sol[i]));
2179566063dSJacob Faibussowitsch   for (l = 0; l < n * Nl; ++l) PetscCall(PetscFree(names[l]));
2189566063dSJacob Faibussowitsch   PetscCall(PetscFree3(sol, names, vals));
2196913077dSMatthew G. Knepley 
2209566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGDraw(lg));
2219566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGDestroy(&lg));
2226913077dSMatthew G. Knepley   PetscFunctionReturn(0);
2236913077dSMatthew G. Knepley }
2246913077dSMatthew G. Knepley 
2259371c9d4SSatish Balay static PetscErrorCode VecView_Plex_Local_Draw_1D(Vec u, PetscViewer viewer) {
2266913077dSMatthew G. Knepley   DM dm;
2276913077dSMatthew G. Knepley 
2286913077dSMatthew G. Knepley   PetscFunctionBegin;
2299566063dSJacob Faibussowitsch   PetscCall(VecGetDM(u, &dm));
2309566063dSJacob Faibussowitsch   PetscCall(DMPlexVecView1D(dm, 1, &u, viewer));
2316913077dSMatthew G. Knepley   PetscFunctionReturn(0);
2326913077dSMatthew G. Knepley }
2336913077dSMatthew G. Knepley 
2349371c9d4SSatish Balay static PetscErrorCode VecView_Plex_Local_Draw_2D(Vec v, PetscViewer viewer) {
235e412dcbdSMatthew G. Knepley   DM                 dm;
236d1df6f1dSMatthew G. Knepley   PetscSection       s;
237e412dcbdSMatthew G. Knepley   PetscDraw          draw, popup;
238e412dcbdSMatthew G. Knepley   DM                 cdm;
239e412dcbdSMatthew G. Knepley   PetscSection       coordSection;
240e412dcbdSMatthew G. Knepley   Vec                coordinates;
241e412dcbdSMatthew G. Knepley   const PetscScalar *coords, *array;
242e412dcbdSMatthew G. Knepley   PetscReal          bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL};
243339e3443SMatthew G. Knepley   PetscReal          vbound[2], time;
2446913077dSMatthew G. Knepley   PetscBool          flg;
245d1df6f1dSMatthew G. Knepley   PetscInt           dim, Nf, f, Nc, comp, vStart, vEnd, cStart, cEnd, c, N, level, step, w = 0;
246e412dcbdSMatthew G. Knepley   const char        *name;
247339e3443SMatthew G. Knepley   char               title[PETSC_MAX_PATH_LEN];
248e412dcbdSMatthew G. Knepley 
249e412dcbdSMatthew G. Knepley   PetscFunctionBegin;
2509566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
2519566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
2529566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dim));
2539566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &s));
2549566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(s, &Nf));
2559566063dSJacob Faibussowitsch   PetscCall(DMGetCoarsenLevel(dm, &level));
2569566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
2579566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(cdm, &coordSection));
2589566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
2599566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
2609566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
261e412dcbdSMatthew G. Knepley 
2629566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)v, &name));
2639566063dSJacob Faibussowitsch   PetscCall(DMGetOutputSequenceNumber(dm, &step, &time));
264e412dcbdSMatthew G. Knepley 
2659566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(coordinates, &N));
2669566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(coordinates, &coords));
267e412dcbdSMatthew G. Knepley   for (c = 0; c < N; c += dim) {
2689371c9d4SSatish Balay     bound[0] = PetscMin(bound[0], PetscRealPart(coords[c]));
2699371c9d4SSatish Balay     bound[2] = PetscMax(bound[2], PetscRealPart(coords[c]));
2709371c9d4SSatish Balay     bound[1] = PetscMin(bound[1], PetscRealPart(coords[c + 1]));
2719371c9d4SSatish Balay     bound[3] = PetscMax(bound[3], PetscRealPart(coords[c + 1]));
272e412dcbdSMatthew G. Knepley   }
2739566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(coordinates, &coords));
2749566063dSJacob Faibussowitsch   PetscCall(PetscDrawClear(draw));
275e412dcbdSMatthew G. Knepley 
276d1df6f1dSMatthew G. Knepley   /* Could implement something like DMDASelectFields() */
277d1df6f1dSMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
278d1df6f1dSMatthew G. Knepley     DM          fdm = dm;
279d1df6f1dSMatthew G. Knepley     Vec         fv  = v;
280d1df6f1dSMatthew G. Knepley     IS          fis;
281d1df6f1dSMatthew G. Knepley     char        prefix[PETSC_MAX_PATH_LEN];
282d1df6f1dSMatthew G. Knepley     const char *fname;
283d1df6f1dSMatthew G. Knepley 
2849566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldComponents(s, f, &Nc));
2859566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldName(s, f, &fname));
286d1df6f1dSMatthew G. Knepley 
2879566063dSJacob Faibussowitsch     if (v->hdr.prefix) PetscCall(PetscStrncpy(prefix, v->hdr.prefix, sizeof(prefix)));
288ad540459SPierre Jolivet     else prefix[0] = '\0';
289d1df6f1dSMatthew G. Knepley     if (Nf > 1) {
2909566063dSJacob Faibussowitsch       PetscCall(DMCreateSubDM(dm, 1, &f, &fis, &fdm));
2919566063dSJacob Faibussowitsch       PetscCall(VecGetSubVector(v, fis, &fv));
2929566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(prefix, fname, sizeof(prefix)));
2939566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(prefix, "_", sizeof(prefix)));
294d1df6f1dSMatthew G. Knepley     }
295d1df6f1dSMatthew G. Knepley     for (comp = 0; comp < Nc; ++comp, ++w) {
296d1df6f1dSMatthew G. Knepley       PetscInt nmax = 2;
297d1df6f1dSMatthew G. Knepley 
2989566063dSJacob Faibussowitsch       PetscCall(PetscViewerDrawGetDraw(viewer, w, &draw));
29963a3b9bcSJacob Faibussowitsch       if (Nc > 1) PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s_%" PetscInt_FMT " Step: %" PetscInt_FMT " Time: %.4g", name, fname, comp, step, (double)time));
30063a3b9bcSJacob Faibussowitsch       else PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s Step: %" PetscInt_FMT " Time: %.4g", name, fname, step, (double)time));
3019566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetTitle(draw, title));
302d1df6f1dSMatthew G. Knepley 
303d1df6f1dSMatthew G. Knepley       /* TODO Get max and min only for this component */
3049566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetRealArray(NULL, prefix, "-vec_view_bounds", vbound, &nmax, &flg));
305339e3443SMatthew G. Knepley       if (!flg) {
3069566063dSJacob Faibussowitsch         PetscCall(VecMin(fv, NULL, &vbound[0]));
3079566063dSJacob Faibussowitsch         PetscCall(VecMax(fv, NULL, &vbound[1]));
308d1df6f1dSMatthew G. Knepley         if (vbound[1] <= vbound[0]) vbound[1] = vbound[0] + 1.0;
309339e3443SMatthew G. Knepley       }
3109566063dSJacob Faibussowitsch       PetscCall(PetscDrawGetPopup(draw, &popup));
3119566063dSJacob Faibussowitsch       PetscCall(PetscDrawScalePopup(popup, vbound[0], vbound[1]));
3129566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetCoordinates(draw, bound[0], bound[1], bound[2], bound[3]));
313e412dcbdSMatthew G. Knepley 
3149566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(fv, &array));
315e412dcbdSMatthew G. Knepley       for (c = cStart; c < cEnd; ++c) {
31699a2f7bcSMatthew G. Knepley         PetscScalar *coords = NULL, *a   = NULL;
317e56f9228SJed Brown         PetscInt     numCoords, color[4] = {-1, -1, -1, -1};
318e412dcbdSMatthew G. Knepley 
3199566063dSJacob Faibussowitsch         PetscCall(DMPlexPointLocalRead(fdm, c, array, &a));
320339e3443SMatthew G. Knepley         if (a) {
321d1df6f1dSMatthew G. Knepley           color[0] = PetscDrawRealToColor(PetscRealPart(a[comp]), vbound[0], vbound[1]);
322339e3443SMatthew G. Knepley           color[1] = color[2] = color[3] = color[0];
323339e3443SMatthew G. Knepley         } else {
324339e3443SMatthew G. Knepley           PetscScalar *vals = NULL;
325339e3443SMatthew G. Knepley           PetscInt     numVals, va;
326339e3443SMatthew G. Knepley 
3279566063dSJacob Faibussowitsch           PetscCall(DMPlexVecGetClosure(fdm, NULL, fv, c, &numVals, &vals));
32863a3b9bcSJacob 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);
329d1df6f1dSMatthew G. Knepley           switch (numVals / Nc) {
330d1df6f1dSMatthew G. Knepley           case 3: /* P1 Triangle */
331d1df6f1dSMatthew G. Knepley           case 4: /* P1 Quadrangle */
332d1df6f1dSMatthew G. Knepley             for (va = 0; va < numVals / Nc; ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va * Nc + comp]), vbound[0], vbound[1]);
333339e3443SMatthew G. Knepley             break;
334d1df6f1dSMatthew G. Knepley           case 6: /* P2 Triangle */
335d1df6f1dSMatthew G. Knepley           case 8: /* P2 Quadrangle */
336d1df6f1dSMatthew 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]);
337d1df6f1dSMatthew G. Knepley             break;
33863a3b9bcSJacob Faibussowitsch           default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of values for cell closure %" PetscInt_FMT " cannot be handled", numVals / Nc);
339339e3443SMatthew G. Knepley           }
3409566063dSJacob Faibussowitsch           PetscCall(DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals));
341339e3443SMatthew G. Knepley         }
3429566063dSJacob Faibussowitsch         PetscCall(DMPlexVecGetClosure(dm, coordSection, coordinates, c, &numCoords, &coords));
343e412dcbdSMatthew G. Knepley         switch (numCoords) {
344e412dcbdSMatthew G. Knepley         case 6:
3459edc3542SMatthew Knepley         case 12: /* Localized triangle */
3469566063dSJacob 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]));
347e412dcbdSMatthew G. Knepley           break;
348e412dcbdSMatthew G. Knepley         case 8:
3499edc3542SMatthew Knepley         case 16: /* Localized quadrilateral */
3509566063dSJacob 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]));
3519566063dSJacob 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]));
352e412dcbdSMatthew G. Knepley           break;
35363a3b9bcSJacob Faibussowitsch         default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %" PetscInt_FMT " coordinates", numCoords);
354e412dcbdSMatthew G. Knepley         }
3559566063dSJacob Faibussowitsch         PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords));
356e412dcbdSMatthew G. Knepley       }
3579566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(fv, &array));
3589566063dSJacob Faibussowitsch       PetscCall(PetscDrawFlush(draw));
3599566063dSJacob Faibussowitsch       PetscCall(PetscDrawPause(draw));
3609566063dSJacob Faibussowitsch       PetscCall(PetscDrawSave(draw));
361d1df6f1dSMatthew G. Knepley     }
362d1df6f1dSMatthew G. Knepley     if (Nf > 1) {
3639566063dSJacob Faibussowitsch       PetscCall(VecRestoreSubVector(v, fis, &fv));
3649566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&fis));
3659566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&fdm));
366d1df6f1dSMatthew G. Knepley     }
367d1df6f1dSMatthew G. Knepley   }
368e412dcbdSMatthew G. Knepley   PetscFunctionReturn(0);
369e412dcbdSMatthew G. Knepley }
370e412dcbdSMatthew G. Knepley 
3719371c9d4SSatish Balay static PetscErrorCode VecView_Plex_Local_Draw(Vec v, PetscViewer viewer) {
3726913077dSMatthew G. Knepley   DM        dm;
3736913077dSMatthew G. Knepley   PetscDraw draw;
3746913077dSMatthew G. Knepley   PetscInt  dim;
3756913077dSMatthew G. Knepley   PetscBool isnull;
3766913077dSMatthew G. Knepley 
3776913077dSMatthew G. Knepley   PetscFunctionBegin;
3789566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
3799566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
3806913077dSMatthew G. Knepley   if (isnull) PetscFunctionReturn(0);
3816913077dSMatthew G. Knepley 
3829566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
3839566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dim));
3846913077dSMatthew G. Knepley   switch (dim) {
3859566063dSJacob Faibussowitsch   case 1: PetscCall(VecView_Plex_Local_Draw_1D(v, viewer)); break;
3869566063dSJacob Faibussowitsch   case 2: PetscCall(VecView_Plex_Local_Draw_2D(v, viewer)); break;
3875f80ce2aSJacob Faibussowitsch   default: SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT ". Try PETSCVIEWERGLVIS", dim);
3886913077dSMatthew G. Knepley   }
3896913077dSMatthew G. Knepley   PetscFunctionReturn(0);
3906913077dSMatthew G. Knepley }
3916913077dSMatthew G. Knepley 
3929371c9d4SSatish Balay static PetscErrorCode VecView_Plex_Local_VTK(Vec v, PetscViewer viewer) {
393684b87d9SLisandro Dalcin   DM                      dm;
394684b87d9SLisandro Dalcin   Vec                     locv;
395684b87d9SLisandro Dalcin   const char             *name;
396684b87d9SLisandro Dalcin   PetscSection            section;
397684b87d9SLisandro Dalcin   PetscInt                pStart, pEnd;
398e630c359SToby Isaac   PetscInt                numFields;
399684b87d9SLisandro Dalcin   PetscViewerVTKFieldType ft;
400684b87d9SLisandro Dalcin 
401684b87d9SLisandro Dalcin   PetscFunctionBegin;
4029566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
4039566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dm, &locv)); /* VTK viewer requires exclusive ownership of the vector */
4049566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)v, &name));
4059566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)locv, name));
4069566063dSJacob Faibussowitsch   PetscCall(VecCopy(v, locv));
4079566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
4089566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
409e630c359SToby Isaac   if (!numFields) {
4109566063dSJacob Faibussowitsch     PetscCall(DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft));
4119566063dSJacob Faibussowitsch     PetscCall(PetscViewerVTKAddField(viewer, (PetscObject)dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, PETSC_TRUE, (PetscObject)locv));
412e630c359SToby Isaac   } else {
413e630c359SToby Isaac     PetscInt f;
414e630c359SToby Isaac 
415e630c359SToby Isaac     for (f = 0; f < numFields; f++) {
4169566063dSJacob Faibussowitsch       PetscCall(DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft));
417e630c359SToby Isaac       if (ft == PETSC_VTK_INVALID) continue;
4189566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)locv));
4199566063dSJacob Faibussowitsch       PetscCall(PetscViewerVTKAddField(viewer, (PetscObject)dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE, (PetscObject)locv));
420e630c359SToby Isaac     }
4219566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&locv));
422e630c359SToby Isaac   }
423684b87d9SLisandro Dalcin   PetscFunctionReturn(0);
424684b87d9SLisandro Dalcin }
425684b87d9SLisandro Dalcin 
4269371c9d4SSatish Balay PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) {
427552f7358SJed Brown   DM        dm;
4285f34f2dcSJed Brown   PetscBool isvtk, ishdf5, isdraw, isglvis, iscgns;
429552f7358SJed Brown 
430552f7358SJed Brown   PetscFunctionBegin;
4319566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
43228b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
4339566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
4349566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
4359566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
4369566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis));
4375f34f2dcSJed Brown   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns));
4385f34f2dcSJed Brown   if (isvtk || ishdf5 || isdraw || isglvis || iscgns) {
439684b87d9SLisandro Dalcin     PetscInt    i, numFields;
440684b87d9SLisandro Dalcin     PetscObject fe;
441ef31f671SMatthew G. Knepley     PetscBool   fem  = PETSC_FALSE;
442684b87d9SLisandro Dalcin     Vec         locv = v;
443684b87d9SLisandro Dalcin     const char *name;
444684b87d9SLisandro Dalcin     PetscInt    step;
445684b87d9SLisandro Dalcin     PetscReal   time;
446ef31f671SMatthew G. Knepley 
4479566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &numFields));
448684b87d9SLisandro Dalcin     for (i = 0; i < numFields; i++) {
4499566063dSJacob Faibussowitsch       PetscCall(DMGetField(dm, i, NULL, &fe));
4509371c9d4SSatish Balay       if (fe->classid == PETSCFE_CLASSID) {
4519371c9d4SSatish Balay         fem = PETSC_TRUE;
4529371c9d4SSatish Balay         break;
4539371c9d4SSatish Balay       }
454ef31f671SMatthew G. Knepley     }
455684b87d9SLisandro Dalcin     if (fem) {
456798534f6SMatthew G. Knepley       PetscObject isZero;
457798534f6SMatthew G. Knepley 
4589566063dSJacob Faibussowitsch       PetscCall(DMGetLocalVector(dm, &locv));
4599566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)v, &name));
4609566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)locv, name));
4619566063dSJacob Faibussowitsch       PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero));
4629566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero));
4639566063dSJacob Faibussowitsch       PetscCall(VecCopy(v, locv));
4649566063dSJacob Faibussowitsch       PetscCall(DMGetOutputSequenceNumber(dm, NULL, &time));
4659566063dSJacob Faibussowitsch       PetscCall(DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL));
466ef31f671SMatthew G. Knepley     }
467552f7358SJed Brown     if (isvtk) {
4689566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_VTK(locv, viewer));
469b136c2c9SMatthew G. Knepley     } else if (ishdf5) {
470b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
4719566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_HDF5_Internal(locv, viewer));
472b136c2c9SMatthew G. Knepley #else
473b136c2c9SMatthew G. Knepley       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
474b136c2c9SMatthew G. Knepley #endif
475f13a32a3SMatthew G. Knepley     } else if (isdraw) {
4769566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_Draw(locv, viewer));
477684b87d9SLisandro Dalcin     } else if (isglvis) {
4789566063dSJacob Faibussowitsch       PetscCall(DMGetOutputSequenceNumber(dm, &step, NULL));
4799566063dSJacob Faibussowitsch       PetscCall(PetscViewerGLVisSetSnapId(viewer, step));
4809566063dSJacob Faibussowitsch       PetscCall(VecView_GLVis(locv, viewer));
4815f34f2dcSJed Brown     } else if (iscgns) {
4825f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS)
4835f34f2dcSJed Brown       PetscCall(VecView_Plex_Local_CGNS(locv, viewer));
4845f34f2dcSJed Brown #else
4855f34f2dcSJed Brown       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "CGNS not supported in this build.\nPlease reconfigure using --download-cgns");
4865f34f2dcSJed Brown #endif
487684b87d9SLisandro Dalcin     }
488798534f6SMatthew G. Knepley     if (fem) {
4899566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL));
4909566063dSJacob Faibussowitsch       PetscCall(DMRestoreLocalVector(dm, &locv));
491798534f6SMatthew G. Knepley     }
492552f7358SJed Brown   } else {
493684b87d9SLisandro Dalcin     PetscBool isseq;
494684b87d9SLisandro Dalcin 
4959566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq));
4969566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
4979566063dSJacob Faibussowitsch     else PetscCall(VecView_MPI(v, viewer));
498552f7358SJed Brown   }
499552f7358SJed Brown   PetscFunctionReturn(0);
500552f7358SJed Brown }
501552f7358SJed Brown 
5029371c9d4SSatish Balay PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) {
503552f7358SJed Brown   DM        dm;
5045f34f2dcSJed Brown   PetscBool isvtk, ishdf5, isdraw, isglvis, isexodusii, iscgns;
505552f7358SJed Brown 
506552f7358SJed Brown   PetscFunctionBegin;
5079566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
50828b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
5099566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
5109566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
5119566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
5129566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis));
5135f34f2dcSJed Brown   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns));
5149566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodusii));
5155f34f2dcSJed Brown   if (isvtk || isdraw || isglvis || iscgns) {
516552f7358SJed Brown     Vec         locv;
517798534f6SMatthew G. Knepley     PetscObject isZero;
518552f7358SJed Brown     const char *name;
519552f7358SJed Brown 
5209566063dSJacob Faibussowitsch     PetscCall(DMGetLocalVector(dm, &locv));
5219566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)v, &name));
5229566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)locv, name));
5239566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv));
5249566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv));
5259566063dSJacob Faibussowitsch     PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero));
5269566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero));
5279566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_Local(locv, viewer));
5289566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL));
5299566063dSJacob Faibussowitsch     PetscCall(DMRestoreLocalVector(dm, &locv));
530b136c2c9SMatthew G. Knepley   } else if (ishdf5) {
531b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
5329566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_HDF5_Internal(v, viewer));
533b136c2c9SMatthew G. Knepley #else
534b136c2c9SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
535b136c2c9SMatthew G. Knepley #endif
5366823f3c5SBlaise Bourdin   } else if (isexodusii) {
5376823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII)
5389566063dSJacob Faibussowitsch     PetscCall(VecView_PlexExodusII_Internal(v, viewer));
5396823f3c5SBlaise Bourdin #else
5406823f3c5SBlaise Bourdin     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii");
5416823f3c5SBlaise Bourdin #endif
542552f7358SJed Brown   } else {
543684b87d9SLisandro Dalcin     PetscBool isseq;
544684b87d9SLisandro Dalcin 
5459566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq));
5469566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
5479566063dSJacob Faibussowitsch     else PetscCall(VecView_MPI(v, viewer));
548552f7358SJed Brown   }
549552f7358SJed Brown   PetscFunctionReturn(0);
550552f7358SJed Brown }
551552f7358SJed Brown 
5529371c9d4SSatish Balay PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer) {
553d930f514SMatthew G. Knepley   DM                dm;
554d930f514SMatthew G. Knepley   MPI_Comm          comm;
555d930f514SMatthew G. Knepley   PetscViewerFormat format;
556d930f514SMatthew G. Knepley   Vec               v;
557d930f514SMatthew G. Knepley   PetscBool         isvtk, ishdf5;
558d930f514SMatthew G. Knepley 
559d930f514SMatthew G. Knepley   PetscFunctionBegin;
5609566063dSJacob Faibussowitsch   PetscCall(VecGetDM(originalv, &dm));
5619566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)originalv, &comm));
56228b400f6SJacob Faibussowitsch   PetscCheck(dm, comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
5639566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
5649566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
5659566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
566d930f514SMatthew G. Knepley   if (format == PETSC_VIEWER_NATIVE) {
567a8ad634aSStefano Zampini     /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */
568a8ad634aSStefano Zampini     /* this need a better fix */
569a8ad634aSStefano Zampini     if (dm->useNatural) {
570a8ad634aSStefano Zampini       if (dm->sfNatural) {
571d930f514SMatthew G. Knepley         const char *vecname;
572d930f514SMatthew G. Knepley         PetscInt    n, nroots;
573d930f514SMatthew G. Knepley 
5749566063dSJacob Faibussowitsch         PetscCall(VecGetLocalSize(originalv, &n));
5759566063dSJacob Faibussowitsch         PetscCall(PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL));
576d930f514SMatthew G. Knepley         if (n == nroots) {
5779566063dSJacob Faibussowitsch           PetscCall(DMGetGlobalVector(dm, &v));
5789566063dSJacob Faibussowitsch           PetscCall(DMPlexGlobalToNaturalBegin(dm, originalv, v));
5799566063dSJacob Faibussowitsch           PetscCall(DMPlexGlobalToNaturalEnd(dm, originalv, v));
5809566063dSJacob Faibussowitsch           PetscCall(PetscObjectGetName((PetscObject)originalv, &vecname));
5819566063dSJacob Faibussowitsch           PetscCall(PetscObjectSetName((PetscObject)v, vecname));
582d930f514SMatthew G. Knepley         } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors");
583d930f514SMatthew G. Knepley       } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created");
584a8ad634aSStefano Zampini     } else v = originalv;
585a8ad634aSStefano Zampini   } else v = originalv;
586a8ad634aSStefano Zampini 
587d930f514SMatthew G. Knepley   if (ishdf5) {
588d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
5899566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_HDF5_Native_Internal(v, viewer));
590d930f514SMatthew G. Knepley #else
591d930f514SMatthew G. Knepley     SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
592d930f514SMatthew G. Knepley #endif
593d930f514SMatthew G. Knepley   } else if (isvtk) {
594d930f514SMatthew G. Knepley     SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5.");
595d930f514SMatthew G. Knepley   } else {
596d930f514SMatthew G. Knepley     PetscBool isseq;
597d930f514SMatthew G. Knepley 
5989566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq));
5999566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
6009566063dSJacob Faibussowitsch     else PetscCall(VecView_MPI(v, viewer));
601d930f514SMatthew G. Knepley   }
6029566063dSJacob Faibussowitsch   if (v != originalv) PetscCall(DMRestoreGlobalVector(dm, &v));
603d930f514SMatthew G. Knepley   PetscFunctionReturn(0);
604d930f514SMatthew G. Knepley }
605d930f514SMatthew G. Knepley 
6069371c9d4SSatish Balay PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer) {
6072c40f234SMatthew G. Knepley   DM        dm;
6082c40f234SMatthew G. Knepley   PetscBool ishdf5;
6092c40f234SMatthew G. Knepley 
6102c40f234SMatthew G. Knepley   PetscFunctionBegin;
6119566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
61228b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
6139566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
6142c40f234SMatthew G. Knepley   if (ishdf5) {
6152c40f234SMatthew G. Knepley     DM          dmBC;
6162c40f234SMatthew G. Knepley     Vec         gv;
6172c40f234SMatthew G. Knepley     const char *name;
6182c40f234SMatthew G. Knepley 
6199566063dSJacob Faibussowitsch     PetscCall(DMGetOutputDM(dm, &dmBC));
6209566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalVector(dmBC, &gv));
6219566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)v, &name));
6229566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)gv, name));
6239566063dSJacob Faibussowitsch     PetscCall(VecLoad_Default(gv, viewer));
6249566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v));
6259566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v));
6269566063dSJacob Faibussowitsch     PetscCall(DMRestoreGlobalVector(dmBC, &gv));
6271baa6e33SBarry Smith   } else PetscCall(VecLoad_Default(v, viewer));
6282c40f234SMatthew G. Knepley   PetscFunctionReturn(0);
6292c40f234SMatthew G. Knepley }
6302c40f234SMatthew G. Knepley 
6319371c9d4SSatish Balay PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer) {
6322c40f234SMatthew G. Knepley   DM        dm;
6336823f3c5SBlaise Bourdin   PetscBool ishdf5, isexodusii;
6342c40f234SMatthew G. Knepley 
6352c40f234SMatthew G. Knepley   PetscFunctionBegin;
6369566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
63728b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
6389566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
6399566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodusii));
6402c40f234SMatthew G. Knepley   if (ishdf5) {
641878b459fSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
6429566063dSJacob Faibussowitsch     PetscCall(VecLoad_Plex_HDF5_Internal(v, viewer));
643b136c2c9SMatthew G. Knepley #else
644b136c2c9SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
645878b459fSMatthew G. Knepley #endif
6466823f3c5SBlaise Bourdin   } else if (isexodusii) {
6476823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII)
6489566063dSJacob Faibussowitsch     PetscCall(VecLoad_PlexExodusII_Internal(v, viewer));
6496823f3c5SBlaise Bourdin #else
6506823f3c5SBlaise Bourdin     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii");
6516823f3c5SBlaise Bourdin #endif
6521baa6e33SBarry Smith   } else PetscCall(VecLoad_Default(v, viewer));
653552f7358SJed Brown   PetscFunctionReturn(0);
654552f7358SJed Brown }
655552f7358SJed Brown 
6569371c9d4SSatish Balay PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer) {
657d930f514SMatthew G. Knepley   DM                dm;
658d930f514SMatthew G. Knepley   PetscViewerFormat format;
659d930f514SMatthew G. Knepley   PetscBool         ishdf5;
660d930f514SMatthew G. Knepley 
661d930f514SMatthew G. Knepley   PetscFunctionBegin;
6629566063dSJacob Faibussowitsch   PetscCall(VecGetDM(originalv, &dm));
66328b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
6649566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
6659566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
666d930f514SMatthew G. Knepley   if (format == PETSC_VIEWER_NATIVE) {
667a8ad634aSStefano Zampini     if (dm->useNatural) {
668d930f514SMatthew G. Knepley       if (dm->sfNatural) {
669d930f514SMatthew G. Knepley         if (ishdf5) {
670d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
671d930f514SMatthew G. Knepley           Vec         v;
672d930f514SMatthew G. Knepley           const char *vecname;
673d930f514SMatthew G. Knepley 
6749566063dSJacob Faibussowitsch           PetscCall(DMGetGlobalVector(dm, &v));
6759566063dSJacob Faibussowitsch           PetscCall(PetscObjectGetName((PetscObject)originalv, &vecname));
6769566063dSJacob Faibussowitsch           PetscCall(PetscObjectSetName((PetscObject)v, vecname));
6779566063dSJacob Faibussowitsch           PetscCall(VecLoad_Plex_HDF5_Native_Internal(v, viewer));
6789566063dSJacob Faibussowitsch           PetscCall(DMPlexNaturalToGlobalBegin(dm, v, originalv));
6799566063dSJacob Faibussowitsch           PetscCall(DMPlexNaturalToGlobalEnd(dm, v, originalv));
6809566063dSJacob Faibussowitsch           PetscCall(DMRestoreGlobalVector(dm, &v));
681d930f514SMatthew G. Knepley #else
682d930f514SMatthew G. Knepley           SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
683d930f514SMatthew G. Knepley #endif
684d930f514SMatthew G. Knepley         } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5.");
685d930f514SMatthew G. Knepley       }
6861baa6e33SBarry Smith     } else PetscCall(VecLoad_Default(originalv, viewer));
687d930f514SMatthew G. Knepley   }
688d930f514SMatthew G. Knepley   PetscFunctionReturn(0);
689d930f514SMatthew G. Knepley }
690d930f514SMatthew G. Knepley 
6919371c9d4SSatish Balay PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer) {
692731e8ddeSMatthew G. Knepley   PetscSection       coordSection;
693731e8ddeSMatthew G. Knepley   Vec                coordinates;
694ba2698f1SMatthew G. Knepley   DMLabel            depthLabel, celltypeLabel;
695731e8ddeSMatthew G. Knepley   const char        *name[4];
696731e8ddeSMatthew G. Knepley   const PetscScalar *a;
697731e8ddeSMatthew G. Knepley   PetscInt           dim, pStart, pEnd, cStart, cEnd, c;
698731e8ddeSMatthew G. Knepley 
699731e8ddeSMatthew G. Knepley   PetscFunctionBegin;
7009566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
7019566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
7029566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
7039566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
7049566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &celltypeLabel));
7059566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
7069566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(coordSection, &pStart, &pEnd));
7079566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(coordinates, &a));
708731e8ddeSMatthew G. Knepley   name[0]       = "vertex";
709731e8ddeSMatthew G. Knepley   name[1]       = "edge";
710731e8ddeSMatthew G. Knepley   name[dim - 1] = "face";
711731e8ddeSMatthew G. Knepley   name[dim]     = "cell";
712731e8ddeSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
713731e8ddeSMatthew G. Knepley     PetscInt *closure = NULL;
714ba2698f1SMatthew G. Knepley     PetscInt  closureSize, cl, ct;
715731e8ddeSMatthew G. Knepley 
7169566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(celltypeLabel, c, &ct));
71763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Geometry for cell %" PetscInt_FMT " polytope type %s:\n", c, DMPolytopeTypes[ct]));
7189566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
7199566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
720731e8ddeSMatthew G. Knepley     for (cl = 0; cl < closureSize * 2; cl += 2) {
721731e8ddeSMatthew G. Knepley       PetscInt point = closure[cl], depth, dof, off, d, p;
722731e8ddeSMatthew G. Knepley 
723731e8ddeSMatthew G. Knepley       if ((point < pStart) || (point >= pEnd)) continue;
7249566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(coordSection, point, &dof));
725731e8ddeSMatthew G. Knepley       if (!dof) continue;
7269566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(depthLabel, point, &depth));
7279566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, point, &off));
72863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s %" PetscInt_FMT " coords:", name[depth], point));
729731e8ddeSMatthew G. Knepley       for (p = 0; p < dof / dim; ++p) {
7309566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " ("));
731731e8ddeSMatthew G. Knepley         for (d = 0; d < dim; ++d) {
7329566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
7339566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "%g", (double)PetscRealPart(a[off + p * dim + d])));
734731e8ddeSMatthew G. Knepley         }
7359566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, ")"));
736731e8ddeSMatthew G. Knepley       }
7379566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
738731e8ddeSMatthew G. Knepley     }
7399566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
7409566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
741731e8ddeSMatthew G. Knepley   }
7429566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(coordinates, &a));
743731e8ddeSMatthew G. Knepley   PetscFunctionReturn(0);
744731e8ddeSMatthew G. Knepley }
745731e8ddeSMatthew G. Knepley 
7469371c9d4SSatish Balay typedef enum {
7479371c9d4SSatish Balay   CS_CARTESIAN,
7489371c9d4SSatish Balay   CS_POLAR,
7499371c9d4SSatish Balay   CS_CYLINDRICAL,
7509371c9d4SSatish Balay   CS_SPHERICAL
7519371c9d4SSatish Balay } CoordSystem;
75219ad8254SMatthew G. Knepley const char *CoordSystems[] = {"cartesian", "polar", "cylindrical", "spherical", "CoordSystem", "CS_", NULL};
75319ad8254SMatthew G. Knepley 
7549371c9d4SSatish Balay static PetscErrorCode DMPlexView_Ascii_Coordinates(PetscViewer viewer, CoordSystem cs, PetscInt dim, const PetscScalar x[]) {
75519ad8254SMatthew G. Knepley   PetscInt i;
75619ad8254SMatthew G. Knepley 
75719ad8254SMatthew G. Knepley   PetscFunctionBegin;
75819ad8254SMatthew G. Knepley   if (dim > 3) {
7599566063dSJacob Faibussowitsch     for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)PetscRealPart(x[i])));
76019ad8254SMatthew G. Knepley   } else {
761bd83fdcbSStefano Zampini     PetscReal coords[3], trcoords[3] = {0., 0., 0.};
76219ad8254SMatthew G. Knepley 
76319ad8254SMatthew G. Knepley     for (i = 0; i < dim; ++i) coords[i] = PetscRealPart(x[i]);
76419ad8254SMatthew G. Knepley     switch (cs) {
7659371c9d4SSatish Balay     case CS_CARTESIAN:
7669371c9d4SSatish Balay       for (i = 0; i < dim; ++i) trcoords[i] = coords[i];
7679371c9d4SSatish Balay       break;
76819ad8254SMatthew G. Knepley     case CS_POLAR:
76963a3b9bcSJacob Faibussowitsch       PetscCheck(dim == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Polar coordinates are for 2 dimension, not %" PetscInt_FMT, dim);
77019ad8254SMatthew G. Knepley       trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]));
77119ad8254SMatthew G. Knepley       trcoords[1] = PetscAtan2Real(coords[1], coords[0]);
77219ad8254SMatthew G. Knepley       break;
77319ad8254SMatthew G. Knepley     case CS_CYLINDRICAL:
77463a3b9bcSJacob Faibussowitsch       PetscCheck(dim == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cylindrical coordinates are for 3 dimension, not %" PetscInt_FMT, dim);
77519ad8254SMatthew G. Knepley       trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]));
77619ad8254SMatthew G. Knepley       trcoords[1] = PetscAtan2Real(coords[1], coords[0]);
77719ad8254SMatthew G. Knepley       trcoords[2] = coords[2];
77819ad8254SMatthew G. Knepley       break;
77919ad8254SMatthew G. Knepley     case CS_SPHERICAL:
78063a3b9bcSJacob Faibussowitsch       PetscCheck(dim == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Spherical coordinates are for 3 dimension, not %" PetscInt_FMT, dim);
78119ad8254SMatthew G. Knepley       trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]) + PetscSqr(coords[2]));
78219ad8254SMatthew G. Knepley       trcoords[1] = PetscAtan2Real(PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])), coords[2]);
78319ad8254SMatthew G. Knepley       trcoords[2] = PetscAtan2Real(coords[1], coords[0]);
78419ad8254SMatthew G. Knepley       break;
78519ad8254SMatthew G. Knepley     }
7869566063dSJacob Faibussowitsch     for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)trcoords[i]));
78719ad8254SMatthew G. Knepley   }
78819ad8254SMatthew G. Knepley   PetscFunctionReturn(0);
78919ad8254SMatthew G. Knepley }
79019ad8254SMatthew G. Knepley 
7919371c9d4SSatish Balay static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) {
792552f7358SJed Brown   DM_Plex          *mesh = (DM_Plex *)dm->data;
7936858538eSMatthew G. Knepley   DM                cdm, cdmCell;
7946858538eSMatthew G. Knepley   PetscSection      coordSection, coordSectionCell;
7956858538eSMatthew G. Knepley   Vec               coordinates, coordinatesCell;
796552f7358SJed Brown   PetscViewerFormat format;
797552f7358SJed Brown 
798552f7358SJed Brown   PetscFunctionBegin;
7999566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
8006858538eSMatthew G. Knepley   PetscCall(DMGetCoordinateSection(dm, &coordSection));
8019566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
8026858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dm, &cdmCell));
8036858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell));
8046858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell));
8059566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
806552f7358SJed Brown   if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
807552f7358SJed Brown     const char *name;
808f73eea6eSMatthew G. Knepley     PetscInt    dim, cellHeight, maxConeSize, maxSupportSize;
8099318fe57SMatthew G. Knepley     PetscInt    pStart, pEnd, p, numLabels, l;
810552f7358SJed Brown     PetscMPIInt rank, size;
811552f7358SJed Brown 
8129566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
8139566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
8149566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
8159566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
8169566063dSJacob Faibussowitsch     PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
8179566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
8189566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
81963a3b9bcSJacob Faibussowitsch     if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s"));
82063a3b9bcSJacob Faibussowitsch     else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s"));
82163a3b9bcSJacob Faibussowitsch     if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, "  Cells are at height %" PetscInt_FMT "\n", cellHeight));
82263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Supports:\n"));
8239566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
82463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %" PetscInt_FMT "\n", rank, maxSupportSize));
825552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
826552f7358SJed Brown       PetscInt dof, off, s;
827552f7358SJed Brown 
8289566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
8299566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
83048a46eb9SPierre Jolivet       for (s = off; s < off + dof; ++s) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " ----> %" PetscInt_FMT "\n", rank, p, mesh->supports[s]));
831552f7358SJed Brown     }
8329566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
83363a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Cones:\n"));
83463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %" PetscInt_FMT "\n", rank, maxConeSize));
835552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
836552f7358SJed Brown       PetscInt dof, off, c;
837552f7358SJed Brown 
8389566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
8399566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
84048a46eb9SPierre Jolivet       for (c = off; c < off + dof; ++c) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " <---- %" PetscInt_FMT " (%" PetscInt_FMT ")\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]));
841552f7358SJed Brown     }
8429566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
8439566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
8443d2e540fSStefano Zampini     if (coordSection && coordinates) {
84519ad8254SMatthew G. Knepley       CoordSystem        cs = CS_CARTESIAN;
8466858538eSMatthew G. Knepley       const PetscScalar *array, *arrayCell = NULL;
8476858538eSMatthew G. Knepley       PetscInt           Nf, Nc, pvStart, pvEnd, pcStart = PETSC_MAX_INT, pcEnd = PETSC_MIN_INT, pStart, pEnd, p;
84819ad8254SMatthew G. Knepley       PetscMPIInt        rank;
84919ad8254SMatthew G. Knepley       const char        *name;
85019ad8254SMatthew G. Knepley 
8519566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetEnum(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_coord_system", CoordSystems, (PetscEnum *)&cs, NULL));
8529566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
8539566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetNumFields(coordSection, &Nf));
85463a3b9bcSJacob Faibussowitsch       PetscCheck(Nf == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate section should have 1 field, not %" PetscInt_FMT, Nf);
8559566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldComponents(coordSection, 0, &Nc));
8566858538eSMatthew G. Knepley       PetscCall(PetscSectionGetChart(coordSection, &pvStart, &pvEnd));
8576858538eSMatthew G. Knepley       if (coordSectionCell) PetscCall(PetscSectionGetChart(coordSectionCell, &pcStart, &pcEnd));
8586858538eSMatthew G. Knepley       pStart = PetscMin(pvStart, pcStart);
8596858538eSMatthew G. Knepley       pEnd   = PetscMax(pvEnd, pcEnd);
8609566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)coordinates, &name));
86163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s with %" PetscInt_FMT " fields\n", name, Nf));
86263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  field 0 with %" PetscInt_FMT " components\n", Nc));
8639566063dSJacob Faibussowitsch       if (cs != CS_CARTESIAN) PetscCall(PetscViewerASCIIPrintf(viewer, "  output coordinate system: %s\n", CoordSystems[cs]));
86419ad8254SMatthew G. Knepley 
8659566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(coordinates, &array));
8666858538eSMatthew G. Knepley       if (coordinatesCell) PetscCall(VecGetArrayRead(coordinatesCell, &arrayCell));
8679566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushSynchronized(viewer));
8689566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank));
86919ad8254SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
87019ad8254SMatthew G. Knepley         PetscInt dof, off;
87119ad8254SMatthew G. Knepley 
8726858538eSMatthew G. Knepley         if (p >= pvStart && p < pvEnd) {
8739566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(coordSection, p, &dof));
8749566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(coordSection, p, &off));
8756858538eSMatthew G. Knepley           if (dof) {
87663a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "  (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off));
8779566063dSJacob Faibussowitsch             PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &array[off]));
8789566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
87919ad8254SMatthew G. Knepley           }
8806858538eSMatthew G. Knepley         }
8816858538eSMatthew G. Knepley         if (cdmCell && p >= pcStart && p < pcEnd) {
8826858538eSMatthew G. Knepley           PetscCall(PetscSectionGetDof(coordSectionCell, p, &dof));
8836858538eSMatthew G. Knepley           PetscCall(PetscSectionGetOffset(coordSectionCell, p, &off));
8846858538eSMatthew G. Knepley           if (dof) {
8856858538eSMatthew G. Knepley             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "  (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off));
8866858538eSMatthew G. Knepley             PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &arrayCell[off]));
8876858538eSMatthew G. Knepley             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
8886858538eSMatthew G. Knepley           }
8896858538eSMatthew G. Knepley         }
8906858538eSMatthew G. Knepley       }
8919566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
8929566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopSynchronized(viewer));
8939566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(coordinates, &array));
8946858538eSMatthew G. Knepley       if (coordinatesCell) PetscCall(VecRestoreArrayRead(coordinatesCell, &arrayCell));
8953d2e540fSStefano Zampini     }
8969566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
8979566063dSJacob Faibussowitsch     if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n"));
8989318fe57SMatthew G. Knepley     for (l = 0; l < numLabels; ++l) {
8999318fe57SMatthew G. Knepley       DMLabel     label;
9009318fe57SMatthew G. Knepley       PetscBool   isdepth;
9019318fe57SMatthew G. Knepley       const char *name;
9029318fe57SMatthew G. Knepley 
9039566063dSJacob Faibussowitsch       PetscCall(DMGetLabelName(dm, l, &name));
9049566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "depth", &isdepth));
9059318fe57SMatthew G. Knepley       if (isdepth) continue;
9069566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, name, &label));
9079566063dSJacob Faibussowitsch       PetscCall(DMLabelView(label, viewer));
9089318fe57SMatthew G. Knepley     }
909552f7358SJed Brown     if (size > 1) {
910552f7358SJed Brown       PetscSF sf;
911552f7358SJed Brown 
9129566063dSJacob Faibussowitsch       PetscCall(DMGetPointSF(dm, &sf));
9139566063dSJacob Faibussowitsch       PetscCall(PetscSFView(sf, viewer));
914552f7358SJed Brown     }
9159566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
916552f7358SJed Brown   } else if (format == PETSC_VIEWER_ASCII_LATEX) {
9170588280cSMatthew G. Knepley     const char  *name, *color;
9180588280cSMatthew G. Knepley     const char  *defcolors[3]  = {"gray", "orange", "green"};
9190588280cSMatthew G. Knepley     const char  *deflcolors[4] = {"blue", "cyan", "red", "magenta"};
920fe1cc32dSStefano Zampini     char         lname[PETSC_MAX_PATH_LEN];
921552f7358SJed Brown     PetscReal    scale      = 2.0;
92278081901SStefano Zampini     PetscReal    tikzscale  = 1.0;
923b7f6ffafSMatthew G. Knepley     PetscBool    useNumbers = PETSC_TRUE, drawNumbers[4], drawColors[4], useLabels, useColors, plotEdges, drawHasse = PETSC_FALSE;
9240588280cSMatthew G. Knepley     double       tcoords[3];
925552f7358SJed Brown     PetscScalar *coords;
926b7f6ffafSMatthew G. Knepley     PetscInt     numLabels, l, numColors, numLColors, dim, d, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p, n;
927552f7358SJed Brown     PetscMPIInt  rank, size;
9280588280cSMatthew G. Knepley     char       **names, **colors, **lcolors;
929b7f6ffafSMatthew G. Knepley     PetscBool    flg, lflg;
930fe1cc32dSStefano Zampini     PetscBT      wp = NULL;
931fe1cc32dSStefano Zampini     PetscInt     pEnd, pStart;
932552f7358SJed Brown 
9339566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
9349566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dm, &depth));
9359566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
9360588280cSMatthew G. Knepley     numLabels  = PetscMax(numLabels, 10);
9370588280cSMatthew G. Knepley     numColors  = 10;
9380588280cSMatthew G. Knepley     numLColors = 10;
9399566063dSJacob Faibussowitsch     PetscCall(PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors));
9409566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetReal(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_scale", &scale, NULL));
9419566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetReal(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL));
9429566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL));
943b7f6ffafSMatthew G. Knepley     for (d = 0; d < 4; ++d) drawNumbers[d] = useNumbers;
944b7f6ffafSMatthew G. Knepley     for (d = 0; d < 4; ++d) drawColors[d] = PETSC_TRUE;
945b7f6ffafSMatthew G. Knepley     n = 4;
9469566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_numbers_depth", drawNumbers, &n, &flg));
9471dca8a05SBarry Smith     PetscCheck(!flg || n == dim + 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %" PetscInt_FMT " != %" PetscInt_FMT " dim+1", n, dim + 1);
9489566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors_depth", drawColors, &n, &flg));
9491dca8a05SBarry Smith     PetscCheck(!flg || n == dim + 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Number of flags %" PetscInt_FMT " != %" PetscInt_FMT " dim+1", n, dim + 1);
9509566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels));
9510588280cSMatthew G. Knepley     if (!useLabels) numLabels = 0;
9529566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors));
9530588280cSMatthew G. Knepley     if (!useColors) {
9540588280cSMatthew G. Knepley       numColors = 3;
9559566063dSJacob Faibussowitsch       for (c = 0; c < numColors; ++c) PetscCall(PetscStrallocpy(defcolors[c], &colors[c]));
9560588280cSMatthew G. Knepley     }
9579566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors));
9580588280cSMatthew G. Knepley     if (!useColors) {
9590588280cSMatthew G. Knepley       numLColors = 4;
9609566063dSJacob Faibussowitsch       for (c = 0; c < numLColors; ++c) PetscCall(PetscStrallocpy(deflcolors[c], &lcolors[c]));
9610588280cSMatthew G. Knepley     }
9629566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetString(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg));
963b7f6ffafSMatthew G. Knepley     plotEdges = (PetscBool)(depth > 1 && drawNumbers[1] && dim < 3);
9649566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg));
9651dca8a05SBarry Smith     PetscCheck(!flg || !plotEdges || depth >= dim, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh must be interpolated");
966202fd40aSStefano Zampini     if (depth < dim) plotEdges = PETSC_FALSE;
9679566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_hasse", &drawHasse, NULL));
968fe1cc32dSStefano Zampini 
969fe1cc32dSStefano Zampini     /* filter points with labelvalue != labeldefaultvalue */
9709566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
9719566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
9729566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd));
9739566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
974fe1cc32dSStefano Zampini     if (lflg) {
975fe1cc32dSStefano Zampini       DMLabel lbl;
976fe1cc32dSStefano Zampini 
9779566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, lname, &lbl));
978fe1cc32dSStefano Zampini       if (lbl) {
979fe1cc32dSStefano Zampini         PetscInt val, defval;
980fe1cc32dSStefano Zampini 
9819566063dSJacob Faibussowitsch         PetscCall(DMLabelGetDefaultValue(lbl, &defval));
9829566063dSJacob Faibussowitsch         PetscCall(PetscBTCreate(pEnd - pStart, &wp));
983fe1cc32dSStefano Zampini         for (c = pStart; c < pEnd; c++) {
984fe1cc32dSStefano Zampini           PetscInt *closure = NULL;
985fe1cc32dSStefano Zampini           PetscInt  closureSize;
986fe1cc32dSStefano Zampini 
9879566063dSJacob Faibussowitsch           PetscCall(DMLabelGetValue(lbl, c, &val));
988fe1cc32dSStefano Zampini           if (val == defval) continue;
989fe1cc32dSStefano Zampini 
9909566063dSJacob Faibussowitsch           PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
99148a46eb9SPierre Jolivet           for (p = 0; p < closureSize * 2; p += 2) PetscCall(PetscBTSet(wp, closure[p] - pStart));
9929566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
993fe1cc32dSStefano Zampini         }
994fe1cc32dSStefano Zampini       }
995fe1cc32dSStefano Zampini     }
996fe1cc32dSStefano Zampini 
9979566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
9989566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
9999566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
10009566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\
10010588280cSMatthew G. Knepley \\documentclass[tikz]{standalone}\n\n\
1002552f7358SJed Brown \\usepackage{pgflibraryshapes}\n\
1003552f7358SJed Brown \\usetikzlibrary{backgrounds}\n\
1004552f7358SJed Brown \\usetikzlibrary{arrows}\n\
10055f80ce2aSJacob Faibussowitsch \\begin{document}\n"));
10060588280cSMatthew G. Knepley     if (size > 1) {
10079566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s for process ", name));
1008770b213bSMatthew G Knepley       for (p = 0; p < size; ++p) {
100963a3b9bcSJacob Faibussowitsch         if (p) PetscCall(PetscViewerASCIIPrintf(viewer, (p == size - 1) ? ", and " : ", "));
101063a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%" PetscInt_FMT "}", colors[p % numColors], p));
1011770b213bSMatthew G Knepley       }
10129566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, ".\n\n\n"));
10130588280cSMatthew G. Knepley     }
1014b7f6ffafSMatthew G. Knepley     if (drawHasse) {
1015b7f6ffafSMatthew G. Knepley       PetscInt maxStratum = PetscMax(vEnd - vStart, PetscMax(eEnd - eStart, cEnd - cStart));
1016b7f6ffafSMatthew G. Knepley 
101763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vStart}{%" PetscInt_FMT "}\n", vStart));
101863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vEnd}{%" PetscInt_FMT "}\n", vEnd - 1));
101963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numVertices}{%" PetscInt_FMT "}\n", vEnd - vStart));
10209566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vShift}{%.2f}\n", 3 + (maxStratum - (vEnd - vStart)) / 2.));
102163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eStart}{%" PetscInt_FMT "}\n", eStart));
102263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eEnd}{%" PetscInt_FMT "}\n", eEnd - 1));
10239566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eShift}{%.2f}\n", 3 + (maxStratum - (eEnd - eStart)) / 2.));
102463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numEdges}{%" PetscInt_FMT "}\n", eEnd - eStart));
102563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cStart}{%" PetscInt_FMT "}\n", cStart));
102663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cEnd}{%" PetscInt_FMT "}\n", cEnd - 1));
102763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numCells}{%" PetscInt_FMT "}\n", cEnd - cStart));
10289566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cShift}{%.2f}\n", 3 + (maxStratum - (cEnd - cStart)) / 2.));
1029b7f6ffafSMatthew G. Knepley     }
10309566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double)tikzscale));
1031fe1cc32dSStefano Zampini 
1032552f7358SJed Brown     /* Plot vertices */
10339566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
10349566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
1035552f7358SJed Brown     for (v = vStart; v < vEnd; ++v) {
1036552f7358SJed Brown       PetscInt  off, dof, d;
10370588280cSMatthew G. Knepley       PetscBool isLabeled = PETSC_FALSE;
1038552f7358SJed Brown 
1039fe1cc32dSStefano Zampini       if (wp && !PetscBTLookup(wp, v - pStart)) continue;
10409566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(coordSection, v, &dof));
10419566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, v, &off));
10429566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path ("));
104363a3b9bcSJacob Faibussowitsch       PetscCheck(dof <= 3, PETSC_COMM_SELF, PETSC_ERR_PLIB, "coordSection vertex %" PetscInt_FMT " has dof %" PetscInt_FMT " > 3", v, dof);
10440588280cSMatthew G. Knepley       for (d = 0; d < dof; ++d) {
10450588280cSMatthew G. Knepley         tcoords[d] = (double)(scale * PetscRealPart(coords[off + d]));
1046c068d9bbSLisandro Dalcin         tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
10470588280cSMatthew G. Knepley       }
10480588280cSMatthew G. Knepley       /* Rotate coordinates since PGF makes z point out of the page instead of up */
10499371c9d4SSatish Balay       if (dim == 3) {
10509371c9d4SSatish Balay         PetscReal tmp = tcoords[1];
10519371c9d4SSatish Balay         tcoords[1]    = tcoords[2];
10529371c9d4SSatish Balay         tcoords[2]    = -tmp;
10539371c9d4SSatish Balay       }
1054552f7358SJed Brown       for (d = 0; d < dof; ++d) {
10559566063dSJacob Faibussowitsch         if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
10569566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d]));
1057552f7358SJed Brown       }
1058b7f6ffafSMatthew G. Knepley       if (drawHasse) color = colors[0 % numColors];
1059b7f6ffafSMatthew G. Knepley       else color = colors[rank % numColors];
10600588280cSMatthew G. Knepley       for (l = 0; l < numLabels; ++l) {
10610588280cSMatthew G. Knepley         PetscInt val;
10629566063dSJacob Faibussowitsch         PetscCall(DMGetLabelValue(dm, names[l], v, &val));
10639371c9d4SSatish Balay         if (val >= 0) {
10649371c9d4SSatish Balay           color     = lcolors[l % numLColors];
10659371c9d4SSatish Balay           isLabeled = PETSC_TRUE;
10669371c9d4SSatish Balay           break;
10679371c9d4SSatish Balay         }
10680588280cSMatthew G. Knepley       }
1069b7f6ffafSMatthew G. Knepley       if (drawNumbers[0]) {
107063a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", v, rank, color, v));
1071b7f6ffafSMatthew G. Knepley       } else if (drawColors[0]) {
107263a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color));
10731baa6e33SBarry Smith       } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", v, rank));
1074552f7358SJed Brown     }
10759566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
10769566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
1077b7f6ffafSMatthew G. Knepley     /* Plot edges */
1078b7f6ffafSMatthew G. Knepley     if (plotEdges) {
10799566063dSJacob Faibussowitsch       PetscCall(VecGetArray(coordinates, &coords));
10809566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\path\n"));
1081b7f6ffafSMatthew G. Knepley       for (e = eStart; e < eEnd; ++e) {
1082b7f6ffafSMatthew G. Knepley         const PetscInt *cone;
1083b7f6ffafSMatthew G. Knepley         PetscInt        coneSize, offA, offB, dof, d;
1084b7f6ffafSMatthew G. Knepley 
1085b7f6ffafSMatthew G. Knepley         if (wp && !PetscBTLookup(wp, e - pStart)) continue;
10869566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, e, &coneSize));
108763a3b9bcSJacob Faibussowitsch         PetscCheck(coneSize == 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %" PetscInt_FMT " cone should have two vertices, not %" PetscInt_FMT, e, coneSize);
10889566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, e, &cone));
10899566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(coordSection, cone[0], &dof));
10909566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(coordSection, cone[0], &offA));
10919566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(coordSection, cone[1], &offB));
10929566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "("));
1093b7f6ffafSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
1094b7f6ffafSMatthew G. Knepley           tcoords[d] = (double)(0.5 * scale * PetscRealPart(coords[offA + d] + coords[offB + d]));
1095b7f6ffafSMatthew G. Knepley           tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
1096b7f6ffafSMatthew G. Knepley         }
1097b7f6ffafSMatthew G. Knepley         /* Rotate coordinates since PGF makes z point out of the page instead of up */
10989371c9d4SSatish Balay         if (dim == 3) {
10999371c9d4SSatish Balay           PetscReal tmp = tcoords[1];
11009371c9d4SSatish Balay           tcoords[1]    = tcoords[2];
11019371c9d4SSatish Balay           tcoords[2]    = -tmp;
11029371c9d4SSatish Balay         }
1103b7f6ffafSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
11049566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
11059566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d]));
1106b7f6ffafSMatthew G. Knepley         }
1107b7f6ffafSMatthew G. Knepley         if (drawHasse) color = colors[1 % numColors];
1108b7f6ffafSMatthew G. Knepley         else color = colors[rank % numColors];
1109b7f6ffafSMatthew G. Knepley         for (l = 0; l < numLabels; ++l) {
1110b7f6ffafSMatthew G. Knepley           PetscInt val;
11119566063dSJacob Faibussowitsch           PetscCall(DMGetLabelValue(dm, names[l], v, &val));
11129371c9d4SSatish Balay           if (val >= 0) {
11139371c9d4SSatish Balay             color = lcolors[l % numLColors];
11149371c9d4SSatish Balay             break;
11159371c9d4SSatish Balay           }
1116b7f6ffafSMatthew G. Knepley         }
111763a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "} --\n", e, rank, color, e));
1118b7f6ffafSMatthew G. Knepley       }
11199566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(coordinates, &coords));
11209566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
11219566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "(0,0);\n"));
1122b7f6ffafSMatthew G. Knepley     }
1123846a3e8bSMatthew G. Knepley     /* Plot cells */
1124b7f6ffafSMatthew G. Knepley     if (dim == 3 || !drawNumbers[1]) {
1125846a3e8bSMatthew G. Knepley       for (e = eStart; e < eEnd; ++e) {
1126846a3e8bSMatthew G. Knepley         const PetscInt *cone;
1127846a3e8bSMatthew G. Knepley 
1128fe1cc32dSStefano Zampini         if (wp && !PetscBTLookup(wp, e - pStart)) continue;
1129846a3e8bSMatthew G. Knepley         color = colors[rank % numColors];
1130846a3e8bSMatthew G. Knepley         for (l = 0; l < numLabels; ++l) {
1131846a3e8bSMatthew G. Knepley           PetscInt val;
11329566063dSJacob Faibussowitsch           PetscCall(DMGetLabelValue(dm, names[l], e, &val));
11339371c9d4SSatish Balay           if (val >= 0) {
11349371c9d4SSatish Balay             color = lcolors[l % numLColors];
11359371c9d4SSatish Balay             break;
11369371c9d4SSatish Balay           }
1137846a3e8bSMatthew G. Knepley         }
11389566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, e, &cone));
113963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", color, cone[0], rank, cone[1], rank));
1140846a3e8bSMatthew G. Knepley       }
1141846a3e8bSMatthew G. Knepley     } else {
1142b7f6ffafSMatthew G. Knepley       DMPolytopeType ct;
1143846a3e8bSMatthew G. Knepley 
1144b7f6ffafSMatthew G. Knepley       /* Drawing a 2D polygon */
1145b7f6ffafSMatthew G. Knepley       for (c = cStart; c < cEnd; ++c) {
1146fe1cc32dSStefano Zampini         if (wp && !PetscBTLookup(wp, c - pStart)) continue;
11479566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, c, &ct));
11489371c9d4SSatish Balay         if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || ct == DM_POLYTOPE_TRI_PRISM_TENSOR || ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) {
1149b7f6ffafSMatthew G. Knepley           const PetscInt *cone;
1150b7f6ffafSMatthew G. Knepley           PetscInt        coneSize, e;
1151b7f6ffafSMatthew G. Knepley 
11529566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCone(dm, c, &cone));
11539566063dSJacob Faibussowitsch           PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
1154b7f6ffafSMatthew G. Knepley           for (e = 0; e < coneSize; ++e) {
1155b7f6ffafSMatthew G. Knepley             const PetscInt *econe;
1156b7f6ffafSMatthew G. Knepley 
11579566063dSJacob Faibussowitsch             PetscCall(DMPlexGetCone(dm, cone[e], &econe));
115863a3b9bcSJacob 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));
1159b7f6ffafSMatthew G. Knepley           }
1160b7f6ffafSMatthew G. Knepley         } else {
1161b7f6ffafSMatthew G. Knepley           PetscInt *closure = NULL;
1162b7f6ffafSMatthew G. Knepley           PetscInt  closureSize, Nv = 0, v;
1163b7f6ffafSMatthew G. Knepley 
11649566063dSJacob Faibussowitsch           PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1165846a3e8bSMatthew G. Knepley           for (p = 0; p < closureSize * 2; p += 2) {
1166846a3e8bSMatthew G. Knepley             const PetscInt point = closure[p];
1167846a3e8bSMatthew G. Knepley 
1168b7f6ffafSMatthew G. Knepley             if ((point >= vStart) && (point < vEnd)) closure[Nv++] = point;
1169846a3e8bSMatthew G. Knepley           }
11709566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank % numColors]));
1171b7f6ffafSMatthew G. Knepley           for (v = 0; v <= Nv; ++v) {
1172b7f6ffafSMatthew G. Knepley             const PetscInt vertex = closure[v % Nv];
1173b7f6ffafSMatthew G. Knepley 
1174b7f6ffafSMatthew G. Knepley             if (v > 0) {
1175b7f6ffafSMatthew G. Knepley               if (plotEdges) {
1176b7f6ffafSMatthew G. Knepley                 const PetscInt *edge;
1177b7f6ffafSMatthew G. Knepley                 PetscInt        endpoints[2], ne;
1178b7f6ffafSMatthew G. Knepley 
11799371c9d4SSatish Balay                 endpoints[0] = closure[v - 1];
11809371c9d4SSatish Balay                 endpoints[1] = vertex;
11819566063dSJacob Faibussowitsch                 PetscCall(DMPlexGetJoin(dm, 2, endpoints, &ne, &edge));
118263a3b9bcSJacob Faibussowitsch                 PetscCheck(ne == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find edge for vertices %" PetscInt_FMT ", %" PetscInt_FMT, endpoints[0], endpoints[1]);
118363a3b9bcSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- (%" PetscInt_FMT "_%d) -- ", edge[0], rank));
11849566063dSJacob Faibussowitsch                 PetscCall(DMPlexRestoreJoin(dm, 2, endpoints, &ne, &edge));
11851baa6e33SBarry Smith               } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- "));
1186b7f6ffafSMatthew G. Knepley             }
118763a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(%" PetscInt_FMT "_%d)", vertex, rank));
1188b7f6ffafSMatthew G. Knepley           }
11899566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ";\n"));
11909566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1191846a3e8bSMatthew G. Knepley         }
1192846a3e8bSMatthew G. Knepley       }
1193b7f6ffafSMatthew G. Knepley     }
1194846a3e8bSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
1195846a3e8bSMatthew G. Knepley       double             ccoords[3] = {0.0, 0.0, 0.0};
1196846a3e8bSMatthew G. Knepley       PetscBool          isLabeled  = PETSC_FALSE;
1197c713ec31SMatthew G. Knepley       PetscScalar       *cellCoords = NULL;
1198c713ec31SMatthew G. Knepley       const PetscScalar *array;
1199c713ec31SMatthew G. Knepley       PetscInt           numCoords, cdim, d;
1200c713ec31SMatthew G. Knepley       PetscBool          isDG;
1201846a3e8bSMatthew G. Knepley 
1202fe1cc32dSStefano Zampini       if (wp && !PetscBTLookup(wp, c - pStart)) continue;
1203c713ec31SMatthew G. Knepley       PetscCall(DMGetCoordinateDim(dm, &cdim));
1204c713ec31SMatthew G. Knepley       PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords));
1205c713ec31SMatthew G. Knepley       PetscCheck(!(numCoords % cdim), PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "coordinate dim %" PetscInt_FMT " does not divide numCoords %" PetscInt_FMT, cdim, numCoords);
12069566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path ("));
1207c713ec31SMatthew G. Knepley       for (p = 0; p < numCoords / cdim; ++p) {
1208c713ec31SMatthew G. Knepley         for (d = 0; d < cdim; ++d) {
1209c713ec31SMatthew G. Knepley           tcoords[d] = (double)(scale * PetscRealPart(cellCoords[p * cdim + d]));
1210846a3e8bSMatthew G. Knepley           tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
1211846a3e8bSMatthew G. Knepley         }
1212846a3e8bSMatthew G. Knepley         /* Rotate coordinates since PGF makes z point out of the page instead of up */
12139371c9d4SSatish Balay         if (cdim == 3) {
12149371c9d4SSatish Balay           PetscReal tmp = tcoords[1];
12159371c9d4SSatish Balay           tcoords[1]    = tcoords[2];
12169371c9d4SSatish Balay           tcoords[2]    = -tmp;
12179371c9d4SSatish Balay         }
1218ad540459SPierre Jolivet         for (d = 0; d < dim; ++d) ccoords[d] += tcoords[d];
1219846a3e8bSMatthew G. Knepley       }
1220ad540459SPierre Jolivet       for (d = 0; d < cdim; ++d) ccoords[d] /= (numCoords / cdim);
1221c713ec31SMatthew G. Knepley       PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords));
1222c713ec31SMatthew G. Knepley       for (d = 0; d < cdim; ++d) {
12239566063dSJacob Faibussowitsch         if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
12249566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)ccoords[d]));
1225846a3e8bSMatthew G. Knepley       }
1226b7f6ffafSMatthew G. Knepley       if (drawHasse) color = colors[depth % numColors];
1227b7f6ffafSMatthew G. Knepley       else color = colors[rank % numColors];
1228846a3e8bSMatthew G. Knepley       for (l = 0; l < numLabels; ++l) {
1229846a3e8bSMatthew G. Knepley         PetscInt val;
12309566063dSJacob Faibussowitsch         PetscCall(DMGetLabelValue(dm, names[l], c, &val));
12319371c9d4SSatish Balay         if (val >= 0) {
12329371c9d4SSatish Balay           color     = lcolors[l % numLColors];
12339371c9d4SSatish Balay           isLabeled = PETSC_TRUE;
12349371c9d4SSatish Balay           break;
12359371c9d4SSatish Balay         }
1236846a3e8bSMatthew G. Knepley       }
1237b7f6ffafSMatthew G. Knepley       if (drawNumbers[dim]) {
123863a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", c, rank, color, c));
1239b7f6ffafSMatthew G. Knepley       } else if (drawColors[dim]) {
124063a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color));
12411baa6e33SBarry Smith       } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", c, rank));
1242846a3e8bSMatthew G. Knepley     }
1243b7f6ffafSMatthew G. Knepley     if (drawHasse) {
1244b7f6ffafSMatthew G. Knepley       color = colors[depth % numColors];
12459566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Cells\n"));
12469566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\c in {\\cStart,...,\\cEnd}\n"));
12479566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
12489566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\c_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\cShift+\\c-\\cStart,0) {\\c};\n", rank, color));
12499566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1250552f7358SJed Brown 
1251b7f6ffafSMatthew G. Knepley       color = colors[1 % numColors];
12529566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Edges\n"));
12539566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\e in {\\eStart,...,\\eEnd}\n"));
12549566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
12559566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\e_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\eShift+\\e-\\eStart,1) {\\e};\n", rank, color));
12569566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1257b7f6ffafSMatthew G. Knepley 
1258b7f6ffafSMatthew G. Knepley       color = colors[0 % numColors];
12599566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Vertices\n"));
12609566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\v in {\\vStart,...,\\vEnd}\n"));
12619566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
12629566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\v_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\vShift+\\v-\\vStart,2) {\\v};\n", rank, color));
12639566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1264b7f6ffafSMatthew G. Knepley 
1265b7f6ffafSMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
1266b7f6ffafSMatthew G. Knepley         const PetscInt *cone;
1267b7f6ffafSMatthew G. Knepley         PetscInt        coneSize, cp;
1268b7f6ffafSMatthew G. Knepley 
12699566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, p, &cone));
12709566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
127148a46eb9SPierre Jolivet         for (cp = 0; cp < coneSize; ++cp) PetscCall(PetscViewerASCIIPrintf(viewer, "\\draw[->, shorten >=1pt] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", cone[cp], rank, p, rank));
12720588280cSMatthew G. Knepley       }
12730588280cSMatthew G. Knepley     }
12749566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
12759566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
12769566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n"));
127763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{document}\n"));
12789566063dSJacob Faibussowitsch     for (l = 0; l < numLabels; ++l) PetscCall(PetscFree(names[l]));
12799566063dSJacob Faibussowitsch     for (c = 0; c < numColors; ++c) PetscCall(PetscFree(colors[c]));
12809566063dSJacob Faibussowitsch     for (c = 0; c < numLColors; ++c) PetscCall(PetscFree(lcolors[c]));
12819566063dSJacob Faibussowitsch     PetscCall(PetscFree3(names, colors, lcolors));
12829566063dSJacob Faibussowitsch     PetscCall(PetscBTDestroy(&wp));
12830f7d6e4aSStefano Zampini   } else if (format == PETSC_VIEWER_LOAD_BALANCE) {
12840f7d6e4aSStefano Zampini     Vec                    cown, acown;
12850f7d6e4aSStefano Zampini     VecScatter             sct;
12860f7d6e4aSStefano Zampini     ISLocalToGlobalMapping g2l;
12870f7d6e4aSStefano Zampini     IS                     gid, acis;
12880f7d6e4aSStefano Zampini     MPI_Comm               comm, ncomm = MPI_COMM_NULL;
12890f7d6e4aSStefano Zampini     MPI_Group              ggroup, ngroup;
12900f7d6e4aSStefano Zampini     PetscScalar           *array, nid;
12910f7d6e4aSStefano Zampini     const PetscInt        *idxs;
12920f7d6e4aSStefano Zampini     PetscInt              *idxs2, *start, *adjacency, *work;
12930f7d6e4aSStefano Zampini     PetscInt64             lm[3], gm[3];
12940f7d6e4aSStefano Zampini     PetscInt               i, c, cStart, cEnd, cum, numVertices, ect, ectn, cellHeight;
12950f7d6e4aSStefano Zampini     PetscMPIInt            d1, d2, rank;
12960f7d6e4aSStefano Zampini 
12979566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
12989566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
1299b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
13009566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_split_type(comm, MPI_COMM_TYPE_SHARED, rank, MPI_INFO_NULL, &ncomm));
13010f7d6e4aSStefano Zampini #endif
13020f7d6e4aSStefano Zampini     if (ncomm != MPI_COMM_NULL) {
13039566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_group(comm, &ggroup));
13049566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_group(ncomm, &ngroup));
13050f7d6e4aSStefano Zampini       d1 = 0;
13069566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_translate_ranks(ngroup, 1, &d1, ggroup, &d2));
13070f7d6e4aSStefano Zampini       nid = d2;
13089566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_free(&ggroup));
13099566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_free(&ngroup));
13109566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_free(&ncomm));
13110f7d6e4aSStefano Zampini     } else nid = 0.0;
13120f7d6e4aSStefano Zampini 
13130f7d6e4aSStefano Zampini     /* Get connectivity */
13149566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
13159566063dSJacob Faibussowitsch     PetscCall(DMPlexCreatePartitionerGraph(dm, cellHeight, &numVertices, &start, &adjacency, &gid));
13160f7d6e4aSStefano Zampini 
13170f7d6e4aSStefano Zampini     /* filter overlapped local cells */
13189566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
13199566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(gid, &idxs));
13209566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(gid, &cum));
13219566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(cum, &idxs2));
13220f7d6e4aSStefano Zampini     for (c = cStart, cum = 0; c < cEnd; c++) {
13230f7d6e4aSStefano Zampini       if (idxs[c - cStart] < 0) continue;
13240f7d6e4aSStefano Zampini       idxs2[cum++] = idxs[c - cStart];
13250f7d6e4aSStefano Zampini     }
13269566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(gid, &idxs));
132763a3b9bcSJacob Faibussowitsch     PetscCheck(numVertices == cum, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected %" PetscInt_FMT " != %" PetscInt_FMT, numVertices, cum);
13289566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&gid));
13299566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm, numVertices, idxs2, PETSC_OWN_POINTER, &gid));
13300f7d6e4aSStefano Zampini 
13310f7d6e4aSStefano Zampini     /* support for node-aware cell locality */
13329566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm, start[numVertices], adjacency, PETSC_USE_POINTER, &acis));
13339566063dSJacob Faibussowitsch     PetscCall(VecCreateSeq(PETSC_COMM_SELF, start[numVertices], &acown));
13349566063dSJacob Faibussowitsch     PetscCall(VecCreateMPI(comm, numVertices, PETSC_DECIDE, &cown));
13359566063dSJacob Faibussowitsch     PetscCall(VecGetArray(cown, &array));
13360f7d6e4aSStefano Zampini     for (c = 0; c < numVertices; c++) array[c] = nid;
13379566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(cown, &array));
13389566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(cown, acis, acown, NULL, &sct));
13399566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD));
13409566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD));
13419566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&acis));
13429566063dSJacob Faibussowitsch     PetscCall(VecScatterDestroy(&sct));
13439566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&cown));
13440f7d6e4aSStefano Zampini 
13450f7d6e4aSStefano Zampini     /* compute edgeCut */
13460f7d6e4aSStefano Zampini     for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum, start[c + 1] - start[c]);
13479566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(cum, &work));
13489566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(gid, &g2l));
13499566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingSetType(g2l, ISLOCALTOGLOBALMAPPINGHASH));
13509566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&gid));
13519566063dSJacob Faibussowitsch     PetscCall(VecGetArray(acown, &array));
13520f7d6e4aSStefano Zampini     for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) {
13530f7d6e4aSStefano Zampini       PetscInt totl;
13540f7d6e4aSStefano Zampini 
13550f7d6e4aSStefano Zampini       totl = start[c + 1] - start[c];
13569566063dSJacob Faibussowitsch       PetscCall(ISGlobalToLocalMappingApply(g2l, IS_GTOLM_MASK, totl, adjacency + start[c], NULL, work));
13570f7d6e4aSStefano Zampini       for (i = 0; i < totl; i++) {
13580f7d6e4aSStefano Zampini         if (work[i] < 0) {
13590f7d6e4aSStefano Zampini           ect += 1;
13600f7d6e4aSStefano Zampini           ectn += (array[i + start[c]] != nid) ? 0 : 1;
13610f7d6e4aSStefano Zampini         }
13620f7d6e4aSStefano Zampini       }
13630f7d6e4aSStefano Zampini     }
13649566063dSJacob Faibussowitsch     PetscCall(PetscFree(work));
13659566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(acown, &array));
13660f7d6e4aSStefano Zampini     lm[0] = numVertices > 0 ? numVertices : PETSC_MAX_INT;
13670f7d6e4aSStefano Zampini     lm[1] = -numVertices;
13681c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(lm, gm, 2, MPIU_INT64, MPI_MIN, comm));
136963a3b9bcSJacob 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]));
13700f7d6e4aSStefano Zampini     lm[0] = ect;                     /* edgeCut */
13710f7d6e4aSStefano Zampini     lm[1] = ectn;                    /* node-aware edgeCut */
13720f7d6e4aSStefano Zampini     lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */
13731c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(lm, gm, 3, MPIU_INT64, MPI_SUM, comm));
137463a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, ", empty %" PetscInt_FMT ")\n", (PetscInt)gm[2]));
1375b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
137663a3b9bcSJacob 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.));
13770f7d6e4aSStefano Zampini #else
137863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Edge Cut: %" PetscInt_FMT " (on node %.3f)\n", (PetscInt)(gm[0] / 2), 0.0));
13790f7d6e4aSStefano Zampini #endif
13809566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&g2l));
13819566063dSJacob Faibussowitsch     PetscCall(PetscFree(start));
13829566063dSJacob Faibussowitsch     PetscCall(PetscFree(adjacency));
13839566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&acown));
1384552f7358SJed Brown   } else {
1385412e9a14SMatthew G. Knepley     const char    *name;
1386d80ece95SMatthew G. Knepley     PetscInt      *sizes, *hybsizes, *ghostsizes;
1387412e9a14SMatthew G. Knepley     PetscInt       locDepth, depth, cellHeight, dim, d;
1388d80ece95SMatthew G. Knepley     PetscInt       pStart, pEnd, p, gcStart, gcEnd, gcNum;
1389ca7bf7eeSMatthew G. Knepley     PetscInt       numLabels, l, maxSize = 17;
13909318fe57SMatthew G. Knepley     DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN;
1391412e9a14SMatthew G. Knepley     MPI_Comm       comm;
1392412e9a14SMatthew G. Knepley     PetscMPIInt    size, rank;
1393552f7358SJed Brown 
13949566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
13959566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(comm, &size));
13969566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
13979566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
13989566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
13999566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
140063a3b9bcSJacob Faibussowitsch     if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s"));
140163a3b9bcSJacob Faibussowitsch     else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s"));
140263a3b9bcSJacob Faibussowitsch     if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, "  Cells are at height %" PetscInt_FMT "\n", cellHeight));
14039566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dm, &locDepth));
14041c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm));
14059566063dSJacob Faibussowitsch     PetscCall(DMPlexGetGhostCellStratum(dm, &gcStart, &gcEnd));
1406d80ece95SMatthew G. Knepley     gcNum = gcEnd - gcStart;
14079566063dSJacob Faibussowitsch     if (size < maxSize) PetscCall(PetscCalloc3(size, &sizes, size, &hybsizes, size, &ghostsizes));
14089566063dSJacob Faibussowitsch     else PetscCall(PetscCalloc3(3, &sizes, 3, &hybsizes, 3, &ghostsizes));
1409412e9a14SMatthew G. Knepley     for (d = 0; d <= depth; d++) {
1410412e9a14SMatthew G. Knepley       PetscInt Nc[2] = {0, 0}, ict;
1411412e9a14SMatthew G. Knepley 
14129566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
14139566063dSJacob Faibussowitsch       if (pStart < pEnd) PetscCall(DMPlexGetCellType(dm, pStart, &ct0));
1414412e9a14SMatthew G. Knepley       ict = ct0;
14159566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Bcast(&ict, 1, MPIU_INT, 0, comm));
1416412e9a14SMatthew G. Knepley       ct0 = (DMPolytopeType)ict;
1417412e9a14SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
1418412e9a14SMatthew G. Knepley         DMPolytopeType ct;
1419412e9a14SMatthew G. Knepley 
14209566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, p, &ct));
1421412e9a14SMatthew G. Knepley         if (ct == ct0) ++Nc[0];
1422412e9a14SMatthew G. Knepley         else ++Nc[1];
1423412e9a14SMatthew G. Knepley       }
1424ca7bf7eeSMatthew G. Knepley       if (size < maxSize) {
14259566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Gather(&Nc[0], 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm));
14269566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm));
14279566063dSJacob Faibussowitsch         if (d == depth) PetscCallMPI(MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm));
142863a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Number of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d));
1429834065abSMatthew G. Knepley         for (p = 0; p < size; ++p) {
1430dd400576SPatrick Sanan           if (rank == 0) {
143163a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sizes[p] + hybsizes[p]));
143263a3b9bcSJacob Faibussowitsch             if (hybsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ")", hybsizes[p]));
143363a3b9bcSJacob Faibussowitsch             if (ghostsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "]", ghostsizes[p]));
1434834065abSMatthew G. Knepley           }
1435cbb7f117SMark Adams         }
1436ca7bf7eeSMatthew G. Knepley       } else {
1437ca7bf7eeSMatthew G. Knepley         PetscInt locMinMax[2];
1438ca7bf7eeSMatthew G. Knepley 
14399371c9d4SSatish Balay         locMinMax[0] = Nc[0] + Nc[1];
14409371c9d4SSatish Balay         locMinMax[1] = Nc[0] + Nc[1];
14419566063dSJacob Faibussowitsch         PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, sizes));
14429371c9d4SSatish Balay         locMinMax[0] = Nc[1];
14439371c9d4SSatish Balay         locMinMax[1] = Nc[1];
14449566063dSJacob Faibussowitsch         PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, hybsizes));
1445ca7bf7eeSMatthew G. Knepley         if (d == depth) {
14469371c9d4SSatish Balay           locMinMax[0] = gcNum;
14479371c9d4SSatish Balay           locMinMax[1] = gcNum;
14489566063dSJacob Faibussowitsch           PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, ghostsizes));
1449ca7bf7eeSMatthew G. Knepley         }
145063a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Min/Max of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d));
14519566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1]));
14529566063dSJacob Faibussowitsch         if (hybsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT "/%" PetscInt_FMT ")", hybsizes[0], hybsizes[1]));
14539566063dSJacob Faibussowitsch         if (ghostsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "/%" PetscInt_FMT "]", ghostsizes[0], ghostsizes[1]));
1454ca7bf7eeSMatthew G. Knepley       }
14559566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
1456552f7358SJed Brown     }
14579566063dSJacob Faibussowitsch     PetscCall(PetscFree3(sizes, hybsizes, ghostsizes));
14589318fe57SMatthew G. Knepley     {
14599318fe57SMatthew G. Knepley       const PetscReal *maxCell;
14609318fe57SMatthew G. Knepley       const PetscReal *L;
14616858538eSMatthew G. Knepley       PetscBool        localized;
14629318fe57SMatthew G. Knepley 
14634fb89dddSMatthew G. Knepley       PetscCall(DMGetPeriodicity(dm, &maxCell, NULL, &L));
14649566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocalized(dm, &localized));
14656858538eSMatthew G. Knepley       if (L || localized) {
14666858538eSMatthew G. Knepley         PetscCall(PetscViewerASCIIPrintf(viewer, "Periodic mesh"));
14679566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
14686858538eSMatthew G. Knepley         if (L) {
14696858538eSMatthew G. Knepley           PetscCall(PetscViewerASCIIPrintf(viewer, " ("));
14709318fe57SMatthew G. Knepley           for (d = 0; d < dim; ++d) {
14716858538eSMatthew G. Knepley             if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
14726858538eSMatthew G. Knepley             PetscCall(PetscViewerASCIIPrintf(viewer, "%s", L[d] > 0.0 ? "PERIODIC" : "NONE"));
14739318fe57SMatthew G. Knepley           }
14746858538eSMatthew G. Knepley           PetscCall(PetscViewerASCIIPrintf(viewer, ")"));
14756858538eSMatthew G. Knepley         }
14766858538eSMatthew G. Knepley         PetscCall(PetscViewerASCIIPrintf(viewer, " coordinates %s\n", localized ? "localized" : "not localized"));
14779566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
14789318fe57SMatthew G. Knepley       }
14799318fe57SMatthew G. Knepley     }
14809566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
14819566063dSJacob Faibussowitsch     if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n"));
1482a57dd577SMatthew G Knepley     for (l = 0; l < numLabels; ++l) {
1483a57dd577SMatthew G Knepley       DMLabel         label;
1484a57dd577SMatthew G Knepley       const char     *name;
1485a57dd577SMatthew G Knepley       IS              valueIS;
1486a57dd577SMatthew G Knepley       const PetscInt *values;
1487a57dd577SMatthew G Knepley       PetscInt        numValues, v;
1488a57dd577SMatthew G Knepley 
14899566063dSJacob Faibussowitsch       PetscCall(DMGetLabelName(dm, l, &name));
14909566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, name, &label));
14919566063dSJacob Faibussowitsch       PetscCall(DMLabelGetNumValues(label, &numValues));
149263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  %s: %" PetscInt_FMT " strata with value/size (", name, numValues));
14939566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValueIS(label, &valueIS));
14949566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(valueIS, &values));
14959566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
1496a57dd577SMatthew G Knepley       for (v = 0; v < numValues; ++v) {
1497a57dd577SMatthew G Knepley         PetscInt size;
1498a57dd577SMatthew G Knepley 
14999566063dSJacob Faibussowitsch         PetscCall(DMLabelGetStratumSize(label, values[v], &size));
15009566063dSJacob Faibussowitsch         if (v > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
150163a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " (%" PetscInt_FMT ")", values[v], size));
1502a57dd577SMatthew G Knepley       }
15039566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, ")\n"));
15049566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
15059566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(valueIS, &values));
15069566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&valueIS));
1507a57dd577SMatthew G Knepley     }
1508c1cad2e7SMatthew G. Knepley     {
1509c1cad2e7SMatthew G. Knepley       char    **labelNames;
1510c1cad2e7SMatthew G. Knepley       PetscInt  Nl = numLabels;
1511c1cad2e7SMatthew G. Knepley       PetscBool flg;
1512c1cad2e7SMatthew G. Knepley 
15139566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Nl, &labelNames));
15149566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetStringArray(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_view_labels", labelNames, &Nl, &flg));
1515c1cad2e7SMatthew G. Knepley       for (l = 0; l < Nl; ++l) {
1516c1cad2e7SMatthew G. Knepley         DMLabel label;
1517c1cad2e7SMatthew G. Knepley 
15189566063dSJacob Faibussowitsch         PetscCall(DMHasLabel(dm, labelNames[l], &flg));
1519c1cad2e7SMatthew G. Knepley         if (flg) {
15209566063dSJacob Faibussowitsch           PetscCall(DMGetLabel(dm, labelNames[l], &label));
15219566063dSJacob Faibussowitsch           PetscCall(DMLabelView(label, viewer));
1522c1cad2e7SMatthew G. Knepley         }
15239566063dSJacob Faibussowitsch         PetscCall(PetscFree(labelNames[l]));
1524c1cad2e7SMatthew G. Knepley       }
15259566063dSJacob Faibussowitsch       PetscCall(PetscFree(labelNames));
1526c1cad2e7SMatthew G. Knepley     }
152734aa8a36SMatthew G. Knepley     /* If no fields are specified, people do not want to see adjacency */
152834aa8a36SMatthew G. Knepley     if (dm->Nf) {
152934aa8a36SMatthew G. Knepley       PetscInt f;
153034aa8a36SMatthew G. Knepley 
153134aa8a36SMatthew G. Knepley       for (f = 0; f < dm->Nf; ++f) {
153234aa8a36SMatthew G. Knepley         const char *name;
153334aa8a36SMatthew G. Knepley 
15349566063dSJacob Faibussowitsch         PetscCall(PetscObjectGetName(dm->fields[f].disc, &name));
15359566063dSJacob Faibussowitsch         if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Field %s:\n", name));
15369566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
15379566063dSJacob Faibussowitsch         if (dm->fields[f].label) PetscCall(DMLabelView(dm->fields[f].label, viewer));
153834aa8a36SMatthew G. Knepley         if (dm->fields[f].adjacency[0]) {
15399566063dSJacob Faibussowitsch           if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n"));
15409566063dSJacob Faibussowitsch           else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM\n"));
154134aa8a36SMatthew G. Knepley         } else {
15429566063dSJacob Faibussowitsch           if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FEM\n"));
15439566063dSJacob Faibussowitsch           else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n"));
154434aa8a36SMatthew G. Knepley         }
15459566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
154634aa8a36SMatthew G. Knepley       }
154734aa8a36SMatthew G. Knepley     }
15489566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dm, &cdm));
15498e7ff633SMatthew G. Knepley     if (cdm) {
15509566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(viewer));
15519566063dSJacob Faibussowitsch       PetscCall(DMPlexView_Ascii(cdm, viewer));
15529566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(viewer));
15538e7ff633SMatthew G. Knepley     }
1554552f7358SJed Brown   }
1555552f7358SJed Brown   PetscFunctionReturn(0);
1556552f7358SJed Brown }
1557552f7358SJed Brown 
15589371c9d4SSatish Balay static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[]) {
1559e5c487bfSMatthew G. Knepley   DMPolytopeType ct;
1560e5c487bfSMatthew G. Knepley   PetscMPIInt    rank;
1561a12d352dSMatthew G. Knepley   PetscInt       cdim;
1562e5c487bfSMatthew G. Knepley 
1563e5c487bfSMatthew G. Knepley   PetscFunctionBegin;
15649566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
15659566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cell, &ct));
15669566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
1567e5c487bfSMatthew G. Knepley   switch (ct) {
1568a12d352dSMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
1569a12d352dSMatthew G. Knepley   case DM_POLYTOPE_POINT_PRISM_TENSOR:
1570a12d352dSMatthew G. Knepley     switch (cdim) {
15719371c9d4SSatish Balay     case 1: {
1572a12d352dSMatthew G. Knepley       const PetscReal y  = 0.5;  /* TODO Put it in the middle of the viewport */
1573a12d352dSMatthew G. Knepley       const PetscReal dy = 0.05; /* TODO Make it a fraction of the total length */
1574a12d352dSMatthew G. Knepley 
15759566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y, PetscRealPart(coords[1]), y, PETSC_DRAW_BLACK));
15769566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y + dy, PetscRealPart(coords[0]), y - dy, PETSC_DRAW_BLACK));
15779566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[1]), y + dy, PetscRealPart(coords[1]), y - dy, PETSC_DRAW_BLACK));
15789371c9d4SSatish Balay     } break;
15799371c9d4SSatish Balay     case 2: {
1580a12d352dSMatthew G. Knepley       const PetscReal dx = (PetscRealPart(coords[3]) - PetscRealPart(coords[1]));
1581a12d352dSMatthew G. Knepley       const PetscReal dy = (PetscRealPart(coords[2]) - PetscRealPart(coords[0]));
1582a12d352dSMatthew G. Knepley       const PetscReal l  = 0.1 / PetscSqrtReal(dx * dx + dy * dy);
1583a12d352dSMatthew G. Knepley 
15849566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
15859566063dSJacob 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));
15869566063dSJacob 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));
15879371c9d4SSatish Balay     } break;
158863a3b9bcSJacob Faibussowitsch     default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of dimension %" PetscInt_FMT, cdim);
1589a12d352dSMatthew G. Knepley     }
1590a12d352dSMatthew G. Knepley     break;
1591e5c487bfSMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
15929371c9d4SSatish Balay     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2));
15939566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
15949566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK));
15959566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK));
1596e5c487bfSMatthew G. Knepley     break;
1597e5c487bfSMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
15989371c9d4SSatish Balay     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2));
15999371c9d4SSatish Balay     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2));
16009566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
16019566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK));
16029566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK));
16039566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK));
1604e5c487bfSMatthew G. Knepley     break;
160598921bdaSJacob Faibussowitsch   default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]);
1606e5c487bfSMatthew G. Knepley   }
1607e5c487bfSMatthew G. Knepley   PetscFunctionReturn(0);
1608e5c487bfSMatthew G. Knepley }
1609e5c487bfSMatthew G. Knepley 
16109371c9d4SSatish Balay static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[]) {
1611e5c487bfSMatthew G. Knepley   DMPolytopeType ct;
1612e5c487bfSMatthew G. Knepley   PetscReal      centroid[2] = {0., 0.};
1613e5c487bfSMatthew G. Knepley   PetscMPIInt    rank;
1614e5c487bfSMatthew G. Knepley   PetscInt       fillColor, v, e, d;
1615e5c487bfSMatthew G. Knepley 
1616e5c487bfSMatthew G. Knepley   PetscFunctionBegin;
16179566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
16189566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cell, &ct));
1619e5c487bfSMatthew G. Knepley   fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2;
1620e5c487bfSMatthew G. Knepley   switch (ct) {
16219371c9d4SSatish Balay   case DM_POLYTOPE_TRIANGLE: {
1622e5c487bfSMatthew G. Knepley     PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.};
1623e5c487bfSMatthew G. Knepley 
16249371c9d4SSatish Balay     for (v = 0; v < 3; ++v) {
16259371c9d4SSatish Balay       centroid[0] += PetscRealPart(coords[v * 2 + 0]) / 3.;
16269371c9d4SSatish Balay       centroid[1] += PetscRealPart(coords[v * 2 + 1]) / 3.;
16279371c9d4SSatish Balay     }
1628e5c487bfSMatthew G. Knepley     for (e = 0; e < 3; ++e) {
1629e5c487bfSMatthew G. Knepley       refCoords[0] = refVertices[e * 2 + 0];
1630e5c487bfSMatthew G. Knepley       refCoords[1] = refVertices[e * 2 + 1];
1631e5c487bfSMatthew G. Knepley       for (d = 1; d <= edgeDiv; ++d) {
1632e5c487bfSMatthew G. Knepley         refCoords[d * 2 + 0] = refCoords[0] + (refVertices[(e + 1) % 3 * 2 + 0] - refCoords[0]) * d / edgeDiv;
1633e5c487bfSMatthew G. Knepley         refCoords[d * 2 + 1] = refCoords[1] + (refVertices[(e + 1) % 3 * 2 + 1] - refCoords[1]) * d / edgeDiv;
1634e5c487bfSMatthew G. Knepley       }
16359566063dSJacob Faibussowitsch       PetscCall(DMPlexReferenceToCoordinates(dm, cell, edgeDiv + 1, refCoords, edgeCoords));
1636e5c487bfSMatthew G. Knepley       for (d = 0; d < edgeDiv; ++d) {
16379566063dSJacob 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));
16389566063dSJacob 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));
1639e5c487bfSMatthew G. Knepley       }
1640e5c487bfSMatthew G. Knepley     }
16419371c9d4SSatish Balay   } break;
164298921bdaSJacob Faibussowitsch   default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]);
1643e5c487bfSMatthew G. Knepley   }
1644e5c487bfSMatthew G. Knepley   PetscFunctionReturn(0);
1645e5c487bfSMatthew G. Knepley }
1646e5c487bfSMatthew G. Knepley 
16479371c9d4SSatish Balay static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer) {
1648e412dcbdSMatthew G. Knepley   PetscDraw          draw;
1649e412dcbdSMatthew G. Knepley   DM                 cdm;
1650e412dcbdSMatthew G. Knepley   PetscSection       coordSection;
1651e412dcbdSMatthew G. Knepley   Vec                coordinates;
1652e412dcbdSMatthew G. Knepley   const PetscScalar *coords;
165329494db1SLisandro Dalcin   PetscReal          xyl[2], xyr[2], bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL};
1654e5c487bfSMatthew G. Knepley   PetscReal         *refCoords, *edgeCoords;
1655e5c487bfSMatthew G. Knepley   PetscBool          isnull, drawAffine = PETSC_TRUE;
1656e5c487bfSMatthew G. Knepley   PetscInt           dim, vStart, vEnd, cStart, cEnd, c, N, edgeDiv = 4;
1657e412dcbdSMatthew G. Knepley 
1658e412dcbdSMatthew G. Knepley   PetscFunctionBegin;
16599566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dim));
166063a3b9bcSJacob Faibussowitsch   PetscCheck(dim <= 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT, dim);
16619566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL));
16629566063dSJacob Faibussowitsch   if (!drawAffine) PetscCall(PetscMalloc2((edgeDiv + 1) * dim, &refCoords, (edgeDiv + 1) * dim, &edgeCoords));
16639566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
16649566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(cdm, &coordSection));
16659566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
16669566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
16679566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
1668e412dcbdSMatthew G. Knepley 
16699566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
16709566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
1671e412dcbdSMatthew G. Knepley   if (isnull) PetscFunctionReturn(0);
16729566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "Mesh"));
1673e412dcbdSMatthew G. Knepley 
16749566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(coordinates, &N));
16759566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(coordinates, &coords));
1676e412dcbdSMatthew G. Knepley   for (c = 0; c < N; c += dim) {
16779371c9d4SSatish Balay     bound[0] = PetscMin(bound[0], PetscRealPart(coords[c]));
16789371c9d4SSatish Balay     bound[2] = PetscMax(bound[2], PetscRealPart(coords[c]));
16799371c9d4SSatish Balay     bound[1] = PetscMin(bound[1], PetscRealPart(coords[c + 1]));
16809371c9d4SSatish Balay     bound[3] = PetscMax(bound[3], PetscRealPart(coords[c + 1]));
1681e412dcbdSMatthew G. Knepley   }
16829566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(coordinates, &coords));
16831c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&bound[0], xyl, 2, MPIU_REAL, MPIU_MIN, PetscObjectComm((PetscObject)dm)));
16841c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&bound[2], xyr, 2, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)dm)));
16859566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1]));
16869566063dSJacob Faibussowitsch   PetscCall(PetscDrawClear(draw));
1687e412dcbdSMatthew G. Knepley 
1688cf3064d3SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1689cf3064d3SMatthew G. Knepley     PetscScalar *coords = NULL;
1690ba2698f1SMatthew G. Knepley     PetscInt     numCoords;
1691cf3064d3SMatthew G. Knepley 
16929566063dSJacob Faibussowitsch     PetscCall(DMPlexVecGetClosureAtDepth_Internal(dm, coordSection, coordinates, c, 0, &numCoords, &coords));
16931baa6e33SBarry Smith     if (drawAffine) PetscCall(DMPlexDrawCell(dm, draw, c, coords));
16941baa6e33SBarry Smith     else PetscCall(DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords));
16959566063dSJacob Faibussowitsch     PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords));
1696cf3064d3SMatthew G. Knepley   }
16979566063dSJacob Faibussowitsch   if (!drawAffine) PetscCall(PetscFree2(refCoords, edgeCoords));
16989566063dSJacob Faibussowitsch   PetscCall(PetscDrawFlush(draw));
16999566063dSJacob Faibussowitsch   PetscCall(PetscDrawPause(draw));
17009566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave(draw));
1701e412dcbdSMatthew G. Knepley   PetscFunctionReturn(0);
1702e412dcbdSMatthew G. Knepley }
1703e412dcbdSMatthew G. Knepley 
17041e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII)
17051e50132fSMatthew G. Knepley #include <exodusII.h>
17066823f3c5SBlaise Bourdin #include <petscviewerexodusii.h>
17071e50132fSMatthew G. Knepley #endif
17081e50132fSMatthew G. Knepley 
17099371c9d4SSatish Balay PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) {
17105f34f2dcSJed Brown   PetscBool iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus, iscgns;
1711002a2709SMatthew G. Knepley   char      name[PETSC_MAX_PATH_LEN];
1712552f7358SJed Brown 
1713552f7358SJed Brown   PetscFunctionBegin;
1714552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1715552f7358SJed Brown   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
17169566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
17179566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
17189566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
17199566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
17209566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis));
17219566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodus));
17225f34f2dcSJed Brown   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns));
1723552f7358SJed Brown   if (iascii) {
17248135c375SStefano Zampini     PetscViewerFormat format;
17259566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
17261baa6e33SBarry Smith     if (format == PETSC_VIEWER_ASCII_GLVIS) PetscCall(DMPlexView_GLVis(dm, viewer));
17271baa6e33SBarry Smith     else PetscCall(DMPlexView_Ascii(dm, viewer));
1728c6ccd67eSMatthew G. Knepley   } else if (ishdf5) {
1729c6ccd67eSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
17309566063dSJacob Faibussowitsch     PetscCall(DMPlexView_HDF5_Internal(dm, viewer));
1731c6ccd67eSMatthew G. Knepley #else
1732c6ccd67eSMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1733552f7358SJed Brown #endif
1734e412dcbdSMatthew G. Knepley   } else if (isvtk) {
17359566063dSJacob Faibussowitsch     PetscCall(DMPlexVTKWriteAll((PetscObject)dm, viewer));
1736e412dcbdSMatthew G. Knepley   } else if (isdraw) {
17379566063dSJacob Faibussowitsch     PetscCall(DMPlexView_Draw(dm, viewer));
17388135c375SStefano Zampini   } else if (isglvis) {
17399566063dSJacob Faibussowitsch     PetscCall(DMPlexView_GLVis(dm, viewer));
17401e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII)
17411e50132fSMatthew G. Knepley   } else if (isexodus) {
17426823f3c5SBlaise Bourdin     /*
17436823f3c5SBlaise Bourdin       exodusII requires that all sets be part of exactly one cell set.
17446823f3c5SBlaise Bourdin       If the dm does not have a "Cell Sets" label defined, we create one
17456823f3c5SBlaise Bourdin       with ID 1, containig all cells.
17466823f3c5SBlaise Bourdin       Note that if the Cell Sets label is defined but does not cover all cells,
17476823f3c5SBlaise Bourdin       we may still have a problem. This should probably be checked here or in the viewer;
17486823f3c5SBlaise Bourdin     */
17496823f3c5SBlaise Bourdin     PetscInt numCS;
17509566063dSJacob Faibussowitsch     PetscCall(DMGetLabelSize(dm, "Cell Sets", &numCS));
17516823f3c5SBlaise Bourdin     if (!numCS) {
17521e50132fSMatthew G. Knepley       PetscInt cStart, cEnd, c;
17539566063dSJacob Faibussowitsch       PetscCall(DMCreateLabel(dm, "Cell Sets"));
17549566063dSJacob Faibussowitsch       PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
17559566063dSJacob Faibussowitsch       for (c = cStart; c < cEnd; ++c) PetscCall(DMSetLabelValue(dm, "Cell Sets", c, 1));
17566823f3c5SBlaise Bourdin     }
17579566063dSJacob Faibussowitsch     PetscCall(DMView_PlexExodusII(dm, viewer));
17581e50132fSMatthew G. Knepley #endif
17595f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS)
17605f34f2dcSJed Brown   } else if (iscgns) {
17615f34f2dcSJed Brown     PetscCall(DMView_PlexCGNS(dm, viewer));
17625f34f2dcSJed Brown #endif
17631baa6e33SBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name);
1764cb3ba0daSMatthew G. Knepley   /* Optionally view the partition */
17659566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_partition_view", &flg));
1766cb3ba0daSMatthew G. Knepley   if (flg) {
1767cb3ba0daSMatthew G. Knepley     Vec ranks;
17689566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateRankField(dm, &ranks));
17699566063dSJacob Faibussowitsch     PetscCall(VecView(ranks, viewer));
17709566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&ranks));
1771cb3ba0daSMatthew G. Knepley   }
1772002a2709SMatthew G. Knepley   /* Optionally view a label */
17739566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetString(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_label_view", name, sizeof(name), &flg));
1774002a2709SMatthew G. Knepley   if (flg) {
1775002a2709SMatthew G. Knepley     DMLabel label;
1776002a2709SMatthew G. Knepley     Vec     val;
1777002a2709SMatthew G. Knepley 
17789566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, name, &label));
177928b400f6SJacob Faibussowitsch     PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name);
17809566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateLabelField(dm, label, &val));
17819566063dSJacob Faibussowitsch     PetscCall(VecView(val, viewer));
17829566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&val));
1783002a2709SMatthew G. Knepley   }
1784552f7358SJed Brown   PetscFunctionReturn(0);
1785552f7358SJed Brown }
1786552f7358SJed Brown 
17877f96f51bSksagiyam /*@
17887f96f51bSksagiyam   DMPlexTopologyView - Saves a DMPlex topology into a file
17897f96f51bSksagiyam 
17907f96f51bSksagiyam   Collective on DM
17917f96f51bSksagiyam 
17927f96f51bSksagiyam   Input Parameters:
17937f96f51bSksagiyam + dm                - The DM whose topology is to be saved
17947f96f51bSksagiyam - viewer            - The PetscViewer for saving
17957f96f51bSksagiyam 
17967f96f51bSksagiyam   Level: advanced
17977f96f51bSksagiyam 
1798db781477SPatrick Sanan .seealso: `DMView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexTopologyLoad()`
17997f96f51bSksagiyam @*/
18009371c9d4SSatish Balay PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer) {
18017f96f51bSksagiyam   PetscBool ishdf5;
18027f96f51bSksagiyam 
18037f96f51bSksagiyam   PetscFunctionBegin;
18047f96f51bSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
18057f96f51bSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
18069566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
18079566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_TopologyView, viewer, 0, 0, 0));
18087f96f51bSksagiyam   if (ishdf5) {
18097f96f51bSksagiyam #if defined(PETSC_HAVE_HDF5)
18107f96f51bSksagiyam     PetscViewerFormat format;
18119566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
18127f96f51bSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
18137f96f51bSksagiyam       IS globalPointNumbering;
18147f96f51bSksagiyam 
18159566063dSJacob Faibussowitsch       PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering));
18169566063dSJacob Faibussowitsch       PetscCall(DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer));
18179566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&globalPointNumbering));
181898921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]);
18197f96f51bSksagiyam #else
18207f96f51bSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
18217f96f51bSksagiyam #endif
18227f96f51bSksagiyam   }
18239566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_TopologyView, viewer, 0, 0, 0));
18247f96f51bSksagiyam   PetscFunctionReturn(0);
18257f96f51bSksagiyam }
18267f96f51bSksagiyam 
182777b8e257Sksagiyam /*@
182877b8e257Sksagiyam   DMPlexCoordinatesView - Saves DMPlex coordinates into a file
182977b8e257Sksagiyam 
183077b8e257Sksagiyam   Collective on DM
183177b8e257Sksagiyam 
183277b8e257Sksagiyam   Input Parameters:
183377b8e257Sksagiyam + dm     - The DM whose coordinates are to be saved
183477b8e257Sksagiyam - viewer - The PetscViewer for saving
183577b8e257Sksagiyam 
183677b8e257Sksagiyam   Level: advanced
183777b8e257Sksagiyam 
1838db781477SPatrick Sanan .seealso: `DMView()`, `DMPlexTopologyView()`, `DMPlexLabelsView()`, `DMPlexCoordinatesLoad()`
183977b8e257Sksagiyam @*/
18409371c9d4SSatish Balay PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer) {
184177b8e257Sksagiyam   PetscBool ishdf5;
184277b8e257Sksagiyam 
184377b8e257Sksagiyam   PetscFunctionBegin;
184477b8e257Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
184577b8e257Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
18469566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
18479566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesView, viewer, 0, 0, 0));
184877b8e257Sksagiyam   if (ishdf5) {
184977b8e257Sksagiyam #if defined(PETSC_HAVE_HDF5)
185077b8e257Sksagiyam     PetscViewerFormat format;
18519566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
185277b8e257Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
18539566063dSJacob Faibussowitsch       PetscCall(DMPlexCoordinatesView_HDF5_Internal(dm, viewer));
1854*fe28d297SMatthew Knepley     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]);
185577b8e257Sksagiyam #else
185677b8e257Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
185777b8e257Sksagiyam #endif
185877b8e257Sksagiyam   }
18599566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesView, viewer, 0, 0, 0));
186077b8e257Sksagiyam   PetscFunctionReturn(0);
186177b8e257Sksagiyam }
186277b8e257Sksagiyam 
1863bd6565f1Sksagiyam /*@
1864bd6565f1Sksagiyam   DMPlexLabelsView - Saves DMPlex labels into a file
1865bd6565f1Sksagiyam 
1866bd6565f1Sksagiyam   Collective on DM
1867bd6565f1Sksagiyam 
1868bd6565f1Sksagiyam   Input Parameters:
1869bd6565f1Sksagiyam + dm     - The DM whose labels are to be saved
1870bd6565f1Sksagiyam - viewer - The PetscViewer for saving
1871bd6565f1Sksagiyam 
1872bd6565f1Sksagiyam   Level: advanced
1873bd6565f1Sksagiyam 
1874db781477SPatrick Sanan .seealso: `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsLoad()`
1875bd6565f1Sksagiyam @*/
18769371c9d4SSatish Balay PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer) {
1877bd6565f1Sksagiyam   PetscBool ishdf5;
1878bd6565f1Sksagiyam 
1879bd6565f1Sksagiyam   PetscFunctionBegin;
1880bd6565f1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1881bd6565f1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
18829566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
18839566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LabelsView, viewer, 0, 0, 0));
1884bd6565f1Sksagiyam   if (ishdf5) {
1885bd6565f1Sksagiyam #if defined(PETSC_HAVE_HDF5)
1886bd6565f1Sksagiyam     IS                globalPointNumbering;
1887bd6565f1Sksagiyam     PetscViewerFormat format;
1888bd6565f1Sksagiyam 
18899566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
1890bd6565f1Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
18919566063dSJacob Faibussowitsch       PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering));
18929566063dSJacob Faibussowitsch       PetscCall(DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer));
18939566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&globalPointNumbering));
189498921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
1895bd6565f1Sksagiyam #else
1896bd6565f1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1897bd6565f1Sksagiyam #endif
1898bd6565f1Sksagiyam   }
18999566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LabelsView, viewer, 0, 0, 0));
1900bd6565f1Sksagiyam   PetscFunctionReturn(0);
1901bd6565f1Sksagiyam }
1902bd6565f1Sksagiyam 
1903021affd3Sksagiyam /*@
1904021affd3Sksagiyam   DMPlexSectionView - Saves a section associated with a DMPlex
1905021affd3Sksagiyam 
1906021affd3Sksagiyam   Collective on DM
1907021affd3Sksagiyam 
1908021affd3Sksagiyam   Input Parameters:
1909021affd3Sksagiyam + dm         - The DM that contains the topology on which the section to be saved is defined
1910021affd3Sksagiyam . viewer     - The PetscViewer for saving
1911021affd3Sksagiyam - sectiondm  - The DM that contains the section to be saved
1912021affd3Sksagiyam 
1913021affd3Sksagiyam   Level: advanced
1914021affd3Sksagiyam 
1915021affd3Sksagiyam   Notes:
1916021affd3Sksagiyam   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.
1917021affd3Sksagiyam 
1918021affd3Sksagiyam   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.
1919021affd3Sksagiyam 
1920db781477SPatrick Sanan .seealso: `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, `PetscSectionView()`, `DMPlexSectionLoad()`
1921021affd3Sksagiyam @*/
19229371c9d4SSatish Balay PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm) {
1923021affd3Sksagiyam   PetscBool ishdf5;
1924021affd3Sksagiyam 
1925021affd3Sksagiyam   PetscFunctionBegin;
1926021affd3Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1927021affd3Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1928021affd3Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
19299566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
19309566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_SectionView, viewer, 0, 0, 0));
1931021affd3Sksagiyam   if (ishdf5) {
1932021affd3Sksagiyam #if defined(PETSC_HAVE_HDF5)
19339566063dSJacob Faibussowitsch     PetscCall(DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm));
1934021affd3Sksagiyam #else
1935021affd3Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1936021affd3Sksagiyam #endif
1937021affd3Sksagiyam   }
19389566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_SectionView, viewer, 0, 0, 0));
1939021affd3Sksagiyam   PetscFunctionReturn(0);
1940021affd3Sksagiyam }
1941021affd3Sksagiyam 
19423e97647fSksagiyam /*@
19433e97647fSksagiyam   DMPlexGlobalVectorView - Saves a global vector
19443e97647fSksagiyam 
19453e97647fSksagiyam   Collective on DM
19463e97647fSksagiyam 
19473e97647fSksagiyam   Input Parameters:
19483e97647fSksagiyam + dm        - The DM that represents the topology
19493e97647fSksagiyam . viewer    - The PetscViewer to save data with
19503e97647fSksagiyam . sectiondm - The DM that contains the global section on which vec is defined
19513e97647fSksagiyam - vec       - The global vector to be saved
19523e97647fSksagiyam 
19533e97647fSksagiyam   Level: advanced
19543e97647fSksagiyam 
19553e97647fSksagiyam   Notes:
19563e97647fSksagiyam   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.
19573e97647fSksagiyam 
19583e97647fSksagiyam   Typical calling sequence
19593e97647fSksagiyam $       DMCreate(PETSC_COMM_WORLD, &dm);
19603e97647fSksagiyam $       DMSetType(dm, DMPLEX);
19613e97647fSksagiyam $       PetscObjectSetName((PetscObject)dm, "topologydm_name");
19623e97647fSksagiyam $       DMClone(dm, &sectiondm);
19633e97647fSksagiyam $       PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
19643e97647fSksagiyam $       PetscSectionCreate(PETSC_COMM_WORLD, &section);
19653e97647fSksagiyam $       DMPlexGetChart(sectiondm, &pStart, &pEnd);
19663e97647fSksagiyam $       PetscSectionSetChart(section, pStart, pEnd);
19673e97647fSksagiyam $       PetscSectionSetUp(section);
19683e97647fSksagiyam $       DMSetLocalSection(sectiondm, section);
19693e97647fSksagiyam $       PetscSectionDestroy(&section);
19703e97647fSksagiyam $       DMGetGlobalVector(sectiondm, &vec);
19713e97647fSksagiyam $       PetscObjectSetName((PetscObject)vec, "vec_name");
19723e97647fSksagiyam $       DMPlexTopologyView(dm, viewer);
19733e97647fSksagiyam $       DMPlexSectionView(dm, viewer, sectiondm);
19743e97647fSksagiyam $       DMPlexGlobalVectorView(dm, viewer, sectiondm, vec);
19753e97647fSksagiyam $       DMRestoreGlobalVector(sectiondm, &vec);
19763e97647fSksagiyam $       DMDestroy(&sectiondm);
19773e97647fSksagiyam $       DMDestroy(&dm);
19783e97647fSksagiyam 
1979db781477SPatrick Sanan .seealso: `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexLocalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`
19803e97647fSksagiyam @*/
19819371c9d4SSatish Balay PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) {
19823e97647fSksagiyam   PetscBool ishdf5;
19833e97647fSksagiyam 
19843e97647fSksagiyam   PetscFunctionBegin;
19853e97647fSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
19863e97647fSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
19873e97647fSksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
19883e97647fSksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 4);
19893e97647fSksagiyam   /* Check consistency */
19903e97647fSksagiyam   {
19913e97647fSksagiyam     PetscSection section;
19923e97647fSksagiyam     PetscBool    includesConstraints;
19933e97647fSksagiyam     PetscInt     m, m1;
19943e97647fSksagiyam 
19959566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
19969566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(sectiondm, &section));
19979566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
19989566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
19999566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
200063a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m);
20013e97647fSksagiyam   }
20029566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
20039566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorView, viewer, 0, 0, 0));
20043e97647fSksagiyam   if (ishdf5) {
20053e97647fSksagiyam #if defined(PETSC_HAVE_HDF5)
20069566063dSJacob Faibussowitsch     PetscCall(DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec));
20073e97647fSksagiyam #else
20083e97647fSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
20093e97647fSksagiyam #endif
20103e97647fSksagiyam   }
20119566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorView, viewer, 0, 0, 0));
20123e97647fSksagiyam   PetscFunctionReturn(0);
20133e97647fSksagiyam }
20143e97647fSksagiyam 
20153e97647fSksagiyam /*@
20163e97647fSksagiyam   DMPlexLocalVectorView - Saves a local vector
20173e97647fSksagiyam 
20183e97647fSksagiyam   Collective on DM
20193e97647fSksagiyam 
20203e97647fSksagiyam   Input Parameters:
20213e97647fSksagiyam + dm        - The DM that represents the topology
20223e97647fSksagiyam . viewer    - The PetscViewer to save data with
20233e97647fSksagiyam . sectiondm - The DM that contains the local section on which vec is defined; may be the same as dm
20243e97647fSksagiyam - vec       - The local vector to be saved
20253e97647fSksagiyam 
20263e97647fSksagiyam   Level: advanced
20273e97647fSksagiyam 
20283e97647fSksagiyam   Notes:
20293e97647fSksagiyam   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.
20303e97647fSksagiyam 
20313e97647fSksagiyam   Typical calling sequence
20323e97647fSksagiyam $       DMCreate(PETSC_COMM_WORLD, &dm);
20333e97647fSksagiyam $       DMSetType(dm, DMPLEX);
20343e97647fSksagiyam $       PetscObjectSetName((PetscObject)dm, "topologydm_name");
20353e97647fSksagiyam $       DMClone(dm, &sectiondm);
20363e97647fSksagiyam $       PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
20373e97647fSksagiyam $       PetscSectionCreate(PETSC_COMM_WORLD, &section);
20383e97647fSksagiyam $       DMPlexGetChart(sectiondm, &pStart, &pEnd);
20393e97647fSksagiyam $       PetscSectionSetChart(section, pStart, pEnd);
20403e97647fSksagiyam $       PetscSectionSetUp(section);
20413e97647fSksagiyam $       DMSetLocalSection(sectiondm, section);
20423e97647fSksagiyam $       DMGetLocalVector(sectiondm, &vec);
20433e97647fSksagiyam $       PetscObjectSetName((PetscObject)vec, "vec_name");
20443e97647fSksagiyam $       DMPlexTopologyView(dm, viewer);
20453e97647fSksagiyam $       DMPlexSectionView(dm, viewer, sectiondm);
20463e97647fSksagiyam $       DMPlexLocalVectorView(dm, viewer, sectiondm, vec);
20473e97647fSksagiyam $       DMRestoreLocalVector(sectiondm, &vec);
20483e97647fSksagiyam $       DMDestroy(&sectiondm);
20493e97647fSksagiyam $       DMDestroy(&dm);
20503e97647fSksagiyam 
2051db781477SPatrick Sanan .seealso: `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexGlobalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`
20523e97647fSksagiyam @*/
20539371c9d4SSatish Balay PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec) {
20543e97647fSksagiyam   PetscBool ishdf5;
20553e97647fSksagiyam 
20563e97647fSksagiyam   PetscFunctionBegin;
20573e97647fSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
20583e97647fSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
20593e97647fSksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
20603e97647fSksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 4);
20613e97647fSksagiyam   /* Check consistency */
20623e97647fSksagiyam   {
20633e97647fSksagiyam     PetscSection section;
20643e97647fSksagiyam     PetscBool    includesConstraints;
20653e97647fSksagiyam     PetscInt     m, m1;
20663e97647fSksagiyam 
20679566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
20689566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(sectiondm, &section));
20699566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
20709566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
20719566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
207263a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m);
20733e97647fSksagiyam   }
20749566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
20759566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorView, viewer, 0, 0, 0));
20763e97647fSksagiyam   if (ishdf5) {
20773e97647fSksagiyam #if defined(PETSC_HAVE_HDF5)
20789566063dSJacob Faibussowitsch     PetscCall(DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec));
20793e97647fSksagiyam #else
20803e97647fSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
20813e97647fSksagiyam #endif
20823e97647fSksagiyam   }
20839566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorView, viewer, 0, 0, 0));
20843e97647fSksagiyam   PetscFunctionReturn(0);
20853e97647fSksagiyam }
20863e97647fSksagiyam 
20879371c9d4SSatish Balay PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer) {
2088d4f5a9a0SVaclav Hapla   PetscBool ishdf5;
20892c40f234SMatthew G. Knepley 
20902c40f234SMatthew G. Knepley   PetscFunctionBegin;
20912c40f234SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
20922c40f234SMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
20939566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
2094d4f5a9a0SVaclav Hapla   if (ishdf5) {
20952c40f234SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
20969c48423bSVaclav Hapla     PetscViewerFormat format;
20979566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
20989c48423bSVaclav Hapla     if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) {
20999566063dSJacob Faibussowitsch       PetscCall(DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer));
2100509517efSVaclav Hapla     } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
21019566063dSJacob Faibussowitsch       PetscCall(DMPlexLoad_HDF5_Internal(dm, viewer));
210298921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2103b458e8f1SJose E. Roman     PetscFunctionReturn(0);
21042c40f234SMatthew G. Knepley #else
21052c40f234SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2106552f7358SJed Brown #endif
210798921bdaSJacob Faibussowitsch   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name);
2108552f7358SJed Brown }
2109552f7358SJed Brown 
2110ea8e1828Sksagiyam /*@
2111ea8e1828Sksagiyam   DMPlexTopologyLoad - Loads a topology into a DMPlex
2112ea8e1828Sksagiyam 
2113ea8e1828Sksagiyam   Collective on DM
2114ea8e1828Sksagiyam 
2115ea8e1828Sksagiyam   Input Parameters:
2116ea8e1828Sksagiyam + dm                - The DM into which the topology is loaded
2117ea8e1828Sksagiyam - viewer            - The PetscViewer for the saved topology
2118ea8e1828Sksagiyam 
2119dec9e869Sksagiyam   Output Parameters:
2120f84dd6b4Sksagiyam . 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
2121dec9e869Sksagiyam 
2122ea8e1828Sksagiyam   Level: advanced
2123ea8e1828Sksagiyam 
2124db781477SPatrick Sanan .seealso: `DMLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`
2125ea8e1828Sksagiyam @*/
21269371c9d4SSatish Balay PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF) {
2127ea8e1828Sksagiyam   PetscBool ishdf5;
2128ea8e1828Sksagiyam 
2129ea8e1828Sksagiyam   PetscFunctionBegin;
2130ea8e1828Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2131ea8e1828Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2132f84dd6b4Sksagiyam   if (globalToLocalPointSF) PetscValidPointer(globalToLocalPointSF, 3);
21339566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
21349566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_TopologyLoad, viewer, 0, 0, 0));
2135ea8e1828Sksagiyam   if (ishdf5) {
2136ea8e1828Sksagiyam #if defined(PETSC_HAVE_HDF5)
2137ea8e1828Sksagiyam     PetscViewerFormat format;
21389566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
2139ea8e1828Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
21409566063dSJacob Faibussowitsch       PetscCall(DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
214198921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2142ea8e1828Sksagiyam #else
2143ea8e1828Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2144ea8e1828Sksagiyam #endif
2145ea8e1828Sksagiyam   }
21469566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_TopologyLoad, viewer, 0, 0, 0));
2147ea8e1828Sksagiyam   PetscFunctionReturn(0);
2148ea8e1828Sksagiyam }
2149ea8e1828Sksagiyam 
21503e701f1cSksagiyam /*@
21513e701f1cSksagiyam   DMPlexCoordinatesLoad - Loads coordinates into a DMPlex
21523e701f1cSksagiyam 
21533e701f1cSksagiyam   Collective on DM
21543e701f1cSksagiyam 
21553e701f1cSksagiyam   Input Parameters:
21563e701f1cSksagiyam + dm     - The DM into which the coordinates are loaded
2157c9ad657eSksagiyam . viewer - The PetscViewer for the saved coordinates
2158c9ad657eSksagiyam - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer
21593e701f1cSksagiyam 
21603e701f1cSksagiyam   Level: advanced
21613e701f1cSksagiyam 
2162db781477SPatrick Sanan .seealso: `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`
21633e701f1cSksagiyam @*/
21649371c9d4SSatish Balay PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) {
21653e701f1cSksagiyam   PetscBool ishdf5;
21663e701f1cSksagiyam 
21673e701f1cSksagiyam   PetscFunctionBegin;
21683e701f1cSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
21693e701f1cSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2170c9ad657eSksagiyam   PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3);
21719566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
21729566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0));
21733e701f1cSksagiyam   if (ishdf5) {
21743e701f1cSksagiyam #if defined(PETSC_HAVE_HDF5)
21753e701f1cSksagiyam     PetscViewerFormat format;
21769566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
21773e701f1cSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
21789566063dSJacob Faibussowitsch       PetscCall(DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
217998921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
21803e701f1cSksagiyam #else
21813e701f1cSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
21823e701f1cSksagiyam #endif
21833e701f1cSksagiyam   }
21849566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0));
21853e701f1cSksagiyam   PetscFunctionReturn(0);
21863e701f1cSksagiyam }
21873e701f1cSksagiyam 
2188b08ad5deSksagiyam /*@
2189b08ad5deSksagiyam   DMPlexLabelsLoad - Loads labels into a DMPlex
2190b08ad5deSksagiyam 
2191b08ad5deSksagiyam   Collective on DM
2192b08ad5deSksagiyam 
2193b08ad5deSksagiyam   Input Parameters:
2194b08ad5deSksagiyam + dm     - The DM into which the labels are loaded
2195e6368b79SVaclav Hapla . viewer - The PetscViewer for the saved labels
2196e6368b79SVaclav Hapla - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer
2197b08ad5deSksagiyam 
2198b08ad5deSksagiyam   Level: advanced
2199b08ad5deSksagiyam 
2200e6368b79SVaclav Hapla   Notes:
2201e6368b79SVaclav Hapla   The PetscSF argument must not be NULL if the DM is distributed, otherwise an error occurs.
2202e6368b79SVaclav Hapla 
2203db781477SPatrick Sanan .seealso: `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`
2204b08ad5deSksagiyam @*/
22059371c9d4SSatish Balay PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF) {
2206b08ad5deSksagiyam   PetscBool ishdf5;
2207b08ad5deSksagiyam 
2208b08ad5deSksagiyam   PetscFunctionBegin;
2209b08ad5deSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2210b08ad5deSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2211e6368b79SVaclav Hapla   if (globalToLocalPointSF) PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3);
22129566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
22139566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LabelsLoad, viewer, 0, 0, 0));
2214b08ad5deSksagiyam   if (ishdf5) {
2215b08ad5deSksagiyam #if defined(PETSC_HAVE_HDF5)
2216b08ad5deSksagiyam     PetscViewerFormat format;
2217b08ad5deSksagiyam 
22189566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
2219b08ad5deSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
22209566063dSJacob Faibussowitsch       PetscCall(DMPlexLabelsLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
222198921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2222b08ad5deSksagiyam #else
2223b08ad5deSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2224b08ad5deSksagiyam #endif
2225b08ad5deSksagiyam   }
22269566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LabelsLoad, viewer, 0, 0, 0));
2227b08ad5deSksagiyam   PetscFunctionReturn(0);
2228b08ad5deSksagiyam }
2229b08ad5deSksagiyam 
2230f84dd6b4Sksagiyam /*@
2231f84dd6b4Sksagiyam   DMPlexSectionLoad - Loads section into a DMPlex
2232f84dd6b4Sksagiyam 
2233f84dd6b4Sksagiyam   Collective on DM
2234f84dd6b4Sksagiyam 
2235f84dd6b4Sksagiyam   Input Parameters:
2236f84dd6b4Sksagiyam + dm          - The DM that represents the topology
2237f84dd6b4Sksagiyam . viewer      - The PetscViewer that represents the on-disk section (sectionA)
2238f84dd6b4Sksagiyam . sectiondm   - The DM into which the on-disk section (sectionA) is migrated
2239f84dd6b4Sksagiyam - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer
2240f84dd6b4Sksagiyam 
2241f84dd6b4Sksagiyam   Output Parameters
2242f84dd6b4Sksagiyam + 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)
2243f84dd6b4Sksagiyam - 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)
2244f84dd6b4Sksagiyam 
2245f84dd6b4Sksagiyam   Level: advanced
2246f84dd6b4Sksagiyam 
2247f84dd6b4Sksagiyam   Notes:
2248f84dd6b4Sksagiyam   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.
2249f84dd6b4Sksagiyam 
2250f84dd6b4Sksagiyam   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.
2251f84dd6b4Sksagiyam 
2252f84dd6b4Sksagiyam   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.
2253f84dd6b4Sksagiyam 
2254f84dd6b4Sksagiyam   Example using 2 processes:
2255f84dd6b4Sksagiyam $  NX (number of points on dm): 4
2256f84dd6b4Sksagiyam $  sectionA                   : the on-disk section
2257f84dd6b4Sksagiyam $  vecA                       : a vector associated with sectionA
2258f84dd6b4Sksagiyam $  sectionB                   : sectiondm's local section constructed in this function
2259f84dd6b4Sksagiyam $  vecB (local)               : a vector associated with sectiondm's local section
2260f84dd6b4Sksagiyam $  vecB (global)              : a vector associated with sectiondm's global section
2261f84dd6b4Sksagiyam $
2262f84dd6b4Sksagiyam $                                     rank 0    rank 1
2263f84dd6b4Sksagiyam $  vecA (global)                  : [.0 .4 .1 | .2 .3]        <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad()
2264f84dd6b4Sksagiyam $  sectionA->atlasOff             :       0 2 | 1             <- loaded in PetscSectionLoad()
2265f84dd6b4Sksagiyam $  sectionA->atlasDof             :       1 3 | 1             <- loaded in PetscSectionLoad()
2266f84dd6b4Sksagiyam $  sectionA's global point numbers:       0 2 | 3             <- loaded in DMPlexSectionLoad()
2267f84dd6b4Sksagiyam $  [0, NX)                        :       0 1 | 2 3           <- conceptual partition used in globalToLocalPointSF
2268f84dd6b4Sksagiyam $  sectionB's global point numbers:     0 1 3 | 3 2           <- associated with [0, NX) by globalToLocalPointSF
2269f84dd6b4Sksagiyam $  sectionB->atlasDof             :     1 0 1 | 1 3
2270f84dd6b4Sksagiyam $  sectionB->atlasOff (no perm)   :     0 1 1 | 0 1
2271f84dd6b4Sksagiyam $  vecB (local)                   :   [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF
2272f84dd6b4Sksagiyam $  vecB (global)                  :    [.0 .4 | .1 .2 .3]     <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF
2273f84dd6b4Sksagiyam $
2274f84dd6b4Sksagiyam $  where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0.
2275f84dd6b4Sksagiyam 
2276db781477SPatrick Sanan .seealso: `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`, `PetscSectionLoad()`, `DMPlexSectionView()`
2277f84dd6b4Sksagiyam @*/
22789371c9d4SSatish Balay PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF globalToLocalPointSF, PetscSF *globalDofSF, PetscSF *localDofSF) {
2279f84dd6b4Sksagiyam   PetscBool ishdf5;
2280f84dd6b4Sksagiyam 
2281f84dd6b4Sksagiyam   PetscFunctionBegin;
2282f84dd6b4Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2283f84dd6b4Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2284f84dd6b4Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
2285f84dd6b4Sksagiyam   PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4);
2286f84dd6b4Sksagiyam   if (globalDofSF) PetscValidPointer(globalDofSF, 5);
2287f84dd6b4Sksagiyam   if (localDofSF) PetscValidPointer(localDofSF, 6);
22889566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
22899566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_SectionLoad, viewer, 0, 0, 0));
2290f84dd6b4Sksagiyam   if (ishdf5) {
2291f84dd6b4Sksagiyam #if defined(PETSC_HAVE_HDF5)
22929566063dSJacob Faibussowitsch     PetscCall(DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF));
2293f84dd6b4Sksagiyam #else
2294f84dd6b4Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2295f84dd6b4Sksagiyam #endif
2296f84dd6b4Sksagiyam   }
22979566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_SectionLoad, viewer, 0, 0, 0));
2298f84dd6b4Sksagiyam   PetscFunctionReturn(0);
2299f84dd6b4Sksagiyam }
2300f84dd6b4Sksagiyam 
23018be3dfe1Sksagiyam /*@
23028be3dfe1Sksagiyam   DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector
23038be3dfe1Sksagiyam 
23048be3dfe1Sksagiyam   Collective on DM
23058be3dfe1Sksagiyam 
23068be3dfe1Sksagiyam   Input Parameters:
23078be3dfe1Sksagiyam + dm        - The DM that represents the topology
23088be3dfe1Sksagiyam . viewer    - The PetscViewer that represents the on-disk vector data
23098be3dfe1Sksagiyam . sectiondm - The DM that contains the global section on which vec is defined
23108be3dfe1Sksagiyam . sf        - The SF that migrates the on-disk vector data into vec
23118be3dfe1Sksagiyam - vec       - The global vector to set values of
23128be3dfe1Sksagiyam 
23138be3dfe1Sksagiyam   Level: advanced
23148be3dfe1Sksagiyam 
23158be3dfe1Sksagiyam   Notes:
23168be3dfe1Sksagiyam   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.
23178be3dfe1Sksagiyam 
23188be3dfe1Sksagiyam   Typical calling sequence
23198be3dfe1Sksagiyam $       DMCreate(PETSC_COMM_WORLD, &dm);
23208be3dfe1Sksagiyam $       DMSetType(dm, DMPLEX);
23218be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)dm, "topologydm_name");
23228be3dfe1Sksagiyam $       DMPlexTopologyLoad(dm, viewer, &sfX);
23238be3dfe1Sksagiyam $       DMClone(dm, &sectiondm);
23248be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
23258be3dfe1Sksagiyam $       DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL);
23268be3dfe1Sksagiyam $       DMGetGlobalVector(sectiondm, &vec);
23278be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)vec, "vec_name");
23288be3dfe1Sksagiyam $       DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec);
23298be3dfe1Sksagiyam $       DMRestoreGlobalVector(sectiondm, &vec);
23308be3dfe1Sksagiyam $       PetscSFDestroy(&gsf);
23318be3dfe1Sksagiyam $       PetscSFDestroy(&sfX);
23328be3dfe1Sksagiyam $       DMDestroy(&sectiondm);
23338be3dfe1Sksagiyam $       DMDestroy(&dm);
23348be3dfe1Sksagiyam 
2335db781477SPatrick Sanan .seealso: `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexLocalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`
23368be3dfe1Sksagiyam @*/
23379371c9d4SSatish Balay PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) {
23388be3dfe1Sksagiyam   PetscBool ishdf5;
23398be3dfe1Sksagiyam 
23408be3dfe1Sksagiyam   PetscFunctionBegin;
23418be3dfe1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
23428be3dfe1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
23438be3dfe1Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
23448be3dfe1Sksagiyam   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4);
23458be3dfe1Sksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 5);
23468be3dfe1Sksagiyam   /* Check consistency */
23478be3dfe1Sksagiyam   {
23488be3dfe1Sksagiyam     PetscSection section;
23498be3dfe1Sksagiyam     PetscBool    includesConstraints;
23508be3dfe1Sksagiyam     PetscInt     m, m1;
23518be3dfe1Sksagiyam 
23529566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
23539566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(sectiondm, &section));
23549566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
23559566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
23569566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
235763a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m);
23588be3dfe1Sksagiyam   }
23599566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
23609566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0));
23618be3dfe1Sksagiyam   if (ishdf5) {
23628be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5)
23639566063dSJacob Faibussowitsch     PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec));
23648be3dfe1Sksagiyam #else
23658be3dfe1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
23668be3dfe1Sksagiyam #endif
23678be3dfe1Sksagiyam   }
23689566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0));
23698be3dfe1Sksagiyam   PetscFunctionReturn(0);
23708be3dfe1Sksagiyam }
23718be3dfe1Sksagiyam 
23728be3dfe1Sksagiyam /*@
23738be3dfe1Sksagiyam   DMPlexLocalVectorLoad - Loads on-disk vector data into a local vector
23748be3dfe1Sksagiyam 
23758be3dfe1Sksagiyam   Collective on DM
23768be3dfe1Sksagiyam 
23778be3dfe1Sksagiyam   Input Parameters:
23788be3dfe1Sksagiyam + dm        - The DM that represents the topology
23798be3dfe1Sksagiyam . viewer    - The PetscViewer that represents the on-disk vector data
23808be3dfe1Sksagiyam . sectiondm - The DM that contains the local section on which vec is defined
23818be3dfe1Sksagiyam . sf        - The SF that migrates the on-disk vector data into vec
23828be3dfe1Sksagiyam - vec       - The local vector to set values of
23838be3dfe1Sksagiyam 
23848be3dfe1Sksagiyam   Level: advanced
23858be3dfe1Sksagiyam 
23868be3dfe1Sksagiyam   Notes:
23878be3dfe1Sksagiyam   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.
23888be3dfe1Sksagiyam 
23898be3dfe1Sksagiyam   Typical calling sequence
23908be3dfe1Sksagiyam $       DMCreate(PETSC_COMM_WORLD, &dm);
23918be3dfe1Sksagiyam $       DMSetType(dm, DMPLEX);
23928be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)dm, "topologydm_name");
23938be3dfe1Sksagiyam $       DMPlexTopologyLoad(dm, viewer, &sfX);
23948be3dfe1Sksagiyam $       DMClone(dm, &sectiondm);
23958be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
23968be3dfe1Sksagiyam $       DMPlexSectionLoad(dm, viewer, sectiondm, sfX, NULL, &lsf);
23978be3dfe1Sksagiyam $       DMGetLocalVector(sectiondm, &vec);
23988be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)vec, "vec_name");
23998be3dfe1Sksagiyam $       DMPlexLocalVectorLoad(dm, viewer, sectiondm, lsf, vec);
24008be3dfe1Sksagiyam $       DMRestoreLocalVector(sectiondm, &vec);
24018be3dfe1Sksagiyam $       PetscSFDestroy(&lsf);
24028be3dfe1Sksagiyam $       PetscSFDestroy(&sfX);
24038be3dfe1Sksagiyam $       DMDestroy(&sectiondm);
24048be3dfe1Sksagiyam $       DMDestroy(&dm);
24058be3dfe1Sksagiyam 
2406db781477SPatrick Sanan .seealso: `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`
24078be3dfe1Sksagiyam @*/
24089371c9d4SSatish Balay PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec) {
24098be3dfe1Sksagiyam   PetscBool ishdf5;
24108be3dfe1Sksagiyam 
24118be3dfe1Sksagiyam   PetscFunctionBegin;
24128be3dfe1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
24138be3dfe1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
24148be3dfe1Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
24158be3dfe1Sksagiyam   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4);
24168be3dfe1Sksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 5);
24178be3dfe1Sksagiyam   /* Check consistency */
24188be3dfe1Sksagiyam   {
24198be3dfe1Sksagiyam     PetscSection section;
24208be3dfe1Sksagiyam     PetscBool    includesConstraints;
24218be3dfe1Sksagiyam     PetscInt     m, m1;
24228be3dfe1Sksagiyam 
24239566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
24249566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(sectiondm, &section));
24259566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
24269566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
24279566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
242863a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m);
24298be3dfe1Sksagiyam   }
24309566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
24319566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0));
24328be3dfe1Sksagiyam   if (ishdf5) {
24338be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5)
24349566063dSJacob Faibussowitsch     PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec));
24358be3dfe1Sksagiyam #else
24368be3dfe1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
24378be3dfe1Sksagiyam #endif
24388be3dfe1Sksagiyam   }
24399566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0));
24408be3dfe1Sksagiyam   PetscFunctionReturn(0);
24418be3dfe1Sksagiyam }
24428be3dfe1Sksagiyam 
24439371c9d4SSatish Balay PetscErrorCode DMDestroy_Plex(DM dm) {
2444552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2445552f7358SJed Brown 
2446552f7358SJed Brown   PetscFunctionBegin;
24479566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", NULL));
24489566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", NULL));
24499566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", NULL));
24509566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", NULL));
24512e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerviativeBoundaryValues_C", NULL));
24522e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL));
24532e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", NULL));
24542e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", NULL));
24552e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "MatComputeNeumannOverlap_C", NULL));
24566bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", NULL));
24576bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", NULL));
2458c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL));
2459c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", NULL));
24600d644c17SKarl Rupp   if (--mesh->refct > 0) PetscFunctionReturn(0);
24619566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->coneSection));
24629566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->cones));
24639566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->coneOrientations));
24649566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->supportSection));
24659566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->subdomainSection));
24669566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->supports));
24679566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->facesTmp));
24689566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->tetgenOpts));
24699566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->triangleOpts));
24709566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->transformType));
24711d1f2f2aSksagiyam   PetscCall(PetscFree(mesh->distributionName));
24729566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerDestroy(&mesh->partitioner));
24739566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&mesh->subpointMap));
24749566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->subpointIS));
24759566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->globalVertexNumbers));
24769566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->globalCellNumbers));
24779566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->anchorSection));
24789566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->anchorIS));
24799566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->parentSection));
24809566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->parents));
24819566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->childIDs));
24829566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->childSection));
24839566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->children));
24849566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&mesh->referenceTree));
24859566063dSJacob Faibussowitsch   PetscCall(PetscGridHashDestroy(&mesh->lbox));
24869566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->neighbors));
24879566063dSJacob Faibussowitsch   if (mesh->metricCtx) PetscCall(PetscFree(mesh->metricCtx));
2488552f7358SJed Brown   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
24899566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh));
2490552f7358SJed Brown   PetscFunctionReturn(0);
2491552f7358SJed Brown }
2492552f7358SJed Brown 
24939371c9d4SSatish Balay PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J) {
24948d1174e4SMatthew G. Knepley   PetscSection           sectionGlobal;
2495acd755d7SMatthew G. Knepley   PetscInt               bs = -1, mbs;
24969fca9976SJed Brown   PetscInt               localSize, localStart = 0;
2497837628f4SStefano Zampini   PetscBool              isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS;
2498b412c318SBarry Smith   MatType                mtype;
24991428887cSShri Abhyankar   ISLocalToGlobalMapping ltog;
2500552f7358SJed Brown 
2501552f7358SJed Brown   PetscFunctionBegin;
25029566063dSJacob Faibussowitsch   PetscCall(MatInitializePackage());
2503b412c318SBarry Smith   mtype = dm->mattype;
25049566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dm, &sectionGlobal));
25059566063dSJacob Faibussowitsch   /* PetscCall(PetscSectionGetStorageSize(sectionGlobal, &localSize)); */
25069566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize));
25079fca9976SJed Brown   PetscCallMPI(MPI_Exscan(&localSize, &localStart, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)dm)));
25089566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), J));
25099566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE));
25109566063dSJacob Faibussowitsch   PetscCall(MatSetType(*J, mtype));
25119566063dSJacob Faibussowitsch   PetscCall(MatSetFromOptions(*J));
25129566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(*J, &mbs));
2513acd755d7SMatthew G. Knepley   if (mbs > 1) bs = mbs;
25149566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSHELL, &isShell));
25159566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATBAIJ, &isBlock));
25169566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock));
25179566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock));
25189566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSBAIJ, &isSymBlock));
25199566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock));
25209566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock));
25219566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATIS, &isMatIS));
2522552f7358SJed Brown   if (!isShell) {
2523837628f4SStefano Zampini     PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS);
25249fca9976SJed Brown     PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *pblocks;
2525fad22124SMatthew G Knepley     PetscInt  pStart, pEnd, p, dof, cdof;
2526552f7358SJed Brown 
25279566063dSJacob Faibussowitsch     PetscCall(DMGetLocalToGlobalMapping(dm, &ltog));
25289fca9976SJed Brown 
25299fca9976SJed Brown     PetscCall(PetscCalloc1(localSize, &pblocks));
25309566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(sectionGlobal, &pStart, &pEnd));
2531e432b41dSStefano Zampini     for (p = pStart; p < pEnd; ++p) {
25329fca9976SJed Brown       PetscInt bdof, offset;
2533a9d99c84SMatthew G. Knepley 
25349566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sectionGlobal, p, &dof));
25359fca9976SJed Brown       PetscCall(PetscSectionGetOffset(sectionGlobal, p, &offset));
25369566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetConstraintDof(sectionGlobal, p, &cdof));
25379371c9d4SSatish Balay       for (PetscInt i = 0; i < dof - cdof; i++) pblocks[offset - localStart + i] = dof - cdof;
25381d17a0a3SMatthew G. Knepley       dof  = dof < 0 ? -(dof + 1) : dof;
25391d17a0a3SMatthew G. Knepley       bdof = cdof && (dof - cdof) ? 1 : dof;
25401d17a0a3SMatthew G. Knepley       if (dof) {
25419371c9d4SSatish Balay         if (bs < 0) {
25429371c9d4SSatish Balay           bs = bdof;
25439371c9d4SSatish Balay         } else if (bs != bdof) {
25449371c9d4SSatish Balay           bs = 1;
25459371c9d4SSatish Balay         }
2546552f7358SJed Brown       }
25472a28c762SMatthew G Knepley     }
25482a28c762SMatthew G Knepley     /* Must have same blocksize on all procs (some might have no points) */
2549e432b41dSStefano Zampini     bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs;
2550e432b41dSStefano Zampini     bsLocal[1] = bs;
25519566063dSJacob Faibussowitsch     PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax));
2552e432b41dSStefano Zampini     if (bsMinMax[0] != bsMinMax[1]) bs = 1;
2553e432b41dSStefano Zampini     else bs = bsMinMax[0];
25546fd5c86aSStefano Zampini     bs = PetscMax(1, bs);
25559566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(*J, ltog, ltog));
25560682b8bbSJed Brown     if (dm->prealloc_skip) { // User will likely use MatSetPreallocationCOO(), but still set structural parameters
25579566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSize(*J, bs));
25589566063dSJacob Faibussowitsch       PetscCall(MatSetUp(*J));
25590682b8bbSJed Brown     } else {
25609566063dSJacob Faibussowitsch       PetscCall(PetscCalloc4(localSize / bs, &dnz, localSize / bs, &onz, localSize / bs, &dnzu, localSize / bs, &onzu));
25619566063dSJacob Faibussowitsch       PetscCall(DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix));
25629566063dSJacob Faibussowitsch       PetscCall(PetscFree4(dnz, onz, dnzu, onzu));
2563552f7358SJed Brown     }
25649fca9976SJed Brown     { // Consolidate blocks
25659fca9976SJed Brown       PetscInt nblocks = 0;
25669fca9976SJed Brown       for (PetscInt i = 0; i < localSize; i += PetscMax(1, pblocks[i])) {
25679fca9976SJed Brown         if (pblocks[i] == 0) continue;
25689fca9976SJed Brown         pblocks[nblocks++] = pblocks[i]; // nblocks always <= i
2569ad540459SPierre Jolivet         for (PetscInt j = 1; j < pblocks[i]; j++) 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]);
25709fca9976SJed Brown       }
25719fca9976SJed Brown       PetscCall(MatSetVariableBlockSizes(*J, nblocks, pblocks));
25729fca9976SJed Brown     }
25739fca9976SJed Brown     PetscCall(PetscFree(pblocks));
2574aa0f6e3cSJed Brown   }
25759566063dSJacob Faibussowitsch   PetscCall(MatSetDM(*J, dm));
2576552f7358SJed Brown   PetscFunctionReturn(0);
2577552f7358SJed Brown }
2578552f7358SJed Brown 
25797cd05799SMatthew G. Knepley /*@
2580a8f00d21SMatthew G. Knepley   DMPlexGetSubdomainSection - Returns the section associated with the subdomain
2581be36d101SStefano Zampini 
2582be36d101SStefano Zampini   Not collective
2583be36d101SStefano Zampini 
2584be36d101SStefano Zampini   Input Parameter:
2585be36d101SStefano Zampini . mesh - The DMPlex
2586be36d101SStefano Zampini 
2587be36d101SStefano Zampini   Output Parameters:
2588be36d101SStefano Zampini . subsection - The subdomain section
2589be36d101SStefano Zampini 
2590be36d101SStefano Zampini   Level: developer
2591be36d101SStefano Zampini 
2592be36d101SStefano Zampini .seealso:
25937cd05799SMatthew G. Knepley @*/
25949371c9d4SSatish Balay PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection) {
2595be36d101SStefano Zampini   DM_Plex *mesh = (DM_Plex *)dm->data;
2596be36d101SStefano Zampini 
2597be36d101SStefano Zampini   PetscFunctionBegin;
2598be36d101SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2599be36d101SStefano Zampini   if (!mesh->subdomainSection) {
2600be36d101SStefano Zampini     PetscSection section;
2601be36d101SStefano Zampini     PetscSF      sf;
2602be36d101SStefano Zampini 
26039566063dSJacob Faibussowitsch     PetscCall(PetscSFCreate(PETSC_COMM_SELF, &sf));
26049566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
26059566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_TRUE, &mesh->subdomainSection));
26069566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sf));
2607be36d101SStefano Zampini   }
2608be36d101SStefano Zampini   *subsection = mesh->subdomainSection;
2609be36d101SStefano Zampini   PetscFunctionReturn(0);
2610be36d101SStefano Zampini }
2611be36d101SStefano Zampini 
2612552f7358SJed Brown /*@
2613552f7358SJed Brown   DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd)
2614552f7358SJed Brown 
2615552f7358SJed Brown   Not collective
2616552f7358SJed Brown 
2617552f7358SJed Brown   Input Parameter:
2618552f7358SJed Brown . mesh - The DMPlex
2619552f7358SJed Brown 
2620552f7358SJed Brown   Output Parameters:
2621552f7358SJed Brown + pStart - The first mesh point
2622552f7358SJed Brown - pEnd   - The upper bound for mesh points
2623552f7358SJed Brown 
2624552f7358SJed Brown   Level: beginner
2625552f7358SJed Brown 
2626db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetChart()`
2627552f7358SJed Brown @*/
26289371c9d4SSatish Balay PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) {
2629552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2630552f7358SJed Brown 
2631552f7358SJed Brown   PetscFunctionBegin;
2632552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
26339566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->coneSection, pStart, pEnd));
2634552f7358SJed Brown   PetscFunctionReturn(0);
2635552f7358SJed Brown }
2636552f7358SJed Brown 
2637552f7358SJed Brown /*@
2638552f7358SJed Brown   DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd)
2639552f7358SJed Brown 
2640552f7358SJed Brown   Not collective
2641552f7358SJed Brown 
2642552f7358SJed Brown   Input Parameters:
2643552f7358SJed Brown + mesh - The DMPlex
2644552f7358SJed Brown . pStart - The first mesh point
2645552f7358SJed Brown - pEnd   - The upper bound for mesh points
2646552f7358SJed Brown 
2647552f7358SJed Brown   Output Parameters:
2648552f7358SJed Brown 
2649552f7358SJed Brown   Level: beginner
2650552f7358SJed Brown 
2651db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetChart()`
2652552f7358SJed Brown @*/
26539371c9d4SSatish Balay PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) {
2654552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2655552f7358SJed Brown 
2656552f7358SJed Brown   PetscFunctionBegin;
2657552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
26589566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(mesh->coneSection, pStart, pEnd));
26599566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(mesh->supportSection, pStart, pEnd));
2660552f7358SJed Brown   PetscFunctionReturn(0);
2661552f7358SJed Brown }
2662552f7358SJed Brown 
2663552f7358SJed Brown /*@
2664eaf898f9SPatrick Sanan   DMPlexGetConeSize - Return the number of in-edges for this point in the DAG
2665552f7358SJed Brown 
2666552f7358SJed Brown   Not collective
2667552f7358SJed Brown 
2668552f7358SJed Brown   Input Parameters:
2669552f7358SJed Brown + mesh - The DMPlex
2670eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
2671552f7358SJed Brown 
2672552f7358SJed Brown   Output Parameter:
2673552f7358SJed Brown . size - The cone size for point p
2674552f7358SJed Brown 
2675552f7358SJed Brown   Level: beginner
2676552f7358SJed Brown 
2677db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`
2678552f7358SJed Brown @*/
26799371c9d4SSatish Balay PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) {
2680552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2681552f7358SJed Brown 
2682552f7358SJed Brown   PetscFunctionBegin;
2683552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2684dadcf809SJacob Faibussowitsch   PetscValidIntPointer(size, 3);
26859566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, size));
2686552f7358SJed Brown   PetscFunctionReturn(0);
2687552f7358SJed Brown }
2688552f7358SJed Brown 
2689552f7358SJed Brown /*@
2690eaf898f9SPatrick Sanan   DMPlexSetConeSize - Set the number of in-edges for this point in the DAG
2691552f7358SJed Brown 
2692552f7358SJed Brown   Not collective
2693552f7358SJed Brown 
2694552f7358SJed Brown   Input Parameters:
2695552f7358SJed Brown + mesh - The DMPlex
2696eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
2697552f7358SJed Brown - size - The cone size for point p
2698552f7358SJed Brown 
2699552f7358SJed Brown   Output Parameter:
2700552f7358SJed Brown 
2701552f7358SJed Brown   Note:
2702552f7358SJed Brown   This should be called after DMPlexSetChart().
2703552f7358SJed Brown 
2704552f7358SJed Brown   Level: beginner
2705552f7358SJed Brown 
2706db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetConeSize()`, `DMPlexSetChart()`
2707552f7358SJed Brown @*/
27089371c9d4SSatish Balay PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) {
2709552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2710552f7358SJed Brown 
2711552f7358SJed Brown   PetscFunctionBegin;
2712552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
27139566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetDof(mesh->coneSection, p, size));
2714552f7358SJed Brown   PetscFunctionReturn(0);
2715552f7358SJed Brown }
2716552f7358SJed Brown 
2717f5a469b9SMatthew G. Knepley /*@
2718eaf898f9SPatrick Sanan   DMPlexAddConeSize - Add the given number of in-edges to this point in the DAG
2719f5a469b9SMatthew G. Knepley 
2720f5a469b9SMatthew G. Knepley   Not collective
2721f5a469b9SMatthew G. Knepley 
2722f5a469b9SMatthew G. Knepley   Input Parameters:
2723f5a469b9SMatthew G. Knepley + mesh - The DMPlex
2724eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
2725f5a469b9SMatthew G. Knepley - size - The additional cone size for point p
2726f5a469b9SMatthew G. Knepley 
2727f5a469b9SMatthew G. Knepley   Output Parameter:
2728f5a469b9SMatthew G. Knepley 
2729f5a469b9SMatthew G. Knepley   Note:
2730f5a469b9SMatthew G. Knepley   This should be called after DMPlexSetChart().
2731f5a469b9SMatthew G. Knepley 
2732f5a469b9SMatthew G. Knepley   Level: beginner
2733f5a469b9SMatthew G. Knepley 
2734db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexGetConeSize()`, `DMPlexSetChart()`
2735f5a469b9SMatthew G. Knepley @*/
27369371c9d4SSatish Balay PetscErrorCode DMPlexAddConeSize(DM dm, PetscInt p, PetscInt size) {
2737f5a469b9SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
2738f5a469b9SMatthew G. Knepley   PetscFunctionBegin;
2739f5a469b9SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
27409566063dSJacob Faibussowitsch   PetscCall(PetscSectionAddDof(mesh->coneSection, p, size));
2741f5a469b9SMatthew G. Knepley   PetscFunctionReturn(0);
2742f5a469b9SMatthew G. Knepley }
2743f5a469b9SMatthew G. Knepley 
2744552f7358SJed Brown /*@C
2745eaf898f9SPatrick Sanan   DMPlexGetCone - Return the points on the in-edges for this point in the DAG
2746552f7358SJed Brown 
2747552f7358SJed Brown   Not collective
2748552f7358SJed Brown 
2749552f7358SJed Brown   Input Parameters:
2750833c876bSVaclav Hapla + dm - The DMPlex
2751eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
2752552f7358SJed Brown 
2753552f7358SJed Brown   Output Parameter:
2754552f7358SJed Brown . cone - An array of points which are on the in-edges for point p
2755552f7358SJed Brown 
2756552f7358SJed Brown   Level: beginner
2757552f7358SJed Brown 
27583813dfbdSMatthew G Knepley   Fortran Notes:
27593813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
27603813dfbdSMatthew G Knepley   include petsc.h90 in your code.
2761922102d1SVaclav Hapla   You must also call DMPlexRestoreCone() after you finish using the returned array.
2762922102d1SVaclav Hapla   DMPlexRestoreCone() is not needed/available in C.
27633813dfbdSMatthew G Knepley 
2764db781477SPatrick Sanan .seealso: `DMPlexGetConeSize()`, `DMPlexSetCone()`, `DMPlexGetConeTuple()`, `DMPlexSetChart()`
2765552f7358SJed Brown @*/
27669371c9d4SSatish Balay PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) {
2767552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2768552f7358SJed Brown   PetscInt off;
2769552f7358SJed Brown 
2770552f7358SJed Brown   PetscFunctionBegin;
2771552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2772552f7358SJed Brown   PetscValidPointer(cone, 3);
27739566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
2774552f7358SJed Brown   *cone = &mesh->cones[off];
2775552f7358SJed Brown   PetscFunctionReturn(0);
2776552f7358SJed Brown }
2777552f7358SJed Brown 
27780ce7577fSVaclav Hapla /*@C
27790ce7577fSVaclav Hapla   DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG
27800ce7577fSVaclav Hapla 
27810ce7577fSVaclav Hapla   Not collective
27820ce7577fSVaclav Hapla 
27830ce7577fSVaclav Hapla   Input Parameters:
27840ce7577fSVaclav Hapla + dm - The DMPlex
27850ce7577fSVaclav Hapla - p - The IS of points, which must lie in the chart set with DMPlexSetChart()
27860ce7577fSVaclav Hapla 
2787d8d19677SJose E. Roman   Output Parameters:
27880ce7577fSVaclav Hapla + pConesSection - PetscSection describing the layout of pCones
27890ce7577fSVaclav Hapla - pCones - An array of points which are on the in-edges for the point set p
27900ce7577fSVaclav Hapla 
27910ce7577fSVaclav Hapla   Level: intermediate
27920ce7577fSVaclav Hapla 
2793db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeRecursive()`, `DMPlexSetChart()`
27940ce7577fSVaclav Hapla @*/
27959371c9d4SSatish Balay PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones) {
27960ce7577fSVaclav Hapla   PetscSection cs, newcs;
27970ce7577fSVaclav Hapla   PetscInt    *cones;
27980ce7577fSVaclav Hapla   PetscInt    *newarr = NULL;
27990ce7577fSVaclav Hapla   PetscInt     n;
28000ce7577fSVaclav Hapla 
28010ce7577fSVaclav Hapla   PetscFunctionBegin;
28029566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCones(dm, &cones));
28039566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSection(dm, &cs));
28049566063dSJacob Faibussowitsch   PetscCall(PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void **)&newarr) : NULL));
28050ce7577fSVaclav Hapla   if (pConesSection) *pConesSection = newcs;
28060ce7577fSVaclav Hapla   if (pCones) {
28079566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(newcs, &n));
28089566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones));
28090ce7577fSVaclav Hapla   }
28100ce7577fSVaclav Hapla   PetscFunctionReturn(0);
28110ce7577fSVaclav Hapla }
28120ce7577fSVaclav Hapla 
2813af9eab45SVaclav Hapla /*@
2814af9eab45SVaclav Hapla   DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices.
2815d4636a37SVaclav Hapla 
2816d4636a37SVaclav Hapla   Not collective
2817d4636a37SVaclav Hapla 
2818d4636a37SVaclav Hapla   Input Parameters:
2819d4636a37SVaclav Hapla + dm - The DMPlex
2820af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart()
2821d4636a37SVaclav Hapla 
2822d4636a37SVaclav Hapla   Output Parameter:
2823af9eab45SVaclav Hapla . expandedPoints - An array of vertices recursively expanded from input points
2824d4636a37SVaclav Hapla 
2825d4636a37SVaclav Hapla   Level: advanced
2826d4636a37SVaclav Hapla 
2827af9eab45SVaclav Hapla   Notes:
2828af9eab45SVaclav Hapla   Like DMPlexGetConeRecursive but returns only the 0-depth IS (i.e. vertices only) and no sections.
2829af9eab45SVaclav Hapla   There is no corresponding Restore function, just call ISDestroy() on the returned IS to deallocate.
2830af9eab45SVaclav Hapla 
2831db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetDepth()`
2832d4636a37SVaclav Hapla @*/
28339371c9d4SSatish Balay PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints) {
2834af9eab45SVaclav Hapla   IS      *expandedPointsAll;
2835af9eab45SVaclav Hapla   PetscInt depth;
2836d4636a37SVaclav Hapla 
2837d4636a37SVaclav Hapla   PetscFunctionBegin;
2838af9eab45SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2839af9eab45SVaclav Hapla   PetscValidHeaderSpecific(points, IS_CLASSID, 2);
2840af9eab45SVaclav Hapla   PetscValidPointer(expandedPoints, 3);
28419566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL));
2842af9eab45SVaclav Hapla   *expandedPoints = expandedPointsAll[0];
28439566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)expandedPointsAll[0]));
28449566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL));
2845af9eab45SVaclav Hapla   PetscFunctionReturn(0);
2846af9eab45SVaclav Hapla }
2847af9eab45SVaclav Hapla 
2848af9eab45SVaclav Hapla /*@
2849af9eab45SVaclav 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).
2850af9eab45SVaclav Hapla 
2851af9eab45SVaclav Hapla   Not collective
2852af9eab45SVaclav Hapla 
2853af9eab45SVaclav Hapla   Input Parameters:
2854af9eab45SVaclav Hapla + dm - The DMPlex
2855af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart()
2856af9eab45SVaclav Hapla 
2857d8d19677SJose E. Roman   Output Parameters:
2858af9eab45SVaclav Hapla + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth()
2859af9eab45SVaclav Hapla . expandedPoints - (optional) An array of index sets with recursively expanded cones
2860af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points
2861af9eab45SVaclav Hapla 
2862af9eab45SVaclav Hapla   Level: advanced
2863af9eab45SVaclav Hapla 
2864af9eab45SVaclav Hapla   Notes:
2865af9eab45SVaclav Hapla   Like DMPlexGetConeTuple() but recursive.
2866af9eab45SVaclav Hapla 
2867af9eab45SVaclav 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.
2868af9eab45SVaclav Hapla   For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc.
2869af9eab45SVaclav Hapla 
2870af9eab45SVaclav 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:
2871af9eab45SVaclav Hapla   (1) DAG points in expandedPoints[d+1] with depth d+1 to their cone points in expandedPoints[d];
2872af9eab45SVaclav Hapla   (2) DAG points in expandedPoints[d+1] with depth in [0,d] to the same points in expandedPoints[d].
2873af9eab45SVaclav Hapla 
2874db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, `DMPlexGetDepth()`
2875af9eab45SVaclav Hapla @*/
28769371c9d4SSatish Balay PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) {
2877af9eab45SVaclav Hapla   const PetscInt *arr0 = NULL, *cone = NULL;
2878af9eab45SVaclav Hapla   PetscInt       *arr = NULL, *newarr = NULL;
2879af9eab45SVaclav Hapla   PetscInt        d, depth_, i, n, newn, cn, co, start, end;
2880af9eab45SVaclav Hapla   IS             *expandedPoints_;
2881af9eab45SVaclav Hapla   PetscSection   *sections_;
2882af9eab45SVaclav Hapla 
2883af9eab45SVaclav Hapla   PetscFunctionBegin;
2884af9eab45SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2885af9eab45SVaclav Hapla   PetscValidHeaderSpecific(points, IS_CLASSID, 2);
2886af9eab45SVaclav Hapla   if (depth) PetscValidIntPointer(depth, 3);
2887af9eab45SVaclav Hapla   if (expandedPoints) PetscValidPointer(expandedPoints, 4);
2888af9eab45SVaclav Hapla   if (sections) PetscValidPointer(sections, 5);
28899566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(points, &n));
28909566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(points, &arr0));
28919566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth_));
28929566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(depth_, &expandedPoints_));
28939566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(depth_, &sections_));
2894af9eab45SVaclav Hapla   arr = (PetscInt *)arr0; /* this is ok because first generation of arr is not modified */
2895af9eab45SVaclav Hapla   for (d = depth_ - 1; d >= 0; d--) {
28969566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &sections_[d]));
28979566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(sections_[d], 0, n));
2898af9eab45SVaclav Hapla     for (i = 0; i < n; i++) {
28999566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d + 1, &start, &end));
2900af9eab45SVaclav Hapla       if (arr[i] >= start && arr[i] < end) {
29019566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, arr[i], &cn));
29029566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetDof(sections_[d], i, cn));
2903af9eab45SVaclav Hapla       } else {
29049566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetDof(sections_[d], i, 1));
2905af9eab45SVaclav Hapla       }
2906af9eab45SVaclav Hapla     }
29079566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(sections_[d]));
29089566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(sections_[d], &newn));
29099566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(newn, &newarr));
2910af9eab45SVaclav Hapla     for (i = 0; i < n; i++) {
29119566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sections_[d], i, &cn));
29129566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(sections_[d], i, &co));
2913af9eab45SVaclav Hapla       if (cn > 1) {
29149566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, arr[i], &cone));
29159566063dSJacob Faibussowitsch         PetscCall(PetscMemcpy(&newarr[co], cone, cn * sizeof(PetscInt)));
2916af9eab45SVaclav Hapla       } else {
2917af9eab45SVaclav Hapla         newarr[co] = arr[i];
2918af9eab45SVaclav Hapla       }
2919af9eab45SVaclav Hapla     }
29209566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d]));
2921af9eab45SVaclav Hapla     arr = newarr;
2922af9eab45SVaclav Hapla     n   = newn;
2923af9eab45SVaclav Hapla   }
29249566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(points, &arr0));
2925af9eab45SVaclav Hapla   *depth = depth_;
2926af9eab45SVaclav Hapla   if (expandedPoints) *expandedPoints = expandedPoints_;
2927af9eab45SVaclav Hapla   else {
29289566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&expandedPoints_[d]));
29299566063dSJacob Faibussowitsch     PetscCall(PetscFree(expandedPoints_));
2930af9eab45SVaclav Hapla   }
2931af9eab45SVaclav Hapla   if (sections) *sections = sections_;
2932af9eab45SVaclav Hapla   else {
29339566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(&sections_[d]));
29349566063dSJacob Faibussowitsch     PetscCall(PetscFree(sections_));
2935af9eab45SVaclav Hapla   }
2936af9eab45SVaclav Hapla   PetscFunctionReturn(0);
2937af9eab45SVaclav Hapla }
2938af9eab45SVaclav Hapla 
2939af9eab45SVaclav Hapla /*@
2940af9eab45SVaclav Hapla   DMPlexRestoreConeRecursive - Deallocates arrays created by DMPlexGetConeRecursive
2941af9eab45SVaclav Hapla 
2942af9eab45SVaclav Hapla   Not collective
2943af9eab45SVaclav Hapla 
2944af9eab45SVaclav Hapla   Input Parameters:
2945af9eab45SVaclav Hapla + dm - The DMPlex
2946af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart()
2947af9eab45SVaclav Hapla 
2948d8d19677SJose E. Roman   Output Parameters:
2949af9eab45SVaclav Hapla + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth()
2950af9eab45SVaclav Hapla . expandedPoints - (optional) An array of recursively expanded cones
2951af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points
2952af9eab45SVaclav Hapla 
2953af9eab45SVaclav Hapla   Level: advanced
2954af9eab45SVaclav Hapla 
2955af9eab45SVaclav Hapla   Notes:
2956af9eab45SVaclav Hapla   See DMPlexGetConeRecursive() for details.
2957af9eab45SVaclav Hapla 
2958db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, `DMPlexGetDepth()`
2959af9eab45SVaclav Hapla @*/
29609371c9d4SSatish Balay PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[]) {
2961af9eab45SVaclav Hapla   PetscInt d, depth_;
2962af9eab45SVaclav Hapla 
2963af9eab45SVaclav Hapla   PetscFunctionBegin;
29649566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth_));
29651dca8a05SBarry Smith   PetscCheck(!depth || *depth == depth_, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive");
2966af9eab45SVaclav Hapla   if (depth) *depth = 0;
2967af9eab45SVaclav Hapla   if (expandedPoints) {
29689566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&((*expandedPoints)[d])));
29699566063dSJacob Faibussowitsch     PetscCall(PetscFree(*expandedPoints));
2970af9eab45SVaclav Hapla   }
2971af9eab45SVaclav Hapla   if (sections) {
29729566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(&((*sections)[d])));
29739566063dSJacob Faibussowitsch     PetscCall(PetscFree(*sections));
2974af9eab45SVaclav Hapla   }
2975d4636a37SVaclav Hapla   PetscFunctionReturn(0);
2976d4636a37SVaclav Hapla }
2977d4636a37SVaclav Hapla 
2978552f7358SJed Brown /*@
297992371b87SBarry 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
2980552f7358SJed Brown 
2981552f7358SJed Brown   Not collective
2982552f7358SJed Brown 
2983552f7358SJed Brown   Input Parameters:
2984552f7358SJed Brown + mesh - The DMPlex
2985eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
2986552f7358SJed Brown - cone - An array of points which are on the in-edges for point p
2987552f7358SJed Brown 
2988552f7358SJed Brown   Output Parameter:
2989552f7358SJed Brown 
2990552f7358SJed Brown   Note:
2991552f7358SJed Brown   This should be called after all calls to DMPlexSetConeSize() and DMSetUp().
2992552f7358SJed Brown 
2993552f7358SJed Brown   Level: beginner
2994552f7358SJed Brown 
2995db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`, `DMPlexSetSupport()`, `DMPlexSetSupportSize()`
2996552f7358SJed Brown @*/
29979371c9d4SSatish Balay PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) {
2998552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2999552f7358SJed Brown   PetscInt pStart, pEnd;
3000552f7358SJed Brown   PetscInt dof, off, c;
3001552f7358SJed Brown 
3002552f7358SJed Brown   PetscFunctionBegin;
3003552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
30049566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
30059566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
3006dadcf809SJacob Faibussowitsch   if (dof) PetscValidIntPointer(cone, 3);
30079566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
300863a3b9bcSJacob 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);
3009552f7358SJed Brown   for (c = 0; c < dof; ++c) {
301063a3b9bcSJacob 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);
3011552f7358SJed Brown     mesh->cones[off + c] = cone[c];
3012552f7358SJed Brown   }
3013552f7358SJed Brown   PetscFunctionReturn(0);
3014552f7358SJed Brown }
3015552f7358SJed Brown 
3016552f7358SJed Brown /*@C
3017eaf898f9SPatrick Sanan   DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG
3018552f7358SJed Brown 
3019552f7358SJed Brown   Not collective
3020552f7358SJed Brown 
3021552f7358SJed Brown   Input Parameters:
3022552f7358SJed Brown + mesh - The DMPlex
3023eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
3024552f7358SJed Brown 
3025552f7358SJed Brown   Output Parameter:
3026552f7358SJed Brown . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an
3027b5a892a1SMatthew G. Knepley                     integer giving the prescription for cone traversal.
3028552f7358SJed Brown 
3029552f7358SJed Brown   Level: beginner
3030552f7358SJed Brown 
3031b5a892a1SMatthew G. Knepley   Notes:
3032b5a892a1SMatthew G. Knepley   The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always
3033b5a892a1SMatthew G. Knepley   the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection
3034b5a892a1SMatthew G. Knepley   of o, however it is not necessarily the inverse. To get the inverse, use DMPolytopeTypeComposeOrientationInv()
3035b5a892a1SMatthew G. Knepley   with the identity.
3036b5a892a1SMatthew G. Knepley 
30373813dfbdSMatthew G Knepley   Fortran Notes:
30383813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
30393813dfbdSMatthew G Knepley   include petsc.h90 in your code.
30403b12b3d8SVaclav Hapla   You must also call DMPlexRestoreConeOrientation() after you finish using the returned array.
3041922102d1SVaclav Hapla   DMPlexRestoreConeOrientation() is not needed/available in C.
30423813dfbdSMatthew G Knepley 
3043db781477SPatrick Sanan .seealso: `DMPolytopeTypeComposeOrientation()`, `DMPolytopeTypeComposeOrientationInv()`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetCone()`, `DMPlexSetChart()`
3044552f7358SJed Brown @*/
30459371c9d4SSatish Balay PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) {
3046552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3047552f7358SJed Brown   PetscInt off;
3048552f7358SJed Brown 
3049552f7358SJed Brown   PetscFunctionBegin;
3050552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
305176bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
3052552f7358SJed Brown     PetscInt dof;
30539566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
3054552f7358SJed Brown     if (dof) PetscValidPointer(coneOrientation, 3);
3055552f7358SJed Brown   }
30569566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
30570d644c17SKarl Rupp 
3058552f7358SJed Brown   *coneOrientation = &mesh->coneOrientations[off];
3059552f7358SJed Brown   PetscFunctionReturn(0);
3060552f7358SJed Brown }
3061552f7358SJed Brown 
3062552f7358SJed Brown /*@
3063eaf898f9SPatrick Sanan   DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG
3064552f7358SJed Brown 
3065552f7358SJed Brown   Not collective
3066552f7358SJed Brown 
3067552f7358SJed Brown   Input Parameters:
3068552f7358SJed Brown + mesh - The DMPlex
3069eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
3070b5a892a1SMatthew G. Knepley - coneOrientation - An array of orientations
3071552f7358SJed Brown   Output Parameter:
3072552f7358SJed Brown 
3073b5a892a1SMatthew G. Knepley   Notes:
3074552f7358SJed Brown   This should be called after all calls to DMPlexSetConeSize() and DMSetUp().
3075552f7358SJed Brown 
3076b5a892a1SMatthew G. Knepley   The meaning of coneOrientation is detailed in DMPlexGetConeOrientation().
3077b5a892a1SMatthew G. Knepley 
3078552f7358SJed Brown   Level: beginner
3079552f7358SJed Brown 
3080db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetConeOrientation()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
3081552f7358SJed Brown @*/
30829371c9d4SSatish Balay PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) {
3083552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3084552f7358SJed Brown   PetscInt pStart, pEnd;
3085552f7358SJed Brown   PetscInt dof, off, c;
3086552f7358SJed Brown 
3087552f7358SJed Brown   PetscFunctionBegin;
3088552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
30899566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
30909566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
3091dadcf809SJacob Faibussowitsch   if (dof) PetscValidIntPointer(coneOrientation, 3);
30929566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
309363a3b9bcSJacob 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);
3094552f7358SJed Brown   for (c = 0; c < dof; ++c) {
3095552f7358SJed Brown     PetscInt cdof, o = coneOrientation[c];
3096552f7358SJed Brown 
30979566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, mesh->cones[off + c], &cdof));
30981dca8a05SBarry 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);
3099552f7358SJed Brown     mesh->coneOrientations[off + c] = o;
3100552f7358SJed Brown   }
3101552f7358SJed Brown   PetscFunctionReturn(0);
3102552f7358SJed Brown }
3103552f7358SJed Brown 
31047cd05799SMatthew G. Knepley /*@
3105eaf898f9SPatrick Sanan   DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG
31067cd05799SMatthew G. Knepley 
31077cd05799SMatthew G. Knepley   Not collective
31087cd05799SMatthew G. Knepley 
31097cd05799SMatthew G. Knepley   Input Parameters:
31107cd05799SMatthew G. Knepley + mesh - The DMPlex
3111eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
31127cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put
31137cd05799SMatthew G. Knepley - conePoint - The mesh point to insert
31147cd05799SMatthew G. Knepley 
31157cd05799SMatthew G. Knepley   Level: beginner
31167cd05799SMatthew G. Knepley 
3117db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
31187cd05799SMatthew G. Knepley @*/
31199371c9d4SSatish Balay PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) {
3120552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3121552f7358SJed Brown   PetscInt pStart, pEnd;
3122552f7358SJed Brown   PetscInt dof, off;
3123552f7358SJed Brown 
3124552f7358SJed Brown   PetscFunctionBegin;
3125552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
31269566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
312763a3b9bcSJacob 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);
312863a3b9bcSJacob 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);
31299566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
31309566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
313163a3b9bcSJacob 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);
3132552f7358SJed Brown   mesh->cones[off + conePos] = conePoint;
3133552f7358SJed Brown   PetscFunctionReturn(0);
3134552f7358SJed Brown }
3135552f7358SJed Brown 
31367cd05799SMatthew G. Knepley /*@
3137eaf898f9SPatrick Sanan   DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG
31387cd05799SMatthew G. Knepley 
31397cd05799SMatthew G. Knepley   Not collective
31407cd05799SMatthew G. Knepley 
31417cd05799SMatthew G. Knepley   Input Parameters:
31427cd05799SMatthew G. Knepley + mesh - The DMPlex
3143eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
31447cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put
31457cd05799SMatthew G. Knepley - coneOrientation - The point orientation to insert
31467cd05799SMatthew G. Knepley 
31477cd05799SMatthew G. Knepley   Level: beginner
31487cd05799SMatthew G. Knepley 
3149b5a892a1SMatthew G. Knepley   Notes:
3150b5a892a1SMatthew G. Knepley   The meaning of coneOrientation values is detailed in DMPlexGetConeOrientation().
3151b5a892a1SMatthew G. Knepley 
3152db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
31537cd05799SMatthew G. Knepley @*/
31549371c9d4SSatish Balay PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) {
315577c88f5bSMatthew G Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
315677c88f5bSMatthew G Knepley   PetscInt pStart, pEnd;
315777c88f5bSMatthew G Knepley   PetscInt dof, off;
315877c88f5bSMatthew G Knepley 
315977c88f5bSMatthew G Knepley   PetscFunctionBegin;
316077c88f5bSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
31619566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
316263a3b9bcSJacob 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);
31639566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
31649566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
316563a3b9bcSJacob 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);
316677c88f5bSMatthew G Knepley   mesh->coneOrientations[off + conePos] = coneOrientation;
316777c88f5bSMatthew G Knepley   PetscFunctionReturn(0);
316877c88f5bSMatthew G Knepley }
316977c88f5bSMatthew G Knepley 
3170552f7358SJed Brown /*@
3171eaf898f9SPatrick Sanan   DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG
3172552f7358SJed Brown 
3173552f7358SJed Brown   Not collective
3174552f7358SJed Brown 
3175552f7358SJed Brown   Input Parameters:
3176552f7358SJed Brown + mesh - The DMPlex
3177eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
3178552f7358SJed Brown 
3179552f7358SJed Brown   Output Parameter:
3180552f7358SJed Brown . size - The support size for point p
3181552f7358SJed Brown 
3182552f7358SJed Brown   Level: beginner
3183552f7358SJed Brown 
3184db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`, `DMPlexGetConeSize()`
3185552f7358SJed Brown @*/
31869371c9d4SSatish Balay PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) {
3187552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3188552f7358SJed Brown 
3189552f7358SJed Brown   PetscFunctionBegin;
3190552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3191dadcf809SJacob Faibussowitsch   PetscValidIntPointer(size, 3);
31929566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, size));
3193552f7358SJed Brown   PetscFunctionReturn(0);
3194552f7358SJed Brown }
3195552f7358SJed Brown 
3196552f7358SJed Brown /*@
3197eaf898f9SPatrick Sanan   DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG
3198552f7358SJed Brown 
3199552f7358SJed Brown   Not collective
3200552f7358SJed Brown 
3201552f7358SJed Brown   Input Parameters:
3202552f7358SJed Brown + mesh - The DMPlex
3203eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
3204552f7358SJed Brown - size - The support size for point p
3205552f7358SJed Brown 
3206552f7358SJed Brown   Output Parameter:
3207552f7358SJed Brown 
3208552f7358SJed Brown   Note:
3209552f7358SJed Brown   This should be called after DMPlexSetChart().
3210552f7358SJed Brown 
3211552f7358SJed Brown   Level: beginner
3212552f7358SJed Brown 
3213db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetSupportSize()`, `DMPlexSetChart()`
3214552f7358SJed Brown @*/
32159371c9d4SSatish Balay PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) {
3216552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3217552f7358SJed Brown 
3218552f7358SJed Brown   PetscFunctionBegin;
3219552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
32209566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetDof(mesh->supportSection, p, size));
3221552f7358SJed Brown   PetscFunctionReturn(0);
3222552f7358SJed Brown }
3223552f7358SJed Brown 
3224552f7358SJed Brown /*@C
3225eaf898f9SPatrick Sanan   DMPlexGetSupport - Return the points on the out-edges for this point in the DAG
3226552f7358SJed Brown 
3227552f7358SJed Brown   Not collective
3228552f7358SJed Brown 
3229552f7358SJed Brown   Input Parameters:
3230552f7358SJed Brown + mesh - The DMPlex
3231eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
3232552f7358SJed Brown 
3233552f7358SJed Brown   Output Parameter:
3234552f7358SJed Brown . support - An array of points which are on the out-edges for point p
3235552f7358SJed Brown 
3236552f7358SJed Brown   Level: beginner
3237552f7358SJed Brown 
32383813dfbdSMatthew G Knepley   Fortran Notes:
32393813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
32403813dfbdSMatthew G Knepley   include petsc.h90 in your code.
32413b12b3d8SVaclav Hapla   You must also call DMPlexRestoreSupport() after you finish using the returned array.
3242922102d1SVaclav Hapla   DMPlexRestoreSupport() is not needed/available in C.
32433813dfbdSMatthew G Knepley 
3244db781477SPatrick Sanan .seealso: `DMPlexGetSupportSize()`, `DMPlexSetSupport()`, `DMPlexGetCone()`, `DMPlexSetChart()`
3245552f7358SJed Brown @*/
32469371c9d4SSatish Balay PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) {
3247552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3248552f7358SJed Brown   PetscInt off;
3249552f7358SJed Brown 
3250552f7358SJed Brown   PetscFunctionBegin;
3251552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3252552f7358SJed Brown   PetscValidPointer(support, 3);
32539566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
3254552f7358SJed Brown   *support = &mesh->supports[off];
3255552f7358SJed Brown   PetscFunctionReturn(0);
3256552f7358SJed Brown }
3257552f7358SJed Brown 
3258552f7358SJed Brown /*@
325992371b87SBarry 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
3260552f7358SJed Brown 
3261552f7358SJed Brown   Not collective
3262552f7358SJed Brown 
3263552f7358SJed Brown   Input Parameters:
3264552f7358SJed Brown + mesh - The DMPlex
3265eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
326692371b87SBarry Smith - support - An array of points which are on the out-edges for point p
3267552f7358SJed Brown 
3268552f7358SJed Brown   Output Parameter:
3269552f7358SJed Brown 
3270552f7358SJed Brown   Note:
3271552f7358SJed Brown   This should be called after all calls to DMPlexSetSupportSize() and DMSetUp().
3272552f7358SJed Brown 
3273552f7358SJed Brown   Level: beginner
3274552f7358SJed Brown 
3275db781477SPatrick Sanan .seealso: `DMPlexSetCone()`, `DMPlexSetConeSize()`, `DMPlexCreate()`, `DMPlexGetSupport()`, `DMPlexSetChart()`, `DMPlexSetSupportSize()`, `DMSetUp()`
3276552f7358SJed Brown @*/
32779371c9d4SSatish Balay PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) {
3278552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3279552f7358SJed Brown   PetscInt pStart, pEnd;
3280552f7358SJed Brown   PetscInt dof, off, c;
3281552f7358SJed Brown 
3282552f7358SJed Brown   PetscFunctionBegin;
3283552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
32849566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd));
32859566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
3286dadcf809SJacob Faibussowitsch   if (dof) PetscValidIntPointer(support, 3);
32879566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
328863a3b9bcSJacob 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);
3289552f7358SJed Brown   for (c = 0; c < dof; ++c) {
329063a3b9bcSJacob 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);
3291552f7358SJed Brown     mesh->supports[off + c] = support[c];
3292552f7358SJed Brown   }
3293552f7358SJed Brown   PetscFunctionReturn(0);
3294552f7358SJed Brown }
3295552f7358SJed Brown 
32967cd05799SMatthew G. Knepley /*@
3297eaf898f9SPatrick Sanan   DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG
32987cd05799SMatthew G. Knepley 
32997cd05799SMatthew G. Knepley   Not collective
33007cd05799SMatthew G. Knepley 
33017cd05799SMatthew G. Knepley   Input Parameters:
33027cd05799SMatthew G. Knepley + mesh - The DMPlex
3303eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
33047cd05799SMatthew G. Knepley . supportPos - The local index in the cone where the point should be put
33057cd05799SMatthew G. Knepley - supportPoint - The mesh point to insert
33067cd05799SMatthew G. Knepley 
33077cd05799SMatthew G. Knepley   Level: beginner
33087cd05799SMatthew G. Knepley 
3309db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
33107cd05799SMatthew G. Knepley @*/
33119371c9d4SSatish Balay PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) {
3312552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3313552f7358SJed Brown   PetscInt pStart, pEnd;
3314552f7358SJed Brown   PetscInt dof, off;
3315552f7358SJed Brown 
3316552f7358SJed Brown   PetscFunctionBegin;
3317552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
33189566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd));
33199566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
33209566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
332163a3b9bcSJacob 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);
332263a3b9bcSJacob 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);
332363a3b9bcSJacob 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);
3324552f7358SJed Brown   mesh->supports[off + supportPos] = supportPoint;
3325552f7358SJed Brown   PetscFunctionReturn(0);
3326552f7358SJed Brown }
3327552f7358SJed Brown 
3328b5a892a1SMatthew G. Knepley /* Converts an orientation o in the current numbering to the previous scheme used in Plex */
33299371c9d4SSatish Balay PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o) {
3330b5a892a1SMatthew G. Knepley   switch (ct) {
3331b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
3332b5a892a1SMatthew G. Knepley     if (o == -1) return -2;
3333b5a892a1SMatthew G. Knepley     break;
3334b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
3335b5a892a1SMatthew G. Knepley     if (o == -3) return -1;
3336b5a892a1SMatthew G. Knepley     if (o == -2) return -3;
3337b5a892a1SMatthew G. Knepley     if (o == -1) return -2;
3338b5a892a1SMatthew G. Knepley     break;
3339b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
3340b5a892a1SMatthew G. Knepley     if (o == -4) return -2;
3341b5a892a1SMatthew G. Knepley     if (o == -3) return -1;
3342b5a892a1SMatthew G. Knepley     if (o == -2) return -4;
3343b5a892a1SMatthew G. Knepley     if (o == -1) return -3;
3344b5a892a1SMatthew G. Knepley     break;
3345b5a892a1SMatthew G. Knepley   default: return o;
3346b5a892a1SMatthew G. Knepley   }
3347b5a892a1SMatthew G. Knepley   return o;
3348b5a892a1SMatthew G. Knepley }
3349b5a892a1SMatthew G. Knepley 
3350b5a892a1SMatthew G. Knepley /* Converts an orientation o in the previous scheme used in Plex to the current numbering */
33519371c9d4SSatish Balay PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o) {
3352b5a892a1SMatthew G. Knepley   switch (ct) {
3353b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
3354b5a892a1SMatthew G. Knepley     if ((o == -2) || (o == 1)) return -1;
3355b5a892a1SMatthew G. Knepley     if (o == -1) return 0;
3356b5a892a1SMatthew G. Knepley     break;
3357b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
3358b5a892a1SMatthew G. Knepley     if (o == -3) return -2;
3359b5a892a1SMatthew G. Knepley     if (o == -2) return -1;
3360b5a892a1SMatthew G. Knepley     if (o == -1) return -3;
3361b5a892a1SMatthew G. Knepley     break;
3362b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
3363b5a892a1SMatthew G. Knepley     if (o == -4) return -2;
3364b5a892a1SMatthew G. Knepley     if (o == -3) return -1;
3365b5a892a1SMatthew G. Knepley     if (o == -2) return -4;
3366b5a892a1SMatthew G. Knepley     if (o == -1) return -3;
3367b5a892a1SMatthew G. Knepley     break;
3368b5a892a1SMatthew G. Knepley   default: return o;
3369b5a892a1SMatthew G. Knepley   }
3370b5a892a1SMatthew G. Knepley   return o;
3371b5a892a1SMatthew G. Knepley }
3372b5a892a1SMatthew G. Knepley 
3373b5a892a1SMatthew G. Knepley /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */
33749371c9d4SSatish Balay PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm) {
3375b5a892a1SMatthew G. Knepley   PetscInt pStart, pEnd, p;
3376b5a892a1SMatthew G. Knepley 
3377b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
33789566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
3379b5a892a1SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
3380b5a892a1SMatthew G. Knepley     const PetscInt *cone, *ornt;
3381b5a892a1SMatthew G. Knepley     PetscInt        coneSize, c;
3382b5a892a1SMatthew G. Knepley 
33839566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
33849566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
33859566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dm, p, &ornt));
3386b5a892a1SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
3387b5a892a1SMatthew G. Knepley       DMPolytopeType ct;
3388b5a892a1SMatthew G. Knepley       const PetscInt o = ornt[c];
3389b5a892a1SMatthew G. Knepley 
33909566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, cone[c], &ct));
3391b5a892a1SMatthew G. Knepley       switch (ct) {
3392b5a892a1SMatthew G. Knepley       case DM_POLYTOPE_SEGMENT:
33939566063dSJacob Faibussowitsch         if ((o == -2) || (o == 1)) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
33949566063dSJacob Faibussowitsch         if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, 0));
3395b5a892a1SMatthew G. Knepley         break;
3396b5a892a1SMatthew G. Knepley       case DM_POLYTOPE_TRIANGLE:
33979566063dSJacob Faibussowitsch         if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2));
33989566063dSJacob Faibussowitsch         if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
33999566063dSJacob Faibussowitsch         if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3));
3400b5a892a1SMatthew G. Knepley         break;
3401b5a892a1SMatthew G. Knepley       case DM_POLYTOPE_QUADRILATERAL:
34029566063dSJacob Faibussowitsch         if (o == -4) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2));
34039566063dSJacob Faibussowitsch         if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
34049566063dSJacob Faibussowitsch         if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -4));
34059566063dSJacob Faibussowitsch         if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3));
3406b5a892a1SMatthew G. Knepley         break;
3407b5a892a1SMatthew G. Knepley       default: break;
3408b5a892a1SMatthew G. Knepley       }
3409b5a892a1SMatthew G. Knepley     }
3410b5a892a1SMatthew G. Knepley   }
3411b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
3412b5a892a1SMatthew G. Knepley }
3413b5a892a1SMatthew G. Knepley 
34149371c9d4SSatish Balay static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) {
3415b5a892a1SMatthew G. Knepley   DMPolytopeType  ct = DM_POLYTOPE_UNKNOWN;
3416b5a892a1SMatthew G. Knepley   PetscInt       *closure;
3417b5a892a1SMatthew G. Knepley   const PetscInt *tmp = NULL, *tmpO = NULL;
3418b5a892a1SMatthew G. Knepley   PetscInt        off = 0, tmpSize, t;
3419b5a892a1SMatthew G. Knepley 
3420b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3421b5a892a1SMatthew G. Knepley   if (ornt) {
34229566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, p, &ct));
3423b5a892a1SMatthew G. Knepley     if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN;
3424b5a892a1SMatthew G. Knepley   }
3425b5a892a1SMatthew G. Knepley   if (*points) {
3426b5a892a1SMatthew G. Knepley     closure = *points;
3427b5a892a1SMatthew G. Knepley   } else {
3428b5a892a1SMatthew G. Knepley     PetscInt maxConeSize, maxSupportSize;
34299566063dSJacob Faibussowitsch     PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
34309566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, 2 * (PetscMax(maxConeSize, maxSupportSize) + 1), MPIU_INT, &closure));
3431b5a892a1SMatthew G. Knepley   }
3432b5a892a1SMatthew G. Knepley   if (useCone) {
34339566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &tmpSize));
34349566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &tmp));
34359566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dm, p, &tmpO));
3436b5a892a1SMatthew G. Knepley   } else {
34379566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dm, p, &tmpSize));
34389566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dm, p, &tmp));
3439b5a892a1SMatthew G. Knepley   }
3440b5a892a1SMatthew G. Knepley   if (ct == DM_POLYTOPE_UNKNOWN) {
3441b5a892a1SMatthew G. Knepley     closure[off++] = p;
3442b5a892a1SMatthew G. Knepley     closure[off++] = 0;
3443b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3444b5a892a1SMatthew G. Knepley       closure[off++] = tmp[t];
3445b5a892a1SMatthew G. Knepley       closure[off++] = tmpO ? tmpO[t] : 0;
3446b5a892a1SMatthew G. Knepley     }
3447b5a892a1SMatthew G. Knepley   } else {
34485f80ce2aSJacob Faibussowitsch     const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, ornt);
3449b5a892a1SMatthew G. Knepley 
3450b5a892a1SMatthew G. Knepley     /* We assume that cells with a valid type have faces with a valid type */
3451b5a892a1SMatthew G. Knepley     closure[off++] = p;
3452b5a892a1SMatthew G. Knepley     closure[off++] = ornt;
3453b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3454b5a892a1SMatthew G. Knepley       DMPolytopeType ft;
3455b5a892a1SMatthew G. Knepley 
34569566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, tmp[t], &ft));
3457b5a892a1SMatthew G. Knepley       closure[off++] = tmp[arr[t]];
3458b5a892a1SMatthew G. Knepley       closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0;
3459b5a892a1SMatthew G. Knepley     }
3460b5a892a1SMatthew G. Knepley   }
3461b5a892a1SMatthew G. Knepley   if (numPoints) *numPoints = tmpSize + 1;
3462b5a892a1SMatthew G. Knepley   if (points) *points = closure;
3463b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
3464b5a892a1SMatthew G. Knepley }
3465b5a892a1SMatthew G. Knepley 
3466b5a892a1SMatthew G. Knepley /* We need a special tensor verison becasue we want to allow duplicate points in the endcaps for hybrid cells */
34679371c9d4SSatish Balay static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points) {
3468b5a892a1SMatthew G. Knepley   const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, o);
3469b5a892a1SMatthew G. Knepley   const PetscInt *cone, *ornt;
3470b5a892a1SMatthew G. Knepley   PetscInt       *pts, *closure = NULL;
3471b5a892a1SMatthew G. Knepley   DMPolytopeType  ft;
3472b5a892a1SMatthew G. Knepley   PetscInt        maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize;
3473b5a892a1SMatthew G. Knepley   PetscInt        dim, coneSize, c, d, clSize, cl;
3474b5a892a1SMatthew G. Knepley 
3475b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
34769566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
34779566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, point, &coneSize));
34789566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, point, &cone));
34799566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeOrientation(dm, point, &ornt));
34809566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
3481b5a892a1SMatthew G. Knepley   coneSeries    = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, dim + 1) - 1) / (maxConeSize - 1)) : dim + 1;
3482b5a892a1SMatthew G. Knepley   supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim + 1) - 1) / (maxSupportSize - 1)) : dim + 1;
3483b5a892a1SMatthew G. Knepley   maxSize       = PetscMax(coneSeries, supportSeries);
34849371c9d4SSatish Balay   if (*points) {
34859371c9d4SSatish Balay     pts = *points;
34869371c9d4SSatish Balay   } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &pts));
3487b5a892a1SMatthew G. Knepley   c        = 0;
3488b5a892a1SMatthew G. Knepley   pts[c++] = point;
3489b5a892a1SMatthew G. Knepley   pts[c++] = o;
34909566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cone[arr[0 * 2 + 0]], &ft));
34919566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[0 * 2 + 1], ornt[0]), useCone, &clSize, &closure));
34929371c9d4SSatish Balay   for (cl = 0; cl < clSize * 2; cl += 2) {
34939371c9d4SSatish Balay     pts[c++] = closure[cl];
34949371c9d4SSatish Balay     pts[c++] = closure[cl + 1];
34959371c9d4SSatish Balay   }
34969566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[1 * 2 + 1], ornt[1]), useCone, &clSize, &closure));
34979371c9d4SSatish Balay   for (cl = 0; cl < clSize * 2; cl += 2) {
34989371c9d4SSatish Balay     pts[c++] = closure[cl];
34999371c9d4SSatish Balay     pts[c++] = closure[cl + 1];
35009371c9d4SSatish Balay   }
35019566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure));
3502b5a892a1SMatthew G. Knepley   for (d = 2; d < coneSize; ++d) {
35039566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, cone[arr[d * 2 + 0]], &ft));
3504b5a892a1SMatthew G. Knepley     pts[c++] = cone[arr[d * 2 + 0]];
3505b5a892a1SMatthew G. Knepley     pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d]);
3506b5a892a1SMatthew G. Knepley   }
3507b5a892a1SMatthew G. Knepley   if (dim >= 3) {
3508b5a892a1SMatthew G. Knepley     for (d = 2; d < coneSize; ++d) {
3509b5a892a1SMatthew G. Knepley       const PetscInt  fpoint = cone[arr[d * 2 + 0]];
3510b5a892a1SMatthew G. Knepley       const PetscInt *fcone, *fornt;
3511b5a892a1SMatthew G. Knepley       PetscInt        fconeSize, fc, i;
3512b5a892a1SMatthew G. Knepley 
35139566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, fpoint, &ft));
3514b5a892a1SMatthew G. Knepley       const PetscInt *farr = DMPolytopeTypeGetArrangment(ft, DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d]));
35159566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, fpoint, &fconeSize));
35169566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, fpoint, &fcone));
35179566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeOrientation(dm, fpoint, &fornt));
3518b5a892a1SMatthew G. Knepley       for (fc = 0; fc < fconeSize; ++fc) {
3519b5a892a1SMatthew G. Knepley         const PetscInt cp = fcone[farr[fc * 2 + 0]];
3520b5a892a1SMatthew G. Knepley         const PetscInt co = farr[fc * 2 + 1];
3521b5a892a1SMatthew G. Knepley 
35229371c9d4SSatish Balay         for (i = 0; i < c; i += 2)
35239371c9d4SSatish Balay           if (pts[i] == cp) break;
3524b5a892a1SMatthew G. Knepley         if (i == c) {
35259566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCellType(dm, cp, &ft));
3526b5a892a1SMatthew G. Knepley           pts[c++] = cp;
3527b5a892a1SMatthew G. Knepley           pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc * 2 + 0]]);
3528b5a892a1SMatthew G. Knepley         }
3529b5a892a1SMatthew G. Knepley       }
3530b5a892a1SMatthew G. Knepley     }
3531b5a892a1SMatthew G. Knepley   }
3532b5a892a1SMatthew G. Knepley   *numPoints = c / 2;
3533b5a892a1SMatthew G. Knepley   *points    = pts;
3534b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
3535b5a892a1SMatthew G. Knepley }
3536b5a892a1SMatthew G. Knepley 
35379371c9d4SSatish Balay PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) {
3538b5a892a1SMatthew G. Knepley   DMPolytopeType ct;
3539b5a892a1SMatthew G. Knepley   PetscInt      *closure, *fifo;
3540b5a892a1SMatthew G. Knepley   PetscInt       closureSize = 0, fifoStart = 0, fifoSize = 0;
3541b5a892a1SMatthew G. Knepley   PetscInt       maxConeSize, maxSupportSize, coneSeries, supportSeries;
3542b5a892a1SMatthew G. Knepley   PetscInt       depth, maxSize;
3543b5a892a1SMatthew G. Knepley 
3544b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
35459566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
3546b5a892a1SMatthew G. Knepley   if (depth == 1) {
35479566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points));
3548b5a892a1SMatthew G. Knepley     PetscFunctionReturn(0);
3549b5a892a1SMatthew G. Knepley   }
35509566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, p, &ct));
3551b5a892a1SMatthew G. Knepley   if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN;
3552b5a892a1SMatthew G. Knepley   if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || ct == DM_POLYTOPE_TRI_PRISM_TENSOR || ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) {
35539566063dSJacob Faibussowitsch     PetscCall(DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points));
3554b5a892a1SMatthew G. Knepley     PetscFunctionReturn(0);
3555b5a892a1SMatthew G. Knepley   }
35569566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
3557b5a892a1SMatthew G. Knepley   coneSeries    = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, depth + 1) - 1) / (maxConeSize - 1)) : depth + 1;
3558b5a892a1SMatthew G. Knepley   supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth + 1) - 1) / (maxSupportSize - 1)) : depth + 1;
3559b5a892a1SMatthew G. Knepley   maxSize       = PetscMax(coneSeries, supportSeries);
35609566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo));
35619371c9d4SSatish Balay   if (*points) {
35629371c9d4SSatish Balay     closure = *points;
35639371c9d4SSatish Balay   } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &closure));
3564b5a892a1SMatthew G. Knepley   closure[closureSize++] = p;
3565b5a892a1SMatthew G. Knepley   closure[closureSize++] = ornt;
3566b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = p;
3567b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = ornt;
3568b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = ct;
3569b5a892a1SMatthew G. Knepley   /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */
3570b5a892a1SMatthew G. Knepley   while (fifoSize - fifoStart) {
3571b5a892a1SMatthew G. Knepley     const PetscInt       q    = fifo[fifoStart++];
3572b5a892a1SMatthew G. Knepley     const PetscInt       o    = fifo[fifoStart++];
3573b5a892a1SMatthew G. Knepley     const DMPolytopeType qt   = (DMPolytopeType)fifo[fifoStart++];
3574b5a892a1SMatthew G. Knepley     const PetscInt      *qarr = DMPolytopeTypeGetArrangment(qt, o);
3575b5a892a1SMatthew G. Knepley     const PetscInt      *tmp, *tmpO;
3576b5a892a1SMatthew G. Knepley     PetscInt             tmpSize, t;
3577b5a892a1SMatthew G. Knepley 
3578b5a892a1SMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) {
3579b5a892a1SMatthew G. Knepley       PetscInt nO = DMPolytopeTypeGetNumArrangments(qt) / 2;
358063a3b9bcSJacob 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);
3581b5a892a1SMatthew G. Knepley     }
3582b5a892a1SMatthew G. Knepley     if (useCone) {
35839566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, q, &tmpSize));
35849566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, q, &tmp));
35859566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeOrientation(dm, q, &tmpO));
3586b5a892a1SMatthew G. Knepley     } else {
35879566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, q, &tmpSize));
35889566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupport(dm, q, &tmp));
3589b5a892a1SMatthew G. Knepley       tmpO = NULL;
3590b5a892a1SMatthew G. Knepley     }
3591b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3592b5a892a1SMatthew G. Knepley       const PetscInt ip = useCone && qarr ? qarr[t * 2] : t;
3593b5a892a1SMatthew G. Knepley       const PetscInt io = useCone && qarr ? qarr[t * 2 + 1] : 0;
3594b5a892a1SMatthew G. Knepley       const PetscInt cp = tmp[ip];
35959566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, cp, &ct));
3596b5a892a1SMatthew G. Knepley       const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0;
3597b5a892a1SMatthew G. Knepley       PetscInt       c;
3598b5a892a1SMatthew G. Knepley 
3599b5a892a1SMatthew G. Knepley       /* Check for duplicate */
3600b5a892a1SMatthew G. Knepley       for (c = 0; c < closureSize; c += 2) {
3601b5a892a1SMatthew G. Knepley         if (closure[c] == cp) break;
3602b5a892a1SMatthew G. Knepley       }
3603b5a892a1SMatthew G. Knepley       if (c == closureSize) {
3604b5a892a1SMatthew G. Knepley         closure[closureSize++] = cp;
3605b5a892a1SMatthew G. Knepley         closure[closureSize++] = co;
3606b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = cp;
3607b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = co;
3608b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = ct;
3609b5a892a1SMatthew G. Knepley       }
3610b5a892a1SMatthew G. Knepley     }
3611b5a892a1SMatthew G. Knepley   }
36129566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo));
3613b5a892a1SMatthew G. Knepley   if (numPoints) *numPoints = closureSize / 2;
3614b5a892a1SMatthew G. Knepley   if (points) *points = closure;
3615b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
3616b5a892a1SMatthew G. Knepley }
3617b5a892a1SMatthew G. Knepley 
3618552f7358SJed Brown /*@C
3619eaf898f9SPatrick Sanan   DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG
3620552f7358SJed Brown 
3621552f7358SJed Brown   Not collective
3622552f7358SJed Brown 
3623552f7358SJed Brown   Input Parameters:
3624b5a892a1SMatthew G. Knepley + dm      - The DMPlex
3625b5a892a1SMatthew G. Knepley . p       - The mesh point
36266b867d5aSJose E. Roman - useCone - PETSC_TRUE for the closure, otherwise return the star
3627552f7358SJed Brown 
36286b867d5aSJose E. Roman   Input/Output Parameter:
36296b867d5aSJose E. Roman . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...];
36306b867d5aSJose E. Roman            if NULL on input, internal storage will be returned, otherwise the provided array is used
36316b867d5aSJose E. Roman 
36326b867d5aSJose E. Roman   Output Parameter:
36336b867d5aSJose E. Roman . numPoints - The number of points in the closure, so points[] is of size 2*numPoints
3634552f7358SJed Brown 
3635552f7358SJed Brown   Note:
36360298fd71SBarry Smith   If using internal storage (points is NULL on input), each call overwrites the last output.
3637552f7358SJed Brown 
36389f22da38SBarry Smith   Fortran Note:
36393813dfbdSMatthew G Knepley   The numPoints argument is not present in the Fortran 90 binding since it is internal to the array.
36403813dfbdSMatthew G Knepley 
3641552f7358SJed Brown   Level: beginner
3642552f7358SJed Brown 
3643db781477SPatrick Sanan .seealso: `DMPlexRestoreTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()`
3644552f7358SJed Brown @*/
36459371c9d4SSatish Balay PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) {
3646b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3647552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3648b5a892a1SMatthew G. Knepley   if (numPoints) PetscValidIntPointer(numPoints, 4);
3649b5a892a1SMatthew G. Knepley   if (points) PetscValidPointer(points, 5);
36509566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points));
36519bf0dad6SMatthew G. Knepley   PetscFunctionReturn(0);
36529bf0dad6SMatthew G. Knepley }
36539bf0dad6SMatthew G. Knepley 
3654552f7358SJed Brown /*@C
3655eaf898f9SPatrick Sanan   DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG
3656552f7358SJed Brown 
3657552f7358SJed Brown   Not collective
3658552f7358SJed Brown 
3659552f7358SJed Brown   Input Parameters:
3660b5a892a1SMatthew G. Knepley + dm        - The DMPlex
3661b5a892a1SMatthew G. Knepley . p         - The mesh point
3662b5a892a1SMatthew G. Knepley . useCone   - PETSC_TRUE for the closure, otherwise return the star
3663b5a892a1SMatthew G. Knepley . numPoints - The number of points in the closure, so points[] is of size 2*numPoints
3664b5a892a1SMatthew G. Knepley - points    - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]
3665552f7358SJed Brown 
3666552f7358SJed Brown   Note:
36670298fd71SBarry Smith   If not using internal storage (points is not NULL on input), this call is unnecessary
3668552f7358SJed Brown 
3669552f7358SJed Brown   Level: beginner
3670552f7358SJed Brown 
3671db781477SPatrick Sanan .seealso: `DMPlexGetTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()`
3672552f7358SJed Brown @*/
36739371c9d4SSatish Balay PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) {
3674b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3675552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
36764ff43b2cSJed Brown   if (numPoints) *numPoints = 0;
36779566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, points));
3678552f7358SJed Brown   PetscFunctionReturn(0);
3679552f7358SJed Brown }
3680552f7358SJed Brown 
3681552f7358SJed Brown /*@
3682eaf898f9SPatrick Sanan   DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG
3683552f7358SJed Brown 
3684552f7358SJed Brown   Not collective
3685552f7358SJed Brown 
3686552f7358SJed Brown   Input Parameter:
3687552f7358SJed Brown . mesh - The DMPlex
3688552f7358SJed Brown 
3689552f7358SJed Brown   Output Parameters:
3690552f7358SJed Brown + maxConeSize - The maximum number of in-edges
3691552f7358SJed Brown - maxSupportSize - The maximum number of out-edges
3692552f7358SJed Brown 
3693552f7358SJed Brown   Level: beginner
3694552f7358SJed Brown 
3695db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`
3696552f7358SJed Brown @*/
36979371c9d4SSatish Balay PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) {
3698552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3699552f7358SJed Brown 
3700552f7358SJed Brown   PetscFunctionBegin;
3701552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
37021baa6e33SBarry Smith   if (maxConeSize) PetscCall(PetscSectionGetMaxDof(mesh->coneSection, maxConeSize));
37031baa6e33SBarry Smith   if (maxSupportSize) PetscCall(PetscSectionGetMaxDof(mesh->supportSection, maxSupportSize));
3704552f7358SJed Brown   PetscFunctionReturn(0);
3705552f7358SJed Brown }
3706552f7358SJed Brown 
37079371c9d4SSatish Balay PetscErrorCode DMSetUp_Plex(DM dm) {
3708552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
37096302a7fbSVaclav Hapla   PetscInt size, maxSupportSize;
3710552f7358SJed Brown 
3711552f7358SJed Brown   PetscFunctionBegin;
3712552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
37139566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(mesh->coneSection));
37149566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(mesh->coneSection, &size));
37159566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, &mesh->cones));
37169566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(size, &mesh->coneOrientations));
37179566063dSJacob Faibussowitsch   PetscCall(PetscLogObjectMemory((PetscObject)dm, size * 2 * sizeof(PetscInt)));
37186302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize));
37196302a7fbSVaclav Hapla   if (maxSupportSize) {
37209566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(mesh->supportSection));
37219566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &size));
37229566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(size, &mesh->supports));
37239566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectMemory((PetscObject)dm, size * sizeof(PetscInt)));
3724552f7358SJed Brown   }
3725552f7358SJed Brown   PetscFunctionReturn(0);
3726552f7358SJed Brown }
3727552f7358SJed Brown 
37289371c9d4SSatish Balay PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm) {
3729552f7358SJed Brown   PetscFunctionBegin;
37309566063dSJacob Faibussowitsch   if (subdm) PetscCall(DMClone(dm, subdm));
37319566063dSJacob Faibussowitsch   PetscCall(DMCreateSectionSubDM(dm, numFields, fields, is, subdm));
3732ad540459SPierre Jolivet   if (subdm) (*subdm)->useNatural = dm->useNatural;
3733736995cdSBlaise Bourdin   if (dm->useNatural && dm->sfMigration) {
373495602cf2SAlexis Marboeuf     PetscSF sfNatural;
3735f94b4a02SBlaise Bourdin 
37363dcd263cSBlaise Bourdin     (*subdm)->sfMigration = dm->sfMigration;
37379566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm->sfMigration));
373895602cf2SAlexis Marboeuf     PetscCall(DMPlexCreateGlobalToNaturalSF(*subdm, NULL, (*subdm)->sfMigration, &sfNatural));
3739c40e9495SBlaise Bourdin     (*subdm)->sfNatural = sfNatural;
3740f94b4a02SBlaise Bourdin   }
3741552f7358SJed Brown   PetscFunctionReturn(0);
3742552f7358SJed Brown }
3743552f7358SJed Brown 
37449371c9d4SSatish Balay PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm) {
37453dcd263cSBlaise Bourdin   PetscInt i = 0;
37462adcc780SMatthew G. Knepley 
37472adcc780SMatthew G. Knepley   PetscFunctionBegin;
37489566063dSJacob Faibussowitsch   PetscCall(DMClone(dms[0], superdm));
37499566063dSJacob Faibussowitsch   PetscCall(DMCreateSectionSuperDM(dms, len, is, superdm));
3750c40e9495SBlaise Bourdin   (*superdm)->useNatural = PETSC_FALSE;
37513dcd263cSBlaise Bourdin   for (i = 0; i < len; i++) {
37523dcd263cSBlaise Bourdin     if (dms[i]->useNatural && dms[i]->sfMigration) {
375395602cf2SAlexis Marboeuf       PetscSF sfNatural;
37543dcd263cSBlaise Bourdin 
37553dcd263cSBlaise Bourdin       (*superdm)->sfMigration = dms[i]->sfMigration;
37569566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)dms[i]->sfMigration));
3757c40e9495SBlaise Bourdin       (*superdm)->useNatural = PETSC_TRUE;
375895602cf2SAlexis Marboeuf       PetscCall(DMPlexCreateGlobalToNaturalSF(*superdm, NULL, (*superdm)->sfMigration, &sfNatural));
3759c40e9495SBlaise Bourdin       (*superdm)->sfNatural = sfNatural;
37603dcd263cSBlaise Bourdin       break;
37613dcd263cSBlaise Bourdin     }
37623dcd263cSBlaise Bourdin   }
37632adcc780SMatthew G. Knepley   PetscFunctionReturn(0);
37642adcc780SMatthew G. Knepley }
37652adcc780SMatthew G. Knepley 
3766552f7358SJed Brown /*@
3767eaf898f9SPatrick Sanan   DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information
3768552f7358SJed Brown 
3769552f7358SJed Brown   Not collective
3770552f7358SJed Brown 
3771552f7358SJed Brown   Input Parameter:
3772552f7358SJed Brown . mesh - The DMPlex
3773552f7358SJed Brown 
3774552f7358SJed Brown   Output Parameter:
3775552f7358SJed Brown 
3776552f7358SJed Brown   Note:
3777552f7358SJed Brown   This should be called after all calls to DMPlexSetCone()
3778552f7358SJed Brown 
3779552f7358SJed Brown   Level: beginner
3780552f7358SJed Brown 
3781db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMPlexSetCone()`
3782552f7358SJed Brown @*/
37839371c9d4SSatish Balay PetscErrorCode DMPlexSymmetrize(DM dm) {
3784552f7358SJed Brown   DM_Plex  *mesh = (DM_Plex *)dm->data;
3785552f7358SJed Brown   PetscInt *offsets;
3786552f7358SJed Brown   PetscInt  supportSize;
3787552f7358SJed Brown   PetscInt  pStart, pEnd, p;
3788552f7358SJed Brown 
3789552f7358SJed Brown   PetscFunctionBegin;
3790552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
379128b400f6SJacob Faibussowitsch   PetscCheck(!mesh->supports, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex");
37929566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_Symmetrize, dm, 0, 0, 0));
3793552f7358SJed Brown   /* Calculate support sizes */
37949566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
3795552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
3796552f7358SJed Brown     PetscInt dof, off, c;
3797552f7358SJed Brown 
37989566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
37999566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
380048a46eb9SPierre Jolivet     for (c = off; c < off + dof; ++c) PetscCall(PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1));
3801552f7358SJed Brown   }
38029566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(mesh->supportSection));
3803552f7358SJed Brown   /* Calculate supports */
38049566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &supportSize));
38059566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(supportSize, &mesh->supports));
38069566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(pEnd - pStart, &offsets));
3807552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
3808552f7358SJed Brown     PetscInt dof, off, c;
3809552f7358SJed Brown 
38109566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
38119566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
3812552f7358SJed Brown     for (c = off; c < off + dof; ++c) {
3813552f7358SJed Brown       const PetscInt q = mesh->cones[c];
3814552f7358SJed Brown       PetscInt       offS;
3815552f7358SJed Brown 
38169566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->supportSection, q, &offS));
38170d644c17SKarl Rupp 
3818552f7358SJed Brown       mesh->supports[offS + offsets[q]] = p;
3819552f7358SJed Brown       ++offsets[q];
3820552f7358SJed Brown     }
3821552f7358SJed Brown   }
38229566063dSJacob Faibussowitsch   PetscCall(PetscFree(offsets));
38239566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_Symmetrize, dm, 0, 0, 0));
3824552f7358SJed Brown   PetscFunctionReturn(0);
3825552f7358SJed Brown }
3826552f7358SJed Brown 
38279371c9d4SSatish Balay static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd) {
3828277ea44aSLisandro Dalcin   IS stratumIS;
3829277ea44aSLisandro Dalcin 
3830277ea44aSLisandro Dalcin   PetscFunctionBegin;
3831277ea44aSLisandro Dalcin   if (pStart >= pEnd) PetscFunctionReturn(0);
383276bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
3833277ea44aSLisandro Dalcin     PetscInt  qStart, qEnd, numLevels, level;
3834277ea44aSLisandro Dalcin     PetscBool overlap = PETSC_FALSE;
38359566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &numLevels));
3836277ea44aSLisandro Dalcin     for (level = 0; level < numLevels; level++) {
38379566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
38389371c9d4SSatish Balay       if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) {
38399371c9d4SSatish Balay         overlap = PETSC_TRUE;
38409371c9d4SSatish Balay         break;
38419371c9d4SSatish Balay       }
3842277ea44aSLisandro Dalcin     }
384363a3b9bcSJacob 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);
3844277ea44aSLisandro Dalcin   }
38459566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &stratumIS));
38469566063dSJacob Faibussowitsch   PetscCall(DMLabelSetStratumIS(label, depth, stratumIS));
38479566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&stratumIS));
3848277ea44aSLisandro Dalcin   PetscFunctionReturn(0);
3849277ea44aSLisandro Dalcin }
3850277ea44aSLisandro Dalcin 
3851552f7358SJed Brown /*@
3852a8d69d7bSBarry Smith   DMPlexStratify - The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and
38536dd80730SBarry Smith   can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the
3854552f7358SJed Brown   same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in
3855552f7358SJed Brown   the DAG.
3856552f7358SJed Brown 
3857bf4602e4SToby Isaac   Collective on dm
3858552f7358SJed Brown 
3859552f7358SJed Brown   Input Parameter:
3860552f7358SJed Brown . mesh - The DMPlex
3861552f7358SJed Brown 
3862552f7358SJed Brown   Output Parameter:
3863552f7358SJed Brown 
3864552f7358SJed Brown   Notes:
3865b1bb481bSMatthew Knepley   Concretely, DMPlexStratify() creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex
3866b1bb481bSMatthew 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
3867b1bb481bSMatthew Knepley   until cells have depth equal to the dimension of the mesh. The depth label can be accessed through DMPlexGetDepthLabel() or DMPlexGetDepthStratum(), or
3868c58f1c22SToby Isaac   manually via DMGetLabel().  The height is defined implicitly by height = maxDimension - depth, and can be accessed
3869150b719bSJed Brown   via DMPlexGetHeightStratum().  For example, cells have height 0 and faces have height 1.
3870552f7358SJed Brown 
3871b1bb481bSMatthew Knepley   The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results
3872b1bb481bSMatthew Knepley   if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that
3873b1bb481bSMatthew 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
3874b1bb481bSMatthew Knepley   to interpolate only that one (e0), so that
3875b1bb481bSMatthew Knepley $  cone(c0) = {e0, v2}
3876b1bb481bSMatthew Knepley $  cone(e0) = {v0, v1}
3877b1bb481bSMatthew Knepley   If DMPlexStratify() is run on this mesh, it will give depths
3878b1bb481bSMatthew Knepley $  depth 0 = {v0, v1, v2}
3879b1bb481bSMatthew Knepley $  depth 1 = {e0, c0}
3880b1bb481bSMatthew Knepley   where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2.
3881b1bb481bSMatthew Knepley 
3882150b719bSJed Brown   DMPlexStratify() should be called after all calls to DMPlexSymmetrize()
3883552f7358SJed Brown 
3884552f7358SJed Brown   Level: beginner
3885552f7358SJed Brown 
3886db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexComputeCellTypes()`
3887552f7358SJed Brown @*/
38889371c9d4SSatish Balay PetscErrorCode DMPlexStratify(DM dm) {
3889df0420ecSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
3890aa50250dSMatthew G. Knepley   DMLabel  label;
3891552f7358SJed Brown   PetscInt pStart, pEnd, p;
3892552f7358SJed Brown   PetscInt numRoots = 0, numLeaves = 0;
3893552f7358SJed Brown 
3894552f7358SJed Brown   PetscFunctionBegin;
3895552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
38969566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_Stratify, dm, 0, 0, 0));
3897277ea44aSLisandro Dalcin 
3898277ea44aSLisandro Dalcin   /* Create depth label */
38999566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
39009566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "depth"));
39019566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
3902277ea44aSLisandro Dalcin 
3903277ea44aSLisandro Dalcin   {
3904552f7358SJed Brown     /* Initialize roots and count leaves */
3905277ea44aSLisandro Dalcin     PetscInt sMin = PETSC_MAX_INT;
3906277ea44aSLisandro Dalcin     PetscInt sMax = PETSC_MIN_INT;
3907552f7358SJed Brown     PetscInt coneSize, supportSize;
3908552f7358SJed Brown 
3909277ea44aSLisandro Dalcin     for (p = pStart; p < pEnd; ++p) {
39109566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
39119566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
3912552f7358SJed Brown       if (!coneSize && supportSize) {
3913277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
3914277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
3915552f7358SJed Brown         ++numRoots;
3916552f7358SJed Brown       } else if (!supportSize && coneSize) {
3917552f7358SJed Brown         ++numLeaves;
3918552f7358SJed Brown       } else if (!supportSize && !coneSize) {
3919552f7358SJed Brown         /* Isolated points */
3920277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
3921277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
3922552f7358SJed Brown       }
3923552f7358SJed Brown     }
39249566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax + 1));
3925277ea44aSLisandro Dalcin   }
3926277ea44aSLisandro Dalcin 
3927552f7358SJed Brown   if (numRoots + numLeaves == (pEnd - pStart)) {
3928277ea44aSLisandro Dalcin     PetscInt sMin = PETSC_MAX_INT;
3929277ea44aSLisandro Dalcin     PetscInt sMax = PETSC_MIN_INT;
3930552f7358SJed Brown     PetscInt coneSize, supportSize;
3931552f7358SJed Brown 
3932277ea44aSLisandro Dalcin     for (p = pStart; p < pEnd; ++p) {
39339566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
39349566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
3935552f7358SJed Brown       if (!supportSize && coneSize) {
3936277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
3937277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
3938552f7358SJed Brown       }
3939552f7358SJed Brown     }
39409566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax + 1));
3941552f7358SJed Brown   } else {
3942277ea44aSLisandro Dalcin     PetscInt level = 0;
3943277ea44aSLisandro Dalcin     PetscInt qStart, qEnd, q;
3944552f7358SJed Brown 
39459566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
3946277ea44aSLisandro Dalcin     while (qEnd > qStart) {
3947277ea44aSLisandro Dalcin       PetscInt sMin = PETSC_MAX_INT;
3948277ea44aSLisandro Dalcin       PetscInt sMax = PETSC_MIN_INT;
394974ef644bSMatthew G. Knepley 
3950277ea44aSLisandro Dalcin       for (q = qStart; q < qEnd; ++q) {
395174ef644bSMatthew G. Knepley         const PetscInt *support;
395274ef644bSMatthew G. Knepley         PetscInt        supportSize, s;
395374ef644bSMatthew G. Knepley 
39549566063dSJacob Faibussowitsch         PetscCall(DMPlexGetSupportSize(dm, q, &supportSize));
39559566063dSJacob Faibussowitsch         PetscCall(DMPlexGetSupport(dm, q, &support));
395674ef644bSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
3957277ea44aSLisandro Dalcin           sMin = PetscMin(support[s], sMin);
3958277ea44aSLisandro Dalcin           sMax = PetscMax(support[s], sMax);
3959552f7358SJed Brown         }
3960552f7358SJed Brown       }
39619566063dSJacob Faibussowitsch       PetscCall(DMLabelGetNumValues(label, &level));
39629566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateDepthStratum(dm, label, level, sMin, sMax + 1));
39639566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
396474ef644bSMatthew G. Knepley     }
396574ef644bSMatthew G. Knepley   }
3966bf4602e4SToby Isaac   { /* just in case there is an empty process */
3967bf4602e4SToby Isaac     PetscInt numValues, maxValues = 0, v;
3968bf4602e4SToby Isaac 
39699566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &numValues));
39709566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(&numValues, &maxValues, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
397148a46eb9SPierre Jolivet     for (v = numValues; v < maxValues; v++) PetscCall(DMLabelAddStratum(label, v));
3972bf4602e4SToby Isaac   }
39739566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateGet((PetscObject)label, &mesh->depthState));
39749566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_Stratify, dm, 0, 0, 0));
3975552f7358SJed Brown   PetscFunctionReturn(0);
3976552f7358SJed Brown }
3977552f7358SJed Brown 
39789371c9d4SSatish Balay PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt) {
3979412e9a14SMatthew G. Knepley   DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
3980412e9a14SMatthew G. Knepley   PetscInt       dim, depth, pheight, coneSize;
3981ba2698f1SMatthew G. Knepley 
3982412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
39839566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
39849566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
39859566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
3986ba2698f1SMatthew G. Knepley   pheight = depth - pdepth;
3987ba2698f1SMatthew G. Knepley   if (depth <= 1) {
3988ba2698f1SMatthew G. Knepley     switch (pdepth) {
3989ba2698f1SMatthew G. Knepley     case 0: ct = DM_POLYTOPE_POINT; break;
3990ba2698f1SMatthew G. Knepley     case 1:
3991ba2698f1SMatthew G. Knepley       switch (coneSize) {
3992ba2698f1SMatthew G. Knepley       case 2: ct = DM_POLYTOPE_SEGMENT; break;
3993ba2698f1SMatthew G. Knepley       case 3: ct = DM_POLYTOPE_TRIANGLE; break;
3994ba2698f1SMatthew G. Knepley       case 4:
3995ba2698f1SMatthew G. Knepley         switch (dim) {
3996ba2698f1SMatthew G. Knepley         case 2: ct = DM_POLYTOPE_QUADRILATERAL; break;
3997ba2698f1SMatthew G. Knepley         case 3: ct = DM_POLYTOPE_TETRAHEDRON; break;
3998ba2698f1SMatthew G. Knepley         default: break;
3999ba2698f1SMatthew G. Knepley         }
4000ba2698f1SMatthew G. Knepley         break;
4001da9060c4SMatthew G. Knepley       case 5: ct = DM_POLYTOPE_PYRAMID; break;
4002ba2698f1SMatthew G. Knepley       case 6: ct = DM_POLYTOPE_TRI_PRISM_TENSOR; break;
4003ba2698f1SMatthew G. Knepley       case 8: ct = DM_POLYTOPE_HEXAHEDRON; break;
4004ba2698f1SMatthew G. Knepley       default: break;
4005ba2698f1SMatthew G. Knepley       }
4006ba2698f1SMatthew G. Knepley     }
4007ba2698f1SMatthew G. Knepley   } else {
4008ba2698f1SMatthew G. Knepley     if (pdepth == 0) {
4009ba2698f1SMatthew G. Knepley       ct = DM_POLYTOPE_POINT;
4010ba2698f1SMatthew G. Knepley     } else if (pheight == 0) {
4011ba2698f1SMatthew G. Knepley       switch (dim) {
4012ba2698f1SMatthew G. Knepley       case 1:
4013ba2698f1SMatthew G. Knepley         switch (coneSize) {
4014ba2698f1SMatthew G. Knepley         case 2: ct = DM_POLYTOPE_SEGMENT; break;
4015ba2698f1SMatthew G. Knepley         default: break;
4016ba2698f1SMatthew G. Knepley         }
4017ba2698f1SMatthew G. Knepley         break;
4018ba2698f1SMatthew G. Knepley       case 2:
4019ba2698f1SMatthew G. Knepley         switch (coneSize) {
4020ba2698f1SMatthew G. Knepley         case 3: ct = DM_POLYTOPE_TRIANGLE; break;
4021ba2698f1SMatthew G. Knepley         case 4: ct = DM_POLYTOPE_QUADRILATERAL; break;
4022ba2698f1SMatthew G. Knepley         default: break;
4023ba2698f1SMatthew G. Knepley         }
4024ba2698f1SMatthew G. Knepley         break;
4025ba2698f1SMatthew G. Knepley       case 3:
4026ba2698f1SMatthew G. Knepley         switch (coneSize) {
4027ba2698f1SMatthew G. Knepley         case 4: ct = DM_POLYTOPE_TETRAHEDRON; break;
40289371c9d4SSatish Balay         case 5: {
4029da9060c4SMatthew G. Knepley           const PetscInt *cone;
4030da9060c4SMatthew G. Knepley           PetscInt        faceConeSize;
4031da9060c4SMatthew G. Knepley 
40329566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCone(dm, p, &cone));
40339566063dSJacob Faibussowitsch           PetscCall(DMPlexGetConeSize(dm, cone[0], &faceConeSize));
4034da9060c4SMatthew G. Knepley           switch (faceConeSize) {
4035da9060c4SMatthew G. Knepley           case 3: ct = DM_POLYTOPE_TRI_PRISM_TENSOR; break;
4036da9060c4SMatthew G. Knepley           case 4: ct = DM_POLYTOPE_PYRAMID; break;
4037da9060c4SMatthew G. Knepley           }
40389371c9d4SSatish Balay         } break;
4039ba2698f1SMatthew G. Knepley         case 6: ct = DM_POLYTOPE_HEXAHEDRON; break;
4040ba2698f1SMatthew G. Knepley         default: break;
4041ba2698f1SMatthew G. Knepley         }
4042ba2698f1SMatthew G. Knepley         break;
4043ba2698f1SMatthew G. Knepley       default: break;
4044ba2698f1SMatthew G. Knepley       }
4045ba2698f1SMatthew G. Knepley     } else if (pheight > 0) {
4046ba2698f1SMatthew G. Knepley       switch (coneSize) {
4047ba2698f1SMatthew G. Knepley       case 2: ct = DM_POLYTOPE_SEGMENT; break;
4048ba2698f1SMatthew G. Knepley       case 3: ct = DM_POLYTOPE_TRIANGLE; break;
4049ba2698f1SMatthew G. Knepley       case 4: ct = DM_POLYTOPE_QUADRILATERAL; break;
4050ba2698f1SMatthew G. Knepley       default: break;
4051ba2698f1SMatthew G. Knepley       }
4052ba2698f1SMatthew G. Knepley     }
4053ba2698f1SMatthew G. Knepley   }
4054412e9a14SMatthew G. Knepley   *pt = ct;
4055412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
4056ba2698f1SMatthew G. Knepley }
4057412e9a14SMatthew G. Knepley 
4058412e9a14SMatthew G. Knepley /*@
4059412e9a14SMatthew G. Knepley   DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size.
4060412e9a14SMatthew G. Knepley 
4061412e9a14SMatthew G. Knepley   Collective on dm
4062412e9a14SMatthew G. Knepley 
4063412e9a14SMatthew G. Knepley   Input Parameter:
4064412e9a14SMatthew G. Knepley . mesh - The DMPlex
4065412e9a14SMatthew G. Knepley 
4066412e9a14SMatthew G. Knepley   DMPlexComputeCellTypes() should be called after all calls to DMPlexSymmetrize() and DMPlexStratify()
4067412e9a14SMatthew G. Knepley 
4068412e9a14SMatthew G. Knepley   Level: developer
4069412e9a14SMatthew G. Knepley 
4070412e9a14SMatthew G. Knepley   Note: This function is normally called automatically by Plex when a cell type is requested. It creates an
4071412e9a14SMatthew G. Knepley   internal DMLabel named "celltype" which can be directly accessed using DMGetLabel(). A user may disable
4072412e9a14SMatthew G. Knepley   automatic creation by creating the label manually, using DMCreateLabel(dm, "celltype").
4073412e9a14SMatthew G. Knepley 
4074db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexStratify()`, `DMGetLabel()`, `DMCreateLabel()`
4075412e9a14SMatthew G. Knepley @*/
40769371c9d4SSatish Balay PetscErrorCode DMPlexComputeCellTypes(DM dm) {
4077412e9a14SMatthew G. Knepley   DM_Plex *mesh;
4078412e9a14SMatthew G. Knepley   DMLabel  ctLabel;
4079412e9a14SMatthew G. Knepley   PetscInt pStart, pEnd, p;
4080412e9a14SMatthew G. Knepley 
4081412e9a14SMatthew G. Knepley   PetscFunctionBegin;
4082412e9a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4083412e9a14SMatthew G. Knepley   mesh = (DM_Plex *)dm->data;
40849566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "celltype"));
40859566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel));
40869566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
4087412e9a14SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
4088327c2912SStefano Zampini     DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
4089412e9a14SMatthew G. Knepley     PetscInt       pdepth;
4090412e9a14SMatthew G. Knepley 
40919566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPointDepth(dm, p, &pdepth));
40929566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellType_Internal(dm, p, pdepth, &ct));
409363a3b9bcSJacob Faibussowitsch     PetscCheck(ct != DM_POLYTOPE_UNKNOWN, PETSC_COMM_SELF, PETSC_ERR_SUP, "Point %" PetscInt_FMT " is screwed up", p);
40949566063dSJacob Faibussowitsch     PetscCall(DMLabelSetValue(ctLabel, p, ct));
4095412e9a14SMatthew G. Knepley   }
40969566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateGet((PetscObject)ctLabel, &mesh->celltypeState));
40979566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)ctLabel, NULL, "-dm_plex_celltypes_view"));
4098ba2698f1SMatthew G. Knepley   PetscFunctionReturn(0);
4099ba2698f1SMatthew G. Knepley }
4100ba2698f1SMatthew G. Knepley 
4101552f7358SJed Brown /*@C
4102552f7358SJed Brown   DMPlexGetJoin - Get an array for the join of the set of points
4103552f7358SJed Brown 
4104552f7358SJed Brown   Not Collective
4105552f7358SJed Brown 
4106552f7358SJed Brown   Input Parameters:
4107552f7358SJed Brown + dm - The DMPlex object
4108552f7358SJed Brown . numPoints - The number of input points for the join
4109552f7358SJed Brown - points - The input points
4110552f7358SJed Brown 
4111552f7358SJed Brown   Output Parameters:
4112552f7358SJed Brown + numCoveredPoints - The number of points in the join
4113552f7358SJed Brown - coveredPoints - The points in the join
4114552f7358SJed Brown 
4115552f7358SJed Brown   Level: intermediate
4116552f7358SJed Brown 
4117552f7358SJed Brown   Note: Currently, this is restricted to a single level join
4118552f7358SJed Brown 
41193813dfbdSMatthew G Knepley   Fortran Notes:
41203813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
41213813dfbdSMatthew G Knepley   include petsc.h90 in your code.
41223813dfbdSMatthew G Knepley 
41233813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
41243813dfbdSMatthew G Knepley 
4125db781477SPatrick Sanan .seealso: `DMPlexRestoreJoin()`, `DMPlexGetMeet()`
4126552f7358SJed Brown @*/
41279371c9d4SSatish Balay PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) {
4128552f7358SJed Brown   DM_Plex  *mesh = (DM_Plex *)dm->data;
4129552f7358SJed Brown   PetscInt *join[2];
4130552f7358SJed Brown   PetscInt  joinSize, i = 0;
4131552f7358SJed Brown   PetscInt  dof, off, p, c, m;
41326302a7fbSVaclav Hapla   PetscInt  maxSupportSize;
4133552f7358SJed Brown 
4134552f7358SJed Brown   PetscFunctionBegin;
4135552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
413648bb261cSVaclav Hapla   PetscValidIntPointer(points, 3);
413748bb261cSVaclav Hapla   PetscValidIntPointer(numCoveredPoints, 4);
413848bb261cSVaclav Hapla   PetscValidPointer(coveredPoints, 5);
41396302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize));
41406302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[0]));
41416302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[1]));
4142552f7358SJed Brown   /* Copy in support of first point */
41439566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, points[0], &dof));
41449566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, points[0], &off));
4145ad540459SPierre Jolivet   for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = mesh->supports[off + joinSize];
4146552f7358SJed Brown   /* Check each successive support */
4147552f7358SJed Brown   for (p = 1; p < numPoints; ++p) {
4148552f7358SJed Brown     PetscInt newJoinSize = 0;
4149552f7358SJed Brown 
41509566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->supportSection, points[p], &dof));
41519566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->supportSection, points[p], &off));
4152552f7358SJed Brown     for (c = 0; c < dof; ++c) {
4153552f7358SJed Brown       const PetscInt point = mesh->supports[off + c];
4154552f7358SJed Brown 
4155552f7358SJed Brown       for (m = 0; m < joinSize; ++m) {
4156552f7358SJed Brown         if (point == join[i][m]) {
4157552f7358SJed Brown           join[1 - i][newJoinSize++] = point;
4158552f7358SJed Brown           break;
4159552f7358SJed Brown         }
4160552f7358SJed Brown       }
4161552f7358SJed Brown     }
4162552f7358SJed Brown     joinSize = newJoinSize;
4163552f7358SJed Brown     i        = 1 - i;
4164552f7358SJed Brown   }
4165552f7358SJed Brown   *numCoveredPoints = joinSize;
4166552f7358SJed Brown   *coveredPoints    = join[i];
41676302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, maxSupportSize, MPIU_INT, &join[1 - i]));
4168552f7358SJed Brown   PetscFunctionReturn(0);
4169552f7358SJed Brown }
4170552f7358SJed Brown 
4171552f7358SJed Brown /*@C
4172552f7358SJed Brown   DMPlexRestoreJoin - Restore an array for the join of the set of points
4173552f7358SJed Brown 
4174552f7358SJed Brown   Not Collective
4175552f7358SJed Brown 
4176552f7358SJed Brown   Input Parameters:
4177552f7358SJed Brown + dm - The DMPlex object
4178552f7358SJed Brown . numPoints - The number of input points for the join
4179552f7358SJed Brown - points - The input points
4180552f7358SJed Brown 
4181552f7358SJed Brown   Output Parameters:
4182552f7358SJed Brown + numCoveredPoints - The number of points in the join
4183552f7358SJed Brown - coveredPoints - The points in the join
4184552f7358SJed Brown 
41853813dfbdSMatthew G Knepley   Fortran Notes:
41863813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
41873813dfbdSMatthew G Knepley   include petsc.h90 in your code.
41883813dfbdSMatthew G Knepley 
41893813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
41903813dfbdSMatthew G Knepley 
4191552f7358SJed Brown   Level: intermediate
4192552f7358SJed Brown 
4193db781477SPatrick Sanan .seealso: `DMPlexGetJoin()`, `DMPlexGetFullJoin()`, `DMPlexGetMeet()`
4194552f7358SJed Brown @*/
41959371c9d4SSatish Balay PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) {
4196552f7358SJed Brown   PetscFunctionBegin;
4197552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4198d7902bd2SMatthew G. Knepley   if (points) PetscValidIntPointer(points, 3);
4199d7902bd2SMatthew G. Knepley   if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints, 4);
4200d7902bd2SMatthew G. Knepley   PetscValidPointer(coveredPoints, 5);
42019566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints));
4202d7902bd2SMatthew G. Knepley   if (numCoveredPoints) *numCoveredPoints = 0;
4203552f7358SJed Brown   PetscFunctionReturn(0);
4204552f7358SJed Brown }
4205552f7358SJed Brown 
4206552f7358SJed Brown /*@C
4207552f7358SJed Brown   DMPlexGetFullJoin - Get an array for the join of the set of points
4208552f7358SJed Brown 
4209552f7358SJed Brown   Not Collective
4210552f7358SJed Brown 
4211552f7358SJed Brown   Input Parameters:
4212552f7358SJed Brown + dm - The DMPlex object
4213552f7358SJed Brown . numPoints - The number of input points for the join
4214552f7358SJed Brown - points - The input points
4215552f7358SJed Brown 
4216552f7358SJed Brown   Output Parameters:
4217552f7358SJed Brown + numCoveredPoints - The number of points in the join
4218552f7358SJed Brown - coveredPoints - The points in the join
4219552f7358SJed Brown 
42203813dfbdSMatthew G Knepley   Fortran Notes:
42213813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
42223813dfbdSMatthew G Knepley   include petsc.h90 in your code.
42233813dfbdSMatthew G Knepley 
42243813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
42253813dfbdSMatthew G Knepley 
4226552f7358SJed Brown   Level: intermediate
4227552f7358SJed Brown 
4228db781477SPatrick Sanan .seealso: `DMPlexGetJoin()`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()`
4229552f7358SJed Brown @*/
42309371c9d4SSatish Balay PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) {
4231552f7358SJed Brown   PetscInt *offsets, **closures;
4232552f7358SJed Brown   PetscInt *join[2];
4233552f7358SJed Brown   PetscInt  depth = 0, maxSize, joinSize = 0, i = 0;
423424c766afSToby Isaac   PetscInt  p, d, c, m, ms;
4235552f7358SJed Brown 
4236552f7358SJed Brown   PetscFunctionBegin;
4237552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
423848bb261cSVaclav Hapla   PetscValidIntPointer(points, 3);
423948bb261cSVaclav Hapla   PetscValidIntPointer(numCoveredPoints, 4);
424048bb261cSVaclav Hapla   PetscValidPointer(coveredPoints, 5);
4241552f7358SJed Brown 
42429566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
42439566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(numPoints, &closures));
42449566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets));
42456302a7fbSVaclav Hapla   PetscCall(DMPlexGetMaxSizes(dm, NULL, &ms));
424624c766afSToby Isaac   maxSize = (ms > 1) ? ((PetscPowInt(ms, depth + 1) - 1) / (ms - 1)) : depth + 1;
42479566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0]));
42489566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1]));
4249552f7358SJed Brown 
4250552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
4251552f7358SJed Brown     PetscInt closureSize;
4252552f7358SJed Brown 
42539566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]));
42540d644c17SKarl Rupp 
4255552f7358SJed Brown     offsets[p * (depth + 2) + 0] = 0;
4256552f7358SJed Brown     for (d = 0; d < depth + 1; ++d) {
4257552f7358SJed Brown       PetscInt pStart, pEnd, i;
4258552f7358SJed Brown 
42599566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
4260552f7358SJed Brown       for (i = offsets[p * (depth + 2) + d]; i < closureSize; ++i) {
4261552f7358SJed Brown         if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) {
4262552f7358SJed Brown           offsets[p * (depth + 2) + d + 1] = i;
4263552f7358SJed Brown           break;
4264552f7358SJed Brown         }
4265552f7358SJed Brown       }
4266552f7358SJed Brown       if (i == closureSize) offsets[p * (depth + 2) + d + 1] = i;
4267552f7358SJed Brown     }
426863a3b9bcSJacob 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);
4269552f7358SJed Brown   }
4270552f7358SJed Brown   for (d = 0; d < depth + 1; ++d) {
4271552f7358SJed Brown     PetscInt dof;
4272552f7358SJed Brown 
4273552f7358SJed Brown     /* Copy in support of first point */
4274552f7358SJed Brown     dof = offsets[d + 1] - offsets[d];
4275ad540459SPierre Jolivet     for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = closures[0][(offsets[d] + joinSize) * 2];
4276552f7358SJed Brown     /* Check each successive cone */
4277552f7358SJed Brown     for (p = 1; p < numPoints && joinSize; ++p) {
4278552f7358SJed Brown       PetscInt newJoinSize = 0;
4279552f7358SJed Brown 
4280552f7358SJed Brown       dof = offsets[p * (depth + 2) + d + 1] - offsets[p * (depth + 2) + d];
4281552f7358SJed Brown       for (c = 0; c < dof; ++c) {
4282552f7358SJed Brown         const PetscInt point = closures[p][(offsets[p * (depth + 2) + d] + c) * 2];
4283552f7358SJed Brown 
4284552f7358SJed Brown         for (m = 0; m < joinSize; ++m) {
4285552f7358SJed Brown           if (point == join[i][m]) {
4286552f7358SJed Brown             join[1 - i][newJoinSize++] = point;
4287552f7358SJed Brown             break;
4288552f7358SJed Brown           }
4289552f7358SJed Brown         }
4290552f7358SJed Brown       }
4291552f7358SJed Brown       joinSize = newJoinSize;
4292552f7358SJed Brown       i        = 1 - i;
4293552f7358SJed Brown     }
4294552f7358SJed Brown     if (joinSize) break;
4295552f7358SJed Brown   }
4296552f7358SJed Brown   *numCoveredPoints = joinSize;
4297552f7358SJed Brown   *coveredPoints    = join[i];
429848a46eb9SPierre Jolivet   for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]));
42999566063dSJacob Faibussowitsch   PetscCall(PetscFree(closures));
43009566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets));
43016302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, ms, MPIU_INT, &join[1 - i]));
4302552f7358SJed Brown   PetscFunctionReturn(0);
4303552f7358SJed Brown }
4304552f7358SJed Brown 
4305552f7358SJed Brown /*@C
4306552f7358SJed Brown   DMPlexGetMeet - Get an array for the meet of the set of points
4307552f7358SJed Brown 
4308552f7358SJed Brown   Not Collective
4309552f7358SJed Brown 
4310552f7358SJed Brown   Input Parameters:
4311552f7358SJed Brown + dm - The DMPlex object
4312552f7358SJed Brown . numPoints - The number of input points for the meet
4313552f7358SJed Brown - points - The input points
4314552f7358SJed Brown 
4315552f7358SJed Brown   Output Parameters:
4316552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4317552f7358SJed Brown - coveredPoints - The points in the meet
4318552f7358SJed Brown 
4319552f7358SJed Brown   Level: intermediate
4320552f7358SJed Brown 
4321552f7358SJed Brown   Note: Currently, this is restricted to a single level meet
4322552f7358SJed Brown 
43233813dfbdSMatthew G Knepley   Fortran Notes:
43243813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
43253813dfbdSMatthew G Knepley   include petsc.h90 in your code.
43263813dfbdSMatthew G Knepley 
43273813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
43283813dfbdSMatthew G Knepley 
4329db781477SPatrick Sanan .seealso: `DMPlexRestoreMeet()`, `DMPlexGetJoin()`
4330552f7358SJed Brown @*/
43319371c9d4SSatish Balay PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) {
4332552f7358SJed Brown   DM_Plex  *mesh = (DM_Plex *)dm->data;
4333552f7358SJed Brown   PetscInt *meet[2];
4334552f7358SJed Brown   PetscInt  meetSize, i = 0;
4335552f7358SJed Brown   PetscInt  dof, off, p, c, m;
43366302a7fbSVaclav Hapla   PetscInt  maxConeSize;
4337552f7358SJed Brown 
4338552f7358SJed Brown   PetscFunctionBegin;
4339552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4340dadcf809SJacob Faibussowitsch   PetscValidIntPointer(points, 3);
4341dadcf809SJacob Faibussowitsch   PetscValidIntPointer(numCoveringPoints, 4);
4342064a246eSJacob Faibussowitsch   PetscValidPointer(coveringPoints, 5);
43436302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->coneSection, &maxConeSize));
43446302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[0]));
43456302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[1]));
4346552f7358SJed Brown   /* Copy in cone of first point */
43479566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, points[0], &dof));
43489566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, points[0], &off));
4349ad540459SPierre Jolivet   for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = mesh->cones[off + meetSize];
4350552f7358SJed Brown   /* Check each successive cone */
4351552f7358SJed Brown   for (p = 1; p < numPoints; ++p) {
4352552f7358SJed Brown     PetscInt newMeetSize = 0;
4353552f7358SJed Brown 
43549566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, points[p], &dof));
43559566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, points[p], &off));
4356552f7358SJed Brown     for (c = 0; c < dof; ++c) {
4357552f7358SJed Brown       const PetscInt point = mesh->cones[off + c];
4358552f7358SJed Brown 
4359552f7358SJed Brown       for (m = 0; m < meetSize; ++m) {
4360552f7358SJed Brown         if (point == meet[i][m]) {
4361552f7358SJed Brown           meet[1 - i][newMeetSize++] = point;
4362552f7358SJed Brown           break;
4363552f7358SJed Brown         }
4364552f7358SJed Brown       }
4365552f7358SJed Brown     }
4366552f7358SJed Brown     meetSize = newMeetSize;
4367552f7358SJed Brown     i        = 1 - i;
4368552f7358SJed Brown   }
4369552f7358SJed Brown   *numCoveringPoints = meetSize;
4370552f7358SJed Brown   *coveringPoints    = meet[i];
43716302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, maxConeSize, MPIU_INT, &meet[1 - i]));
4372552f7358SJed Brown   PetscFunctionReturn(0);
4373552f7358SJed Brown }
4374552f7358SJed Brown 
4375552f7358SJed Brown /*@C
4376552f7358SJed Brown   DMPlexRestoreMeet - Restore an array for the meet of the set of points
4377552f7358SJed Brown 
4378552f7358SJed Brown   Not Collective
4379552f7358SJed Brown 
4380552f7358SJed Brown   Input Parameters:
4381552f7358SJed Brown + dm - The DMPlex object
4382552f7358SJed Brown . numPoints - The number of input points for the meet
4383552f7358SJed Brown - points - The input points
4384552f7358SJed Brown 
4385552f7358SJed Brown   Output Parameters:
4386552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4387552f7358SJed Brown - coveredPoints - The points in the meet
4388552f7358SJed Brown 
4389552f7358SJed Brown   Level: intermediate
4390552f7358SJed Brown 
43913813dfbdSMatthew G Knepley   Fortran Notes:
43923813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
43933813dfbdSMatthew G Knepley   include petsc.h90 in your code.
43943813dfbdSMatthew G Knepley 
43953813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
43963813dfbdSMatthew G Knepley 
4397db781477SPatrick Sanan .seealso: `DMPlexGetMeet()`, `DMPlexGetFullMeet()`, `DMPlexGetJoin()`
4398552f7358SJed Brown @*/
43999371c9d4SSatish Balay PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) {
4400552f7358SJed Brown   PetscFunctionBegin;
4401552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4402d7902bd2SMatthew G. Knepley   if (points) PetscValidIntPointer(points, 3);
4403d7902bd2SMatthew G. Knepley   if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints, 4);
4404d7902bd2SMatthew G. Knepley   PetscValidPointer(coveredPoints, 5);
44059566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints));
4406d7902bd2SMatthew G. Knepley   if (numCoveredPoints) *numCoveredPoints = 0;
4407552f7358SJed Brown   PetscFunctionReturn(0);
4408552f7358SJed Brown }
4409552f7358SJed Brown 
4410552f7358SJed Brown /*@C
4411552f7358SJed Brown   DMPlexGetFullMeet - Get an array for the meet of the set of points
4412552f7358SJed Brown 
4413552f7358SJed Brown   Not Collective
4414552f7358SJed Brown 
4415552f7358SJed Brown   Input Parameters:
4416552f7358SJed Brown + dm - The DMPlex object
4417552f7358SJed Brown . numPoints - The number of input points for the meet
4418552f7358SJed Brown - points - The input points
4419552f7358SJed Brown 
4420552f7358SJed Brown   Output Parameters:
4421552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4422552f7358SJed Brown - coveredPoints - The points in the meet
4423552f7358SJed Brown 
4424552f7358SJed Brown   Level: intermediate
4425552f7358SJed Brown 
44263813dfbdSMatthew G Knepley   Fortran Notes:
44273813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
44283813dfbdSMatthew G Knepley   include petsc.h90 in your code.
44293813dfbdSMatthew G Knepley 
44303813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
44313813dfbdSMatthew G Knepley 
4432db781477SPatrick Sanan .seealso: `DMPlexGetMeet()`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()`
4433552f7358SJed Brown @*/
44349371c9d4SSatish Balay PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) {
4435552f7358SJed Brown   PetscInt *offsets, **closures;
4436552f7358SJed Brown   PetscInt *meet[2];
4437552f7358SJed Brown   PetscInt  height = 0, maxSize, meetSize = 0, i = 0;
443824c766afSToby Isaac   PetscInt  p, h, c, m, mc;
4439552f7358SJed Brown 
4440552f7358SJed Brown   PetscFunctionBegin;
4441552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4442dadcf809SJacob Faibussowitsch   PetscValidIntPointer(points, 3);
4443dadcf809SJacob Faibussowitsch   PetscValidIntPointer(numCoveredPoints, 4);
4444064a246eSJacob Faibussowitsch   PetscValidPointer(coveredPoints, 5);
4445552f7358SJed Brown 
44469566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &height));
44479566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(numPoints, &closures));
44489566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets));
44496302a7fbSVaclav Hapla   PetscCall(DMPlexGetMaxSizes(dm, &mc, NULL));
445024c766afSToby Isaac   maxSize = (mc > 1) ? ((PetscPowInt(mc, height + 1) - 1) / (mc - 1)) : height + 1;
44519566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0]));
44529566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1]));
4453552f7358SJed Brown 
4454552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
4455552f7358SJed Brown     PetscInt closureSize;
4456552f7358SJed Brown 
44579566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]));
44580d644c17SKarl Rupp 
4459552f7358SJed Brown     offsets[p * (height + 2) + 0] = 0;
4460552f7358SJed Brown     for (h = 0; h < height + 1; ++h) {
4461552f7358SJed Brown       PetscInt pStart, pEnd, i;
4462552f7358SJed Brown 
44639566063dSJacob Faibussowitsch       PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd));
4464552f7358SJed Brown       for (i = offsets[p * (height + 2) + h]; i < closureSize; ++i) {
4465552f7358SJed Brown         if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) {
4466552f7358SJed Brown           offsets[p * (height + 2) + h + 1] = i;
4467552f7358SJed Brown           break;
4468552f7358SJed Brown         }
4469552f7358SJed Brown       }
4470552f7358SJed Brown       if (i == closureSize) offsets[p * (height + 2) + h + 1] = i;
4471552f7358SJed Brown     }
447263a3b9bcSJacob 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);
4473552f7358SJed Brown   }
4474552f7358SJed Brown   for (h = 0; h < height + 1; ++h) {
4475552f7358SJed Brown     PetscInt dof;
4476552f7358SJed Brown 
4477552f7358SJed Brown     /* Copy in cone of first point */
4478552f7358SJed Brown     dof = offsets[h + 1] - offsets[h];
4479ad540459SPierre Jolivet     for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = closures[0][(offsets[h] + meetSize) * 2];
4480552f7358SJed Brown     /* Check each successive cone */
4481552f7358SJed Brown     for (p = 1; p < numPoints && meetSize; ++p) {
4482552f7358SJed Brown       PetscInt newMeetSize = 0;
4483552f7358SJed Brown 
4484552f7358SJed Brown       dof = offsets[p * (height + 2) + h + 1] - offsets[p * (height + 2) + h];
4485552f7358SJed Brown       for (c = 0; c < dof; ++c) {
4486552f7358SJed Brown         const PetscInt point = closures[p][(offsets[p * (height + 2) + h] + c) * 2];
4487552f7358SJed Brown 
4488552f7358SJed Brown         for (m = 0; m < meetSize; ++m) {
4489552f7358SJed Brown           if (point == meet[i][m]) {
4490552f7358SJed Brown             meet[1 - i][newMeetSize++] = point;
4491552f7358SJed Brown             break;
4492552f7358SJed Brown           }
4493552f7358SJed Brown         }
4494552f7358SJed Brown       }
4495552f7358SJed Brown       meetSize = newMeetSize;
4496552f7358SJed Brown       i        = 1 - i;
4497552f7358SJed Brown     }
4498552f7358SJed Brown     if (meetSize) break;
4499552f7358SJed Brown   }
4500552f7358SJed Brown   *numCoveredPoints = meetSize;
4501552f7358SJed Brown   *coveredPoints    = meet[i];
450248a46eb9SPierre Jolivet   for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]));
45039566063dSJacob Faibussowitsch   PetscCall(PetscFree(closures));
45049566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets));
45056302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, mc, MPIU_INT, &meet[1 - i]));
4506552f7358SJed Brown   PetscFunctionReturn(0);
4507552f7358SJed Brown }
4508552f7358SJed Brown 
45094e3744c5SMatthew G. Knepley /*@C
45104e3744c5SMatthew G. Knepley   DMPlexEqual - Determine if two DMs have the same topology
45114e3744c5SMatthew G. Knepley 
45124e3744c5SMatthew G. Knepley   Not Collective
45134e3744c5SMatthew G. Knepley 
45144e3744c5SMatthew G. Knepley   Input Parameters:
45154e3744c5SMatthew G. Knepley + dmA - A DMPlex object
45164e3744c5SMatthew G. Knepley - dmB - A DMPlex object
45174e3744c5SMatthew G. Knepley 
45184e3744c5SMatthew G. Knepley   Output Parameters:
45194e3744c5SMatthew G. Knepley . equal - PETSC_TRUE if the topologies are identical
45204e3744c5SMatthew G. Knepley 
45214e3744c5SMatthew G. Knepley   Level: intermediate
45224e3744c5SMatthew G. Knepley 
45234e3744c5SMatthew G. Knepley   Notes:
45244e3744c5SMatthew G. Knepley   We are not solving graph isomorphism, so we do not permutation.
45254e3744c5SMatthew G. Knepley 
4526db781477SPatrick Sanan .seealso: `DMPlexGetCone()`
45274e3744c5SMatthew G. Knepley @*/
45289371c9d4SSatish Balay PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) {
45294e3744c5SMatthew G. Knepley   PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p;
45304e3744c5SMatthew G. Knepley 
45314e3744c5SMatthew G. Knepley   PetscFunctionBegin;
45324e3744c5SMatthew G. Knepley   PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
45334e3744c5SMatthew G. Knepley   PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
4534dadcf809SJacob Faibussowitsch   PetscValidBoolPointer(equal, 3);
45354e3744c5SMatthew G. Knepley 
45364e3744c5SMatthew G. Knepley   *equal = PETSC_FALSE;
45379566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmA, &depth));
45389566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmB, &depthB));
45394e3744c5SMatthew G. Knepley   if (depth != depthB) PetscFunctionReturn(0);
45409566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dmA, &pStart, &pEnd));
45419566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dmB, &pStartB, &pEndB));
45424e3744c5SMatthew G. Knepley   if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(0);
45434e3744c5SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
45444e3744c5SMatthew G. Knepley     const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB;
45454e3744c5SMatthew G. Knepley     PetscInt        coneSize, coneSizeB, c, supportSize, supportSizeB, s;
45464e3744c5SMatthew G. Knepley 
45479566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dmA, p, &coneSize));
45489566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dmA, p, &cone));
45499566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dmA, p, &ornt));
45509566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dmB, p, &coneSizeB));
45519566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dmB, p, &coneB));
45529566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dmB, p, &orntB));
45534e3744c5SMatthew G. Knepley     if (coneSize != coneSizeB) PetscFunctionReturn(0);
45544e3744c5SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
45554e3744c5SMatthew G. Knepley       if (cone[c] != coneB[c]) PetscFunctionReturn(0);
45564e3744c5SMatthew G. Knepley       if (ornt[c] != orntB[c]) PetscFunctionReturn(0);
45574e3744c5SMatthew G. Knepley     }
45589566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dmA, p, &supportSize));
45599566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dmA, p, &support));
45609566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dmB, p, &supportSizeB));
45619566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dmB, p, &supportB));
45624e3744c5SMatthew G. Knepley     if (supportSize != supportSizeB) PetscFunctionReturn(0);
45634e3744c5SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
45644e3744c5SMatthew G. Knepley       if (support[s] != supportB[s]) PetscFunctionReturn(0);
45654e3744c5SMatthew G. Knepley     }
45664e3744c5SMatthew G. Knepley   }
45674e3744c5SMatthew G. Knepley   *equal = PETSC_TRUE;
45684e3744c5SMatthew G. Knepley   PetscFunctionReturn(0);
45694e3744c5SMatthew G. Knepley }
45704e3744c5SMatthew G. Knepley 
45717cd05799SMatthew G. Knepley /*@C
45727cd05799SMatthew G. Knepley   DMPlexGetNumFaceVertices - Returns the number of vertices on a face
45737cd05799SMatthew G. Knepley 
45747cd05799SMatthew G. Knepley   Not Collective
45757cd05799SMatthew G. Knepley 
45767cd05799SMatthew G. Knepley   Input Parameters:
45777cd05799SMatthew G. Knepley + dm         - The DMPlex
45787cd05799SMatthew G. Knepley . cellDim    - The cell dimension
45797cd05799SMatthew G. Knepley - numCorners - The number of vertices on a cell
45807cd05799SMatthew G. Knepley 
45817cd05799SMatthew G. Knepley   Output Parameters:
45827cd05799SMatthew G. Knepley . numFaceVertices - The number of vertices on a face
45837cd05799SMatthew G. Knepley 
45847cd05799SMatthew G. Knepley   Level: developer
45857cd05799SMatthew G. Knepley 
45867cd05799SMatthew G. Knepley   Notes:
45877cd05799SMatthew G. Knepley   Of course this can only work for a restricted set of symmetric shapes
45887cd05799SMatthew G. Knepley 
4589db781477SPatrick Sanan .seealso: `DMPlexGetCone()`
45907cd05799SMatthew G. Knepley @*/
45919371c9d4SSatish Balay PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) {
459282f516ccSBarry Smith   MPI_Comm comm;
4593552f7358SJed Brown 
4594552f7358SJed Brown   PetscFunctionBegin;
45959566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
4596dadcf809SJacob Faibussowitsch   PetscValidIntPointer(numFaceVertices, 4);
4597552f7358SJed Brown   switch (cellDim) {
45989371c9d4SSatish Balay   case 0: *numFaceVertices = 0; break;
45999371c9d4SSatish Balay   case 1: *numFaceVertices = 1; break;
4600552f7358SJed Brown   case 2:
4601552f7358SJed Brown     switch (numCorners) {
460219436ca2SJed Brown     case 3:                 /* triangle */
460319436ca2SJed Brown       *numFaceVertices = 2; /* Edge has 2 vertices */
4604552f7358SJed Brown       break;
460519436ca2SJed Brown     case 4:                 /* quadrilateral */
460619436ca2SJed Brown       *numFaceVertices = 2; /* Edge has 2 vertices */
4607552f7358SJed Brown       break;
460819436ca2SJed Brown     case 6:                 /* quadratic triangle, tri and quad cohesive Lagrange cells */
460919436ca2SJed Brown       *numFaceVertices = 3; /* Edge has 3 vertices */
4610552f7358SJed Brown       break;
461119436ca2SJed Brown     case 9:                 /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */
461219436ca2SJed Brown       *numFaceVertices = 3; /* Edge has 3 vertices */
4613552f7358SJed Brown       break;
46149371c9d4SSatish Balay     default: SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim);
4615552f7358SJed Brown     }
4616552f7358SJed Brown     break;
4617552f7358SJed Brown   case 3:
4618552f7358SJed Brown     switch (numCorners) {
461919436ca2SJed Brown     case 4:                 /* tetradehdron */
462019436ca2SJed Brown       *numFaceVertices = 3; /* Face has 3 vertices */
4621552f7358SJed Brown       break;
462219436ca2SJed Brown     case 6:                 /* tet cohesive cells */
462319436ca2SJed Brown       *numFaceVertices = 4; /* Face has 4 vertices */
4624552f7358SJed Brown       break;
462519436ca2SJed Brown     case 8:                 /* hexahedron */
462619436ca2SJed Brown       *numFaceVertices = 4; /* Face has 4 vertices */
4627552f7358SJed Brown       break;
462819436ca2SJed Brown     case 9:                 /* tet cohesive Lagrange cells */
462919436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4630552f7358SJed Brown       break;
463119436ca2SJed Brown     case 10:                /* quadratic tetrahedron */
463219436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4633552f7358SJed Brown       break;
463419436ca2SJed Brown     case 12:                /* hex cohesive Lagrange cells */
463519436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4636552f7358SJed Brown       break;
463719436ca2SJed Brown     case 18:                /* quadratic tet cohesive Lagrange cells */
463819436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4639552f7358SJed Brown       break;
464019436ca2SJed Brown     case 27:                /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */
464119436ca2SJed Brown       *numFaceVertices = 9; /* Face has 9 vertices */
4642552f7358SJed Brown       break;
46439371c9d4SSatish Balay     default: SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim);
4644552f7358SJed Brown     }
4645552f7358SJed Brown     break;
46469371c9d4SSatish Balay   default: SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %" PetscInt_FMT, cellDim);
4647552f7358SJed Brown   }
4648552f7358SJed Brown   PetscFunctionReturn(0);
4649552f7358SJed Brown }
4650552f7358SJed Brown 
4651552f7358SJed Brown /*@
4652aa50250dSMatthew G. Knepley   DMPlexGetDepthLabel - Get the DMLabel recording the depth of each point
4653552f7358SJed Brown 
4654552f7358SJed Brown   Not Collective
4655552f7358SJed Brown 
4656aa50250dSMatthew G. Knepley   Input Parameter:
4657552f7358SJed Brown . dm    - The DMPlex object
4658552f7358SJed Brown 
4659aa50250dSMatthew G. Knepley   Output Parameter:
4660aa50250dSMatthew G. Knepley . depthLabel - The DMLabel recording point depth
4661552f7358SJed Brown 
4662552f7358SJed Brown   Level: developer
4663552f7358SJed Brown 
4664db781477SPatrick Sanan .seealso: `DMPlexGetDepth()`, `DMPlexGetHeightStratum()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`,
4665aa50250dSMatthew G. Knepley @*/
46669371c9d4SSatish Balay PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) {
4667aa50250dSMatthew G. Knepley   PetscFunctionBegin;
4668aa50250dSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4669aa50250dSMatthew G. Knepley   PetscValidPointer(depthLabel, 2);
4670c58f1c22SToby Isaac   *depthLabel = dm->depthLabel;
4671aa50250dSMatthew G. Knepley   PetscFunctionReturn(0);
4672aa50250dSMatthew G. Knepley }
4673aa50250dSMatthew G. Knepley 
4674aa50250dSMatthew G. Knepley /*@
4675aa50250dSMatthew G. Knepley   DMPlexGetDepth - Get the depth of the DAG representing this mesh
4676aa50250dSMatthew G. Knepley 
4677aa50250dSMatthew G. Knepley   Not Collective
4678aa50250dSMatthew G. Knepley 
4679aa50250dSMatthew G. Knepley   Input Parameter:
4680aa50250dSMatthew G. Knepley . dm    - The DMPlex object
4681aa50250dSMatthew G. Knepley 
4682aa50250dSMatthew G. Knepley   Output Parameter:
4683aa50250dSMatthew G. Knepley . depth - The number of strata (breadth first levels) in the DAG
4684aa50250dSMatthew G. Knepley 
4685aa50250dSMatthew G. Knepley   Level: developer
4686552f7358SJed Brown 
4687b1bb481bSMatthew Knepley   Notes:
4688b1bb481bSMatthew Knepley   This returns maximum of point depths over all points, i.e. maximum value of the label returned by DMPlexGetDepthLabel().
4689dc287ab2SVaclav Hapla   The point depth is described more in detail in DMPlexGetDepthStratum().
4690dc287ab2SVaclav Hapla   An empty mesh gives -1.
4691b1bb481bSMatthew Knepley 
4692db781477SPatrick Sanan .seealso: `DMPlexGetDepthLabel()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`
4693552f7358SJed Brown @*/
46949371c9d4SSatish Balay PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) {
4695aa50250dSMatthew G. Knepley   DMLabel  label;
4696aa50250dSMatthew G. Knepley   PetscInt d = 0;
4697552f7358SJed Brown 
4698552f7358SJed Brown   PetscFunctionBegin;
4699552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4700dadcf809SJacob Faibussowitsch   PetscValidIntPointer(depth, 2);
47019566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
47029566063dSJacob Faibussowitsch   if (label) PetscCall(DMLabelGetNumValues(label, &d));
4703552f7358SJed Brown   *depth = d - 1;
4704552f7358SJed Brown   PetscFunctionReturn(0);
4705552f7358SJed Brown }
4706552f7358SJed Brown 
4707552f7358SJed Brown /*@
4708552f7358SJed Brown   DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth.
4709552f7358SJed Brown 
4710552f7358SJed Brown   Not Collective
4711552f7358SJed Brown 
4712552f7358SJed Brown   Input Parameters:
4713552f7358SJed Brown + dm    - The DMPlex object
4714570fa34dSVaclav Hapla - depth - The requested depth
4715552f7358SJed Brown 
4716552f7358SJed Brown   Output Parameters:
4717552f7358SJed Brown + start - The first point at this depth
4718552f7358SJed Brown - end   - One beyond the last point at this depth
4719552f7358SJed Brown 
4720647867b2SJed Brown   Notes:
4721647867b2SJed Brown   Depth indexing is related to topological dimension.  Depth stratum 0 contains the lowest topological dimension points,
4722647867b2SJed Brown   often "vertices".  If the mesh is "interpolated" (see DMPlexInterpolate()), then depth stratum 1 contains the next
4723647867b2SJed Brown   higher dimension, e.g., "edges".
4724647867b2SJed Brown 
4725552f7358SJed Brown   Level: developer
4726552f7358SJed Brown 
4727db781477SPatrick Sanan .seealso: `DMPlexGetHeightStratum()`, `DMPlexGetDepth()`, `DMPlexGetDepthLabel()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`, `DMPlexInterpolate()`
4728552f7358SJed Brown @*/
47299371c9d4SSatish Balay PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt depth, PetscInt *start, PetscInt *end) {
4730aa50250dSMatthew G. Knepley   DMLabel  label;
473163d1a920SMatthew G. Knepley   PetscInt pStart, pEnd;
4732552f7358SJed Brown 
4733552f7358SJed Brown   PetscFunctionBegin;
4734552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
47359371c9d4SSatish Balay   if (start) {
47369371c9d4SSatish Balay     PetscValidIntPointer(start, 3);
47379371c9d4SSatish Balay     *start = 0;
47389371c9d4SSatish Balay   }
47399371c9d4SSatish Balay   if (end) {
47409371c9d4SSatish Balay     PetscValidIntPointer(end, 4);
47419371c9d4SSatish Balay     *end = 0;
47429371c9d4SSatish Balay   }
47439566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
47440d644c17SKarl Rupp   if (pStart == pEnd) PetscFunctionReturn(0);
4745570fa34dSVaclav Hapla   if (depth < 0) {
474663d1a920SMatthew G. Knepley     if (start) *start = pStart;
474763d1a920SMatthew G. Knepley     if (end) *end = pEnd;
474863d1a920SMatthew G. Knepley     PetscFunctionReturn(0);
4749552f7358SJed Brown   }
47509566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
475128b400f6SJacob Faibussowitsch   PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");
4752570fa34dSVaclav Hapla   PetscCall(DMLabelGetStratumBounds(label, depth, start, end));
4753552f7358SJed Brown   PetscFunctionReturn(0);
4754552f7358SJed Brown }
4755552f7358SJed Brown 
4756552f7358SJed Brown /*@
4757552f7358SJed Brown   DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height.
4758552f7358SJed Brown 
4759552f7358SJed Brown   Not Collective
4760552f7358SJed Brown 
4761552f7358SJed Brown   Input Parameters:
4762552f7358SJed Brown + dm     - The DMPlex object
4763570fa34dSVaclav Hapla - height - The requested height
4764552f7358SJed Brown 
4765552f7358SJed Brown   Output Parameters:
4766552f7358SJed Brown + start - The first point at this height
4767552f7358SJed Brown - end   - One beyond the last point at this height
4768552f7358SJed Brown 
4769647867b2SJed Brown   Notes:
4770647867b2SJed Brown   Height indexing is related to topological codimension.  Height stratum 0 contains the highest topological dimension
4771647867b2SJed Brown   points, often called "cells" or "elements".  If the mesh is "interpolated" (see DMPlexInterpolate()), then height
4772647867b2SJed Brown   stratum 1 contains the boundary of these "cells", often called "faces" or "facets".
4773647867b2SJed Brown 
4774552f7358SJed Brown   Level: developer
4775552f7358SJed Brown 
4776db781477SPatrick Sanan .seealso: `DMPlexGetDepthStratum()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()`
4777552f7358SJed Brown @*/
47789371c9d4SSatish Balay PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt height, PetscInt *start, PetscInt *end) {
4779aa50250dSMatthew G. Knepley   DMLabel  label;
478063d1a920SMatthew G. Knepley   PetscInt depth, pStart, pEnd;
4781552f7358SJed Brown 
4782552f7358SJed Brown   PetscFunctionBegin;
4783552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
47849371c9d4SSatish Balay   if (start) {
47859371c9d4SSatish Balay     PetscValidIntPointer(start, 3);
47869371c9d4SSatish Balay     *start = 0;
47879371c9d4SSatish Balay   }
47889371c9d4SSatish Balay   if (end) {
47899371c9d4SSatish Balay     PetscValidIntPointer(end, 4);
47909371c9d4SSatish Balay     *end = 0;
47919371c9d4SSatish Balay   }
47929566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
47930d644c17SKarl Rupp   if (pStart == pEnd) PetscFunctionReturn(0);
4794570fa34dSVaclav Hapla   if (height < 0) {
479563d1a920SMatthew G. Knepley     if (start) *start = pStart;
479663d1a920SMatthew G. Knepley     if (end) *end = pEnd;
479763d1a920SMatthew G. Knepley     PetscFunctionReturn(0);
4798552f7358SJed Brown   }
47999566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
480028b400f6SJacob Faibussowitsch   PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");
48019566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(label, &depth));
4802570fa34dSVaclav Hapla   PetscCall(DMLabelGetStratumBounds(label, depth - 1 - height, start, end));
4803552f7358SJed Brown   PetscFunctionReturn(0);
4804552f7358SJed Brown }
4805552f7358SJed Brown 
4806ba2698f1SMatthew G. Knepley /*@
4807ba2698f1SMatthew G. Knepley   DMPlexGetPointDepth - Get the depth of a given point
4808ba2698f1SMatthew G. Knepley 
4809ba2698f1SMatthew G. Knepley   Not Collective
4810ba2698f1SMatthew G. Knepley 
4811d8d19677SJose E. Roman   Input Parameters:
4812ba2698f1SMatthew G. Knepley + dm    - The DMPlex object
4813ba2698f1SMatthew G. Knepley - point - The point
4814ba2698f1SMatthew G. Knepley 
4815ba2698f1SMatthew G. Knepley   Output Parameter:
4816ba2698f1SMatthew G. Knepley . depth - The depth of the point
4817ba2698f1SMatthew G. Knepley 
4818ba2698f1SMatthew G. Knepley   Level: intermediate
4819ba2698f1SMatthew G. Knepley 
4820db781477SPatrick Sanan .seealso: `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()`
4821ba2698f1SMatthew G. Knepley @*/
48229371c9d4SSatish Balay PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth) {
4823ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
4824ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
482540a2aa30SMatthew G. Knepley   PetscValidIntPointer(depth, 3);
48269566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(dm->depthLabel, point, depth));
4827ba2698f1SMatthew G. Knepley   PetscFunctionReturn(0);
4828ba2698f1SMatthew G. Knepley }
4829ba2698f1SMatthew G. Knepley 
4830ba2698f1SMatthew G. Knepley /*@
48310c0a32dcSVaclav Hapla   DMPlexGetPointHeight - Get the height of a given point
48320c0a32dcSVaclav Hapla 
48330c0a32dcSVaclav Hapla   Not Collective
48340c0a32dcSVaclav Hapla 
4835d8d19677SJose E. Roman   Input Parameters:
48360c0a32dcSVaclav Hapla + dm    - The DMPlex object
48370c0a32dcSVaclav Hapla - point - The point
48380c0a32dcSVaclav Hapla 
48390c0a32dcSVaclav Hapla   Output Parameter:
48400c0a32dcSVaclav Hapla . height - The height of the point
48410c0a32dcSVaclav Hapla 
48420c0a32dcSVaclav Hapla   Level: intermediate
48430c0a32dcSVaclav Hapla 
4844db781477SPatrick Sanan .seealso: `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointDepth()`
48450c0a32dcSVaclav Hapla @*/
48469371c9d4SSatish Balay PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height) {
48470c0a32dcSVaclav Hapla   PetscInt n, pDepth;
48480c0a32dcSVaclav Hapla 
48490c0a32dcSVaclav Hapla   PetscFunctionBegin;
48500c0a32dcSVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
48510c0a32dcSVaclav Hapla   PetscValidIntPointer(height, 3);
48529566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(dm->depthLabel, &n));
48539566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(dm->depthLabel, point, &pDepth));
48540c0a32dcSVaclav Hapla   *height = n - 1 - pDepth; /* DAG depth is n-1 */
48550c0a32dcSVaclav Hapla   PetscFunctionReturn(0);
48560c0a32dcSVaclav Hapla }
48570c0a32dcSVaclav Hapla 
48580c0a32dcSVaclav Hapla /*@
4859ba2698f1SMatthew G. Knepley   DMPlexGetCellTypeLabel - Get the DMLabel recording the polytope type of each cell
4860ba2698f1SMatthew G. Knepley 
4861ba2698f1SMatthew G. Knepley   Not Collective
4862ba2698f1SMatthew G. Knepley 
4863ba2698f1SMatthew G. Knepley   Input Parameter:
4864ba2698f1SMatthew G. Knepley . dm - The DMPlex object
4865ba2698f1SMatthew G. Knepley 
4866ba2698f1SMatthew G. Knepley   Output Parameter:
4867ba2698f1SMatthew G. Knepley . celltypeLabel - The DMLabel recording cell polytope type
4868ba2698f1SMatthew G. Knepley 
4869412e9a14SMatthew G. Knepley   Note: This function will trigger automatica computation of cell types. This can be disabled by calling
4870412e9a14SMatthew G. Knepley   DMCreateLabel(dm, "celltype") beforehand.
4871412e9a14SMatthew G. Knepley 
4872ba2698f1SMatthew G. Knepley   Level: developer
4873ba2698f1SMatthew G. Knepley 
4874db781477SPatrick Sanan .seealso: `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMCreateLabel()`
4875ba2698f1SMatthew G. Knepley @*/
48769371c9d4SSatish Balay PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel) {
4877ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
4878ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4879ba2698f1SMatthew G. Knepley   PetscValidPointer(celltypeLabel, 2);
48809566063dSJacob Faibussowitsch   if (!dm->celltypeLabel) PetscCall(DMPlexComputeCellTypes(dm));
4881ba2698f1SMatthew G. Knepley   *celltypeLabel = dm->celltypeLabel;
4882ba2698f1SMatthew G. Knepley   PetscFunctionReturn(0);
4883ba2698f1SMatthew G. Knepley }
4884ba2698f1SMatthew G. Knepley 
4885ba2698f1SMatthew G. Knepley /*@
4886ba2698f1SMatthew G. Knepley   DMPlexGetCellType - Get the polytope type of a given cell
4887ba2698f1SMatthew G. Knepley 
4888ba2698f1SMatthew G. Knepley   Not Collective
4889ba2698f1SMatthew G. Knepley 
4890d8d19677SJose E. Roman   Input Parameters:
4891ba2698f1SMatthew G. Knepley + dm   - The DMPlex object
4892ba2698f1SMatthew G. Knepley - cell - The cell
4893ba2698f1SMatthew G. Knepley 
4894ba2698f1SMatthew G. Knepley   Output Parameter:
4895ba2698f1SMatthew G. Knepley . celltype - The polytope type of the cell
4896ba2698f1SMatthew G. Knepley 
4897ba2698f1SMatthew G. Knepley   Level: intermediate
4898ba2698f1SMatthew G. Knepley 
4899db781477SPatrick Sanan .seealso: `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`
4900ba2698f1SMatthew G. Knepley @*/
49019371c9d4SSatish Balay PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype) {
4902ba2698f1SMatthew G. Knepley   DMLabel  label;
4903ba2698f1SMatthew G. Knepley   PetscInt ct;
4904ba2698f1SMatthew G. Knepley 
4905ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
4906ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4907ba2698f1SMatthew G. Knepley   PetscValidPointer(celltype, 3);
49089566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &label));
49099566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(label, cell, &ct));
491063a3b9bcSJacob Faibussowitsch   PetscCheck(ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %" PetscInt_FMT " has not been assigned a cell type", cell);
4911ba2698f1SMatthew G. Knepley   *celltype = (DMPolytopeType)ct;
4912ba2698f1SMatthew G. Knepley   PetscFunctionReturn(0);
4913ba2698f1SMatthew G. Knepley }
4914ba2698f1SMatthew G. Knepley 
4915412e9a14SMatthew G. Knepley /*@
4916412e9a14SMatthew G. Knepley   DMPlexSetCellType - Set the polytope type of a given cell
4917412e9a14SMatthew G. Knepley 
4918412e9a14SMatthew G. Knepley   Not Collective
4919412e9a14SMatthew G. Knepley 
4920412e9a14SMatthew G. Knepley   Input Parameters:
4921412e9a14SMatthew G. Knepley + dm   - The DMPlex object
4922412e9a14SMatthew G. Knepley . cell - The cell
4923412e9a14SMatthew G. Knepley - celltype - The polytope type of the cell
4924412e9a14SMatthew G. Knepley 
4925412e9a14SMatthew G. Knepley   Note: By default, cell types will be automatically computed using DMPlexComputeCellTypes() before this function
4926412e9a14SMatthew G. Knepley   is executed. This function will override the computed type. However, if automatic classification will not succeed
4927412e9a14SMatthew G. Knepley   and a user wants to manually specify all types, the classification must be disabled by calling
4928412e9a14SMatthew G. Knepley   DMCreaateLabel(dm, "celltype") before getting or setting any cell types.
4929412e9a14SMatthew G. Knepley 
4930412e9a14SMatthew G. Knepley   Level: advanced
4931412e9a14SMatthew G. Knepley 
4932db781477SPatrick Sanan .seealso: `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexComputeCellTypes()`, `DMCreateLabel()`
4933412e9a14SMatthew G. Knepley @*/
49349371c9d4SSatish Balay PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype) {
4935412e9a14SMatthew G. Knepley   DMLabel label;
4936412e9a14SMatthew G. Knepley 
4937412e9a14SMatthew G. Knepley   PetscFunctionBegin;
4938412e9a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
49399566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &label));
49409566063dSJacob Faibussowitsch   PetscCall(DMLabelSetValue(label, cell, celltype));
4941412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
4942412e9a14SMatthew G. Knepley }
4943412e9a14SMatthew G. Knepley 
49449371c9d4SSatish Balay PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) {
4945efe440bfSMatthew G. Knepley   PetscSection section, s;
4946efe440bfSMatthew G. Knepley   Mat          m;
49473e922f36SToby Isaac   PetscInt     maxHeight;
4948552f7358SJed Brown 
4949552f7358SJed Brown   PetscFunctionBegin;
49509566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, cdm));
49519566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxProjectionHeight(dm, &maxHeight));
49529566063dSJacob Faibussowitsch   PetscCall(DMPlexSetMaxProjectionHeight(*cdm, maxHeight));
49539566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section));
49549566063dSJacob Faibussowitsch   PetscCall(DMSetLocalSection(*cdm, section));
49559566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&section));
49569566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &s));
49579566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_SELF, &m));
49589566063dSJacob Faibussowitsch   PetscCall(DMSetDefaultConstraints(*cdm, s, m, NULL));
49599566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&s));
49609566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&m));
49618f4c458bSMatthew G. Knepley 
49629566063dSJacob Faibussowitsch   PetscCall(DMSetNumFields(*cdm, 1));
49639566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(*cdm));
4964552f7358SJed Brown   PetscFunctionReturn(0);
4965552f7358SJed Brown }
4966552f7358SJed Brown 
49679371c9d4SSatish Balay PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field) {
49686858538eSMatthew G. Knepley   Vec coordsLocal, cellCoordsLocal;
49696858538eSMatthew G. Knepley   DM  coordsDM, cellCoordsDM;
4970f19dbd58SToby Isaac 
4971f19dbd58SToby Isaac   PetscFunctionBegin;
4972f19dbd58SToby Isaac   *field = NULL;
49739566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal));
49749566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &coordsDM));
49756858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dm, &cellCoordsLocal));
49766858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dm, &cellCoordsDM));
4977f19dbd58SToby Isaac   if (coordsLocal && coordsDM) {
49786858538eSMatthew G. Knepley     if (cellCoordsLocal && cellCoordsDM) PetscCall(DMFieldCreateDSWithDG(coordsDM, cellCoordsDM, 0, coordsLocal, cellCoordsLocal, field));
49796858538eSMatthew G. Knepley     else PetscCall(DMFieldCreateDS(coordsDM, 0, coordsLocal, field));
4980f19dbd58SToby Isaac   }
4981f19dbd58SToby Isaac   PetscFunctionReturn(0);
4982f19dbd58SToby Isaac }
4983f19dbd58SToby Isaac 
49847cd05799SMatthew G. Knepley /*@C
49857cd05799SMatthew G. Knepley   DMPlexGetConeSection - Return a section which describes the layout of cone data
49867cd05799SMatthew G. Knepley 
49877cd05799SMatthew G. Knepley   Not Collective
49887cd05799SMatthew G. Knepley 
49897cd05799SMatthew G. Knepley   Input Parameters:
49907cd05799SMatthew G. Knepley . dm        - The DMPlex object
49917cd05799SMatthew G. Knepley 
49927cd05799SMatthew G. Knepley   Output Parameter:
49937cd05799SMatthew G. Knepley . section - The PetscSection object
49947cd05799SMatthew G. Knepley 
49957cd05799SMatthew G. Knepley   Level: developer
49967cd05799SMatthew G. Knepley 
4997db781477SPatrick Sanan .seealso: `DMPlexGetSupportSection()`, `DMPlexGetCones()`, `DMPlexGetConeOrientations()`
49987cd05799SMatthew G. Knepley @*/
49999371c9d4SSatish Balay PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) {
5000552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
5001552f7358SJed Brown 
5002552f7358SJed Brown   PetscFunctionBegin;
5003552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5004552f7358SJed Brown   if (section) *section = mesh->coneSection;
5005552f7358SJed Brown   PetscFunctionReturn(0);
5006552f7358SJed Brown }
5007552f7358SJed Brown 
50087cd05799SMatthew G. Knepley /*@C
50097cd05799SMatthew G. Knepley   DMPlexGetSupportSection - Return a section which describes the layout of support data
50107cd05799SMatthew G. Knepley 
50117cd05799SMatthew G. Knepley   Not Collective
50127cd05799SMatthew G. Knepley 
50137cd05799SMatthew G. Knepley   Input Parameters:
50147cd05799SMatthew G. Knepley . dm        - The DMPlex object
50157cd05799SMatthew G. Knepley 
50167cd05799SMatthew G. Knepley   Output Parameter:
50177cd05799SMatthew G. Knepley . section - The PetscSection object
50187cd05799SMatthew G. Knepley 
50197cd05799SMatthew G. Knepley   Level: developer
50207cd05799SMatthew G. Knepley 
5021db781477SPatrick Sanan .seealso: `DMPlexGetConeSection()`
50227cd05799SMatthew G. Knepley @*/
50239371c9d4SSatish Balay PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) {
50248cb4d582SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
50258cb4d582SMatthew G. Knepley 
50268cb4d582SMatthew G. Knepley   PetscFunctionBegin;
50278cb4d582SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
50288cb4d582SMatthew G. Knepley   if (section) *section = mesh->supportSection;
50298cb4d582SMatthew G. Knepley   PetscFunctionReturn(0);
50308cb4d582SMatthew G. Knepley }
50318cb4d582SMatthew G. Knepley 
50327cd05799SMatthew G. Knepley /*@C
50337cd05799SMatthew G. Knepley   DMPlexGetCones - Return cone data
50347cd05799SMatthew G. Knepley 
50357cd05799SMatthew G. Knepley   Not Collective
50367cd05799SMatthew G. Knepley 
50377cd05799SMatthew G. Knepley   Input Parameters:
50387cd05799SMatthew G. Knepley . dm        - The DMPlex object
50397cd05799SMatthew G. Knepley 
50407cd05799SMatthew G. Knepley   Output Parameter:
50417cd05799SMatthew G. Knepley . cones - The cone for each point
50427cd05799SMatthew G. Knepley 
50437cd05799SMatthew G. Knepley   Level: developer
50447cd05799SMatthew G. Knepley 
5045db781477SPatrick Sanan .seealso: `DMPlexGetConeSection()`
50467cd05799SMatthew G. Knepley @*/
50479371c9d4SSatish Balay PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) {
5048552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
5049552f7358SJed Brown 
5050552f7358SJed Brown   PetscFunctionBegin;
5051552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5052552f7358SJed Brown   if (cones) *cones = mesh->cones;
5053552f7358SJed Brown   PetscFunctionReturn(0);
5054552f7358SJed Brown }
5055552f7358SJed Brown 
50567cd05799SMatthew G. Knepley /*@C
50577cd05799SMatthew G. Knepley   DMPlexGetConeOrientations - Return cone orientation data
50587cd05799SMatthew G. Knepley 
50597cd05799SMatthew G. Knepley   Not Collective
50607cd05799SMatthew G. Knepley 
50617cd05799SMatthew G. Knepley   Input Parameters:
50627cd05799SMatthew G. Knepley . dm        - The DMPlex object
50637cd05799SMatthew G. Knepley 
50647cd05799SMatthew G. Knepley   Output Parameter:
5065b5a892a1SMatthew G. Knepley . coneOrientations - The array of cone orientations for all points
50667cd05799SMatthew G. Knepley 
50677cd05799SMatthew G. Knepley   Level: developer
50687cd05799SMatthew G. Knepley 
5069b5a892a1SMatthew G. Knepley   Notes:
5070b5a892a1SMatthew G. Knepley   The PetscSection returned by DMPlexGetConeSection() partitions coneOrientations into cone orientations of particular points as returned by DMPlexGetConeOrientation().
5071b5a892a1SMatthew G. Knepley 
5072b5a892a1SMatthew G. Knepley   The meaning of coneOrientations values is detailed in DMPlexGetConeOrientation().
5073b5a892a1SMatthew G. Knepley 
5074db781477SPatrick Sanan .seealso: `DMPlexGetConeSection()`, `DMPlexGetConeOrientation()`
50757cd05799SMatthew G. Knepley @*/
50769371c9d4SSatish Balay PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) {
5077552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
5078552f7358SJed Brown 
5079552f7358SJed Brown   PetscFunctionBegin;
5080552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5081552f7358SJed Brown   if (coneOrientations) *coneOrientations = mesh->coneOrientations;
5082552f7358SJed Brown   PetscFunctionReturn(0);
5083552f7358SJed Brown }
5084552f7358SJed Brown 
5085552f7358SJed Brown /******************************** FEM Support **********************************/
5086552f7358SJed Brown 
50879e8305c2SJed Brown /*
50889e8305c2SJed Brown  Returns number of components and tensor degree for the field.  For interpolated meshes, line should be a point
50899e8305c2SJed Brown  representing a line in the section.
50909e8305c2SJed Brown */
50919371c9d4SSatish Balay static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(PetscSection section, PetscInt field, PetscInt line, PetscBool vertexchart, PetscInt *Nc, PetscInt *k) {
50929e8305c2SJed Brown   PetscFunctionBeginHot;
50939566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldComponents(section, field, Nc));
5094a433471fSStefano Zampini   if (line < 0) {
5095a433471fSStefano Zampini     *k  = 0;
5096a433471fSStefano Zampini     *Nc = 0;
5097a433471fSStefano Zampini   } else if (vertexchart) { /* If we only have a vertex chart, we must have degree k=1 */
50989e8305c2SJed Brown     *k = 1;
50999e8305c2SJed Brown   } else { /* Assume the full interpolated mesh is in the chart; lines in particular */
51009e8305c2SJed Brown     /* An order k SEM disc has k-1 dofs on an edge */
51019566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, line, field, k));
51029e8305c2SJed Brown     *k = *k / *Nc + 1;
51039e8305c2SJed Brown   }
51049e8305c2SJed Brown   PetscFunctionReturn(0);
51059e8305c2SJed Brown }
51069e8305c2SJed Brown 
5107a4355906SMatthew Knepley /*@
5108bc1eb3faSJed Brown 
5109bc1eb3faSJed Brown   DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a
5110bc1eb3faSJed Brown   lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the
51111bb6d2a8SBarry Smith   section provided (or the section of the DM).
5112a4355906SMatthew Knepley 
5113a4355906SMatthew Knepley   Input Parameters:
5114a4355906SMatthew Knepley + dm      - The DM
5115a4355906SMatthew Knepley . point   - Either a cell (highest dim point) or an edge (dim 1 point), or PETSC_DETERMINE
5116a4355906SMatthew Knepley - section - The PetscSection to reorder, or NULL for the default section
5117a4355906SMatthew Knepley 
5118a4355906SMatthew Knepley   Note: The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial
5119a4355906SMatthew Knepley   degree of the basis.
5120a4355906SMatthew Knepley 
5121bc1eb3faSJed Brown   Example:
5122bc1eb3faSJed Brown   A typical interpolated single-quad mesh might order points as
5123bc1eb3faSJed Brown .vb
5124bc1eb3faSJed Brown   [c0, v1, v2, v3, v4, e5, e6, e7, e8]
5125bc1eb3faSJed Brown 
5126bc1eb3faSJed Brown   v4 -- e6 -- v3
5127bc1eb3faSJed Brown   |           |
5128bc1eb3faSJed Brown   e7    c0    e8
5129bc1eb3faSJed Brown   |           |
5130bc1eb3faSJed Brown   v1 -- e5 -- v2
5131bc1eb3faSJed Brown .ve
5132bc1eb3faSJed Brown 
5133bc1eb3faSJed Brown   (There is no significance to the ordering described here.)  The default section for a Q3 quad might typically assign
5134bc1eb3faSJed Brown   dofs in the order of points, e.g.,
5135bc1eb3faSJed Brown .vb
5136bc1eb3faSJed Brown     c0 -> [0,1,2,3]
5137bc1eb3faSJed Brown     v1 -> [4]
5138bc1eb3faSJed Brown     ...
5139bc1eb3faSJed Brown     e5 -> [8, 9]
5140bc1eb3faSJed Brown .ve
5141bc1eb3faSJed Brown 
5142bc1eb3faSJed Brown   which corresponds to the dofs
5143bc1eb3faSJed Brown .vb
5144bc1eb3faSJed Brown     6   10  11  7
5145bc1eb3faSJed Brown     13  2   3   15
5146bc1eb3faSJed Brown     12  0   1   14
5147bc1eb3faSJed Brown     4   8   9   5
5148bc1eb3faSJed Brown .ve
5149bc1eb3faSJed Brown 
5150bc1eb3faSJed Brown   The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering
5151bc1eb3faSJed Brown .vb
5152bc1eb3faSJed Brown   0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6
5153bc1eb3faSJed Brown .ve
5154bc1eb3faSJed Brown 
5155bc1eb3faSJed Brown   After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically,
5156bc1eb3faSJed Brown .vb
5157bc1eb3faSJed Brown    4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7
5158bc1eb3faSJed Brown .ve
5159bc1eb3faSJed Brown 
5160a4355906SMatthew Knepley   Level: developer
5161a4355906SMatthew Knepley 
5162db781477SPatrick Sanan .seealso: `DMGetLocalSection()`, `PetscSectionSetClosurePermutation()`, `DMSetGlobalSection()`
5163a4355906SMatthew Knepley @*/
51649371c9d4SSatish Balay PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section) {
51657391a63aSMatthew G. Knepley   DMLabel   label;
5166bb197d40SJed Brown   PetscInt  dim, depth = -1, eStart = -1, Nf;
51679e8305c2SJed Brown   PetscBool vertexchart;
51683194fc30SMatthew G. Knepley 
51693194fc30SMatthew G. Knepley   PetscFunctionBegin;
51709566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
5171a433471fSStefano Zampini   if (dim < 1) PetscFunctionReturn(0);
5172a433471fSStefano Zampini   if (point < 0) {
5173a433471fSStefano Zampini     PetscInt sStart, sEnd;
5174a433471fSStefano Zampini 
51759566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd));
5176a433471fSStefano Zampini     point = sEnd - sStart ? sStart : point;
5177a433471fSStefano Zampini   }
51789566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
51799566063dSJacob Faibussowitsch   if (point >= 0) PetscCall(DMLabelGetValue(label, point, &depth));
51809566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
51819371c9d4SSatish Balay   if (depth == 1) {
51829371c9d4SSatish Balay     eStart = point;
51839371c9d4SSatish Balay   } else if (depth == dim) {
51847391a63aSMatthew G. Knepley     const PetscInt *cone;
51857391a63aSMatthew G. Knepley 
51869566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, point, &cone));
5187d4e6627bSStefano Zampini     if (dim == 2) eStart = cone[0];
5188d4e6627bSStefano Zampini     else if (dim == 3) {
5189d4e6627bSStefano Zampini       const PetscInt *cone2;
51909566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, cone[0], &cone2));
5191d4e6627bSStefano Zampini       eStart = cone2[0];
519263a3b9bcSJacob 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);
519363a3b9bcSJacob 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);
51949e8305c2SJed Brown   { /* Determine whether the chart covers all points or just vertices. */
51959e8305c2SJed Brown     PetscInt pStart, pEnd, cStart, cEnd;
51969566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 0, &pStart, &pEnd));
51979566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(section, &cStart, &cEnd));
5198796d0a68SJed Brown     if (pStart == cStart && pEnd == cEnd) vertexchart = PETSC_TRUE;      /* Only vertices are in the chart */
5199796d0a68SJed Brown     else if (cStart <= point && point < cEnd) vertexchart = PETSC_FALSE; /* Some interpolated points exist in the chart */
5200796d0a68SJed Brown     else vertexchart = PETSC_TRUE;                                       /* Some interpolated points are not in chart; assume dofs only at cells and vertices */
52019e8305c2SJed Brown   }
52029566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &Nf));
5203bb197d40SJed Brown   for (PetscInt d = 1; d <= dim; d++) {
5204bb197d40SJed Brown     PetscInt  k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0;
5205bb197d40SJed Brown     PetscInt *perm;
5206bb197d40SJed Brown 
52073194fc30SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
52089566063dSJacob Faibussowitsch       PetscCall(PetscSectionFieldGetTensorDegree_Private(section, f, eStart, vertexchart, &Nc, &k));
5209bb197d40SJed Brown       size += PetscPowInt(k + 1, d) * Nc;
52103194fc30SMatthew G. Knepley     }
52119566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(size, &perm));
52123194fc30SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
5213bb197d40SJed Brown       switch (d) {
5214babf31e0SJed Brown       case 1:
52159566063dSJacob Faibussowitsch         PetscCall(PetscSectionFieldGetTensorDegree_Private(section, f, eStart, vertexchart, &Nc, &k));
5216babf31e0SJed Brown         /*
5217babf31e0SJed Brown          Original ordering is [ edge of length k-1; vtx0; vtx1 ]
5218babf31e0SJed Brown          We want              [ vtx0; edge of length k-1; vtx1 ]
5219babf31e0SJed Brown          */
5220babf31e0SJed Brown         for (c = 0; c < Nc; c++, offset++) perm[offset] = (k - 1) * Nc + c + foffset;
52219371c9d4SSatish Balay         for (i = 0; i < k - 1; i++)
52229371c9d4SSatish Balay           for (c = 0; c < Nc; c++, offset++) perm[offset] = i * Nc + c + foffset;
5223babf31e0SJed Brown         for (c = 0; c < Nc; c++, offset++) perm[offset] = k * Nc + c + foffset;
5224babf31e0SJed Brown         foffset = offset;
5225babf31e0SJed Brown         break;
522689eabcffSMatthew G. Knepley       case 2:
52273194fc30SMatthew 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} */
52289566063dSJacob Faibussowitsch         PetscCall(PetscSectionFieldGetTensorDegree_Private(section, f, eStart, vertexchart, &Nc, &k));
52293194fc30SMatthew G. Knepley         /* The SEM order is
52303194fc30SMatthew G. Knepley 
52313194fc30SMatthew G. Knepley          v_lb, {e_b}, v_rb,
523289eabcffSMatthew G. Knepley          e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r,
52333194fc30SMatthew G. Knepley          v_lt, reverse {e_t}, v_rt
52343194fc30SMatthew G. Knepley          */
52353194fc30SMatthew G. Knepley         {
52363194fc30SMatthew G. Knepley           const PetscInt of   = 0;
52373194fc30SMatthew G. Knepley           const PetscInt oeb  = of + PetscSqr(k - 1);
52383194fc30SMatthew G. Knepley           const PetscInt oer  = oeb + (k - 1);
52393194fc30SMatthew G. Knepley           const PetscInt oet  = oer + (k - 1);
52403194fc30SMatthew G. Knepley           const PetscInt oel  = oet + (k - 1);
52413194fc30SMatthew G. Knepley           const PetscInt ovlb = oel + (k - 1);
52423194fc30SMatthew G. Knepley           const PetscInt ovrb = ovlb + 1;
52433194fc30SMatthew G. Knepley           const PetscInt ovrt = ovrb + 1;
52443194fc30SMatthew G. Knepley           const PetscInt ovlt = ovrt + 1;
52453194fc30SMatthew G. Knepley           PetscInt       o;
52463194fc30SMatthew G. Knepley 
52473194fc30SMatthew G. Knepley           /* bottom */
52483194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb * Nc + c + foffset;
52499371c9d4SSatish Balay           for (o = oeb; o < oer; ++o)
52509371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
52513194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb * Nc + c + foffset;
52523194fc30SMatthew G. Knepley           /* middle */
52533194fc30SMatthew G. Knepley           for (i = 0; i < k - 1; ++i) {
52543194fc30SMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel + (k - 2) - i) * Nc + c + foffset;
52559371c9d4SSatish Balay             for (o = of + (k - 1) * i; o < of + (k - 1) * (i + 1); ++o)
52569371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
52573194fc30SMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer + i) * Nc + c + foffset;
52583194fc30SMatthew G. Knepley           }
52593194fc30SMatthew G. Knepley           /* top */
52603194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt * Nc + c + foffset;
52619371c9d4SSatish Balay           for (o = oel - 1; o >= oet; --o)
52629371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
52633194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt * Nc + c + foffset;
52643194fc30SMatthew G. Knepley           foffset = offset;
52653194fc30SMatthew G. Knepley         }
526689eabcffSMatthew G. Knepley         break;
526789eabcffSMatthew G. Knepley       case 3:
526889eabcffSMatthew G. Knepley         /* The original hex closure is
526989eabcffSMatthew G. Knepley 
527089eabcffSMatthew G. Knepley          {c,
527189eabcffSMatthew G. Knepley          f_b, f_t, f_f, f_b, f_r, f_l,
527289eabcffSMatthew 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,
527389eabcffSMatthew G. Knepley          v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb}
527489eabcffSMatthew G. Knepley          */
52759566063dSJacob Faibussowitsch         PetscCall(PetscSectionFieldGetTensorDegree_Private(section, f, eStart, vertexchart, &Nc, &k));
527689eabcffSMatthew G. Knepley         /* The SEM order is
527789eabcffSMatthew G. Knepley          Bottom Slice
527889eabcffSMatthew G. Knepley          v_blf, {e^{(k-1)-n}_bf}, v_brf,
527989eabcffSMatthew G. Knepley          e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br,
528089eabcffSMatthew G. Knepley          v_blb, {e_bb}, v_brb,
528189eabcffSMatthew G. Knepley 
528289eabcffSMatthew G. Knepley          Middle Slice (j)
528389eabcffSMatthew G. Knepley          {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf,
528489eabcffSMatthew G. Knepley          f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r,
528589eabcffSMatthew G. Knepley          e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb,
528689eabcffSMatthew G. Knepley 
528789eabcffSMatthew G. Knepley          Top Slice
528889eabcffSMatthew G. Knepley          v_tlf, {e_tf}, v_trf,
528989eabcffSMatthew G. Knepley          e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr,
529089eabcffSMatthew G. Knepley          v_tlb, {e^{(k-1)-n}_tb}, v_trb,
529189eabcffSMatthew G. Knepley          */
529289eabcffSMatthew G. Knepley         {
529389eabcffSMatthew G. Knepley           const PetscInt oc    = 0;
529489eabcffSMatthew G. Knepley           const PetscInt ofb   = oc + PetscSqr(k - 1) * (k - 1);
529589eabcffSMatthew G. Knepley           const PetscInt oft   = ofb + PetscSqr(k - 1);
529689eabcffSMatthew G. Knepley           const PetscInt off   = oft + PetscSqr(k - 1);
529789eabcffSMatthew G. Knepley           const PetscInt ofk   = off + PetscSqr(k - 1);
529889eabcffSMatthew G. Knepley           const PetscInt ofr   = ofk + PetscSqr(k - 1);
529989eabcffSMatthew G. Knepley           const PetscInt ofl   = ofr + PetscSqr(k - 1);
530089eabcffSMatthew G. Knepley           const PetscInt oebl  = ofl + PetscSqr(k - 1);
530189eabcffSMatthew G. Knepley           const PetscInt oebb  = oebl + (k - 1);
530289eabcffSMatthew G. Knepley           const PetscInt oebr  = oebb + (k - 1);
530389eabcffSMatthew G. Knepley           const PetscInt oebf  = oebr + (k - 1);
530489eabcffSMatthew G. Knepley           const PetscInt oetf  = oebf + (k - 1);
530589eabcffSMatthew G. Knepley           const PetscInt oetr  = oetf + (k - 1);
530689eabcffSMatthew G. Knepley           const PetscInt oetb  = oetr + (k - 1);
530789eabcffSMatthew G. Knepley           const PetscInt oetl  = oetb + (k - 1);
530889eabcffSMatthew G. Knepley           const PetscInt oerf  = oetl + (k - 1);
530989eabcffSMatthew G. Knepley           const PetscInt oelf  = oerf + (k - 1);
531089eabcffSMatthew G. Knepley           const PetscInt oelb  = oelf + (k - 1);
531189eabcffSMatthew G. Knepley           const PetscInt oerb  = oelb + (k - 1);
531289eabcffSMatthew G. Knepley           const PetscInt ovblf = oerb + (k - 1);
531389eabcffSMatthew G. Knepley           const PetscInt ovblb = ovblf + 1;
531489eabcffSMatthew G. Knepley           const PetscInt ovbrb = ovblb + 1;
531589eabcffSMatthew G. Knepley           const PetscInt ovbrf = ovbrb + 1;
531689eabcffSMatthew G. Knepley           const PetscInt ovtlf = ovbrf + 1;
531789eabcffSMatthew G. Knepley           const PetscInt ovtrf = ovtlf + 1;
531889eabcffSMatthew G. Knepley           const PetscInt ovtrb = ovtrf + 1;
531989eabcffSMatthew G. Knepley           const PetscInt ovtlb = ovtrb + 1;
532089eabcffSMatthew G. Knepley           PetscInt       o, n;
532189eabcffSMatthew G. Knepley 
532289eabcffSMatthew G. Knepley           /* Bottom Slice */
532389eabcffSMatthew G. Knepley           /*   bottom */
532489eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf * Nc + c + foffset;
53259371c9d4SSatish Balay           for (o = oetf - 1; o >= oebf; --o)
53269371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
532789eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf * Nc + c + foffset;
532889eabcffSMatthew G. Knepley           /*   middle */
532989eabcffSMatthew G. Knepley           for (i = 0; i < k - 1; ++i) {
533089eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl + i) * Nc + c + foffset;
53319371c9d4SSatish Balay             for (n = 0; n < k - 1; ++n) {
53329371c9d4SSatish Balay               o = ofb + n * (k - 1) + i;
53339371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
53349371c9d4SSatish Balay             }
533589eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr + (k - 2) - i) * Nc + c + foffset;
53363194fc30SMatthew G. Knepley           }
533789eabcffSMatthew G. Knepley           /*   top */
533889eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb * Nc + c + foffset;
53399371c9d4SSatish Balay           for (o = oebb; o < oebr; ++o)
53409371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
534189eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb * Nc + c + foffset;
534289eabcffSMatthew G. Knepley 
534389eabcffSMatthew G. Knepley           /* Middle Slice */
534489eabcffSMatthew G. Knepley           for (j = 0; j < k - 1; ++j) {
534589eabcffSMatthew G. Knepley             /*   bottom */
534689eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf + (k - 2) - j) * Nc + c + foffset;
53479371c9d4SSatish Balay             for (o = off + j * (k - 1); o < off + (j + 1) * (k - 1); ++o)
53489371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
534989eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf + j) * Nc + c + foffset;
535089eabcffSMatthew G. Knepley             /*   middle */
535189eabcffSMatthew G. Knepley             for (i = 0; i < k - 1; ++i) {
535289eabcffSMatthew G. Knepley               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl + i * (k - 1) + j) * Nc + c + foffset;
53539371c9d4SSatish Balay               for (n = 0; n < k - 1; ++n)
53549371c9d4SSatish Balay                 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oc + (j * (k - 1) + i) * (k - 1) + n) * Nc + c + foffset;
535589eabcffSMatthew G. Knepley               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr + j * (k - 1) + i) * Nc + c + foffset;
535689eabcffSMatthew G. Knepley             }
535789eabcffSMatthew G. Knepley             /*   top */
535889eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb + j) * Nc + c + foffset;
53599371c9d4SSatish Balay             for (o = ofk + j * (k - 1) + (k - 2); o >= ofk + j * (k - 1); --o)
53609371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
536189eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb + (k - 2) - j) * Nc + c + foffset;
536289eabcffSMatthew G. Knepley           }
536389eabcffSMatthew G. Knepley 
536489eabcffSMatthew G. Knepley           /* Top Slice */
536589eabcffSMatthew G. Knepley           /*   bottom */
536689eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf * Nc + c + foffset;
53679371c9d4SSatish Balay           for (o = oetf; o < oetr; ++o)
53689371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
536989eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf * Nc + c + foffset;
537089eabcffSMatthew G. Knepley           /*   middle */
537189eabcffSMatthew G. Knepley           for (i = 0; i < k - 1; ++i) {
537289eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl + (k - 2) - i) * Nc + c + foffset;
53739371c9d4SSatish Balay             for (n = 0; n < k - 1; ++n)
53749371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft + i * (k - 1) + n) * Nc + c + foffset;
537589eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr + i) * Nc + c + foffset;
537689eabcffSMatthew G. Knepley           }
537789eabcffSMatthew G. Knepley           /*   top */
537889eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb * Nc + c + foffset;
53799371c9d4SSatish Balay           for (o = oetl - 1; o >= oetb; --o)
53809371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
538189eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb * Nc + c + foffset;
538289eabcffSMatthew G. Knepley 
538389eabcffSMatthew G. Knepley           foffset = offset;
538489eabcffSMatthew G. Knepley         }
538589eabcffSMatthew G. Knepley         break;
538663a3b9bcSJacob Faibussowitsch       default: SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %" PetscInt_FMT, d);
538789eabcffSMatthew G. Knepley       }
538889eabcffSMatthew G. Knepley     }
538963a3b9bcSJacob Faibussowitsch     PetscCheck(offset == size, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Number of permutation entries %" PetscInt_FMT " != %" PetscInt_FMT, offset, size);
53903194fc30SMatthew G. Knepley     /* Check permutation */
53913194fc30SMatthew G. Knepley     {
53923194fc30SMatthew G. Knepley       PetscInt *check;
53933194fc30SMatthew G. Knepley 
53949566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(size, &check));
53951dca8a05SBarry Smith       for (i = 0; i < size; ++i) {
53961dca8a05SBarry Smith         check[i] = -1;
53971dca8a05SBarry 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]);
53981dca8a05SBarry Smith       }
53993194fc30SMatthew G. Knepley       for (i = 0; i < size; ++i) check[perm[i]] = i;
54001dca8a05SBarry Smith       for (i = 0; i < size; ++i) PetscCheck(check[i] >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing permutation index %" PetscInt_FMT, i);
54019566063dSJacob Faibussowitsch       PetscCall(PetscFree(check));
54023194fc30SMatthew G. Knepley     }
54039566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size, PETSC_OWN_POINTER, perm));
5404a05c9aa3SJed Brown     if (d == dim) { // Add permutation for localized (in case this is a coordinate DM)
5405a05c9aa3SJed Brown       PetscInt *loc_perm;
54069566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(size * 2, &loc_perm));
5407a05c9aa3SJed Brown       for (PetscInt i = 0; i < size; i++) {
5408a05c9aa3SJed Brown         loc_perm[i]        = perm[i];
5409a05c9aa3SJed Brown         loc_perm[size + i] = size + perm[i];
5410a05c9aa3SJed Brown       }
54119566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size * 2, PETSC_OWN_POINTER, loc_perm));
5412a05c9aa3SJed Brown     }
5413bb197d40SJed Brown   }
54143194fc30SMatthew G. Knepley   PetscFunctionReturn(0);
54153194fc30SMatthew G. Knepley }
54163194fc30SMatthew G. Knepley 
54179371c9d4SSatish Balay PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace) {
5418e071409bSToby Isaac   PetscDS  prob;
5419e071409bSToby Isaac   PetscInt depth, Nf, h;
5420e071409bSToby Isaac   DMLabel  label;
5421e071409bSToby Isaac 
5422e071409bSToby Isaac   PetscFunctionBeginHot;
54239566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &prob));
5424e071409bSToby Isaac   Nf      = prob->Nf;
5425e071409bSToby Isaac   label   = dm->depthLabel;
5426e071409bSToby Isaac   *dspace = NULL;
5427e071409bSToby Isaac   if (field < Nf) {
5428e071409bSToby Isaac     PetscObject disc = prob->disc[field];
5429e071409bSToby Isaac 
5430e071409bSToby Isaac     if (disc->classid == PETSCFE_CLASSID) {
5431e071409bSToby Isaac       PetscDualSpace dsp;
5432e071409bSToby Isaac 
54339566063dSJacob Faibussowitsch       PetscCall(PetscFEGetDualSpace((PetscFE)disc, &dsp));
54349566063dSJacob Faibussowitsch       PetscCall(DMLabelGetNumValues(label, &depth));
54359566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(label, point, &h));
5436e071409bSToby Isaac       h = depth - 1 - h;
5437e071409bSToby Isaac       if (h) {
54389566063dSJacob Faibussowitsch         PetscCall(PetscDualSpaceGetHeightSubspace(dsp, h, dspace));
5439e071409bSToby Isaac       } else {
5440e071409bSToby Isaac         *dspace = dsp;
5441e071409bSToby Isaac       }
5442e071409bSToby Isaac     }
5443e071409bSToby Isaac   }
5444e071409bSToby Isaac   PetscFunctionReturn(0);
5445e071409bSToby Isaac }
5446e071409bSToby Isaac 
54479371c9d4SSatish Balay static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) {
544828351e22SJed Brown   PetscScalar       *array;
544928351e22SJed Brown   const PetscScalar *vArray;
5450d9917b9dSMatthew G. Knepley   const PetscInt    *cone, *coneO;
54511a271a75SMatthew G. Knepley   PetscInt           pStart, pEnd, p, numPoints, size = 0, offset = 0;
5452552f7358SJed Brown 
54531b406b76SMatthew G. Knepley   PetscFunctionBeginHot;
54549566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
54559566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, point, &numPoints));
54569566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, point, &cone));
54579566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeOrientation(dm, point, &coneO));
54583f7cbbe7SMatthew G. Knepley   if (!values || !*values) {
54599df71ca4SMatthew G. Knepley     if ((point >= pStart) && (point < pEnd)) {
54609df71ca4SMatthew G. Knepley       PetscInt dof;
5461d9917b9dSMatthew G. Knepley 
54629566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, point, &dof));
54639df71ca4SMatthew G. Knepley       size += dof;
54649df71ca4SMatthew G. Knepley     }
54659df71ca4SMatthew G. Knepley     for (p = 0; p < numPoints; ++p) {
54669df71ca4SMatthew G. Knepley       const PetscInt cp = cone[p];
54672a3aaacfSMatthew G. Knepley       PetscInt       dof;
54685a1bb5cfSMatthew G. Knepley 
54695a1bb5cfSMatthew G. Knepley       if ((cp < pStart) || (cp >= pEnd)) continue;
54709566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, cp, &dof));
54715a1bb5cfSMatthew G. Knepley       size += dof;
54725a1bb5cfSMatthew G. Knepley     }
54733f7cbbe7SMatthew G. Knepley     if (!values) {
54743f7cbbe7SMatthew G. Knepley       if (csize) *csize = size;
54753f7cbbe7SMatthew G. Knepley       PetscFunctionReturn(0);
54763f7cbbe7SMatthew G. Knepley     }
54779566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, size, MPIU_SCALAR, &array));
5478982e9ed1SMatthew G. Knepley   } else {
5479982e9ed1SMatthew G. Knepley     array = *values;
5480982e9ed1SMatthew G. Knepley   }
54819df71ca4SMatthew G. Knepley   size = 0;
548228351e22SJed Brown   PetscCall(VecGetArrayRead(v, &vArray));
54839df71ca4SMatthew G. Knepley   if ((point >= pStart) && (point < pEnd)) {
54849df71ca4SMatthew G. Knepley     PetscInt           dof, off, d;
548528351e22SJed Brown     const PetscScalar *varr;
5486d9917b9dSMatthew G. Knepley 
54879566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, point, &dof));
54889566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, point, &off));
54899df71ca4SMatthew G. Knepley     varr = &vArray[off];
5490ad540459SPierre Jolivet     for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d];
54919df71ca4SMatthew G. Knepley     size += dof;
54929df71ca4SMatthew G. Knepley   }
54939df71ca4SMatthew G. Knepley   for (p = 0; p < numPoints; ++p) {
54949df71ca4SMatthew G. Knepley     const PetscInt     cp = cone[p];
54959df71ca4SMatthew G. Knepley     PetscInt           o  = coneO[p];
54965a1bb5cfSMatthew G. Knepley     PetscInt           dof, off, d;
549728351e22SJed Brown     const PetscScalar *varr;
54985a1bb5cfSMatthew G. Knepley 
549952ed52e8SMatthew G. Knepley     if ((cp < pStart) || (cp >= pEnd)) continue;
55009566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, cp, &dof));
55019566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, cp, &off));
55025a1bb5cfSMatthew G. Knepley     varr = &vArray[off];
55035a1bb5cfSMatthew G. Knepley     if (o >= 0) {
5504ad540459SPierre Jolivet       for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d];
55055a1bb5cfSMatthew G. Knepley     } else {
5506ad540459SPierre Jolivet       for (d = dof - 1; d >= 0; --d, ++offset) array[offset] = varr[d];
55075a1bb5cfSMatthew G. Knepley     }
55089df71ca4SMatthew G. Knepley     size += dof;
55095a1bb5cfSMatthew G. Knepley   }
551028351e22SJed Brown   PetscCall(VecRestoreArrayRead(v, &vArray));
55119df71ca4SMatthew G. Knepley   if (!*values) {
55125a1bb5cfSMatthew G. Knepley     if (csize) *csize = size;
55135a1bb5cfSMatthew G. Knepley     *values = array;
55149df71ca4SMatthew G. Knepley   } else {
551563a3b9bcSJacob Faibussowitsch     PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size);
55168c312ff3SMatthew G. Knepley     *csize = size;
55179df71ca4SMatthew G. Knepley   }
55185a1bb5cfSMatthew G. Knepley   PetscFunctionReturn(0);
55195a1bb5cfSMatthew G. Knepley }
5520d9917b9dSMatthew G. Knepley 
552127f02ce8SMatthew G. Knepley /* Compress out points not in the section */
55229371c9d4SSatish Balay static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[]) {
552327f02ce8SMatthew G. Knepley   const PetscInt np = *numPoints;
552427f02ce8SMatthew G. Knepley   PetscInt       pStart, pEnd, p, q;
552527f02ce8SMatthew G. Knepley 
55269566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
552727f02ce8SMatthew G. Knepley   for (p = 0, q = 0; p < np; ++p) {
552827f02ce8SMatthew G. Knepley     const PetscInt r = points[p * 2];
552927f02ce8SMatthew G. Knepley     if ((r >= pStart) && (r < pEnd)) {
553027f02ce8SMatthew G. Knepley       points[q * 2]     = r;
553127f02ce8SMatthew G. Knepley       points[q * 2 + 1] = points[p * 2 + 1];
553227f02ce8SMatthew G. Knepley       ++q;
553327f02ce8SMatthew G. Knepley     }
553427f02ce8SMatthew G. Knepley   }
553527f02ce8SMatthew G. Knepley   *numPoints = q;
553627f02ce8SMatthew G. Knepley   return 0;
553727f02ce8SMatthew G. Knepley }
553827f02ce8SMatthew G. Knepley 
553997529cf3SJed Brown /* Compressed closure does not apply closure permutation */
55409371c9d4SSatish Balay PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) {
554127f02ce8SMatthew G. Knepley   const PetscInt *cla = NULL;
5542923c78e0SToby Isaac   PetscInt        np, *pts = NULL;
5543923c78e0SToby Isaac 
5544923c78e0SToby Isaac   PetscFunctionBeginHot;
55459566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureIndex(section, (PetscObject)dm, clSec, clPoints));
554627f02ce8SMatthew G. Knepley   if (*clPoints) {
5547923c78e0SToby Isaac     PetscInt dof, off;
5548923c78e0SToby Isaac 
55499566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(*clSec, point, &dof));
55509566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(*clSec, point, &off));
55519566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(*clPoints, &cla));
5552923c78e0SToby Isaac     np  = dof / 2;
5553923c78e0SToby Isaac     pts = (PetscInt *)&cla[off];
555427f02ce8SMatthew G. Knepley   } else {
55559566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &np, &pts));
55569566063dSJacob Faibussowitsch     PetscCall(CompressPoints_Private(section, &np, pts));
5557923c78e0SToby Isaac   }
5558923c78e0SToby Isaac   *numPoints = np;
5559923c78e0SToby Isaac   *points    = pts;
5560923c78e0SToby Isaac   *clp       = cla;
5561923c78e0SToby Isaac   PetscFunctionReturn(0);
5562923c78e0SToby Isaac }
5563923c78e0SToby Isaac 
55649371c9d4SSatish Balay PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp) {
5565923c78e0SToby Isaac   PetscFunctionBeginHot;
5566923c78e0SToby Isaac   if (!*clPoints) {
55679566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points));
5568923c78e0SToby Isaac   } else {
55699566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(*clPoints, clp));
5570923c78e0SToby Isaac   }
5571923c78e0SToby Isaac   *numPoints = 0;
5572923c78e0SToby Isaac   *points    = NULL;
5573923c78e0SToby Isaac   *clSec     = NULL;
5574923c78e0SToby Isaac   *clPoints  = NULL;
5575923c78e0SToby Isaac   *clp       = NULL;
5576923c78e0SToby Isaac   PetscFunctionReturn(0);
5577923c78e0SToby Isaac }
5578923c78e0SToby Isaac 
55799371c9d4SSatish Balay static inline PetscErrorCode DMPlexVecGetClosure_Static(DM dm, PetscSection section, PetscInt numPoints, const PetscInt points[], const PetscInt clperm[], const PetscScalar vArray[], PetscInt *size, PetscScalar array[]) {
55801a271a75SMatthew G. Knepley   PetscInt            offset = 0, p;
558197e99dd9SToby Isaac   const PetscInt    **perms  = NULL;
558297e99dd9SToby Isaac   const PetscScalar **flips  = NULL;
55831a271a75SMatthew G. Knepley 
55841a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
5585fe02ba77SJed Brown   *size = 0;
55869566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips));
558797e99dd9SToby Isaac   for (p = 0; p < numPoints; p++) {
558897e99dd9SToby Isaac     const PetscInt     point = points[2 * p];
558997e99dd9SToby Isaac     const PetscInt    *perm  = perms ? perms[p] : NULL;
559097e99dd9SToby Isaac     const PetscScalar *flip  = flips ? flips[p] : NULL;
55911a271a75SMatthew G. Knepley     PetscInt           dof, off, d;
55921a271a75SMatthew G. Knepley     const PetscScalar *varr;
55931a271a75SMatthew G. Knepley 
55949566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, point, &dof));
55959566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, point, &off));
55961a271a75SMatthew G. Knepley     varr = &vArray[off];
559797e99dd9SToby Isaac     if (clperm) {
559897e99dd9SToby Isaac       if (perm) {
559997e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d];
56001a271a75SMatthew G. Knepley       } else {
560197e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset + d]] = varr[d];
560297e99dd9SToby Isaac       }
560397e99dd9SToby Isaac       if (flip) {
560497e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset + d]] *= flip[d];
560597e99dd9SToby Isaac       }
560697e99dd9SToby Isaac     } else {
560797e99dd9SToby Isaac       if (perm) {
560897e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d];
560997e99dd9SToby Isaac       } else {
561097e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset + d] = varr[d];
561197e99dd9SToby Isaac       }
561297e99dd9SToby Isaac       if (flip) {
561397e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset + d] *= flip[d];
56141a271a75SMatthew G. Knepley       }
56151a271a75SMatthew G. Knepley     }
561697e99dd9SToby Isaac     offset += dof;
561797e99dd9SToby Isaac   }
56189566063dSJacob Faibussowitsch   PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips));
56191a271a75SMatthew G. Knepley   *size = offset;
56201a271a75SMatthew G. Knepley   PetscFunctionReturn(0);
56211a271a75SMatthew G. Knepley }
56221a271a75SMatthew G. Knepley 
56239371c9d4SSatish Balay 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[]) {
56241a271a75SMatthew G. Knepley   PetscInt offset = 0, f;
56251a271a75SMatthew G. Knepley 
56261a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
5627fe02ba77SJed Brown   *size = 0;
56281a271a75SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
562997e99dd9SToby Isaac     PetscInt            p;
563097e99dd9SToby Isaac     const PetscInt    **perms = NULL;
563197e99dd9SToby Isaac     const PetscScalar **flips = NULL;
56321a271a75SMatthew G. Knepley 
56339566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips));
563497e99dd9SToby Isaac     for (p = 0; p < numPoints; p++) {
563597e99dd9SToby Isaac       const PetscInt     point = points[2 * p];
563697e99dd9SToby Isaac       PetscInt           fdof, foff, b;
56371a271a75SMatthew G. Knepley       const PetscScalar *varr;
563897e99dd9SToby Isaac       const PetscInt    *perm = perms ? perms[p] : NULL;
563997e99dd9SToby Isaac       const PetscScalar *flip = flips ? flips[p] : NULL;
56401a271a75SMatthew G. Knepley 
56419566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
56429566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
56431a271a75SMatthew G. Knepley       varr = &vArray[foff];
564497e99dd9SToby Isaac       if (clperm) {
56459371c9d4SSatish Balay         if (perm) {
5646ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[clperm[offset + perm[b]]] = varr[b];
56471a271a75SMatthew G. Knepley         } else {
5648ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[clperm[offset + b]] = varr[b];
56499371c9d4SSatish Balay         }
56509371c9d4SSatish Balay         if (flip) {
5651ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[clperm[offset + b]] *= flip[b];
56529371c9d4SSatish Balay         }
56539371c9d4SSatish Balay       } else {
56549371c9d4SSatish Balay         if (perm) {
5655ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[offset + perm[b]] = varr[b];
56569371c9d4SSatish Balay         } else {
5657ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[offset + b] = varr[b];
56589371c9d4SSatish Balay         }
56599371c9d4SSatish Balay         if (flip) {
5660ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[offset + b] *= flip[b];
56619371c9d4SSatish Balay         }
56621a271a75SMatthew G. Knepley       }
566397e99dd9SToby Isaac       offset += fdof;
56641a271a75SMatthew G. Knepley     }
56659566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips));
56661a271a75SMatthew G. Knepley   }
56671a271a75SMatthew G. Knepley   *size = offset;
56681a271a75SMatthew G. Knepley   PetscFunctionReturn(0);
56691a271a75SMatthew G. Knepley }
56701a271a75SMatthew G. Knepley 
5671552f7358SJed Brown /*@C
5672552f7358SJed Brown   DMPlexVecGetClosure - Get an array of the values on the closure of 'point'
5673552f7358SJed Brown 
5674552f7358SJed Brown   Not collective
5675552f7358SJed Brown 
5676552f7358SJed Brown   Input Parameters:
5677552f7358SJed Brown + dm - The DM
5678552f7358SJed Brown . section - The section describing the layout in v, or NULL to use the default section
5679552f7358SJed Brown . v - The local vector
56806b867d5aSJose E. Roman - point - The point in the DM
5681552f7358SJed Brown 
56826b867d5aSJose E. Roman   Input/Output Parameters:
56836b867d5aSJose E. Roman + csize  - The size of the input values array, or NULL; on output the number of values in the closure
56846b867d5aSJose E. Roman - values - An array to use for the values, or NULL to have it allocated automatically;
56856b867d5aSJose E. Roman            if the user provided NULL, it is a borrowed array and should not be freed
568622c1ee49SMatthew G. Knepley 
568722c1ee49SMatthew G. Knepley $ Note that DMPlexVecGetClosure/DMPlexVecRestoreClosure only allocates the values array if it set to NULL in the
568822c1ee49SMatthew G. Knepley $ calling function. This is because DMPlexVecGetClosure() is typically called in the inner loop of a Vec or Mat
568922c1ee49SMatthew G. Knepley $ assembly function, and a user may already have allocated storage for this operation.
569022c1ee49SMatthew G. Knepley $
569122c1ee49SMatthew G. Knepley $ A typical use could be
569222c1ee49SMatthew G. Knepley $
569322c1ee49SMatthew G. Knepley $  values = NULL;
56949566063dSJacob Faibussowitsch $  PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values));
569522c1ee49SMatthew G. Knepley $  for (cl = 0; cl < clSize; ++cl) {
569622c1ee49SMatthew G. Knepley $    <Compute on closure>
569722c1ee49SMatthew G. Knepley $  }
56989566063dSJacob Faibussowitsch $  PetscCall(DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values));
569922c1ee49SMatthew G. Knepley $
570022c1ee49SMatthew G. Knepley $ or
570122c1ee49SMatthew G. Knepley $
570222c1ee49SMatthew G. Knepley $  PetscMalloc1(clMaxSize, &values);
570322c1ee49SMatthew G. Knepley $  for (p = pStart; p < pEnd; ++p) {
570422c1ee49SMatthew G. Knepley $    clSize = clMaxSize;
57059566063dSJacob Faibussowitsch $    PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values));
570622c1ee49SMatthew G. Knepley $    for (cl = 0; cl < clSize; ++cl) {
570722c1ee49SMatthew G. Knepley $      <Compute on closure>
570822c1ee49SMatthew G. Knepley $    }
570922c1ee49SMatthew G. Knepley $  }
571022c1ee49SMatthew G. Knepley $  PetscFree(values);
5711552f7358SJed Brown 
5712552f7358SJed Brown   Fortran Notes:
5713552f7358SJed Brown   Since it returns an array, this routine is only available in Fortran 90, and you must
5714552f7358SJed Brown   include petsc.h90 in your code.
5715552f7358SJed Brown 
5716552f7358SJed Brown   The csize argument is not present in the Fortran 90 binding since it is internal to the array.
5717552f7358SJed Brown 
5718552f7358SJed Brown   Level: intermediate
5719552f7358SJed Brown 
5720db781477SPatrick Sanan .seealso `DMPlexVecRestoreClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()`
5721552f7358SJed Brown @*/
57229371c9d4SSatish Balay PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) {
5723552f7358SJed Brown   PetscSection    clSection;
5724d9917b9dSMatthew G. Knepley   IS              clPoints;
5725552f7358SJed Brown   PetscInt       *points = NULL;
5726c459fbc1SJed Brown   const PetscInt *clp, *perm;
5727c459fbc1SJed Brown   PetscInt        depth, numFields, numPoints, asize;
5728552f7358SJed Brown 
5729d9917b9dSMatthew G. Knepley   PetscFunctionBeginHot;
5730552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
57319566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
57321a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
57331a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
57349566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
57359566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
5736552f7358SJed Brown   if (depth == 1 && numFields < 2) {
57379566063dSJacob Faibussowitsch     PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values));
5738552f7358SJed Brown     PetscFunctionReturn(0);
5739552f7358SJed Brown   }
57401a271a75SMatthew G. Knepley   /* Get points */
57419566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
5742c459fbc1SJed Brown   /* Get sizes */
5743c459fbc1SJed Brown   asize = 0;
5744c459fbc1SJed Brown   for (PetscInt p = 0; p < numPoints * 2; p += 2) {
5745c459fbc1SJed Brown     PetscInt dof;
57469566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[p], &dof));
57471a271a75SMatthew G. Knepley     asize += dof;
5748552f7358SJed Brown   }
5749c459fbc1SJed Brown   if (values) {
5750c459fbc1SJed Brown     const PetscScalar *vArray;
5751c459fbc1SJed Brown     PetscInt           size;
5752c459fbc1SJed Brown 
5753c459fbc1SJed Brown     if (*values) {
575463a3b9bcSJacob 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);
57559566063dSJacob Faibussowitsch     } else PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, values));
57569566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, asize, &perm));
57579566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(v, &vArray));
57581a271a75SMatthew G. Knepley     /* Get values */
57599566063dSJacob Faibussowitsch     if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values));
57609566063dSJacob Faibussowitsch     else PetscCall(DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values));
576163a3b9bcSJacob Faibussowitsch     PetscCheck(asize == size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Section size %" PetscInt_FMT " does not match Vec closure size %" PetscInt_FMT, asize, size);
57621a271a75SMatthew G. Knepley     /* Cleanup array */
57639566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(v, &vArray));
5764d0f6b257SMatthew G. Knepley   }
5765c459fbc1SJed Brown   if (csize) *csize = asize;
5766c459fbc1SJed Brown   /* Cleanup points */
57679566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
5768552f7358SJed Brown   PetscFunctionReturn(0);
5769552f7358SJed Brown }
5770552f7358SJed Brown 
57719371c9d4SSatish Balay PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[]) {
5772e5c487bfSMatthew G. Knepley   DMLabel            depthLabel;
5773e5c487bfSMatthew G. Knepley   PetscSection       clSection;
5774e5c487bfSMatthew G. Knepley   IS                 clPoints;
5775e5c487bfSMatthew G. Knepley   PetscScalar       *array;
5776e5c487bfSMatthew G. Knepley   const PetscScalar *vArray;
5777e5c487bfSMatthew G. Knepley   PetscInt          *points = NULL;
5778c459fbc1SJed Brown   const PetscInt    *clp, *perm = NULL;
5779c459fbc1SJed Brown   PetscInt           mdepth, numFields, numPoints, Np = 0, p, clsize, size;
5780e5c487bfSMatthew G. Knepley 
5781e5c487bfSMatthew G. Knepley   PetscFunctionBeginHot;
5782e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
57839566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
5784e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
5785e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
57869566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &mdepth));
57879566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
57889566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
5789e5c487bfSMatthew G. Knepley   if (mdepth == 1 && numFields < 2) {
57909566063dSJacob Faibussowitsch     PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values));
5791e5c487bfSMatthew G. Knepley     PetscFunctionReturn(0);
5792e5c487bfSMatthew G. Knepley   }
5793e5c487bfSMatthew G. Knepley   /* Get points */
57949566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
5795c459fbc1SJed Brown   for (clsize = 0, p = 0; p < Np; p++) {
5796c459fbc1SJed Brown     PetscInt dof;
57979566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[2 * p], &dof));
5798c459fbc1SJed Brown     clsize += dof;
5799c459fbc1SJed Brown   }
58009566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &perm));
5801e5c487bfSMatthew G. Knepley   /* Filter points */
5802e5c487bfSMatthew G. Knepley   for (p = 0; p < numPoints * 2; p += 2) {
5803e5c487bfSMatthew G. Knepley     PetscInt dep;
5804e5c487bfSMatthew G. Knepley 
58059566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(depthLabel, points[p], &dep));
5806e5c487bfSMatthew G. Knepley     if (dep != depth) continue;
5807e5c487bfSMatthew G. Knepley     points[Np * 2 + 0] = points[p];
5808e5c487bfSMatthew G. Knepley     points[Np * 2 + 1] = points[p + 1];
5809e5c487bfSMatthew G. Knepley     ++Np;
5810e5c487bfSMatthew G. Knepley   }
5811e5c487bfSMatthew G. Knepley   /* Get array */
5812e5c487bfSMatthew G. Knepley   if (!values || !*values) {
5813e5c487bfSMatthew G. Knepley     PetscInt asize = 0, dof;
5814e5c487bfSMatthew G. Knepley 
5815e5c487bfSMatthew G. Knepley     for (p = 0; p < Np * 2; p += 2) {
58169566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, points[p], &dof));
5817e5c487bfSMatthew G. Knepley       asize += dof;
5818e5c487bfSMatthew G. Knepley     }
5819e5c487bfSMatthew G. Knepley     if (!values) {
58209566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
5821e5c487bfSMatthew G. Knepley       if (csize) *csize = asize;
5822e5c487bfSMatthew G. Knepley       PetscFunctionReturn(0);
5823e5c487bfSMatthew G. Knepley     }
58249566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, &array));
5825e5c487bfSMatthew G. Knepley   } else {
5826e5c487bfSMatthew G. Knepley     array = *values;
5827e5c487bfSMatthew G. Knepley   }
58289566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(v, &vArray));
5829e5c487bfSMatthew G. Knepley   /* Get values */
58309566063dSJacob Faibussowitsch   if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array));
58319566063dSJacob Faibussowitsch   else PetscCall(DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array));
5832e5c487bfSMatthew G. Knepley   /* Cleanup points */
58339566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
5834e5c487bfSMatthew G. Knepley   /* Cleanup array */
58359566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(v, &vArray));
5836e5c487bfSMatthew G. Knepley   if (!*values) {
5837e5c487bfSMatthew G. Knepley     if (csize) *csize = size;
5838e5c487bfSMatthew G. Knepley     *values = array;
5839e5c487bfSMatthew G. Knepley   } else {
584063a3b9bcSJacob Faibussowitsch     PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size);
5841e5c487bfSMatthew G. Knepley     *csize = size;
5842e5c487bfSMatthew G. Knepley   }
5843e5c487bfSMatthew G. Knepley   PetscFunctionReturn(0);
5844e5c487bfSMatthew G. Knepley }
5845e5c487bfSMatthew G. Knepley 
5846552f7358SJed Brown /*@C
5847552f7358SJed Brown   DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point'
5848552f7358SJed Brown 
5849552f7358SJed Brown   Not collective
5850552f7358SJed Brown 
5851552f7358SJed Brown   Input Parameters:
5852552f7358SJed Brown + dm - The DM
58530298fd71SBarry Smith . section - The section describing the layout in v, or NULL to use the default section
5854552f7358SJed Brown . v - The local vector
5855eaf898f9SPatrick Sanan . point - The point in the DM
58560298fd71SBarry Smith . csize - The number of values in the closure, or NULL
5857552f7358SJed Brown - values - The array of values, which is a borrowed array and should not be freed
5858552f7358SJed Brown 
585922c1ee49SMatthew 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()
586022c1ee49SMatthew G. Knepley 
58613813dfbdSMatthew G Knepley   Fortran Notes:
58623813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
58633813dfbdSMatthew G Knepley   include petsc.h90 in your code.
58643813dfbdSMatthew G Knepley 
58653813dfbdSMatthew G Knepley   The csize argument is not present in the Fortran 90 binding since it is internal to the array.
58663813dfbdSMatthew G Knepley 
5867552f7358SJed Brown   Level: intermediate
5868552f7358SJed Brown 
5869db781477SPatrick Sanan .seealso `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()`
5870552f7358SJed Brown @*/
58719371c9d4SSatish Balay PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) {
5872552f7358SJed Brown   PetscInt size = 0;
5873552f7358SJed Brown 
5874552f7358SJed Brown   PetscFunctionBegin;
5875552f7358SJed Brown   /* Should work without recalculating size */
58769566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void *)values));
5877c9fdaa05SMatthew G. Knepley   *values = NULL;
5878552f7358SJed Brown   PetscFunctionReturn(0);
5879552f7358SJed Brown }
5880552f7358SJed Brown 
58819371c9d4SSatish Balay static inline void add(PetscScalar *x, PetscScalar y) {
58829371c9d4SSatish Balay   *x += y;
58839371c9d4SSatish Balay }
58849371c9d4SSatish Balay static inline void insert(PetscScalar *x, PetscScalar y) {
58859371c9d4SSatish Balay   *x = y;
58869371c9d4SSatish Balay }
5887552f7358SJed Brown 
58889371c9d4SSatish Balay 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[]) {
5889552f7358SJed Brown   PetscInt        cdof;  /* The number of constraints on this point */
5890552f7358SJed Brown   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
5891552f7358SJed Brown   PetscScalar    *a;
5892552f7358SJed Brown   PetscInt        off, cind = 0, k;
5893552f7358SJed Brown 
5894552f7358SJed Brown   PetscFunctionBegin;
58959566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
58969566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(section, point, &off));
5897552f7358SJed Brown   a = &array[off];
5898552f7358SJed Brown   if (!cdof || setBC) {
589997e99dd9SToby Isaac     if (clperm) {
59009371c9d4SSatish Balay       if (perm) {
5901ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.));
5902552f7358SJed Brown       } else {
5903ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.));
59049371c9d4SSatish Balay       }
59059371c9d4SSatish Balay     } else {
59069371c9d4SSatish Balay       if (perm) {
5907ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.));
59089371c9d4SSatish Balay       } else {
5909ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.));
59109371c9d4SSatish Balay       }
5911552f7358SJed Brown     }
5912552f7358SJed Brown   } else {
59139566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
591497e99dd9SToby Isaac     if (clperm) {
59159371c9d4SSatish Balay       if (perm) {
59169371c9d4SSatish Balay         for (k = 0; k < dof; ++k) {
59179371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
59189371c9d4SSatish Balay             ++cind;
59199371c9d4SSatish Balay             continue;
59209371c9d4SSatish Balay           }
592197e99dd9SToby Isaac           fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.));
5922552f7358SJed Brown         }
5923552f7358SJed Brown       } else {
5924552f7358SJed Brown         for (k = 0; k < dof; ++k) {
59259371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
59269371c9d4SSatish Balay             ++cind;
59279371c9d4SSatish Balay             continue;
59289371c9d4SSatish Balay           }
592997e99dd9SToby Isaac           fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.));
593097e99dd9SToby Isaac         }
593197e99dd9SToby Isaac       }
593297e99dd9SToby Isaac     } else {
593397e99dd9SToby Isaac       if (perm) {
593497e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
59359371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
59369371c9d4SSatish Balay             ++cind;
59379371c9d4SSatish Balay             continue;
59389371c9d4SSatish Balay           }
593997e99dd9SToby Isaac           fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.));
594097e99dd9SToby Isaac         }
594197e99dd9SToby Isaac       } else {
594297e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
59439371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
59449371c9d4SSatish Balay             ++cind;
59459371c9d4SSatish Balay             continue;
59469371c9d4SSatish Balay           }
594797e99dd9SToby Isaac           fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.));
594897e99dd9SToby Isaac         }
5949552f7358SJed Brown       }
5950552f7358SJed Brown     }
5951552f7358SJed Brown   }
5952552f7358SJed Brown   PetscFunctionReturn(0);
5953552f7358SJed Brown }
5954552f7358SJed Brown 
59559371c9d4SSatish Balay 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[]) {
5956a5e93ea8SMatthew G. Knepley   PetscInt        cdof;  /* The number of constraints on this point */
5957a5e93ea8SMatthew G. Knepley   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
5958a5e93ea8SMatthew G. Knepley   PetscScalar    *a;
5959a5e93ea8SMatthew G. Knepley   PetscInt        off, cind = 0, k;
5960a5e93ea8SMatthew G. Knepley 
5961a5e93ea8SMatthew G. Knepley   PetscFunctionBegin;
59629566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
59639566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(section, point, &off));
5964a5e93ea8SMatthew G. Knepley   a = &array[off];
5965a5e93ea8SMatthew G. Knepley   if (cdof) {
59669566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
596797e99dd9SToby Isaac     if (clperm) {
596897e99dd9SToby Isaac       if (perm) {
5969a5e93ea8SMatthew G. Knepley         for (k = 0; k < dof; ++k) {
5970a5e93ea8SMatthew G. Knepley           if ((cind < cdof) && (k == cdofs[cind])) {
597197e99dd9SToby Isaac             fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.));
597297e99dd9SToby Isaac             cind++;
5973a5e93ea8SMatthew G. Knepley           }
5974a5e93ea8SMatthew G. Knepley         }
5975a5e93ea8SMatthew G. Knepley       } else {
5976a5e93ea8SMatthew G. Knepley         for (k = 0; k < dof; ++k) {
5977a5e93ea8SMatthew G. Knepley           if ((cind < cdof) && (k == cdofs[cind])) {
597897e99dd9SToby Isaac             fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.));
597997e99dd9SToby Isaac             cind++;
598097e99dd9SToby Isaac           }
598197e99dd9SToby Isaac         }
598297e99dd9SToby Isaac       }
598397e99dd9SToby Isaac     } else {
598497e99dd9SToby Isaac       if (perm) {
598597e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
598697e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {
598797e99dd9SToby Isaac             fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.));
598897e99dd9SToby Isaac             cind++;
598997e99dd9SToby Isaac           }
599097e99dd9SToby Isaac         }
599197e99dd9SToby Isaac       } else {
599297e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
599397e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {
599497e99dd9SToby Isaac             fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.));
599597e99dd9SToby Isaac             cind++;
599697e99dd9SToby Isaac           }
5997a5e93ea8SMatthew G. Knepley         }
5998a5e93ea8SMatthew G. Knepley       }
5999a5e93ea8SMatthew G. Knepley     }
6000a5e93ea8SMatthew G. Knepley   }
6001a5e93ea8SMatthew G. Knepley   PetscFunctionReturn(0);
6002a5e93ea8SMatthew G. Knepley }
6003a5e93ea8SMatthew G. Knepley 
60049371c9d4SSatish Balay 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[]) {
6005552f7358SJed Brown   PetscScalar    *a;
60061a271a75SMatthew G. Knepley   PetscInt        fdof, foff, fcdof, foffset = *offset;
60071a271a75SMatthew G. Knepley   const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
600897e99dd9SToby Isaac   PetscInt        cind = 0, b;
6009552f7358SJed Brown 
6010552f7358SJed Brown   PetscFunctionBegin;
60119566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
60129566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof));
60139566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
60141a271a75SMatthew G. Knepley   a = &array[foff];
6015552f7358SJed Brown   if (!fcdof || setBC) {
601697e99dd9SToby Isaac     if (clperm) {
60179371c9d4SSatish Balay       if (perm) {
6018ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6019552f7358SJed Brown       } else {
6020ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
60219371c9d4SSatish Balay       }
60229371c9d4SSatish Balay     } else {
60239371c9d4SSatish Balay       if (perm) {
6024ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
60259371c9d4SSatish Balay       } else {
6026ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
60279371c9d4SSatish Balay       }
6028552f7358SJed Brown     }
6029552f7358SJed Brown   } else {
60309566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
603197e99dd9SToby Isaac     if (clperm) {
603297e99dd9SToby Isaac       if (perm) {
603397e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
60349371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
60359371c9d4SSatish Balay             ++cind;
60369371c9d4SSatish Balay             continue;
60379371c9d4SSatish Balay           }
603897e99dd9SToby Isaac           fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6039552f7358SJed Brown         }
6040552f7358SJed Brown       } else {
604197e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
60429371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
60439371c9d4SSatish Balay             ++cind;
60449371c9d4SSatish Balay             continue;
60459371c9d4SSatish Balay           }
604697e99dd9SToby Isaac           fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
604797e99dd9SToby Isaac         }
604897e99dd9SToby Isaac       }
604997e99dd9SToby Isaac     } else {
605097e99dd9SToby Isaac       if (perm) {
605197e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
60529371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
60539371c9d4SSatish Balay             ++cind;
60549371c9d4SSatish Balay             continue;
60559371c9d4SSatish Balay           }
605697e99dd9SToby Isaac           fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
605797e99dd9SToby Isaac         }
605897e99dd9SToby Isaac       } else {
605997e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
60609371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
60619371c9d4SSatish Balay             ++cind;
60629371c9d4SSatish Balay             continue;
60639371c9d4SSatish Balay           }
606497e99dd9SToby Isaac           fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
6065552f7358SJed Brown         }
6066552f7358SJed Brown       }
6067552f7358SJed Brown     }
6068552f7358SJed Brown   }
60691a271a75SMatthew G. Knepley   *offset += fdof;
6070552f7358SJed Brown   PetscFunctionReturn(0);
6071552f7358SJed Brown }
6072552f7358SJed Brown 
60739371c9d4SSatish Balay 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[]) {
6074a5e93ea8SMatthew G. Knepley   PetscScalar    *a;
60751a271a75SMatthew G. Knepley   PetscInt        fdof, foff, fcdof, foffset = *offset;
60761a271a75SMatthew G. Knepley   const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
60775da9d227SMatthew G. Knepley   PetscInt        Nc, cind = 0, ncind = 0, b;
6078ba322698SMatthew G. Knepley   PetscBool       ncSet, fcSet;
6079a5e93ea8SMatthew G. Knepley 
6080a5e93ea8SMatthew G. Knepley   PetscFunctionBegin;
60819566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldComponents(section, f, &Nc));
60829566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
60839566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof));
60849566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
60851a271a75SMatthew G. Knepley   a = &array[foff];
6086a5e93ea8SMatthew G. Knepley   if (fcdof) {
6087ba322698SMatthew G. Knepley     /* We just override fcdof and fcdofs with Ncc and comps */
60889566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
608997e99dd9SToby Isaac     if (clperm) {
609097e99dd9SToby Isaac       if (perm) {
6091ba322698SMatthew G. Knepley         if (comps) {
6092ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6093ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
60949371c9d4SSatish Balay             if (b % Nc == comps[ncind]) {
60959371c9d4SSatish Balay               ncind = (ncind + 1) % Ncc;
60969371c9d4SSatish Balay               ncSet = PETSC_TRUE;
60979371c9d4SSatish Balay             }
60989371c9d4SSatish Balay             if ((cind < fcdof) && (b == fcdofs[cind])) {
60999371c9d4SSatish Balay               ++cind;
61009371c9d4SSatish Balay               fcSet = PETSC_TRUE;
61019371c9d4SSatish Balay             }
6102ad540459SPierre Jolivet             if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6103ba322698SMatthew G. Knepley           }
6104ba322698SMatthew G. Knepley         } else {
610597e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
610697e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
610797e99dd9SToby Isaac               fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6108a5e93ea8SMatthew G. Knepley               ++cind;
6109a5e93ea8SMatthew G. Knepley             }
6110a5e93ea8SMatthew G. Knepley           }
6111ba322698SMatthew G. Knepley         }
6112ba322698SMatthew G. Knepley       } else {
6113ba322698SMatthew G. Knepley         if (comps) {
6114ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6115ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
61169371c9d4SSatish Balay             if (b % Nc == comps[ncind]) {
61179371c9d4SSatish Balay               ncind = (ncind + 1) % Ncc;
61189371c9d4SSatish Balay               ncSet = PETSC_TRUE;
61199371c9d4SSatish Balay             }
61209371c9d4SSatish Balay             if ((cind < fcdof) && (b == fcdofs[cind])) {
61219371c9d4SSatish Balay               ++cind;
61229371c9d4SSatish Balay               fcSet = PETSC_TRUE;
61239371c9d4SSatish Balay             }
6124ad540459SPierre Jolivet             if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
6125ba322698SMatthew G. Knepley           }
6126a5e93ea8SMatthew G. Knepley         } else {
612797e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
612897e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
612997e99dd9SToby Isaac               fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
613097e99dd9SToby Isaac               ++cind;
613197e99dd9SToby Isaac             }
613297e99dd9SToby Isaac           }
613397e99dd9SToby Isaac         }
6134ba322698SMatthew G. Knepley       }
613597e99dd9SToby Isaac     } else {
613697e99dd9SToby Isaac       if (perm) {
6137ba322698SMatthew G. Knepley         if (comps) {
6138ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6139ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
61409371c9d4SSatish Balay             if (b % Nc == comps[ncind]) {
61419371c9d4SSatish Balay               ncind = (ncind + 1) % Ncc;
61429371c9d4SSatish Balay               ncSet = PETSC_TRUE;
61439371c9d4SSatish Balay             }
61449371c9d4SSatish Balay             if ((cind < fcdof) && (b == fcdofs[cind])) {
61459371c9d4SSatish Balay               ++cind;
61469371c9d4SSatish Balay               fcSet = PETSC_TRUE;
61479371c9d4SSatish Balay             }
6148ad540459SPierre Jolivet             if (ncSet && fcSet) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
6149ba322698SMatthew G. Knepley           }
6150ba322698SMatthew G. Knepley         } else {
615197e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
615297e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
615397e99dd9SToby Isaac               fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
615497e99dd9SToby Isaac               ++cind;
615597e99dd9SToby Isaac             }
615697e99dd9SToby Isaac           }
6157ba322698SMatthew G. Knepley         }
6158ba322698SMatthew G. Knepley       } else {
6159ba322698SMatthew G. Knepley         if (comps) {
6160ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6161ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
61629371c9d4SSatish Balay             if (b % Nc == comps[ncind]) {
61639371c9d4SSatish Balay               ncind = (ncind + 1) % Ncc;
61649371c9d4SSatish Balay               ncSet = PETSC_TRUE;
61659371c9d4SSatish Balay             }
61669371c9d4SSatish Balay             if ((cind < fcdof) && (b == fcdofs[cind])) {
61679371c9d4SSatish Balay               ++cind;
61689371c9d4SSatish Balay               fcSet = PETSC_TRUE;
61699371c9d4SSatish Balay             }
6170ad540459SPierre Jolivet             if (ncSet && fcSet) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
6171ba322698SMatthew G. Knepley           }
617297e99dd9SToby Isaac         } else {
617397e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
617497e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
617597e99dd9SToby Isaac               fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
6176a5e93ea8SMatthew G. Knepley               ++cind;
6177a5e93ea8SMatthew G. Knepley             }
6178a5e93ea8SMatthew G. Knepley           }
6179a5e93ea8SMatthew G. Knepley         }
6180a5e93ea8SMatthew G. Knepley       }
6181a5e93ea8SMatthew G. Knepley     }
6182ba322698SMatthew G. Knepley   }
61831a271a75SMatthew G. Knepley   *offset += fdof;
6184a5e93ea8SMatthew G. Knepley   PetscFunctionReturn(0);
6185a5e93ea8SMatthew G. Knepley }
6186a5e93ea8SMatthew G. Knepley 
61879371c9d4SSatish Balay static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) {
6188552f7358SJed Brown   PetscScalar    *array;
61891b406b76SMatthew G. Knepley   const PetscInt *cone, *coneO;
61901b406b76SMatthew G. Knepley   PetscInt        pStart, pEnd, p, numPoints, off, dof;
6191552f7358SJed Brown 
61921b406b76SMatthew G. Knepley   PetscFunctionBeginHot;
61939566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
61949566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, point, &numPoints));
61959566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, point, &cone));
61969566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeOrientation(dm, point, &coneO));
61979566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
6198b6ebb6e6SMatthew G. Knepley   for (p = 0, off = 0; p <= numPoints; ++p, off += dof) {
6199b6ebb6e6SMatthew G. Knepley     const PetscInt cp = !p ? point : cone[p - 1];
6200b6ebb6e6SMatthew G. Knepley     const PetscInt o  = !p ? 0 : coneO[p - 1];
6201b6ebb6e6SMatthew G. Knepley 
62029371c9d4SSatish Balay     if ((cp < pStart) || (cp >= pEnd)) {
62039371c9d4SSatish Balay       dof = 0;
62049371c9d4SSatish Balay       continue;
62059371c9d4SSatish Balay     }
62069566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, cp, &dof));
6207b6ebb6e6SMatthew G. Knepley     /* ADD_VALUES */
6208b6ebb6e6SMatthew G. Knepley     {
6209b6ebb6e6SMatthew G. Knepley       const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6210b6ebb6e6SMatthew G. Knepley       PetscScalar    *a;
6211b6ebb6e6SMatthew G. Knepley       PetscInt        cdof, coff, cind = 0, k;
6212b6ebb6e6SMatthew G. Knepley 
62139566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetConstraintDof(section, cp, &cdof));
62149566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(section, cp, &coff));
6215b6ebb6e6SMatthew G. Knepley       a = &array[coff];
6216b6ebb6e6SMatthew G. Knepley       if (!cdof) {
6217b6ebb6e6SMatthew G. Knepley         if (o >= 0) {
6218ad540459SPierre Jolivet           for (k = 0; k < dof; ++k) a[k] += values[off + k];
6219b6ebb6e6SMatthew G. Knepley         } else {
6220ad540459SPierre Jolivet           for (k = 0; k < dof; ++k) a[k] += values[off + dof - k - 1];
6221b6ebb6e6SMatthew G. Knepley         }
6222b6ebb6e6SMatthew G. Knepley       } else {
62239566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintIndices(section, cp, &cdofs));
6224b6ebb6e6SMatthew G. Knepley         if (o >= 0) {
6225b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
62269371c9d4SSatish Balay             if ((cind < cdof) && (k == cdofs[cind])) {
62279371c9d4SSatish Balay               ++cind;
62289371c9d4SSatish Balay               continue;
62299371c9d4SSatish Balay             }
6230b6ebb6e6SMatthew G. Knepley             a[k] += values[off + k];
6231b6ebb6e6SMatthew G. Knepley           }
6232b6ebb6e6SMatthew G. Knepley         } else {
6233b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
62349371c9d4SSatish Balay             if ((cind < cdof) && (k == cdofs[cind])) {
62359371c9d4SSatish Balay               ++cind;
62369371c9d4SSatish Balay               continue;
62379371c9d4SSatish Balay             }
6238b6ebb6e6SMatthew G. Knepley             a[k] += values[off + dof - k - 1];
6239b6ebb6e6SMatthew G. Knepley           }
6240b6ebb6e6SMatthew G. Knepley         }
6241b6ebb6e6SMatthew G. Knepley       }
6242b6ebb6e6SMatthew G. Knepley     }
6243b6ebb6e6SMatthew G. Knepley   }
62449566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
6245b6ebb6e6SMatthew G. Knepley   PetscFunctionReturn(0);
6246b6ebb6e6SMatthew G. Knepley }
62471b406b76SMatthew G. Knepley 
62481b406b76SMatthew G. Knepley /*@C
62491b406b76SMatthew G. Knepley   DMPlexVecSetClosure - Set an array of the values on the closure of 'point'
62501b406b76SMatthew G. Knepley 
62511b406b76SMatthew G. Knepley   Not collective
62521b406b76SMatthew G. Knepley 
62531b406b76SMatthew G. Knepley   Input Parameters:
62541b406b76SMatthew G. Knepley + dm - The DM
62551b406b76SMatthew G. Knepley . section - The section describing the layout in v, or NULL to use the default section
62561b406b76SMatthew G. Knepley . v - The local vector
6257eaf898f9SPatrick Sanan . point - The point in the DM
62581b406b76SMatthew G. Knepley . values - The array of values
625922c1ee49SMatthew 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,
626022c1ee49SMatthew G. Knepley          where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions.
62611b406b76SMatthew G. Knepley 
62621b406b76SMatthew G. Knepley   Fortran Notes:
62631b406b76SMatthew G. Knepley   This routine is only available in Fortran 90, and you must include petsc.h90 in your code.
62641b406b76SMatthew G. Knepley 
62651b406b76SMatthew G. Knepley   Level: intermediate
62661b406b76SMatthew G. Knepley 
6267db781477SPatrick Sanan .seealso `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`
62681b406b76SMatthew G. Knepley @*/
62699371c9d4SSatish Balay PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) {
62701b406b76SMatthew G. Knepley   PetscSection    clSection;
62711b406b76SMatthew G. Knepley   IS              clPoints;
62721b406b76SMatthew G. Knepley   PetscScalar    *array;
62731b406b76SMatthew G. Knepley   PetscInt       *points = NULL;
627427f02ce8SMatthew G. Knepley   const PetscInt *clp, *clperm = NULL;
6275c459fbc1SJed Brown   PetscInt        depth, numFields, numPoints, p, clsize;
62761b406b76SMatthew G. Knepley 
62771a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
62781b406b76SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
62799566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
62801a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
62811a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
62829566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
62839566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
62841b406b76SMatthew G. Knepley   if (depth == 1 && numFields < 2 && mode == ADD_VALUES) {
62859566063dSJacob Faibussowitsch     PetscCall(DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode));
62861b406b76SMatthew G. Knepley     PetscFunctionReturn(0);
62871b406b76SMatthew G. Knepley   }
62881a271a75SMatthew G. Knepley   /* Get points */
62899566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
6290c459fbc1SJed Brown   for (clsize = 0, p = 0; p < numPoints; p++) {
6291c459fbc1SJed Brown     PetscInt dof;
62929566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[2 * p], &dof));
6293c459fbc1SJed Brown     clsize += dof;
6294c459fbc1SJed Brown   }
62959566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm));
62961a271a75SMatthew G. Knepley   /* Get array */
62979566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
62981a271a75SMatthew G. Knepley   /* Get values */
6299ef90cfe2SMatthew G. Knepley   if (numFields > 0) {
630097e99dd9SToby Isaac     PetscInt offset = 0, f;
6301552f7358SJed Brown     for (f = 0; f < numFields; ++f) {
630297e99dd9SToby Isaac       const PetscInt    **perms = NULL;
630397e99dd9SToby Isaac       const PetscScalar **flips = NULL;
630497e99dd9SToby Isaac 
63059566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips));
6306552f7358SJed Brown       switch (mode) {
6307552f7358SJed Brown       case INSERT_VALUES:
630897e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
630997e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
631097e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
631197e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
631297e99dd9SToby Isaac           updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array);
63139371c9d4SSatish Balay         }
63149371c9d4SSatish Balay         break;
6315552f7358SJed Brown       case INSERT_ALL_VALUES:
631697e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
631797e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
631897e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
631997e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
632097e99dd9SToby Isaac           updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array);
63219371c9d4SSatish Balay         }
63229371c9d4SSatish Balay         break;
6323a5e93ea8SMatthew G. Knepley       case INSERT_BC_VALUES:
632497e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
632597e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
632697e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
632797e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
6328ba322698SMatthew G. Knepley           updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array);
63299371c9d4SSatish Balay         }
63309371c9d4SSatish Balay         break;
6331552f7358SJed Brown       case ADD_VALUES:
633297e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
633397e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
633497e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
633597e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
633697e99dd9SToby Isaac           updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array);
63379371c9d4SSatish Balay         }
63389371c9d4SSatish Balay         break;
6339552f7358SJed Brown       case ADD_ALL_VALUES:
634097e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
634197e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
634297e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
634397e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
634497e99dd9SToby Isaac           updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array);
63459371c9d4SSatish Balay         }
63469371c9d4SSatish Balay         break;
6347304ab55fSMatthew G. Knepley       case ADD_BC_VALUES:
634897e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
634997e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
635097e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
635197e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
6352ba322698SMatthew G. Knepley           updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array);
63539371c9d4SSatish Balay         }
63549371c9d4SSatish Balay         break;
63559371c9d4SSatish Balay       default: SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
6356552f7358SJed Brown       }
63579566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips));
63581a271a75SMatthew G. Knepley     }
6359552f7358SJed Brown   } else {
63601a271a75SMatthew G. Knepley     PetscInt            dof, off;
636197e99dd9SToby Isaac     const PetscInt    **perms = NULL;
636297e99dd9SToby Isaac     const PetscScalar **flips = NULL;
63631a271a75SMatthew G. Knepley 
63649566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips));
6365552f7358SJed Brown     switch (mode) {
6366552f7358SJed Brown     case INSERT_VALUES:
636797e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
636897e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
636997e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
637097e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
63719566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
637297e99dd9SToby Isaac         updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array);
63739371c9d4SSatish Balay       }
63749371c9d4SSatish Balay       break;
6375552f7358SJed Brown     case INSERT_ALL_VALUES:
637697e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
637797e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
637897e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
637997e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
63809566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
638197e99dd9SToby Isaac         updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array);
63829371c9d4SSatish Balay       }
63839371c9d4SSatish Balay       break;
6384a5e93ea8SMatthew G. Knepley     case INSERT_BC_VALUES:
638597e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
638697e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
638797e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
638897e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
63899566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
639097e99dd9SToby Isaac         updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array);
63919371c9d4SSatish Balay       }
63929371c9d4SSatish Balay       break;
6393552f7358SJed Brown     case ADD_VALUES:
639497e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
639597e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
639697e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
639797e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
63989566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
639997e99dd9SToby Isaac         updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array);
64009371c9d4SSatish Balay       }
64019371c9d4SSatish Balay       break;
6402552f7358SJed Brown     case ADD_ALL_VALUES:
640397e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
640497e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
640597e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
640697e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
64079566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
640897e99dd9SToby Isaac         updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array);
64099371c9d4SSatish Balay       }
64109371c9d4SSatish Balay       break;
6411304ab55fSMatthew G. Knepley     case ADD_BC_VALUES:
641297e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
641397e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
641497e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
641597e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
64169566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
641797e99dd9SToby Isaac         updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array);
64189371c9d4SSatish Balay       }
64199371c9d4SSatish Balay       break;
64209371c9d4SSatish Balay     default: SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
6421552f7358SJed Brown     }
64229566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips));
6423552f7358SJed Brown   }
64241a271a75SMatthew G. Knepley   /* Cleanup points */
64259566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
64261a271a75SMatthew G. Knepley   /* Cleanup array */
64279566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
6428552f7358SJed Brown   PetscFunctionReturn(0);
6429552f7358SJed Brown }
6430552f7358SJed Brown 
64315f790a90SMatthew G. Knepley /* Check whether the given point is in the label. If not, update the offset to skip this point */
643211cc89d2SBarry Smith static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset, PetscBool *contains) {
64335f790a90SMatthew G. Knepley   PetscFunctionBegin;
643411cc89d2SBarry Smith   *contains = PETSC_TRUE;
64355f790a90SMatthew G. Knepley   if (label) {
6436d6177c40SToby Isaac     PetscInt fdof;
64375f790a90SMatthew G. Knepley 
643811cc89d2SBarry Smith     PetscCall(DMLabelStratumHasPoint(label, labelId, point, contains));
643911cc89d2SBarry Smith     if (!*contains) {
64409566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
64415f790a90SMatthew G. Knepley       *offset += fdof;
644211cc89d2SBarry Smith       PetscFunctionReturn(0);
64435f790a90SMatthew G. Knepley     }
64445f790a90SMatthew G. Knepley   }
64455f790a90SMatthew G. Knepley   PetscFunctionReturn(0);
64465f790a90SMatthew G. Knepley }
64475f790a90SMatthew G. Knepley 
644897529cf3SJed Brown /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */
64499371c9d4SSatish Balay 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) {
6450e07394fbSMatthew G. Knepley   PetscSection    clSection;
6451e07394fbSMatthew G. Knepley   IS              clPoints;
6452e07394fbSMatthew G. Knepley   PetscScalar    *array;
6453e07394fbSMatthew G. Knepley   PetscInt       *points = NULL;
645497529cf3SJed Brown   const PetscInt *clp;
6455e07394fbSMatthew G. Knepley   PetscInt        numFields, numPoints, p;
645697e99dd9SToby Isaac   PetscInt        offset = 0, f;
6457e07394fbSMatthew G. Knepley 
6458e07394fbSMatthew G. Knepley   PetscFunctionBeginHot;
6459e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
64609566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
6461e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
6462e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
64639566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
6464e07394fbSMatthew G. Knepley   /* Get points */
64659566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
6466e07394fbSMatthew G. Knepley   /* Get array */
64679566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
6468e07394fbSMatthew G. Knepley   /* Get values */
6469e07394fbSMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
647097e99dd9SToby Isaac     const PetscInt    **perms = NULL;
647197e99dd9SToby Isaac     const PetscScalar **flips = NULL;
647211cc89d2SBarry Smith     PetscBool           contains;
647397e99dd9SToby Isaac 
6474e07394fbSMatthew G. Knepley     if (!fieldActive[f]) {
6475e07394fbSMatthew G. Knepley       for (p = 0; p < numPoints * 2; p += 2) {
6476e07394fbSMatthew G. Knepley         PetscInt fdof;
64779566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof));
6478e07394fbSMatthew G. Knepley         offset += fdof;
6479e07394fbSMatthew G. Knepley       }
6480e07394fbSMatthew G. Knepley       continue;
6481e07394fbSMatthew G. Knepley     }
64829566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips));
6483e07394fbSMatthew G. Knepley     switch (mode) {
6484e07394fbSMatthew G. Knepley     case INSERT_VALUES:
648597e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
648697e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
648797e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
648897e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
648911cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
649011cc89d2SBarry Smith         if (!contains) continue;
64919566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array));
64929371c9d4SSatish Balay       }
64939371c9d4SSatish Balay       break;
6494e07394fbSMatthew G. Knepley     case INSERT_ALL_VALUES:
649597e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
649697e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
649797e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
649897e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
649911cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
650011cc89d2SBarry Smith         if (!contains) continue;
65019566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array));
65029371c9d4SSatish Balay       }
65039371c9d4SSatish Balay       break;
6504e07394fbSMatthew G. Knepley     case INSERT_BC_VALUES:
650597e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
650697e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
650797e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
650897e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
650911cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
651011cc89d2SBarry Smith         if (!contains) continue;
65119566063dSJacob Faibussowitsch         PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array));
65129371c9d4SSatish Balay       }
65139371c9d4SSatish Balay       break;
6514e07394fbSMatthew G. Knepley     case ADD_VALUES:
651597e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
651697e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
651797e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
651897e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
651911cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
652011cc89d2SBarry Smith         if (!contains) continue;
65219566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array));
65229371c9d4SSatish Balay       }
65239371c9d4SSatish Balay       break;
6524e07394fbSMatthew G. Knepley     case ADD_ALL_VALUES:
652597e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
652697e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
652797e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
652897e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
652911cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
653011cc89d2SBarry Smith         if (!contains) continue;
65319566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array));
65329371c9d4SSatish Balay       }
65339371c9d4SSatish Balay       break;
65349371c9d4SSatish Balay     default: SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
6535e07394fbSMatthew G. Knepley     }
65369566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips));
6537e07394fbSMatthew G. Knepley   }
6538e07394fbSMatthew G. Knepley   /* Cleanup points */
65399566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
6540e07394fbSMatthew G. Knepley   /* Cleanup array */
65419566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
6542e07394fbSMatthew G. Knepley   PetscFunctionReturn(0);
6543e07394fbSMatthew G. Knepley }
6544e07394fbSMatthew G. Knepley 
65459371c9d4SSatish Balay static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) {
6546552f7358SJed Brown   PetscMPIInt rank;
6547552f7358SJed Brown   PetscInt    i, j;
6548552f7358SJed Brown 
6549552f7358SJed Brown   PetscFunctionBegin;
65509566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
655163a3b9bcSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat for point %" PetscInt_FMT "\n", rank, point));
655263a3b9bcSJacob Faibussowitsch   for (i = 0; i < numRIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, rindices[i]));
655363a3b9bcSJacob Faibussowitsch   for (i = 0; i < numCIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, cindices[i]));
6554b0ecff45SMatthew G. Knepley   numCIndices = numCIndices ? numCIndices : numRIndices;
6555557cf195SMatthew G. Knepley   if (!values) PetscFunctionReturn(0);
6556b0ecff45SMatthew G. Knepley   for (i = 0; i < numRIndices; i++) {
65579566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]", rank));
6558b0ecff45SMatthew G. Knepley     for (j = 0; j < numCIndices; j++) {
6559519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX)
65609566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i * numCIndices + j]), (double)PetscImaginaryPart(values[i * numCIndices + j])));
6561552f7358SJed Brown #else
65629566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, " %g", (double)values[i * numCIndices + j]));
6563552f7358SJed Brown #endif
6564552f7358SJed Brown     }
65659566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
6566552f7358SJed Brown   }
6567552f7358SJed Brown   PetscFunctionReturn(0);
6568552f7358SJed Brown }
6569552f7358SJed Brown 
657005586334SMatthew G. Knepley /*
657105586334SMatthew G. Knepley   DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array
657205586334SMatthew G. Knepley 
657305586334SMatthew G. Knepley   Input Parameters:
657405586334SMatthew G. Knepley + section - The section for this data layout
657536fa2b79SJed Brown . islocal - Is the section (and thus indices being requested) local or global?
657605586334SMatthew G. Knepley . point   - The point contributing dofs with these indices
657705586334SMatthew G. Knepley . off     - The global offset of this point
657805586334SMatthew G. Knepley . loff    - The local offset of each field
6579a5b23f4aSJose E. Roman . setBC   - The flag determining whether to include indices of boundary values
658005586334SMatthew G. Knepley . perm    - A permutation of the dofs on this point, or NULL
658105586334SMatthew G. Knepley - indperm - A permutation of the entire indices array, or NULL
658205586334SMatthew G. Knepley 
658305586334SMatthew G. Knepley   Output Parameter:
658405586334SMatthew G. Knepley . indices - Indices for dofs on this point
658505586334SMatthew G. Knepley 
658605586334SMatthew G. Knepley   Level: developer
658705586334SMatthew G. Knepley 
658805586334SMatthew G. Knepley   Note: The indices could be local or global, depending on the value of 'off'.
658905586334SMatthew G. Knepley */
65909371c9d4SSatish Balay PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[]) {
6591e6ccafaeSMatthew G Knepley   PetscInt        dof;   /* The number of unknowns on this point */
6592552f7358SJed Brown   PetscInt        cdof;  /* The number of constraints on this point */
6593552f7358SJed Brown   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6594552f7358SJed Brown   PetscInt        cind = 0, k;
6595552f7358SJed Brown 
6596552f7358SJed Brown   PetscFunctionBegin;
659708401ef6SPierre Jolivet   PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC");
65989566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(section, point, &dof));
65999566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
6600552f7358SJed Brown   if (!cdof || setBC) {
660105586334SMatthew G. Knepley     for (k = 0; k < dof; ++k) {
660205586334SMatthew G. Knepley       const PetscInt preind = perm ? *loff + perm[k] : *loff + k;
660305586334SMatthew G. Knepley       const PetscInt ind    = indperm ? indperm[preind] : preind;
660405586334SMatthew G. Knepley 
660505586334SMatthew G. Knepley       indices[ind] = off + k;
6606552f7358SJed Brown     }
6607552f7358SJed Brown   } else {
66089566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
66094acb8e1eSToby Isaac     for (k = 0; k < dof; ++k) {
661005586334SMatthew G. Knepley       const PetscInt preind = perm ? *loff + perm[k] : *loff + k;
661105586334SMatthew G. Knepley       const PetscInt ind    = indperm ? indperm[preind] : preind;
661205586334SMatthew G. Knepley 
66134acb8e1eSToby Isaac       if ((cind < cdof) && (k == cdofs[cind])) {
66144acb8e1eSToby Isaac         /* Insert check for returning constrained indices */
661505586334SMatthew G. Knepley         indices[ind] = -(off + k + 1);
66164acb8e1eSToby Isaac         ++cind;
66174acb8e1eSToby Isaac       } else {
661836fa2b79SJed Brown         indices[ind] = off + k - (islocal ? 0 : cind);
6619552f7358SJed Brown       }
6620552f7358SJed Brown     }
6621552f7358SJed Brown   }
6622e6ccafaeSMatthew G Knepley   *loff += dof;
6623552f7358SJed Brown   PetscFunctionReturn(0);
6624552f7358SJed Brown }
6625552f7358SJed Brown 
66267e29afd2SMatthew G. Knepley /*
662736fa2b79SJed Brown  DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering.
66287e29afd2SMatthew G. Knepley 
662936fa2b79SJed Brown  Input Parameters:
663036fa2b79SJed Brown + section - a section (global or local)
663136fa2b79SJed Brown - islocal - PETSC_TRUE if requesting local indices (i.e., section is local); PETSC_FALSE for global
663236fa2b79SJed Brown . point - point within section
663336fa2b79SJed Brown . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section
663436fa2b79SJed Brown . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field
663536fa2b79SJed Brown . setBC - identify constrained (boundary condition) points via involution.
663636fa2b79SJed Brown . perms - perms[f][permsoff][:] is a permutation of dofs within each field
663736fa2b79SJed Brown . permsoff - offset
663836fa2b79SJed Brown - indperm - index permutation
663936fa2b79SJed Brown 
664036fa2b79SJed Brown  Output Parameter:
664136fa2b79SJed Brown . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field
664236fa2b79SJed Brown . indices - array to hold indices (as defined by section) of each dof associated with point
664336fa2b79SJed Brown 
664436fa2b79SJed Brown  Notes:
664536fa2b79SJed Brown  If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs.
664636fa2b79SJed Brown  If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position
664736fa2b79SJed Brown  in the local vector.
664836fa2b79SJed Brown 
664936fa2b79SJed Brown  If section is global and setBC=false, the indices for constrained points are negative (and their value is not
665036fa2b79SJed Brown  significant).  It is invalid to call with a global section and setBC=true.
665136fa2b79SJed Brown 
665236fa2b79SJed Brown  Developer Note:
665336fa2b79SJed Brown  The section is only used for field layout, so islocal is technically a statement about the offset (off).  At some point
665436fa2b79SJed Brown  in the future, global sections may have fields set, in which case we could pass the global section and obtain the
665536fa2b79SJed Brown  offset could be obtained from the section instead of passing it explicitly as we do now.
665636fa2b79SJed Brown 
665736fa2b79SJed Brown  Example:
665836fa2b79SJed Brown  Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}.
665936fa2b79SJed Brown  When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE).
666036fa2b79SJed Brown  Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices.
666136fa2b79SJed 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.
666236fa2b79SJed Brown 
666336fa2b79SJed Brown  Level: developer
66647e29afd2SMatthew G. Knepley */
66659371c9d4SSatish Balay 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[]) {
6666552f7358SJed Brown   PetscInt numFields, foff, f;
6667552f7358SJed Brown 
6668552f7358SJed Brown   PetscFunctionBegin;
666908401ef6SPierre Jolivet   PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC");
66709566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
6671552f7358SJed Brown   for (f = 0, foff = 0; f < numFields; ++f) {
66724acb8e1eSToby Isaac     PetscInt        fdof, cfdof;
6673552f7358SJed Brown     const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
66744acb8e1eSToby Isaac     PetscInt        cind = 0, b;
66754acb8e1eSToby Isaac     const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL;
6676552f7358SJed Brown 
66779566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
66789566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof));
6679552f7358SJed Brown     if (!cfdof || setBC) {
668005586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
668105586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
668205586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
668305586334SMatthew G. Knepley 
668405586334SMatthew G. Knepley         indices[ind] = off + foff + b;
668505586334SMatthew G. Knepley       }
6686552f7358SJed Brown     } else {
66879566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
668805586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
668905586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
669005586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
669105586334SMatthew G. Knepley 
66924acb8e1eSToby Isaac         if ((cind < cfdof) && (b == fcdofs[cind])) {
669305586334SMatthew G. Knepley           indices[ind] = -(off + foff + b + 1);
6694552f7358SJed Brown           ++cind;
6695552f7358SJed Brown         } else {
669636fa2b79SJed Brown           indices[ind] = off + foff + b - (islocal ? 0 : cind);
6697552f7358SJed Brown         }
6698552f7358SJed Brown       }
6699552f7358SJed Brown     }
670036fa2b79SJed Brown     foff += (setBC || islocal ? fdof : (fdof - cfdof));
6701552f7358SJed Brown     foffs[f] += fdof;
6702552f7358SJed Brown   }
6703552f7358SJed Brown   PetscFunctionReturn(0);
6704552f7358SJed Brown }
6705552f7358SJed Brown 
67067e29afd2SMatthew G. Knepley /*
67077e29afd2SMatthew G. Knepley   This version believes the globalSection offsets for each field, rather than just the point offset
67087e29afd2SMatthew G. Knepley 
67097e29afd2SMatthew G. Knepley  . foffs - The offset into 'indices' for each field, since it is segregated by field
6710645102dcSJed Brown 
6711645102dcSJed Brown  Notes:
6712645102dcSJed Brown  The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal.
6713645102dcSJed Brown  Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists.
67147e29afd2SMatthew G. Knepley */
67159371c9d4SSatish Balay static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[]) {
67167e29afd2SMatthew G. Knepley   PetscInt numFields, foff, f;
67177e29afd2SMatthew G. Knepley 
67187e29afd2SMatthew G. Knepley   PetscFunctionBegin;
67199566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
67207e29afd2SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
67217e29afd2SMatthew G. Knepley     PetscInt        fdof, cfdof;
67227e29afd2SMatthew G. Knepley     const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
67237e29afd2SMatthew G. Knepley     PetscInt        cind = 0, b;
67247e29afd2SMatthew G. Knepley     const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL;
67257e29afd2SMatthew G. Knepley 
67269566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
67279566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof));
67289566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldOffset(globalSection, point, f, &foff));
6729645102dcSJed Brown     if (!cfdof) {
673005586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
673105586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
673205586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
673305586334SMatthew G. Knepley 
673405586334SMatthew G. Knepley         indices[ind] = foff + b;
673505586334SMatthew G. Knepley       }
67367e29afd2SMatthew G. Knepley     } else {
67379566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
673805586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
673905586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
674005586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
674105586334SMatthew G. Knepley 
67427e29afd2SMatthew G. Knepley         if ((cind < cfdof) && (b == fcdofs[cind])) {
674305586334SMatthew G. Knepley           indices[ind] = -(foff + b + 1);
67447e29afd2SMatthew G. Knepley           ++cind;
67457e29afd2SMatthew G. Knepley         } else {
674605586334SMatthew G. Knepley           indices[ind] = foff + b - cind;
67477e29afd2SMatthew G. Knepley         }
67487e29afd2SMatthew G. Knepley       }
67497e29afd2SMatthew G. Knepley     }
67507e29afd2SMatthew G. Knepley     foffs[f] += fdof;
67517e29afd2SMatthew G. Knepley   }
67527e29afd2SMatthew G. Knepley   PetscFunctionReturn(0);
67537e29afd2SMatthew G. Knepley }
67547e29afd2SMatthew G. Knepley 
67559371c9d4SSatish Balay 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) {
6756d3d1a6afSToby Isaac   Mat             cMat;
6757d3d1a6afSToby Isaac   PetscSection    aSec, cSec;
6758d3d1a6afSToby Isaac   IS              aIS;
6759d3d1a6afSToby Isaac   PetscInt        aStart = -1, aEnd = -1;
6760d3d1a6afSToby Isaac   const PetscInt *anchors;
6761e17c06e0SMatthew G. Knepley   PetscInt        numFields, f, p, q, newP = 0;
6762d3d1a6afSToby Isaac   PetscInt        newNumPoints = 0, newNumIndices = 0;
6763d3d1a6afSToby Isaac   PetscInt       *newPoints, *indices, *newIndices;
6764d3d1a6afSToby Isaac   PetscInt        maxAnchor, maxDof;
6765d3d1a6afSToby Isaac   PetscInt        newOffsets[32];
6766d3d1a6afSToby Isaac   PetscInt       *pointMatOffsets[32];
6767d3d1a6afSToby Isaac   PetscInt       *newPointOffsets[32];
6768d3d1a6afSToby Isaac   PetscScalar    *pointMat[32];
67696ecaa68aSToby Isaac   PetscScalar    *newValues      = NULL, *tmpValues;
6770d3d1a6afSToby Isaac   PetscBool       anyConstrained = PETSC_FALSE;
6771d3d1a6afSToby Isaac 
6772d3d1a6afSToby Isaac   PetscFunctionBegin;
6773d3d1a6afSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6774d3d1a6afSToby Isaac   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
67759566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
6776d3d1a6afSToby Isaac 
67779566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS));
6778d3d1a6afSToby Isaac   /* if there are point-to-point constraints */
6779d3d1a6afSToby Isaac   if (aSec) {
67809566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(newOffsets, 32));
67819566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(aIS, &anchors));
67829566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd));
6783d3d1a6afSToby Isaac     /* figure out how many points are going to be in the new element matrix
6784d3d1a6afSToby Isaac      * (we allow double counting, because it's all just going to be summed
6785d3d1a6afSToby Isaac      * into the global matrix anyway) */
6786d3d1a6afSToby Isaac     for (p = 0; p < 2 * numPoints; p += 2) {
6787d3d1a6afSToby Isaac       PetscInt b    = points[p];
67884b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
6789d3d1a6afSToby Isaac 
67909566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
6791ad540459SPierre Jolivet       if (!bSecDof) continue;
679248a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
6793d3d1a6afSToby Isaac       if (bDof) {
6794d3d1a6afSToby Isaac         /* this point is constrained */
6795d3d1a6afSToby Isaac         /* it is going to be replaced by its anchors */
6796d3d1a6afSToby Isaac         PetscInt bOff, q;
6797d3d1a6afSToby Isaac 
6798d3d1a6afSToby Isaac         anyConstrained = PETSC_TRUE;
6799d3d1a6afSToby Isaac         newNumPoints += bDof;
68009566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
6801d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
6802d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q];
6803d3d1a6afSToby Isaac           PetscInt aDof;
6804d3d1a6afSToby Isaac 
68059566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section, a, &aDof));
6806d3d1a6afSToby Isaac           newNumIndices += aDof;
6807d3d1a6afSToby Isaac           for (f = 0; f < numFields; ++f) {
6808d3d1a6afSToby Isaac             PetscInt fDof;
6809d3d1a6afSToby Isaac 
68109566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, a, f, &fDof));
6811d3d1a6afSToby Isaac             newOffsets[f + 1] += fDof;
6812d3d1a6afSToby Isaac           }
6813d3d1a6afSToby Isaac         }
68149371c9d4SSatish Balay       } else {
6815d3d1a6afSToby Isaac         /* this point is not constrained */
6816d3d1a6afSToby Isaac         newNumPoints++;
68174b2f2278SToby Isaac         newNumIndices += bSecDof;
6818d3d1a6afSToby Isaac         for (f = 0; f < numFields; ++f) {
6819d3d1a6afSToby Isaac           PetscInt fDof;
6820d3d1a6afSToby Isaac 
68219566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
6822d3d1a6afSToby Isaac           newOffsets[f + 1] += fDof;
6823d3d1a6afSToby Isaac         }
6824d3d1a6afSToby Isaac       }
6825d3d1a6afSToby Isaac     }
6826d3d1a6afSToby Isaac   }
6827d3d1a6afSToby Isaac   if (!anyConstrained) {
682872b80496SMatthew G. Knepley     if (outNumPoints) *outNumPoints = 0;
682972b80496SMatthew G. Knepley     if (outNumIndices) *outNumIndices = 0;
683072b80496SMatthew G. Knepley     if (outPoints) *outPoints = NULL;
683172b80496SMatthew G. Knepley     if (outValues) *outValues = NULL;
68329566063dSJacob Faibussowitsch     if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors));
6833d3d1a6afSToby Isaac     PetscFunctionReturn(0);
6834d3d1a6afSToby Isaac   }
6835d3d1a6afSToby Isaac 
68366ecaa68aSToby Isaac   if (outNumPoints) *outNumPoints = newNumPoints;
68376ecaa68aSToby Isaac   if (outNumIndices) *outNumIndices = newNumIndices;
68386ecaa68aSToby Isaac 
6839f13f9184SToby Isaac   for (f = 0; f < numFields; ++f) newOffsets[f + 1] += newOffsets[f];
6840d3d1a6afSToby Isaac 
68416ecaa68aSToby Isaac   if (!outPoints && !outValues) {
68426ecaa68aSToby Isaac     if (offsets) {
6843ad540459SPierre Jolivet       for (f = 0; f <= numFields; f++) offsets[f] = newOffsets[f];
68446ecaa68aSToby Isaac     }
68459566063dSJacob Faibussowitsch     if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors));
68466ecaa68aSToby Isaac     PetscFunctionReturn(0);
68476ecaa68aSToby Isaac   }
68486ecaa68aSToby Isaac 
68491dca8a05SBarry 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);
6850d3d1a6afSToby Isaac 
68519566063dSJacob Faibussowitsch   PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, NULL));
6852d3d1a6afSToby Isaac 
6853d3d1a6afSToby Isaac   /* workspaces */
6854d3d1a6afSToby Isaac   if (numFields) {
6855d3d1a6afSToby Isaac     for (f = 0; f < numFields; f++) {
68569566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[f]));
68579566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[f]));
6858d3d1a6afSToby Isaac     }
68599371c9d4SSatish Balay   } else {
68609566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[0]));
68619566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, numPoints, MPIU_INT, &newPointOffsets[0]));
6862d3d1a6afSToby Isaac   }
6863d3d1a6afSToby Isaac 
6864d3d1a6afSToby Isaac   /* get workspaces for the point-to-point matrices */
6865d3d1a6afSToby Isaac   if (numFields) {
68664b2f2278SToby Isaac     PetscInt totalOffset, totalMatOffset;
68674b2f2278SToby Isaac 
6868d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
6869d3d1a6afSToby Isaac       PetscInt b    = points[2 * p];
68704b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
6871d3d1a6afSToby Isaac 
68729566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
68734b2f2278SToby Isaac       if (!bSecDof) {
68744b2f2278SToby Isaac         for (f = 0; f < numFields; f++) {
68754b2f2278SToby Isaac           newPointOffsets[f][p + 1] = 0;
68764b2f2278SToby Isaac           pointMatOffsets[f][p + 1] = 0;
68774b2f2278SToby Isaac         }
68784b2f2278SToby Isaac         continue;
68794b2f2278SToby Isaac       }
688048a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
6881d3d1a6afSToby Isaac       if (bDof) {
6882d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
6883d3d1a6afSToby Isaac           PetscInt fDof, q, bOff, allFDof = 0;
6884d3d1a6afSToby Isaac 
68859566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
68869566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
6887d3d1a6afSToby Isaac           for (q = 0; q < bDof; q++) {
6888d3d1a6afSToby Isaac             PetscInt a = anchors[bOff + q];
6889d3d1a6afSToby Isaac             PetscInt aFDof;
6890d3d1a6afSToby Isaac 
68919566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, a, f, &aFDof));
6892d3d1a6afSToby Isaac             allFDof += aFDof;
6893d3d1a6afSToby Isaac           }
6894d3d1a6afSToby Isaac           newPointOffsets[f][p + 1] = allFDof;
6895d3d1a6afSToby Isaac           pointMatOffsets[f][p + 1] = fDof * allFDof;
6896d3d1a6afSToby Isaac         }
68979371c9d4SSatish Balay       } else {
6898d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
6899d3d1a6afSToby Isaac           PetscInt fDof;
6900d3d1a6afSToby Isaac 
69019566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
6902d3d1a6afSToby Isaac           newPointOffsets[f][p + 1] = fDof;
6903d3d1a6afSToby Isaac           pointMatOffsets[f][p + 1] = 0;
6904d3d1a6afSToby Isaac         }
6905d3d1a6afSToby Isaac       }
6906d3d1a6afSToby Isaac     }
69074b2f2278SToby Isaac     for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) {
69084b2f2278SToby Isaac       newPointOffsets[f][0] = totalOffset;
69094b2f2278SToby Isaac       pointMatOffsets[f][0] = totalMatOffset;
6910d3d1a6afSToby Isaac       for (p = 0; p < numPoints; p++) {
6911d3d1a6afSToby Isaac         newPointOffsets[f][p + 1] += newPointOffsets[f][p];
6912d3d1a6afSToby Isaac         pointMatOffsets[f][p + 1] += pointMatOffsets[f][p];
6913d3d1a6afSToby Isaac       }
691419f70fd5SToby Isaac       totalOffset    = newPointOffsets[f][numPoints];
691519f70fd5SToby Isaac       totalMatOffset = pointMatOffsets[f][numPoints];
69169566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm, pointMatOffsets[f][numPoints], MPIU_SCALAR, &pointMat[f]));
6917d3d1a6afSToby Isaac     }
69189371c9d4SSatish Balay   } else {
6919d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
6920d3d1a6afSToby Isaac       PetscInt b    = points[2 * p];
69214b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
6922d3d1a6afSToby Isaac 
69239566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
69244b2f2278SToby Isaac       if (!bSecDof) {
69254b2f2278SToby Isaac         newPointOffsets[0][p + 1] = 0;
69264b2f2278SToby Isaac         pointMatOffsets[0][p + 1] = 0;
69274b2f2278SToby Isaac         continue;
69284b2f2278SToby Isaac       }
692948a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
6930d3d1a6afSToby Isaac       if (bDof) {
69314b2f2278SToby Isaac         PetscInt bOff, q, allDof = 0;
6932d3d1a6afSToby Isaac 
69339566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
6934d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
6935d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aDof;
6936d3d1a6afSToby Isaac 
69379566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section, a, &aDof));
6938d3d1a6afSToby Isaac           allDof += aDof;
6939d3d1a6afSToby Isaac         }
6940d3d1a6afSToby Isaac         newPointOffsets[0][p + 1] = allDof;
69414b2f2278SToby Isaac         pointMatOffsets[0][p + 1] = bSecDof * allDof;
69429371c9d4SSatish Balay       } else {
69434b2f2278SToby Isaac         newPointOffsets[0][p + 1] = bSecDof;
6944d3d1a6afSToby Isaac         pointMatOffsets[0][p + 1] = 0;
6945d3d1a6afSToby Isaac       }
6946d3d1a6afSToby Isaac     }
6947d3d1a6afSToby Isaac     newPointOffsets[0][0] = 0;
6948d3d1a6afSToby Isaac     pointMatOffsets[0][0] = 0;
6949d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
6950d3d1a6afSToby Isaac       newPointOffsets[0][p + 1] += newPointOffsets[0][p];
6951d3d1a6afSToby Isaac       pointMatOffsets[0][p + 1] += pointMatOffsets[0][p];
6952d3d1a6afSToby Isaac     }
69539566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, pointMatOffsets[0][numPoints], MPIU_SCALAR, &pointMat[0]));
6954d3d1a6afSToby Isaac   }
6955d3d1a6afSToby Isaac 
69566ecaa68aSToby Isaac   /* output arrays */
69579566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints));
69586ecaa68aSToby Isaac 
6959d3d1a6afSToby Isaac   /* get the point-to-point matrices; construct newPoints */
69609566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetMaxDof(aSec, &maxAnchor));
69619566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetMaxDof(section, &maxDof));
69629566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxDof, MPIU_INT, &indices));
69639566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxAnchor * maxDof, MPIU_INT, &newIndices));
6964d3d1a6afSToby Isaac   if (numFields) {
6965d3d1a6afSToby Isaac     for (p = 0, newP = 0; p < numPoints; p++) {
6966d3d1a6afSToby Isaac       PetscInt b    = points[2 * p];
6967d3d1a6afSToby Isaac       PetscInt o    = points[2 * p + 1];
69684b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
6969d3d1a6afSToby Isaac 
69709566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
6971ad540459SPierre Jolivet       if (!bSecDof) continue;
697248a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
6973d3d1a6afSToby Isaac       if (bDof) {
6974d3d1a6afSToby Isaac         PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q;
6975d3d1a6afSToby Isaac 
6976d3d1a6afSToby Isaac         fStart[0] = 0;
6977d3d1a6afSToby Isaac         fEnd[0]   = 0;
6978d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
6979d3d1a6afSToby Isaac           PetscInt fDof;
6980d3d1a6afSToby Isaac 
69819566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(cSec, b, f, &fDof));
6982d3d1a6afSToby Isaac           fStart[f + 1] = fStart[f] + fDof;
6983d3d1a6afSToby Isaac           fEnd[f + 1]   = fStart[f + 1];
6984d3d1a6afSToby Isaac         }
69859566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(cSec, b, &bOff));
69869566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices));
6987d3d1a6afSToby Isaac 
6988d3d1a6afSToby Isaac         fAnchorStart[0] = 0;
6989d3d1a6afSToby Isaac         fAnchorEnd[0]   = 0;
6990d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
6991d3d1a6afSToby Isaac           PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p];
6992d3d1a6afSToby Isaac 
6993d3d1a6afSToby Isaac           fAnchorStart[f + 1] = fAnchorStart[f] + fDof;
6994d3d1a6afSToby Isaac           fAnchorEnd[f + 1]   = fAnchorStart[f + 1];
6995d3d1a6afSToby Isaac         }
69969566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
6997d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
6998d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aOff;
6999d3d1a6afSToby Isaac 
7000d3d1a6afSToby 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 */
7001d3d1a6afSToby Isaac           newPoints[2 * (newP + q)]     = a;
7002d3d1a6afSToby Isaac           newPoints[2 * (newP + q) + 1] = 0;
70039566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(section, a, &aOff));
70049566063dSJacob Faibussowitsch           PetscCall(DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices));
7005d3d1a6afSToby Isaac         }
7006d3d1a6afSToby Isaac         newP += bDof;
7007d3d1a6afSToby Isaac 
70086ecaa68aSToby Isaac         if (outValues) {
7009d3d1a6afSToby Isaac           /* get the point-to-point submatrix */
701048a46eb9SPierre Jolivet           for (f = 0; f < numFields; f++) PetscCall(MatGetValues(cMat, fEnd[f] - fStart[f], indices + fStart[f], fAnchorEnd[f] - fAnchorStart[f], newIndices + fAnchorStart[f], pointMat[f] + pointMatOffsets[f][p]));
7011d3d1a6afSToby Isaac         }
70129371c9d4SSatish Balay       } else {
7013d3d1a6afSToby Isaac         newPoints[2 * newP]     = b;
7014d3d1a6afSToby Isaac         newPoints[2 * newP + 1] = o;
7015d3d1a6afSToby Isaac         newP++;
7016d3d1a6afSToby Isaac       }
7017d3d1a6afSToby Isaac     }
7018d3d1a6afSToby Isaac   } else {
7019d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
7020d3d1a6afSToby Isaac       PetscInt b    = points[2 * p];
7021d3d1a6afSToby Isaac       PetscInt o    = points[2 * p + 1];
70224b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7023d3d1a6afSToby Isaac 
70249566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
7025ad540459SPierre Jolivet       if (!bSecDof) continue;
702648a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7027d3d1a6afSToby Isaac       if (bDof) {
7028d3d1a6afSToby Isaac         PetscInt bEnd = 0, bAnchorEnd = 0, bOff;
7029d3d1a6afSToby Isaac 
70309566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(cSec, b, &bOff));
70319566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices));
7032d3d1a6afSToby Isaac 
70339566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7034d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7035d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aOff;
7036d3d1a6afSToby Isaac 
7037d3d1a6afSToby 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 */
7038d3d1a6afSToby Isaac 
7039d3d1a6afSToby Isaac           newPoints[2 * (newP + q)]     = a;
7040d3d1a6afSToby Isaac           newPoints[2 * (newP + q) + 1] = 0;
70419566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(section, a, &aOff));
70429566063dSJacob Faibussowitsch           PetscCall(DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices));
7043d3d1a6afSToby Isaac         }
7044d3d1a6afSToby Isaac         newP += bDof;
7045d3d1a6afSToby Isaac 
7046d3d1a6afSToby Isaac         /* get the point-to-point submatrix */
704748a46eb9SPierre Jolivet         if (outValues) PetscCall(MatGetValues(cMat, bEnd, indices, bAnchorEnd, newIndices, pointMat[0] + pointMatOffsets[0][p]));
70489371c9d4SSatish Balay       } else {
7049d3d1a6afSToby Isaac         newPoints[2 * newP]     = b;
7050d3d1a6afSToby Isaac         newPoints[2 * newP + 1] = o;
7051d3d1a6afSToby Isaac         newP++;
7052d3d1a6afSToby Isaac       }
7053d3d1a6afSToby Isaac     }
7054d3d1a6afSToby Isaac   }
7055d3d1a6afSToby Isaac 
70566ecaa68aSToby Isaac   if (outValues) {
70579566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, newNumIndices * numIndices, MPIU_SCALAR, &tmpValues));
70589566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(tmpValues, newNumIndices * numIndices));
7059d3d1a6afSToby Isaac     /* multiply constraints on the right */
7060d3d1a6afSToby Isaac     if (numFields) {
7061d3d1a6afSToby Isaac       for (f = 0; f < numFields; f++) {
7062d3d1a6afSToby Isaac         PetscInt oldOff = offsets[f];
7063d3d1a6afSToby Isaac 
7064d3d1a6afSToby Isaac         for (p = 0; p < numPoints; p++) {
7065d3d1a6afSToby Isaac           PetscInt cStart = newPointOffsets[f][p];
7066d3d1a6afSToby Isaac           PetscInt b      = points[2 * p];
7067d3d1a6afSToby Isaac           PetscInt c, r, k;
7068d3d1a6afSToby Isaac           PetscInt dof;
7069d3d1a6afSToby Isaac 
70709566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &dof));
7071ad540459SPierre Jolivet           if (!dof) continue;
7072d3d1a6afSToby Isaac           if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) {
7073d3d1a6afSToby Isaac             PetscInt           nCols = newPointOffsets[f][p + 1] - cStart;
7074d3d1a6afSToby Isaac             const PetscScalar *mat   = pointMat[f] + pointMatOffsets[f][p];
7075d3d1a6afSToby Isaac 
7076d3d1a6afSToby Isaac             for (r = 0; r < numIndices; r++) {
7077d3d1a6afSToby Isaac               for (c = 0; c < nCols; c++) {
7078ad540459SPierre Jolivet                 for (k = 0; k < dof; k++) tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c];
7079d3d1a6afSToby Isaac               }
7080d3d1a6afSToby Isaac             }
70819371c9d4SSatish Balay           } else {
7082d3d1a6afSToby Isaac             /* copy this column as is */
7083d3d1a6afSToby Isaac             for (r = 0; r < numIndices; r++) {
7084ad540459SPierre Jolivet               for (c = 0; c < dof; c++) tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c];
7085d3d1a6afSToby Isaac             }
7086d3d1a6afSToby Isaac           }
7087d3d1a6afSToby Isaac           oldOff += dof;
7088d3d1a6afSToby Isaac         }
7089d3d1a6afSToby Isaac       }
70909371c9d4SSatish Balay     } else {
7091d3d1a6afSToby Isaac       PetscInt oldOff = 0;
7092d3d1a6afSToby Isaac       for (p = 0; p < numPoints; p++) {
7093d3d1a6afSToby Isaac         PetscInt cStart = newPointOffsets[0][p];
7094d3d1a6afSToby Isaac         PetscInt b      = points[2 * p];
7095d3d1a6afSToby Isaac         PetscInt c, r, k;
7096d3d1a6afSToby Isaac         PetscInt dof;
7097d3d1a6afSToby Isaac 
70989566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, b, &dof));
7099ad540459SPierre Jolivet         if (!dof) continue;
7100d3d1a6afSToby Isaac         if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) {
7101d3d1a6afSToby Isaac           PetscInt           nCols = newPointOffsets[0][p + 1] - cStart;
7102d3d1a6afSToby Isaac           const PetscScalar *mat   = pointMat[0] + pointMatOffsets[0][p];
7103d3d1a6afSToby Isaac 
7104d3d1a6afSToby Isaac           for (r = 0; r < numIndices; r++) {
7105d3d1a6afSToby Isaac             for (c = 0; c < nCols; c++) {
7106ad540459SPierre Jolivet               for (k = 0; k < dof; k++) tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k];
7107d3d1a6afSToby Isaac             }
7108d3d1a6afSToby Isaac           }
71099371c9d4SSatish Balay         } else {
7110d3d1a6afSToby Isaac           /* copy this column as is */
7111d3d1a6afSToby Isaac           for (r = 0; r < numIndices; r++) {
7112ad540459SPierre Jolivet             for (c = 0; c < dof; c++) tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c];
7113d3d1a6afSToby Isaac           }
7114d3d1a6afSToby Isaac         }
7115d3d1a6afSToby Isaac         oldOff += dof;
7116d3d1a6afSToby Isaac       }
7117d3d1a6afSToby Isaac     }
7118d3d1a6afSToby Isaac 
71196ecaa68aSToby Isaac     if (multiplyLeft) {
71209566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm, newNumIndices * newNumIndices, MPIU_SCALAR, &newValues));
71219566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(newValues, newNumIndices * newNumIndices));
7122d3d1a6afSToby Isaac       /* multiply constraints transpose on the left */
7123d3d1a6afSToby Isaac       if (numFields) {
7124d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7125d3d1a6afSToby Isaac           PetscInt oldOff = offsets[f];
7126d3d1a6afSToby Isaac 
7127d3d1a6afSToby Isaac           for (p = 0; p < numPoints; p++) {
7128d3d1a6afSToby Isaac             PetscInt rStart = newPointOffsets[f][p];
7129d3d1a6afSToby Isaac             PetscInt b      = points[2 * p];
7130d3d1a6afSToby Isaac             PetscInt c, r, k;
7131d3d1a6afSToby Isaac             PetscInt dof;
7132d3d1a6afSToby Isaac 
71339566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, b, f, &dof));
7134d3d1a6afSToby Isaac             if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) {
7135d3d1a6afSToby Isaac               PetscInt                          nRows = newPointOffsets[f][p + 1] - rStart;
7136d3d1a6afSToby Isaac               const PetscScalar *PETSC_RESTRICT mat   = pointMat[f] + pointMatOffsets[f][p];
7137d3d1a6afSToby Isaac 
7138d3d1a6afSToby Isaac               for (r = 0; r < nRows; r++) {
7139d3d1a6afSToby Isaac                 for (c = 0; c < newNumIndices; c++) {
7140ad540459SPierre Jolivet                   for (k = 0; k < dof; k++) newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c];
7141d3d1a6afSToby Isaac                 }
7142d3d1a6afSToby Isaac               }
71439371c9d4SSatish Balay             } else {
7144d3d1a6afSToby Isaac               /* copy this row as is */
7145d3d1a6afSToby Isaac               for (r = 0; r < dof; r++) {
7146ad540459SPierre Jolivet                 for (c = 0; c < newNumIndices; c++) newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c];
7147d3d1a6afSToby Isaac               }
7148d3d1a6afSToby Isaac             }
7149d3d1a6afSToby Isaac             oldOff += dof;
7150d3d1a6afSToby Isaac           }
7151d3d1a6afSToby Isaac         }
71529371c9d4SSatish Balay       } else {
7153d3d1a6afSToby Isaac         PetscInt oldOff = 0;
7154d3d1a6afSToby Isaac 
7155d3d1a6afSToby Isaac         for (p = 0; p < numPoints; p++) {
7156d3d1a6afSToby Isaac           PetscInt rStart = newPointOffsets[0][p];
7157d3d1a6afSToby Isaac           PetscInt b      = points[2 * p];
7158d3d1a6afSToby Isaac           PetscInt c, r, k;
7159d3d1a6afSToby Isaac           PetscInt dof;
7160d3d1a6afSToby Isaac 
71619566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section, b, &dof));
7162d3d1a6afSToby Isaac           if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) {
7163d3d1a6afSToby Isaac             PetscInt                          nRows = newPointOffsets[0][p + 1] - rStart;
7164d3d1a6afSToby Isaac             const PetscScalar *PETSC_RESTRICT mat   = pointMat[0] + pointMatOffsets[0][p];
7165d3d1a6afSToby Isaac 
7166d3d1a6afSToby Isaac             for (r = 0; r < nRows; r++) {
7167d3d1a6afSToby Isaac               for (c = 0; c < newNumIndices; c++) {
7168ad540459SPierre Jolivet                 for (k = 0; k < dof; k++) newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c];
7169d3d1a6afSToby Isaac               }
7170d3d1a6afSToby Isaac             }
71719371c9d4SSatish Balay           } else {
7172d3d1a6afSToby Isaac             /* copy this row as is */
71739fc93327SToby Isaac             for (r = 0; r < dof; r++) {
7174ad540459SPierre Jolivet               for (c = 0; c < newNumIndices; c++) newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c];
7175d3d1a6afSToby Isaac             }
7176d3d1a6afSToby Isaac           }
7177d3d1a6afSToby Isaac           oldOff += dof;
7178d3d1a6afSToby Isaac         }
7179d3d1a6afSToby Isaac       }
7180d3d1a6afSToby Isaac 
71819566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm, newNumIndices * numIndices, MPIU_SCALAR, &tmpValues));
71829371c9d4SSatish Balay     } else {
71836ecaa68aSToby Isaac       newValues = tmpValues;
71846ecaa68aSToby Isaac     }
71856ecaa68aSToby Isaac   }
71866ecaa68aSToby Isaac 
7187d3d1a6afSToby Isaac   /* clean up */
71889566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, maxDof, MPIU_INT, &indices));
71899566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, maxAnchor * maxDof, MPIU_INT, &newIndices));
71906ecaa68aSToby Isaac 
7191d3d1a6afSToby Isaac   if (numFields) {
7192d3d1a6afSToby Isaac     for (f = 0; f < numFields; f++) {
71939566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm, pointMatOffsets[f][numPoints], MPIU_SCALAR, &pointMat[f]));
71949566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[f]));
71959566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[f]));
7196d3d1a6afSToby Isaac     }
71979371c9d4SSatish Balay   } else {
71989566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, pointMatOffsets[0][numPoints], MPIU_SCALAR, &pointMat[0]));
71999566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[0]));
72009566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[0]));
7201d3d1a6afSToby Isaac   }
72029566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(aIS, &anchors));
7203d3d1a6afSToby Isaac 
7204d3d1a6afSToby Isaac   /* output */
72056ecaa68aSToby Isaac   if (outPoints) {
7206d3d1a6afSToby Isaac     *outPoints = newPoints;
72079371c9d4SSatish Balay   } else {
72089566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints));
72096ecaa68aSToby Isaac   }
7210ad540459SPierre Jolivet   if (outValues) *outValues = newValues;
7211ad540459SPierre Jolivet   for (f = 0; f <= numFields; f++) offsets[f] = newOffsets[f];
7212d3d1a6afSToby Isaac   PetscFunctionReturn(0);
7213d3d1a6afSToby Isaac }
7214d3d1a6afSToby Isaac 
72154a1e0b3eSMatthew G. Knepley /*@C
721671f0bbf9SMatthew G. Knepley   DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections.
72177cd05799SMatthew G. Knepley 
72187cd05799SMatthew G. Knepley   Not collective
72197cd05799SMatthew G. Knepley 
72207cd05799SMatthew G. Knepley   Input Parameters:
72217cd05799SMatthew G. Knepley + dm         - The DM
722271f0bbf9SMatthew G. Knepley . section    - The PetscSection describing the points (a local section)
722371f0bbf9SMatthew G. Knepley . idxSection - The PetscSection from which to obtain indices (may be local or global)
722471f0bbf9SMatthew G. Knepley . point      - The point defining the closure
722571f0bbf9SMatthew G. Knepley - useClPerm  - Use the closure point permutation if available
72267cd05799SMatthew G. Knepley 
722771f0bbf9SMatthew G. Knepley   Output Parameters:
722871f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections
722971f0bbf9SMatthew G. Knepley . indices    - The dof indices
723071f0bbf9SMatthew G. Knepley . outOffsets - Array to write the field offsets into, or NULL
723171f0bbf9SMatthew G. Knepley - values     - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL
72327cd05799SMatthew G. Knepley 
723336fa2b79SJed Brown   Notes:
723436fa2b79SJed Brown   Must call DMPlexRestoreClosureIndices() to free allocated memory
723536fa2b79SJed Brown 
723636fa2b79SJed Brown   If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices.  The value
723736fa2b79SJed Brown   of those indices is not significant.  If idxSection is local, the constrained dofs will yield the involution -(idx+1)
723836fa2b79SJed Brown   of their index in a local vector.  A caller who does not wish to distinguish those points may recover the nonnegative
723936fa2b79SJed Brown   indices via involution, -(-(idx+1)+1)==idx.  Local indices are provided when idxSection == section, otherwise global
724036fa2b79SJed Brown   indices (with the above semantics) are implied.
72417cd05799SMatthew G. Knepley 
72427cd05799SMatthew G. Knepley   Level: advanced
72437cd05799SMatthew G. Knepley 
7244db781477SPatrick Sanan .seealso `DMPlexRestoreClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()`
72454a1e0b3eSMatthew G. Knepley @*/
72469371c9d4SSatish Balay PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) {
724771f0bbf9SMatthew G. Knepley   /* Closure ordering */
72487773e69fSMatthew G. Knepley   PetscSection        clSection;
72497773e69fSMatthew G. Knepley   IS                  clPoints;
725071f0bbf9SMatthew G. Knepley   const PetscInt     *clp;
725171f0bbf9SMatthew G. Knepley   PetscInt           *points;
725271f0bbf9SMatthew G. Knepley   const PetscInt     *clperm    = NULL;
725371f0bbf9SMatthew G. Knepley   /* Dof permutation and sign flips */
72544acb8e1eSToby Isaac   const PetscInt    **perms[32] = {NULL};
725571f0bbf9SMatthew G. Knepley   const PetscScalar **flips[32] = {NULL};
725671f0bbf9SMatthew G. Knepley   PetscScalar        *valCopy   = NULL;
725771f0bbf9SMatthew G. Knepley   /* Hanging node constraints */
725871f0bbf9SMatthew G. Knepley   PetscInt           *pointsC   = NULL;
725971f0bbf9SMatthew G. Knepley   PetscScalar        *valuesC   = NULL;
726071f0bbf9SMatthew G. Knepley   PetscInt            NclC, NiC;
726171f0bbf9SMatthew G. Knepley 
726271f0bbf9SMatthew G. Knepley   PetscInt *idx;
726371f0bbf9SMatthew G. Knepley   PetscInt  Nf, Ncl, Ni = 0, offsets[32], p, f;
726471f0bbf9SMatthew G. Knepley   PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE;
72657773e69fSMatthew G. Knepley 
726671f0bbf9SMatthew G. Knepley   PetscFunctionBeginHot;
72677773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
72687773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
726936fa2b79SJed Brown   PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3);
7270dadcf809SJacob Faibussowitsch   if (numIndices) PetscValidIntPointer(numIndices, 6);
727171f0bbf9SMatthew G. Knepley   if (indices) PetscValidPointer(indices, 7);
7272dadcf809SJacob Faibussowitsch   if (outOffsets) PetscValidIntPointer(outOffsets, 8);
727371f0bbf9SMatthew G. Knepley   if (values) PetscValidPointer(values, 9);
72749566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &Nf));
727563a3b9bcSJacob Faibussowitsch   PetscCheck(Nf <= 31, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", Nf);
72769566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(offsets, 32));
727771f0bbf9SMatthew G. Knepley   /* 1) Get points in closure */
72789566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
7279c459fbc1SJed Brown   if (useClPerm) {
7280c459fbc1SJed Brown     PetscInt depth, clsize;
72819566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPointDepth(dm, point, &depth));
7282c459fbc1SJed Brown     for (clsize = 0, p = 0; p < Ncl; p++) {
7283c459fbc1SJed Brown       PetscInt dof;
72849566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, points[2 * p], &dof));
7285c459fbc1SJed Brown       clsize += dof;
7286c459fbc1SJed Brown     }
72879566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm));
7288c459fbc1SJed Brown   }
728971f0bbf9SMatthew G. Knepley   /* 2) Get number of indices on these points and field offsets from section */
729071f0bbf9SMatthew G. Knepley   for (p = 0; p < Ncl * 2; p += 2) {
72917773e69fSMatthew G. Knepley     PetscInt dof, fdof;
72927773e69fSMatthew G. Knepley 
72939566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[p], &dof));
72947773e69fSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
72959566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof));
72967773e69fSMatthew G. Knepley       offsets[f + 1] += fdof;
72977773e69fSMatthew G. Knepley     }
729871f0bbf9SMatthew G. Knepley     Ni += dof;
72997773e69fSMatthew G. Knepley   }
73007773e69fSMatthew G. Knepley   for (f = 1; f < Nf; ++f) offsets[f + 1] += offsets[f];
73011dca8a05SBarry 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);
730271f0bbf9SMatthew G. Knepley   /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */
730371f0bbf9SMatthew G. Knepley   for (f = 0; f < PetscMax(1, Nf); ++f) {
73049566063dSJacob Faibussowitsch     if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
73059566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f]));
730671f0bbf9SMatthew G. Knepley     /* may need to apply sign changes to the element matrix */
730771f0bbf9SMatthew G. Knepley     if (values && flips[f]) {
730871f0bbf9SMatthew G. Knepley       PetscInt foffset = offsets[f];
73096ecaa68aSToby Isaac 
731071f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
731171f0bbf9SMatthew G. Knepley         PetscInt           pnt  = points[2 * p], fdof;
731271f0bbf9SMatthew G. Knepley         const PetscScalar *flip = flips[f] ? flips[f][p] : NULL;
731371f0bbf9SMatthew G. Knepley 
73149566063dSJacob Faibussowitsch         if (!Nf) PetscCall(PetscSectionGetDof(section, pnt, &fdof));
73159566063dSJacob Faibussowitsch         else PetscCall(PetscSectionGetFieldDof(section, pnt, f, &fdof));
731671f0bbf9SMatthew G. Knepley         if (flip) {
731771f0bbf9SMatthew G. Knepley           PetscInt i, j, k;
731871f0bbf9SMatthew G. Knepley 
731971f0bbf9SMatthew G. Knepley           if (!valCopy) {
73209566063dSJacob Faibussowitsch             PetscCall(DMGetWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy));
732171f0bbf9SMatthew G. Knepley             for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j];
732271f0bbf9SMatthew G. Knepley             *values = valCopy;
732371f0bbf9SMatthew G. Knepley           }
732471f0bbf9SMatthew G. Knepley           for (i = 0; i < fdof; ++i) {
732571f0bbf9SMatthew G. Knepley             PetscScalar fval = flip[i];
732671f0bbf9SMatthew G. Knepley 
732771f0bbf9SMatthew G. Knepley             for (k = 0; k < Ni; ++k) {
732871f0bbf9SMatthew G. Knepley               valCopy[Ni * (foffset + i) + k] *= fval;
732971f0bbf9SMatthew G. Knepley               valCopy[Ni * k + (foffset + i)] *= fval;
73306ecaa68aSToby Isaac             }
73316ecaa68aSToby Isaac           }
733271f0bbf9SMatthew G. Knepley         }
733371f0bbf9SMatthew G. Knepley         foffset += fdof;
733471f0bbf9SMatthew G. Knepley       }
733571f0bbf9SMatthew G. Knepley     }
733671f0bbf9SMatthew G. Knepley   }
733771f0bbf9SMatthew G. Knepley   /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */
73389566063dSJacob Faibussowitsch   PetscCall(DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE));
733971f0bbf9SMatthew G. Knepley   if (NclC) {
73409566063dSJacob Faibussowitsch     if (valCopy) PetscCall(DMRestoreWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy));
734171f0bbf9SMatthew G. Knepley     for (f = 0; f < PetscMax(1, Nf); ++f) {
73429566063dSJacob Faibussowitsch       if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
73439566063dSJacob Faibussowitsch       else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]));
734471f0bbf9SMatthew G. Knepley     }
734571f0bbf9SMatthew G. Knepley     for (f = 0; f < PetscMax(1, Nf); ++f) {
73469566063dSJacob Faibussowitsch       if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f]));
73479566063dSJacob Faibussowitsch       else PetscCall(PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f]));
734871f0bbf9SMatthew G. Knepley     }
73499566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
735071f0bbf9SMatthew G. Knepley     Ncl    = NclC;
735171f0bbf9SMatthew G. Knepley     Ni     = NiC;
735271f0bbf9SMatthew G. Knepley     points = pointsC;
735371f0bbf9SMatthew G. Knepley     if (values) *values = valuesC;
735471f0bbf9SMatthew G. Knepley   }
735571f0bbf9SMatthew G. Knepley   /* 5) Calculate indices */
73569566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, Ni, MPIU_INT, &idx));
735771f0bbf9SMatthew G. Knepley   if (Nf) {
735871f0bbf9SMatthew G. Knepley     PetscInt  idxOff;
735971f0bbf9SMatthew G. Knepley     PetscBool useFieldOffsets;
736071f0bbf9SMatthew G. Knepley 
73619371c9d4SSatish Balay     if (outOffsets) {
73629371c9d4SSatish Balay       for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f];
73639371c9d4SSatish Balay     }
73649566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets));
736571f0bbf9SMatthew G. Knepley     if (useFieldOffsets) {
736671f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
736771f0bbf9SMatthew G. Knepley         const PetscInt pnt = points[p * 2];
736871f0bbf9SMatthew G. Knepley 
73699566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx));
73707773e69fSMatthew G. Knepley       }
73717773e69fSMatthew G. Knepley     } else {
737271f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
737371f0bbf9SMatthew G. Knepley         const PetscInt pnt = points[p * 2];
737471f0bbf9SMatthew G. Knepley 
73759566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff));
737671f0bbf9SMatthew G. Knepley         /* Note that we pass a local section even though we're using global offsets.  This is because global sections do
737771f0bbf9SMatthew G. Knepley          * not (at the time of this writing) have fields set. They probably should, in which case we would pass the
737871f0bbf9SMatthew G. Knepley          * global section. */
73799566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx));
738071f0bbf9SMatthew G. Knepley       }
738171f0bbf9SMatthew G. Knepley     }
738271f0bbf9SMatthew G. Knepley   } else {
738371f0bbf9SMatthew G. Knepley     PetscInt off = 0, idxOff;
738471f0bbf9SMatthew G. Knepley 
738571f0bbf9SMatthew G. Knepley     for (p = 0; p < Ncl; ++p) {
738671f0bbf9SMatthew G. Knepley       const PetscInt  pnt  = points[p * 2];
73874acb8e1eSToby Isaac       const PetscInt *perm = perms[0] ? perms[0][p] : NULL;
73884acb8e1eSToby Isaac 
73899566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff));
739071f0bbf9SMatthew G. Knepley       /* Note that we pass a local section even though we're using global offsets.  This is because global sections do
739171f0bbf9SMatthew G. Knepley        * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */
73929566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx));
73937773e69fSMatthew G. Knepley     }
73947773e69fSMatthew G. Knepley   }
739571f0bbf9SMatthew G. Knepley   /* 6) Cleanup */
739671f0bbf9SMatthew G. Knepley   for (f = 0; f < PetscMax(1, Nf); ++f) {
73979566063dSJacob Faibussowitsch     if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
73989566063dSJacob Faibussowitsch     else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]));
73994acb8e1eSToby Isaac   }
740071f0bbf9SMatthew G. Knepley   if (NclC) {
74019566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, NclC * 2, MPIU_INT, &pointsC));
74027773e69fSMatthew G. Knepley   } else {
74039566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
74047773e69fSMatthew G. Knepley   }
740571f0bbf9SMatthew G. Knepley 
740671f0bbf9SMatthew G. Knepley   if (numIndices) *numIndices = Ni;
740771f0bbf9SMatthew G. Knepley   if (indices) *indices = idx;
74087773e69fSMatthew G. Knepley   PetscFunctionReturn(0);
74097773e69fSMatthew G. Knepley }
74107773e69fSMatthew G. Knepley 
74117cd05799SMatthew G. Knepley /*@C
741271f0bbf9SMatthew G. Knepley   DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections.
74137cd05799SMatthew G. Knepley 
74147cd05799SMatthew G. Knepley   Not collective
74157cd05799SMatthew G. Knepley 
74167cd05799SMatthew G. Knepley   Input Parameters:
74177cd05799SMatthew G. Knepley + dm         - The DM
741871f0bbf9SMatthew G. Knepley . section    - The PetscSection describing the points (a local section)
741971f0bbf9SMatthew G. Knepley . idxSection - The PetscSection from which to obtain indices (may be local or global)
742071f0bbf9SMatthew G. Knepley . point      - The point defining the closure
742171f0bbf9SMatthew G. Knepley - useClPerm  - Use the closure point permutation if available
742271f0bbf9SMatthew G. Knepley 
742371f0bbf9SMatthew G. Knepley   Output Parameters:
742471f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections
742571f0bbf9SMatthew G. Knepley . indices    - The dof indices
742671f0bbf9SMatthew G. Knepley . outOffsets - Array to write the field offsets into, or NULL
742771f0bbf9SMatthew G. Knepley - values     - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL
742871f0bbf9SMatthew G. Knepley 
742971f0bbf9SMatthew G. Knepley   Notes:
743071f0bbf9SMatthew G. Knepley   If values were modified, the user is responsible for calling DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values).
743171f0bbf9SMatthew G. Knepley 
743271f0bbf9SMatthew G. Knepley   If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices.  The value
743371f0bbf9SMatthew G. Knepley   of those indices is not significant.  If idxSection is local, the constrained dofs will yield the involution -(idx+1)
743471f0bbf9SMatthew G. Knepley   of their index in a local vector.  A caller who does not wish to distinguish those points may recover the nonnegative
743571f0bbf9SMatthew G. Knepley   indices via involution, -(-(idx+1)+1)==idx.  Local indices are provided when idxSection == section, otherwise global
743671f0bbf9SMatthew G. Knepley   indices (with the above semantics) are implied.
74377cd05799SMatthew G. Knepley 
74387cd05799SMatthew G. Knepley   Level: advanced
74397cd05799SMatthew G. Knepley 
7440db781477SPatrick Sanan .seealso `DMPlexGetClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()`
74417cd05799SMatthew G. Knepley @*/
74429371c9d4SSatish Balay PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[]) {
74437773e69fSMatthew G. Knepley   PetscFunctionBegin;
74447773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7445064a246eSJacob Faibussowitsch   PetscValidPointer(indices, 7);
74469566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, indices));
74477773e69fSMatthew G. Knepley   PetscFunctionReturn(0);
74487773e69fSMatthew G. Knepley }
74497773e69fSMatthew G. Knepley 
74507f5d1fdeSMatthew G. Knepley /*@C
74517f5d1fdeSMatthew G. Knepley   DMPlexMatSetClosure - Set an array of the values on the closure of 'point'
74527f5d1fdeSMatthew G. Knepley 
74537f5d1fdeSMatthew G. Knepley   Not collective
74547f5d1fdeSMatthew G. Knepley 
74557f5d1fdeSMatthew G. Knepley   Input Parameters:
74567f5d1fdeSMatthew G. Knepley + dm - The DM
7457ebd6d717SJed Brown . section - The section describing the layout in v, or NULL to use the default section
7458ebd6d717SJed Brown . globalSection - The section describing the layout in v, or NULL to use the default global section
74597f5d1fdeSMatthew G. Knepley . A - The matrix
7460eaf898f9SPatrick Sanan . point - The point in the DM
74617f5d1fdeSMatthew G. Knepley . values - The array of values
74627f5d1fdeSMatthew G. Knepley - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions
74637f5d1fdeSMatthew G. Knepley 
74647f5d1fdeSMatthew G. Knepley   Fortran Notes:
74657f5d1fdeSMatthew G. Knepley   This routine is only available in Fortran 90, and you must include petsc.h90 in your code.
74667f5d1fdeSMatthew G. Knepley 
74677f5d1fdeSMatthew G. Knepley   Level: intermediate
74687f5d1fdeSMatthew G. Knepley 
7469db781477SPatrick Sanan .seealso `DMPlexMatSetClosureGeneral()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`
74707f5d1fdeSMatthew G. Knepley @*/
74719371c9d4SSatish Balay PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) {
7472552f7358SJed Brown   DM_Plex           *mesh = (DM_Plex *)dm->data;
7473552f7358SJed Brown   PetscInt          *indices;
747471f0bbf9SMatthew G. Knepley   PetscInt           numIndices;
747571f0bbf9SMatthew G. Knepley   const PetscScalar *valuesOrig = values;
7476552f7358SJed Brown   PetscErrorCode     ierr;
7477552f7358SJed Brown 
7478552f7358SJed Brown   PetscFunctionBegin;
7479552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
74809566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
74813dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
74829566063dSJacob Faibussowitsch   if (!globalSection) PetscCall(DMGetGlobalSection(dm, &globalSection));
74833dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3);
74843dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 4);
7485552f7358SJed Brown 
74869566063dSJacob Faibussowitsch   PetscCall(DMPlexGetClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values));
74870d644c17SKarl Rupp 
74889566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values));
7489d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
74904a1e0b3eSMatthew G. Knepley   ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode);
7491552f7358SJed Brown   if (ierr) {
7492552f7358SJed Brown     PetscMPIInt rank;
7493552f7358SJed Brown 
74949566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
74959566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
74969566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values));
74979566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values));
74989566063dSJacob Faibussowitsch     if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values));
7499c3e24edfSBarry Smith     SETERRQ(PetscObjectComm((PetscObject)dm), ierr, "Not possible to set matrix values");
7500552f7358SJed Brown   }
75014a1e0b3eSMatthew G. Knepley   if (mesh->printFEM > 1) {
75024a1e0b3eSMatthew G. Knepley     PetscInt i;
75039566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "  Indices:"));
750463a3b9bcSJacob Faibussowitsch     for (i = 0; i < numIndices; ++i) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, indices[i]));
75059566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
75064a1e0b3eSMatthew G. Knepley   }
750771f0bbf9SMatthew G. Knepley 
75089566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values));
75099566063dSJacob Faibussowitsch   if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values));
751071f0bbf9SMatthew G. Knepley   PetscFunctionReturn(0);
75114acb8e1eSToby Isaac }
751271f0bbf9SMatthew G. Knepley 
75134a1e0b3eSMatthew G. Knepley /*@C
75144a1e0b3eSMatthew G. Knepley   DMPlexMatSetClosure - Set an array of the values on the closure of 'point' using a different row and column section
75154a1e0b3eSMatthew G. Knepley 
75164a1e0b3eSMatthew G. Knepley   Not collective
75174a1e0b3eSMatthew G. Knepley 
75184a1e0b3eSMatthew G. Knepley   Input Parameters:
75194a1e0b3eSMatthew G. Knepley + dmRow - The DM for the row fields
75204a1e0b3eSMatthew G. Knepley . sectionRow - The section describing the layout, or NULL to use the default section in dmRow
75214a1e0b3eSMatthew G. Knepley . globalSectionRow - The section describing the layout, or NULL to use the default global section in dmRow
75224a1e0b3eSMatthew G. Knepley . dmCol - The DM for the column fields
75234a1e0b3eSMatthew G. Knepley . sectionCol - The section describing the layout, or NULL to use the default section in dmCol
75244a1e0b3eSMatthew G. Knepley . globalSectionCol - The section describing the layout, or NULL to use the default global section in dmCol
75254a1e0b3eSMatthew G. Knepley . A - The matrix
75264a1e0b3eSMatthew G. Knepley . point - The point in the DMs
75274a1e0b3eSMatthew G. Knepley . values - The array of values
75284a1e0b3eSMatthew G. Knepley - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions
75294a1e0b3eSMatthew G. Knepley 
75304a1e0b3eSMatthew G. Knepley   Level: intermediate
75314a1e0b3eSMatthew G. Knepley 
7532db781477SPatrick Sanan .seealso `DMPlexMatSetClosure()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`
75334a1e0b3eSMatthew G. Knepley @*/
75349371c9d4SSatish Balay PetscErrorCode DMPlexMatSetClosureGeneral(DM dmRow, PetscSection sectionRow, PetscSection globalSectionRow, DM dmCol, PetscSection sectionCol, PetscSection globalSectionCol, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) {
753571f0bbf9SMatthew G. Knepley   DM_Plex           *mesh = (DM_Plex *)dmRow->data;
753671f0bbf9SMatthew G. Knepley   PetscInt          *indicesRow, *indicesCol;
753771f0bbf9SMatthew G. Knepley   PetscInt           numIndicesRow, numIndicesCol;
753871f0bbf9SMatthew G. Knepley   const PetscScalar *valuesOrig = values;
753971f0bbf9SMatthew G. Knepley   PetscErrorCode     ierr;
754071f0bbf9SMatthew G. Knepley 
754171f0bbf9SMatthew G. Knepley   PetscFunctionBegin;
754271f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1);
75439566063dSJacob Faibussowitsch   if (!sectionRow) PetscCall(DMGetLocalSection(dmRow, &sectionRow));
754471f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2);
75459566063dSJacob Faibussowitsch   if (!globalSectionRow) PetscCall(DMGetGlobalSection(dmRow, &globalSectionRow));
754671f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3);
754771f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(dmCol, DM_CLASSID, 4);
75489566063dSJacob Faibussowitsch   if (!sectionCol) PetscCall(DMGetLocalSection(dmCol, &sectionCol));
754971f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 5);
75509566063dSJacob Faibussowitsch   if (!globalSectionCol) PetscCall(DMGetGlobalSection(dmCol, &globalSectionCol));
755171f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 6);
755271f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 7);
755371f0bbf9SMatthew G. Knepley 
75549566063dSJacob Faibussowitsch   PetscCall(DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values));
75559566063dSJacob Faibussowitsch   PetscCall(DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&values));
755671f0bbf9SMatthew G. Knepley 
75579566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values));
7558d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
75594a1e0b3eSMatthew G. Knepley   ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode);
756071f0bbf9SMatthew G. Knepley   if (ierr) {
756171f0bbf9SMatthew G. Knepley     PetscMPIInt rank;
756271f0bbf9SMatthew G. Knepley 
75639566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
75649566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
75659566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values));
75669566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values));
75679566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **)&values));
75689566063dSJacob Faibussowitsch     if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values));
7569d3d1a6afSToby Isaac   }
757071f0bbf9SMatthew G. Knepley 
75719566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values));
75729566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&values));
75739566063dSJacob Faibussowitsch   if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values));
7574552f7358SJed Brown   PetscFunctionReturn(0);
7575552f7358SJed Brown }
7576552f7358SJed Brown 
75779371c9d4SSatish Balay PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) {
7578de41b84cSMatthew G. Knepley   DM_Plex        *mesh    = (DM_Plex *)dmf->data;
7579de41b84cSMatthew G. Knepley   PetscInt       *fpoints = NULL, *ftotpoints = NULL;
7580de41b84cSMatthew G. Knepley   PetscInt       *cpoints = NULL;
7581de41b84cSMatthew G. Knepley   PetscInt       *findices, *cindices;
758217c0192bSMatthew G. Knepley   const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */
7583de41b84cSMatthew G. Knepley   PetscInt        foffsets[32], coffsets[32];
7584412e9a14SMatthew G. Knepley   DMPolytopeType  ct;
75854ca5e9f5SMatthew G. Knepley   PetscInt        numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f;
7586de41b84cSMatthew G. Knepley   PetscErrorCode  ierr;
7587de41b84cSMatthew G. Knepley 
7588de41b84cSMatthew G. Knepley   PetscFunctionBegin;
7589de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 1);
7590de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 4);
75919566063dSJacob Faibussowitsch   if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection));
7592de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2);
75939566063dSJacob Faibussowitsch   if (!csection) PetscCall(DMGetLocalSection(dmc, &csection));
7594de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5);
75959566063dSJacob Faibussowitsch   if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection));
7596de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3);
75979566063dSJacob Faibussowitsch   if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection));
7598de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6);
7599de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 7);
76009566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(fsection, &numFields));
760163a3b9bcSJacob Faibussowitsch   PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields);
76029566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(foffsets, 32));
76039566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(coffsets, 32));
7604de41b84cSMatthew G. Knepley   /* Column indices */
76059566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
76064ca5e9f5SMatthew G. Knepley   maxFPoints = numCPoints;
7607de41b84cSMatthew G. Knepley   /* Compress out points not in the section */
7608de41b84cSMatthew G. Knepley   /*   TODO: Squeeze out points with 0 dof as well */
76099566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd));
7610de41b84cSMatthew G. Knepley   for (p = 0, q = 0; p < numCPoints * 2; p += 2) {
7611de41b84cSMatthew G. Knepley     if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) {
7612de41b84cSMatthew G. Knepley       cpoints[q * 2]     = cpoints[p];
7613de41b84cSMatthew G. Knepley       cpoints[q * 2 + 1] = cpoints[p + 1];
7614de41b84cSMatthew G. Knepley       ++q;
7615de41b84cSMatthew G. Knepley     }
7616de41b84cSMatthew G. Knepley   }
7617de41b84cSMatthew G. Knepley   numCPoints = q;
7618de41b84cSMatthew G. Knepley   for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) {
7619de41b84cSMatthew G. Knepley     PetscInt fdof;
7620de41b84cSMatthew G. Knepley 
76219566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof));
76224ca5e9f5SMatthew G. Knepley     if (!dof) continue;
7623de41b84cSMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
76249566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof));
7625de41b84cSMatthew G. Knepley       coffsets[f + 1] += fdof;
7626de41b84cSMatthew G. Knepley     }
7627de41b84cSMatthew G. Knepley     numCIndices += dof;
7628de41b84cSMatthew G. Knepley   }
7629de41b84cSMatthew G. Knepley   for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f];
7630de41b84cSMatthew G. Knepley   /* Row indices */
76319566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dmc, point, &ct));
7632412e9a14SMatthew G. Knepley   {
7633012bc364SMatthew G. Knepley     DMPlexTransform tr;
7634012bc364SMatthew G. Knepley     DMPolytopeType *rct;
7635012bc364SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt, Nt;
7636012bc364SMatthew G. Knepley 
76379566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr));
76389566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR));
76399566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt));
7640012bc364SMatthew G. Knepley     numSubcells = rsize[Nt - 1];
76419566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformDestroy(&tr));
7642412e9a14SMatthew G. Knepley   }
76439566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints));
7644de41b84cSMatthew G. Knepley   for (r = 0, q = 0; r < numSubcells; ++r) {
7645de41b84cSMatthew G. Knepley     /* TODO Map from coarse to fine cells */
76469566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints));
7647de41b84cSMatthew G. Knepley     /* Compress out points not in the section */
76489566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd));
7649de41b84cSMatthew G. Knepley     for (p = 0; p < numFPoints * 2; p += 2) {
7650de41b84cSMatthew G. Knepley       if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) {
76519566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof));
76524ca5e9f5SMatthew G. Knepley         if (!dof) continue;
76539371c9d4SSatish Balay         for (s = 0; s < q; ++s)
76549371c9d4SSatish Balay           if (fpoints[p] == ftotpoints[s * 2]) break;
76554ca5e9f5SMatthew G. Knepley         if (s < q) continue;
7656de41b84cSMatthew G. Knepley         ftotpoints[q * 2]     = fpoints[p];
7657de41b84cSMatthew G. Knepley         ftotpoints[q * 2 + 1] = fpoints[p + 1];
7658de41b84cSMatthew G. Knepley         ++q;
7659de41b84cSMatthew G. Knepley       }
7660de41b84cSMatthew G. Knepley     }
76619566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints));
7662de41b84cSMatthew G. Knepley   }
7663de41b84cSMatthew G. Knepley   numFPoints = q;
7664de41b84cSMatthew G. Knepley   for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) {
7665de41b84cSMatthew G. Knepley     PetscInt fdof;
7666de41b84cSMatthew G. Knepley 
76679566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof));
76684ca5e9f5SMatthew G. Knepley     if (!dof) continue;
7669de41b84cSMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
76709566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof));
7671de41b84cSMatthew G. Knepley       foffsets[f + 1] += fdof;
7672de41b84cSMatthew G. Knepley     }
7673de41b84cSMatthew G. Knepley     numFIndices += dof;
7674de41b84cSMatthew G. Knepley   }
7675de41b84cSMatthew G. Knepley   for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f];
7676de41b84cSMatthew G. Knepley 
76771dca8a05SBarry 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);
76781dca8a05SBarry 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);
76799566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices));
76809566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
7681de41b84cSMatthew G. Knepley   if (numFields) {
76824acb8e1eSToby Isaac     const PetscInt **permsF[32] = {NULL};
76834acb8e1eSToby Isaac     const PetscInt **permsC[32] = {NULL};
76844acb8e1eSToby Isaac 
76854acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
76869566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
76879566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
7688de41b84cSMatthew G. Knepley     }
76894acb8e1eSToby Isaac     for (p = 0; p < numFPoints; p++) {
76909566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
76919566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices));
76924acb8e1eSToby Isaac     }
76934acb8e1eSToby Isaac     for (p = 0; p < numCPoints; p++) {
76949566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
76959566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices));
76964acb8e1eSToby Isaac     }
76974acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
76989566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
76999566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
7700de41b84cSMatthew G. Knepley     }
7701de41b84cSMatthew G. Knepley   } else {
77024acb8e1eSToby Isaac     const PetscInt **permsF = NULL;
77034acb8e1eSToby Isaac     const PetscInt **permsC = NULL;
77044acb8e1eSToby Isaac 
77059566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
77069566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL));
77074acb8e1eSToby Isaac     for (p = 0, off = 0; p < numFPoints; p++) {
77084acb8e1eSToby Isaac       const PetscInt *perm = permsF ? permsF[p] : NULL;
77094acb8e1eSToby Isaac 
77109566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
77119566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices));
7712de41b84cSMatthew G. Knepley     }
77134acb8e1eSToby Isaac     for (p = 0, off = 0; p < numCPoints; p++) {
77144acb8e1eSToby Isaac       const PetscInt *perm = permsC ? permsC[p] : NULL;
77154acb8e1eSToby Isaac 
77169566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
77179566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices));
7718de41b84cSMatthew G. Knepley     }
77199566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
77209566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL));
7721de41b84cSMatthew G. Knepley   }
77229566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values));
77234acb8e1eSToby Isaac   /* TODO: flips */
7724d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
7725de41b84cSMatthew G. Knepley   ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode);
7726de41b84cSMatthew G. Knepley   if (ierr) {
7727de41b84cSMatthew G. Knepley     PetscMPIInt rank;
7728de41b84cSMatthew G. Knepley 
77299566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
77309566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
77319566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values));
77329566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices));
77339566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
7734de41b84cSMatthew G. Knepley   }
77359566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints));
77369566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
77379566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices));
77389566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
7739de41b84cSMatthew G. Knepley   PetscFunctionReturn(0);
7740de41b84cSMatthew G. Knepley }
7741de41b84cSMatthew G. Knepley 
77429371c9d4SSatish Balay PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) {
77437c927364SMatthew G. Knepley   PetscInt       *fpoints = NULL, *ftotpoints = NULL;
77447c927364SMatthew G. Knepley   PetscInt       *cpoints = NULL;
77457c927364SMatthew G. Knepley   PetscInt        foffsets[32], coffsets[32];
774617c0192bSMatthew G. Knepley   const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */
7747412e9a14SMatthew G. Knepley   DMPolytopeType  ct;
77487c927364SMatthew G. Knepley   PetscInt        numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f;
77497c927364SMatthew G. Knepley 
77507c927364SMatthew G. Knepley   PetscFunctionBegin;
77517c927364SMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 1);
77527c927364SMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 4);
77539566063dSJacob Faibussowitsch   if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection));
77547c927364SMatthew G. Knepley   PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2);
77559566063dSJacob Faibussowitsch   if (!csection) PetscCall(DMGetLocalSection(dmc, &csection));
77567c927364SMatthew G. Knepley   PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5);
77579566063dSJacob Faibussowitsch   if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection));
77587c927364SMatthew G. Knepley   PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3);
77599566063dSJacob Faibussowitsch   if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection));
77607c927364SMatthew G. Knepley   PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6);
77619566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(fsection, &numFields));
776263a3b9bcSJacob Faibussowitsch   PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields);
77639566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(foffsets, 32));
77649566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(coffsets, 32));
77657c927364SMatthew G. Knepley   /* Column indices */
77669566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
77677c927364SMatthew G. Knepley   maxFPoints = numCPoints;
77687c927364SMatthew G. Knepley   /* Compress out points not in the section */
77697c927364SMatthew G. Knepley   /*   TODO: Squeeze out points with 0 dof as well */
77709566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd));
77717c927364SMatthew G. Knepley   for (p = 0, q = 0; p < numCPoints * 2; p += 2) {
77727c927364SMatthew G. Knepley     if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) {
77737c927364SMatthew G. Knepley       cpoints[q * 2]     = cpoints[p];
77747c927364SMatthew G. Knepley       cpoints[q * 2 + 1] = cpoints[p + 1];
77757c927364SMatthew G. Knepley       ++q;
77767c927364SMatthew G. Knepley     }
77777c927364SMatthew G. Knepley   }
77787c927364SMatthew G. Knepley   numCPoints = q;
77797c927364SMatthew G. Knepley   for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) {
77807c927364SMatthew G. Knepley     PetscInt fdof;
77817c927364SMatthew G. Knepley 
77829566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof));
77837c927364SMatthew G. Knepley     if (!dof) continue;
77847c927364SMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
77859566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof));
77867c927364SMatthew G. Knepley       coffsets[f + 1] += fdof;
77877c927364SMatthew G. Knepley     }
77887c927364SMatthew G. Knepley     numCIndices += dof;
77897c927364SMatthew G. Knepley   }
77907c927364SMatthew G. Knepley   for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f];
77917c927364SMatthew G. Knepley   /* Row indices */
77929566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dmc, point, &ct));
7793412e9a14SMatthew G. Knepley   {
7794012bc364SMatthew G. Knepley     DMPlexTransform tr;
7795012bc364SMatthew G. Knepley     DMPolytopeType *rct;
7796012bc364SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt, Nt;
7797012bc364SMatthew G. Knepley 
77989566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr));
77999566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR));
78009566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt));
7801012bc364SMatthew G. Knepley     numSubcells = rsize[Nt - 1];
78029566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformDestroy(&tr));
7803412e9a14SMatthew G. Knepley   }
78049566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints));
78057c927364SMatthew G. Knepley   for (r = 0, q = 0; r < numSubcells; ++r) {
78067c927364SMatthew G. Knepley     /* TODO Map from coarse to fine cells */
78079566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints));
78087c927364SMatthew G. Knepley     /* Compress out points not in the section */
78099566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd));
78107c927364SMatthew G. Knepley     for (p = 0; p < numFPoints * 2; p += 2) {
78117c927364SMatthew G. Knepley       if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) {
78129566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof));
78137c927364SMatthew G. Knepley         if (!dof) continue;
78149371c9d4SSatish Balay         for (s = 0; s < q; ++s)
78159371c9d4SSatish Balay           if (fpoints[p] == ftotpoints[s * 2]) break;
78167c927364SMatthew G. Knepley         if (s < q) continue;
78177c927364SMatthew G. Knepley         ftotpoints[q * 2]     = fpoints[p];
78187c927364SMatthew G. Knepley         ftotpoints[q * 2 + 1] = fpoints[p + 1];
78197c927364SMatthew G. Knepley         ++q;
78207c927364SMatthew G. Knepley       }
78217c927364SMatthew G. Knepley     }
78229566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints));
78237c927364SMatthew G. Knepley   }
78247c927364SMatthew G. Knepley   numFPoints = q;
78257c927364SMatthew G. Knepley   for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) {
78267c927364SMatthew G. Knepley     PetscInt fdof;
78277c927364SMatthew G. Knepley 
78289566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof));
78297c927364SMatthew G. Knepley     if (!dof) continue;
78307c927364SMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
78319566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof));
78327c927364SMatthew G. Knepley       foffsets[f + 1] += fdof;
78337c927364SMatthew G. Knepley     }
78347c927364SMatthew G. Knepley     numFIndices += dof;
78357c927364SMatthew G. Knepley   }
78367c927364SMatthew G. Knepley   for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f];
78377c927364SMatthew G. Knepley 
78381dca8a05SBarry 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);
78391dca8a05SBarry 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);
78407c927364SMatthew G. Knepley   if (numFields) {
78414acb8e1eSToby Isaac     const PetscInt **permsF[32] = {NULL};
78424acb8e1eSToby Isaac     const PetscInt **permsC[32] = {NULL};
78434acb8e1eSToby Isaac 
78444acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
78459566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
78469566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
78477c927364SMatthew G. Knepley     }
78484acb8e1eSToby Isaac     for (p = 0; p < numFPoints; p++) {
78499566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
78509566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices));
78514acb8e1eSToby Isaac     }
78524acb8e1eSToby Isaac     for (p = 0; p < numCPoints; p++) {
78539566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
78549566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices));
78554acb8e1eSToby Isaac     }
78564acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
78579566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
78589566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
78597c927364SMatthew G. Knepley     }
78607c927364SMatthew G. Knepley   } else {
78614acb8e1eSToby Isaac     const PetscInt **permsF = NULL;
78624acb8e1eSToby Isaac     const PetscInt **permsC = NULL;
78634acb8e1eSToby Isaac 
78649566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
78659566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL));
78664acb8e1eSToby Isaac     for (p = 0, off = 0; p < numFPoints; p++) {
78674acb8e1eSToby Isaac       const PetscInt *perm = permsF ? permsF[p] : NULL;
78684acb8e1eSToby Isaac 
78699566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
78709566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices));
78717c927364SMatthew G. Knepley     }
78724acb8e1eSToby Isaac     for (p = 0, off = 0; p < numCPoints; p++) {
78734acb8e1eSToby Isaac       const PetscInt *perm = permsC ? permsC[p] : NULL;
78744acb8e1eSToby Isaac 
78759566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
78769566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices));
78777c927364SMatthew G. Knepley     }
78789566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
78799566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL));
78807c927364SMatthew G. Knepley   }
78819566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints));
78829566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
78837c927364SMatthew G. Knepley   PetscFunctionReturn(0);
78847c927364SMatthew G. Knepley }
78857c927364SMatthew G. Knepley 
78867cd05799SMatthew G. Knepley /*@C
78877cd05799SMatthew G. Knepley   DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0)
78887cd05799SMatthew G. Knepley 
78897cd05799SMatthew G. Knepley   Input Parameter:
78907cd05799SMatthew G. Knepley . dm   - The DMPlex object
78917cd05799SMatthew G. Knepley 
78927cd05799SMatthew G. Knepley   Output Parameter:
78937cd05799SMatthew G. Knepley . cellHeight - The height of a cell
78947cd05799SMatthew G. Knepley 
78957cd05799SMatthew G. Knepley   Level: developer
78967cd05799SMatthew G. Knepley 
7897db781477SPatrick Sanan .seealso `DMPlexSetVTKCellHeight()`
78987cd05799SMatthew G. Knepley @*/
78999371c9d4SSatish Balay PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) {
7900552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
7901552f7358SJed Brown 
7902552f7358SJed Brown   PetscFunctionBegin;
7903552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7904dadcf809SJacob Faibussowitsch   PetscValidIntPointer(cellHeight, 2);
7905552f7358SJed Brown   *cellHeight = mesh->vtkCellHeight;
7906552f7358SJed Brown   PetscFunctionReturn(0);
7907552f7358SJed Brown }
7908552f7358SJed Brown 
79097cd05799SMatthew G. Knepley /*@C
79107cd05799SMatthew G. Knepley   DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0)
79117cd05799SMatthew G. Knepley 
79127cd05799SMatthew G. Knepley   Input Parameters:
79137cd05799SMatthew G. Knepley + dm   - The DMPlex object
79147cd05799SMatthew G. Knepley - cellHeight - The height of a cell
79157cd05799SMatthew G. Knepley 
79167cd05799SMatthew G. Knepley   Level: developer
79177cd05799SMatthew G. Knepley 
7918db781477SPatrick Sanan .seealso `DMPlexGetVTKCellHeight()`
79197cd05799SMatthew G. Knepley @*/
79209371c9d4SSatish Balay PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) {
7921552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
7922552f7358SJed Brown 
7923552f7358SJed Brown   PetscFunctionBegin;
7924552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7925552f7358SJed Brown   mesh->vtkCellHeight = cellHeight;
7926552f7358SJed Brown   PetscFunctionReturn(0);
7927552f7358SJed Brown }
7928552f7358SJed Brown 
7929e6139122SMatthew G. Knepley /*@
7930e6139122SMatthew G. Knepley   DMPlexGetGhostCellStratum - Get the range of cells which are used to enforce FV boundary conditions
7931e6139122SMatthew G. Knepley 
7932e6139122SMatthew G. Knepley   Input Parameter:
7933e6139122SMatthew G. Knepley . dm - The DMPlex object
7934e6139122SMatthew G. Knepley 
7935e6139122SMatthew G. Knepley   Output Parameters:
79362a9f31c0SMatthew G. Knepley + gcStart - The first ghost cell, or NULL
79372a9f31c0SMatthew G. Knepley - gcEnd   - The upper bound on ghost cells, or NULL
7938e6139122SMatthew G. Knepley 
79392a9f31c0SMatthew G. Knepley   Level: advanced
7940e6139122SMatthew G. Knepley 
7941db781477SPatrick Sanan .seealso `DMPlexConstructGhostCells()`, `DMPlexGetGhostCellStratum()`
7942e6139122SMatthew G. Knepley @*/
79439371c9d4SSatish Balay PetscErrorCode DMPlexGetGhostCellStratum(DM dm, PetscInt *gcStart, PetscInt *gcEnd) {
7944412e9a14SMatthew G. Knepley   DMLabel ctLabel;
7945e6139122SMatthew G. Knepley 
7946e6139122SMatthew G. Knepley   PetscFunctionBegin;
7947e6139122SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
79489566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel));
79499566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_FV_GHOST, gcStart, gcEnd));
7950695799ffSMatthew G. Knepley   // Reset label for fast lookup
7951695799ffSMatthew G. Knepley   PetscCall(DMLabelMakeAllInvalid_Internal(ctLabel));
7952e6139122SMatthew G. Knepley   PetscFunctionReturn(0);
7953e6139122SMatthew G. Knepley }
7954e6139122SMatthew G. Knepley 
79559371c9d4SSatish Balay PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) {
7956552f7358SJed Brown   PetscSection section, globalSection;
7957552f7358SJed Brown   PetscInt    *numbers, p;
7958552f7358SJed Brown 
7959552f7358SJed Brown   PetscFunctionBegin;
7960d7d32a9aSMatthew G. Knepley   if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf, PETSC_TRUE));
79619566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section));
79629566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(section, pStart, pEnd));
796348a46eb9SPierre Jolivet   for (p = pStart; p < pEnd; ++p) PetscCall(PetscSectionSetDof(section, p, 1));
79649566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(section));
79659566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection));
79669566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(pEnd - pStart, &numbers));
7967552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
79689566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(globalSection, p, &numbers[p - pStart]));
7969ef48cebcSMatthew G. Knepley     if (numbers[p - pStart] < 0) numbers[p - pStart] -= shift;
7970ef48cebcSMatthew G. Knepley     else numbers[p - pStart] += shift;
7971552f7358SJed Brown   }
79729566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering));
7973ef48cebcSMatthew G. Knepley   if (globalSize) {
7974ef48cebcSMatthew G. Knepley     PetscLayout layout;
79759566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointLayout(PetscObjectComm((PetscObject)dm), globalSection, &layout));
79769566063dSJacob Faibussowitsch     PetscCall(PetscLayoutGetSize(layout, globalSize));
79779566063dSJacob Faibussowitsch     PetscCall(PetscLayoutDestroy(&layout));
7978ef48cebcSMatthew G. Knepley   }
79799566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&section));
79809566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&globalSection));
7981552f7358SJed Brown   PetscFunctionReturn(0);
7982552f7358SJed Brown }
7983552f7358SJed Brown 
79849371c9d4SSatish Balay PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers) {
7985412e9a14SMatthew G. Knepley   PetscInt cellHeight, cStart, cEnd;
7986552f7358SJed Brown 
7987552f7358SJed Brown   PetscFunctionBegin;
79889566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
79899566063dSJacob Faibussowitsch   if (includeHybrid) PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
79909566063dSJacob Faibussowitsch   else PetscCall(DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd));
79919566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers));
799281ed3555SMatthew G. Knepley   PetscFunctionReturn(0);
7993552f7358SJed Brown }
799481ed3555SMatthew G. Knepley 
79958dab3259SMatthew G. Knepley /*@
79967cd05799SMatthew G. Knepley   DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process
79977cd05799SMatthew G. Knepley 
79987cd05799SMatthew G. Knepley   Input Parameter:
79997cd05799SMatthew G. Knepley . dm   - The DMPlex object
80007cd05799SMatthew G. Knepley 
80017cd05799SMatthew G. Knepley   Output Parameter:
80027cd05799SMatthew G. Knepley . globalCellNumbers - Global cell numbers for all cells on this process
80037cd05799SMatthew G. Knepley 
80047cd05799SMatthew G. Knepley   Level: developer
80057cd05799SMatthew G. Knepley 
8006db781477SPatrick Sanan .seealso `DMPlexGetVertexNumbering()`
80077cd05799SMatthew G. Knepley @*/
80089371c9d4SSatish Balay PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) {
800981ed3555SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
801081ed3555SMatthew G. Knepley 
801181ed3555SMatthew G. Knepley   PetscFunctionBegin;
801281ed3555SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
80139566063dSJacob Faibussowitsch   if (!mesh->globalCellNumbers) PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers));
8014552f7358SJed Brown   *globalCellNumbers = mesh->globalCellNumbers;
8015552f7358SJed Brown   PetscFunctionReturn(0);
8016552f7358SJed Brown }
8017552f7358SJed Brown 
80189371c9d4SSatish Balay PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers) {
8019412e9a14SMatthew G. Knepley   PetscInt vStart, vEnd;
802081ed3555SMatthew G. Knepley 
802181ed3555SMatthew G. Knepley   PetscFunctionBegin;
802281ed3555SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
80239566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
80249566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers));
802581ed3555SMatthew G. Knepley   PetscFunctionReturn(0);
802681ed3555SMatthew G. Knepley }
802781ed3555SMatthew G. Knepley 
80288dab3259SMatthew G. Knepley /*@
80296aa51ba9SJacob Faibussowitsch   DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process
80307cd05799SMatthew G. Knepley 
80317cd05799SMatthew G. Knepley   Input Parameter:
80327cd05799SMatthew G. Knepley . dm   - The DMPlex object
80337cd05799SMatthew G. Knepley 
80347cd05799SMatthew G. Knepley   Output Parameter:
80357cd05799SMatthew G. Knepley . globalVertexNumbers - Global vertex numbers for all vertices on this process
80367cd05799SMatthew G. Knepley 
80377cd05799SMatthew G. Knepley   Level: developer
80387cd05799SMatthew G. Knepley 
8039db781477SPatrick Sanan .seealso `DMPlexGetCellNumbering()`
80407cd05799SMatthew G. Knepley @*/
80419371c9d4SSatish Balay PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) {
8042552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
8043552f7358SJed Brown 
8044552f7358SJed Brown   PetscFunctionBegin;
8045552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
80469566063dSJacob Faibussowitsch   if (!mesh->globalVertexNumbers) PetscCall(DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers));
8047552f7358SJed Brown   *globalVertexNumbers = mesh->globalVertexNumbers;
8048552f7358SJed Brown   PetscFunctionReturn(0);
8049552f7358SJed Brown }
8050552f7358SJed Brown 
80518dab3259SMatthew G. Knepley /*@
8052966484cfSJed Brown   DMPlexCreatePointNumbering - Create a global numbering for all points.
8053966484cfSJed Brown 
8054966484cfSJed Brown   Collective on dm
80557cd05799SMatthew G. Knepley 
80567cd05799SMatthew G. Knepley   Input Parameter:
80577cd05799SMatthew G. Knepley . dm   - The DMPlex object
80587cd05799SMatthew G. Knepley 
80597cd05799SMatthew G. Knepley   Output Parameter:
80607cd05799SMatthew G. Knepley . globalPointNumbers - Global numbers for all points on this process
80617cd05799SMatthew G. Knepley 
8062966484cfSJed Brown   Notes:
8063966484cfSJed Brown 
8064966484cfSJed Brown   The point numbering IS is parallel, with local portion indexed by local points (see `DMGetLocalSection()`). The global
8065966484cfSJed Brown   points are taken as stratified, with each MPI rank owning a contiguous subset of each stratum. In the IS, owned points
8066966484cfSJed Brown   will have their non-negative value while points owned by different ranks will be involuted -(idx+1). As an example,
8067966484cfSJed Brown   consider a parallel mesh in which the first two elements and first two vertices are owned by rank 0.
8068966484cfSJed Brown 
8069966484cfSJed Brown   The partitioned mesh is
8070966484cfSJed Brown ```
8071966484cfSJed Brown  (2)--0--(3)--1--(4)    (1)--0--(2)
8072966484cfSJed Brown ```
8073966484cfSJed Brown   and its global numbering is
8074966484cfSJed Brown ```
8075966484cfSJed Brown   (3)--0--(4)--1--(5)--2--(6)
8076966484cfSJed Brown ```
8077966484cfSJed Brown   Then the global numbering is provided as
8078966484cfSJed Brown ```
8079966484cfSJed Brown [0] Number of indices in set 5
8080966484cfSJed Brown [0] 0 0
8081966484cfSJed Brown [0] 1 1
8082966484cfSJed Brown [0] 2 3
8083966484cfSJed Brown [0] 3 4
8084966484cfSJed Brown [0] 4 -6
8085966484cfSJed Brown [1] Number of indices in set 3
8086966484cfSJed Brown [1] 0 2
8087966484cfSJed Brown [1] 1 5
8088966484cfSJed Brown [1] 2 6
8089966484cfSJed Brown ```
8090966484cfSJed Brown 
80917cd05799SMatthew G. Knepley   Level: developer
80927cd05799SMatthew G. Knepley 
8093db781477SPatrick Sanan .seealso `DMPlexGetCellNumbering()`
80947cd05799SMatthew G. Knepley @*/
80959371c9d4SSatish Balay PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) {
8096ef48cebcSMatthew G. Knepley   IS        nums[4];
8097862913ffSStefano Zampini   PetscInt  depths[4], gdepths[4], starts[4];
8098ef48cebcSMatthew G. Knepley   PetscInt  depth, d, shift = 0;
80990c15888dSMatthew G. Knepley   PetscBool empty = PETSC_FALSE;
8100ef48cebcSMatthew G. Knepley 
8101ef48cebcSMatthew G. Knepley   PetscFunctionBegin;
8102ef48cebcSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
81039566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
81040c15888dSMatthew G. Knepley   // For unstratified meshes use dim instead of depth
81059566063dSJacob Faibussowitsch   if (depth < 0) PetscCall(DMGetDimension(dm, &depth));
81060c15888dSMatthew G. Knepley   // If any stratum is empty, we must mark all empty
8107862913ffSStefano Zampini   for (d = 0; d <= depth; ++d) {
8108862913ffSStefano Zampini     PetscInt end;
8109862913ffSStefano Zampini 
8110862913ffSStefano Zampini     depths[d] = depth - d;
81119566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end));
81120c15888dSMatthew G. Knepley     if (!(starts[d] - end)) empty = PETSC_TRUE;
8113862913ffSStefano Zampini   }
81140c15888dSMatthew G. Knepley   if (empty)
81150c15888dSMatthew G. Knepley     for (d = 0; d <= depth; ++d) {
81160c15888dSMatthew G. Knepley       depths[d] = -1;
81170c15888dSMatthew G. Knepley       starts[d] = -1;
81180c15888dSMatthew G. Knepley     }
81190c15888dSMatthew G. Knepley   else PetscCall(PetscSortIntWithArray(depth + 1, starts, depths));
81201c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(depths, gdepths, depth + 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
8121ad540459SPierre Jolivet   for (d = 0; d <= depth; ++d) 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]);
81220c15888dSMatthew G. Knepley   // Note here that 'shift' is collective, so that the numbering is stratified by depth
8123ef48cebcSMatthew G. Knepley   for (d = 0; d <= depth; ++d) {
8124ef48cebcSMatthew G. Knepley     PetscInt pStart, pEnd, gsize;
8125ef48cebcSMatthew G. Knepley 
81269566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd));
81279566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]));
8128ef48cebcSMatthew G. Knepley     shift += gsize;
8129ef48cebcSMatthew G. Knepley   }
81309566063dSJacob Faibussowitsch   PetscCall(ISConcatenate(PetscObjectComm((PetscObject)dm), depth + 1, nums, globalPointNumbers));
81319566063dSJacob Faibussowitsch   for (d = 0; d <= depth; ++d) PetscCall(ISDestroy(&nums[d]));
8132ef48cebcSMatthew G. Knepley   PetscFunctionReturn(0);
8133ef48cebcSMatthew G. Knepley }
8134ef48cebcSMatthew G. Knepley 
813508a22f4bSMatthew G. Knepley /*@
813608a22f4bSMatthew G. Knepley   DMPlexCreateRankField - Create a cell field whose value is the rank of the owner
813708a22f4bSMatthew G. Knepley 
813808a22f4bSMatthew G. Knepley   Input Parameter:
813908a22f4bSMatthew G. Knepley . dm - The DMPlex object
814008a22f4bSMatthew G. Knepley 
814108a22f4bSMatthew G. Knepley   Output Parameter:
814208a22f4bSMatthew G. Knepley . ranks - The rank field
814308a22f4bSMatthew G. Knepley 
814408a22f4bSMatthew G. Knepley   Options Database Keys:
814508a22f4bSMatthew G. Knepley . -dm_partition_view - Adds the rank field into the DM output from -dm_view using the same viewer
814608a22f4bSMatthew G. Knepley 
814708a22f4bSMatthew G. Knepley   Level: intermediate
814808a22f4bSMatthew G. Knepley 
8149db781477SPatrick Sanan .seealso: `DMView()`
815008a22f4bSMatthew G. Knepley @*/
81519371c9d4SSatish Balay PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks) {
815208a22f4bSMatthew G. Knepley   DM             rdm;
815308a22f4bSMatthew G. Knepley   PetscFE        fe;
815408a22f4bSMatthew G. Knepley   PetscScalar   *r;
815508a22f4bSMatthew G. Knepley   PetscMPIInt    rank;
8156a55f9a55SMatthew G. Knepley   DMPolytopeType ct;
815708a22f4bSMatthew G. Knepley   PetscInt       dim, cStart, cEnd, c;
8158a55f9a55SMatthew G. Knepley   PetscBool      simplex;
815908a22f4bSMatthew G. Knepley 
816008a22f4bSMatthew G. Knepley   PetscFunctionBeginUser;
8161f95ace6aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8162f95ace6aSMatthew G. Knepley   PetscValidPointer(ranks, 2);
81639566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
81649566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &rdm));
81659566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(rdm, &dim));
81669566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd));
81679566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cStart, &ct));
8168a55f9a55SMatthew G. Knepley   simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE;
81699566063dSJacob Faibussowitsch   PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe));
81709566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)fe, "rank"));
81719566063dSJacob Faibussowitsch   PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe));
81729566063dSJacob Faibussowitsch   PetscCall(PetscFEDestroy(&fe));
81739566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(rdm));
81749566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(rdm, ranks));
81759566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*ranks, "partition"));
81769566063dSJacob Faibussowitsch   PetscCall(VecGetArray(*ranks, &r));
817708a22f4bSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
817808a22f4bSMatthew G. Knepley     PetscScalar *lr;
817908a22f4bSMatthew G. Knepley 
81809566063dSJacob Faibussowitsch     PetscCall(DMPlexPointGlobalRef(rdm, c, r, &lr));
818171f09efeSPierre Jolivet     if (lr) *lr = rank;
818208a22f4bSMatthew G. Knepley   }
81839566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(*ranks, &r));
81849566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&rdm));
818508a22f4bSMatthew G. Knepley   PetscFunctionReturn(0);
818608a22f4bSMatthew G. Knepley }
818708a22f4bSMatthew G. Knepley 
8188ca8062c8SMatthew G. Knepley /*@
818918e14f0cSMatthew G. Knepley   DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell
819018e14f0cSMatthew G. Knepley 
819118e14f0cSMatthew G. Knepley   Input Parameters:
819218e14f0cSMatthew G. Knepley + dm    - The DMPlex
819318e14f0cSMatthew G. Knepley - label - The DMLabel
819418e14f0cSMatthew G. Knepley 
819518e14f0cSMatthew G. Knepley   Output Parameter:
819618e14f0cSMatthew G. Knepley . val - The label value field
819718e14f0cSMatthew G. Knepley 
819818e14f0cSMatthew G. Knepley   Options Database Keys:
819918e14f0cSMatthew G. Knepley . -dm_label_view - Adds the label value field into the DM output from -dm_view using the same viewer
820018e14f0cSMatthew G. Knepley 
820118e14f0cSMatthew G. Knepley   Level: intermediate
820218e14f0cSMatthew G. Knepley 
8203db781477SPatrick Sanan .seealso: `DMView()`
820418e14f0cSMatthew G. Knepley @*/
82059371c9d4SSatish Balay PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val) {
820618e14f0cSMatthew G. Knepley   DM           rdm;
820718e14f0cSMatthew G. Knepley   PetscFE      fe;
820818e14f0cSMatthew G. Knepley   PetscScalar *v;
820918e14f0cSMatthew G. Knepley   PetscInt     dim, cStart, cEnd, c;
821018e14f0cSMatthew G. Knepley 
821118e14f0cSMatthew G. Knepley   PetscFunctionBeginUser;
821218e14f0cSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
821318e14f0cSMatthew G. Knepley   PetscValidPointer(label, 2);
821418e14f0cSMatthew G. Knepley   PetscValidPointer(val, 3);
82159566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &rdm));
82169566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(rdm, &dim));
82179566063dSJacob Faibussowitsch   PetscCall(PetscFECreateDefault(PetscObjectComm((PetscObject)rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe));
82189566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)fe, "label_value"));
82199566063dSJacob Faibussowitsch   PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe));
82209566063dSJacob Faibussowitsch   PetscCall(PetscFEDestroy(&fe));
82219566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(rdm));
82229566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd));
82239566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(rdm, val));
82249566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*val, "label_value"));
82259566063dSJacob Faibussowitsch   PetscCall(VecGetArray(*val, &v));
822618e14f0cSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
822718e14f0cSMatthew G. Knepley     PetscScalar *lv;
822818e14f0cSMatthew G. Knepley     PetscInt     cval;
822918e14f0cSMatthew G. Knepley 
82309566063dSJacob Faibussowitsch     PetscCall(DMPlexPointGlobalRef(rdm, c, v, &lv));
82319566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(label, c, &cval));
823218e14f0cSMatthew G. Knepley     *lv = cval;
823318e14f0cSMatthew G. Knepley   }
82349566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(*val, &v));
82359566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&rdm));
823618e14f0cSMatthew G. Knepley   PetscFunctionReturn(0);
823718e14f0cSMatthew G. Knepley }
823818e14f0cSMatthew G. Knepley 
823918e14f0cSMatthew G. Knepley /*@
8240ca8062c8SMatthew G. Knepley   DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric.
8241ca8062c8SMatthew G. Knepley 
824269916449SMatthew G. Knepley   Input Parameter:
824369916449SMatthew G. Knepley . dm - The DMPlex object
8244ca8062c8SMatthew G. Knepley 
824595eb5ee5SVaclav Hapla   Notes:
824695eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
824795eb5ee5SVaclav Hapla 
824895eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
8249ca8062c8SMatthew G. Knepley 
8250ca8062c8SMatthew G. Knepley   Level: developer
8251ca8062c8SMatthew G. Knepley 
8252db781477SPatrick Sanan .seealso: `DMCreate()`, `DMSetFromOptions()`
8253ca8062c8SMatthew G. Knepley @*/
82549371c9d4SSatish Balay PetscErrorCode DMPlexCheckSymmetry(DM dm) {
8255ca8062c8SMatthew G. Knepley   PetscSection    coneSection, supportSection;
8256ca8062c8SMatthew G. Knepley   const PetscInt *cone, *support;
8257ca8062c8SMatthew G. Knepley   PetscInt        coneSize, c, supportSize, s;
825857beb4faSStefano Zampini   PetscInt        pStart, pEnd, p, pp, csize, ssize;
825957beb4faSStefano Zampini   PetscBool       storagecheck = PETSC_TRUE;
8260ca8062c8SMatthew G. Knepley 
8261ca8062c8SMatthew G. Knepley   PetscFunctionBegin;
8262ca8062c8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
82639566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(dm, NULL, "-sym_dm_view"));
82649566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSection(dm, &coneSection));
82659566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSupportSection(dm, &supportSection));
8266ca8062c8SMatthew G. Knepley   /* Check that point p is found in the support of its cone points, and vice versa */
82679566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
8268ca8062c8SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
82699566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
82709566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
8271ca8062c8SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
827242e66dfaSMatthew G. Knepley       PetscBool dup = PETSC_FALSE;
827342e66dfaSMatthew G. Knepley       PetscInt  d;
827442e66dfaSMatthew G. Knepley       for (d = c - 1; d >= 0; --d) {
82759371c9d4SSatish Balay         if (cone[c] == cone[d]) {
82769371c9d4SSatish Balay           dup = PETSC_TRUE;
82779371c9d4SSatish Balay           break;
82789371c9d4SSatish Balay         }
827942e66dfaSMatthew G. Knepley       }
82809566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, cone[c], &supportSize));
82819566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupport(dm, cone[c], &support));
8282ca8062c8SMatthew G. Knepley       for (s = 0; s < supportSize; ++s) {
8283ca8062c8SMatthew G. Knepley         if (support[s] == p) break;
8284ca8062c8SMatthew G. Knepley       }
828542e66dfaSMatthew G. Knepley       if ((s >= supportSize) || (dup && (support[s + 1] != p))) {
828663a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", p));
828748a46eb9SPierre Jolivet         for (s = 0; s < coneSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[s]));
82889566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
828963a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", cone[c]));
829048a46eb9SPierre Jolivet         for (s = 0; s < supportSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[s]));
82919566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
829263a3b9bcSJacob 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]);
8293f7d195e4SLawrence Mitchell         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in support of cone point %" PetscInt_FMT, p, cone[c]);
8294ca8062c8SMatthew G. Knepley       }
829542e66dfaSMatthew G. Knepley     }
82969566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTreeParent(dm, p, &pp, NULL));
82979371c9d4SSatish Balay     if (p != pp) {
82989371c9d4SSatish Balay       storagecheck = PETSC_FALSE;
82999371c9d4SSatish Balay       continue;
83009371c9d4SSatish Balay     }
83019566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
83029566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dm, p, &support));
8303ca8062c8SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
83049566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, support[s], &coneSize));
83059566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, support[s], &cone));
8306ca8062c8SMatthew G. Knepley       for (c = 0; c < coneSize; ++c) {
83079566063dSJacob Faibussowitsch         PetscCall(DMPlexGetTreeParent(dm, cone[c], &pp, NULL));
83089371c9d4SSatish Balay         if (cone[c] != pp) {
83099371c9d4SSatish Balay           c = 0;
83109371c9d4SSatish Balay           break;
83119371c9d4SSatish Balay         }
8312ca8062c8SMatthew G. Knepley         if (cone[c] == p) break;
8313ca8062c8SMatthew G. Knepley       }
8314ca8062c8SMatthew G. Knepley       if (c >= coneSize) {
831563a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", p));
831648a46eb9SPierre Jolivet         for (c = 0; c < supportSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[c]));
83179566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
831863a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", support[s]));
831948a46eb9SPierre Jolivet         for (c = 0; c < coneSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[c]));
83209566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
832163a3b9bcSJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in cone of support point %" PetscInt_FMT, p, support[s]);
8322ca8062c8SMatthew G. Knepley       }
8323ca8062c8SMatthew G. Knepley     }
8324ca8062c8SMatthew G. Knepley   }
832557beb4faSStefano Zampini   if (storagecheck) {
83269566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coneSection, &csize));
83279566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(supportSection, &ssize));
832863a3b9bcSJacob Faibussowitsch     PetscCheck(csize == ssize, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %" PetscInt_FMT " != Total support size %" PetscInt_FMT, csize, ssize);
832957beb4faSStefano Zampini   }
8330ca8062c8SMatthew G. Knepley   PetscFunctionReturn(0);
8331ca8062c8SMatthew G. Knepley }
8332ca8062c8SMatthew G. Knepley 
8333412e9a14SMatthew G. Knepley /*
8334412e9a14SMatthew 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.
8335412e9a14SMatthew G. Knepley */
83369371c9d4SSatish Balay static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit) {
8337412e9a14SMatthew G. Knepley   DMPolytopeType  cct;
8338412e9a14SMatthew G. Knepley   PetscInt        ptpoints[4];
8339412e9a14SMatthew G. Knepley   const PetscInt *cone, *ccone, *ptcone;
8340412e9a14SMatthew G. Knepley   PetscInt        coneSize, cp, cconeSize, ccp, npt = 0, pt;
8341412e9a14SMatthew G. Knepley 
8342412e9a14SMatthew G. Knepley   PetscFunctionBegin;
8343412e9a14SMatthew G. Knepley   *unsplit = 0;
8344412e9a14SMatthew G. Knepley   switch (ct) {
83459371c9d4SSatish Balay   case DM_POLYTOPE_POINT_PRISM_TENSOR: ptpoints[npt++] = c; break;
8346412e9a14SMatthew G. Knepley   case DM_POLYTOPE_SEG_PRISM_TENSOR:
83479566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
83489566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
8349412e9a14SMatthew G. Knepley     for (cp = 0; cp < coneSize; ++cp) {
83509566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, cone[cp], &cct));
8351412e9a14SMatthew G. Knepley       if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp];
8352412e9a14SMatthew G. Knepley     }
8353412e9a14SMatthew G. Knepley     break;
8354412e9a14SMatthew G. Knepley   case DM_POLYTOPE_TRI_PRISM_TENSOR:
8355412e9a14SMatthew G. Knepley   case DM_POLYTOPE_QUAD_PRISM_TENSOR:
83569566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
83579566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
8358412e9a14SMatthew G. Knepley     for (cp = 0; cp < coneSize; ++cp) {
83599566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, cone[cp], &ccone));
83609566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, cone[cp], &cconeSize));
8361412e9a14SMatthew G. Knepley       for (ccp = 0; ccp < cconeSize; ++ccp) {
83629566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, ccone[ccp], &cct));
8363412e9a14SMatthew G. Knepley         if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) {
8364412e9a14SMatthew G. Knepley           PetscInt p;
83659371c9d4SSatish Balay           for (p = 0; p < npt; ++p)
83669371c9d4SSatish Balay             if (ptpoints[p] == ccone[ccp]) break;
8367412e9a14SMatthew G. Knepley           if (p == npt) ptpoints[npt++] = ccone[ccp];
8368412e9a14SMatthew G. Knepley         }
8369412e9a14SMatthew G. Knepley       }
8370412e9a14SMatthew G. Knepley     }
8371412e9a14SMatthew G. Knepley     break;
8372412e9a14SMatthew G. Knepley   default: break;
8373412e9a14SMatthew G. Knepley   }
8374412e9a14SMatthew G. Knepley   for (pt = 0; pt < npt; ++pt) {
83759566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, ptpoints[pt], &ptcone));
8376412e9a14SMatthew G. Knepley     if (ptcone[0] == ptcone[1]) ++(*unsplit);
8377412e9a14SMatthew G. Knepley   }
8378412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
8379412e9a14SMatthew G. Knepley }
8380412e9a14SMatthew G. Knepley 
8381ca8062c8SMatthew G. Knepley /*@
8382ca8062c8SMatthew G. Knepley   DMPlexCheckSkeleton - Check that each cell has the correct number of vertices
8383ca8062c8SMatthew G. Knepley 
8384ca8062c8SMatthew G. Knepley   Input Parameters:
8385ca8062c8SMatthew G. Knepley + dm - The DMPlex object
838658723a97SMatthew G. Knepley - cellHeight - Normally 0
8387ca8062c8SMatthew G. Knepley 
838895eb5ee5SVaclav Hapla   Notes:
838995eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
839025c50c26SVaclav Hapla   Currently applicable only to homogeneous simplex or tensor meshes.
8391ca8062c8SMatthew G. Knepley 
839295eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
839395eb5ee5SVaclav Hapla 
8394ca8062c8SMatthew G. Knepley   Level: developer
8395ca8062c8SMatthew G. Knepley 
8396db781477SPatrick Sanan .seealso: `DMCreate()`, `DMSetFromOptions()`
8397ca8062c8SMatthew G. Knepley @*/
83989371c9d4SSatish Balay PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight) {
8399412e9a14SMatthew G. Knepley   DMPlexInterpolatedFlag interp;
8400412e9a14SMatthew G. Knepley   DMPolytopeType         ct;
8401412e9a14SMatthew G. Knepley   PetscInt               vStart, vEnd, cStart, cEnd, c;
8402ca8062c8SMatthew G. Knepley 
8403ca8062c8SMatthew G. Knepley   PetscFunctionBegin;
8404ca8062c8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
84059566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolated(dm, &interp));
84069566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
84079566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
8408412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
8409412e9a14SMatthew G. Knepley     PetscInt *closure = NULL;
8410412e9a14SMatthew G. Knepley     PetscInt  coneSize, closureSize, cl, Nv = 0;
841158723a97SMatthew G. Knepley 
84129566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
841363a3b9bcSJacob Faibussowitsch     PetscCheck((PetscInt)ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " has no cell type", c);
8414412e9a14SMatthew G. Knepley     if (ct == DM_POLYTOPE_UNKNOWN) continue;
8415412e9a14SMatthew G. Knepley     if (interp == DMPLEX_INTERPOLATED_FULL) {
84169566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
841763a3b9bcSJacob 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));
8418412e9a14SMatthew G. Knepley     }
84199566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
842058723a97SMatthew G. Knepley     for (cl = 0; cl < closureSize * 2; cl += 2) {
842158723a97SMatthew G. Knepley       const PetscInt p = closure[cl];
8422412e9a14SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) ++Nv;
842358723a97SMatthew G. Knepley     }
84249566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
8425412e9a14SMatthew G. Knepley     /* Special Case: Tensor faces with identified vertices */
8426412e9a14SMatthew G. Knepley     if (Nv < DMPolytopeTypeGetNumVertices(ct)) {
8427412e9a14SMatthew G. Knepley       PetscInt unsplit;
842842363296SMatthew G. Knepley 
84299566063dSJacob Faibussowitsch       PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
8430412e9a14SMatthew G. Knepley       if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue;
843142363296SMatthew G. Knepley     }
843263a3b9bcSJacob 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));
843342363296SMatthew G. Knepley   }
8434ca8062c8SMatthew G. Knepley   PetscFunctionReturn(0);
8435ca8062c8SMatthew G. Knepley }
84369bf0dad6SMatthew G. Knepley 
84379bf0dad6SMatthew G. Knepley /*@
84389bf0dad6SMatthew 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
84399bf0dad6SMatthew G. Knepley 
84408f6815adSVaclav Hapla   Collective
8441899ea2b8SJacob Faibussowitsch 
84429bf0dad6SMatthew G. Knepley   Input Parameters:
84439bf0dad6SMatthew G. Knepley + dm - The DMPlex object
84449bf0dad6SMatthew G. Knepley - cellHeight - Normally 0
84459bf0dad6SMatthew G. Knepley 
844645da879fSVaclav Hapla   Notes:
844745da879fSVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
844845da879fSVaclav Hapla   This routine is only relevant for meshes that are fully interpolated across all ranks.
844945da879fSVaclav Hapla   It will error out if a partially interpolated mesh is given on some rank.
845045da879fSVaclav Hapla   It will do nothing for locally uninterpolated mesh (as there is nothing to check).
84519bf0dad6SMatthew G. Knepley 
845295eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
845395eb5ee5SVaclav Hapla 
84549bf0dad6SMatthew G. Knepley   Level: developer
84559bf0dad6SMatthew G. Knepley 
8456db781477SPatrick Sanan .seealso: `DMCreate()`, `DMPlexGetVTKCellHeight()`, `DMSetFromOptions()`
84579bf0dad6SMatthew G. Knepley @*/
84589371c9d4SSatish Balay PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight) {
8459ab91121cSMatthew G. Knepley   PetscInt               dim, depth, vStart, vEnd, cStart, cEnd, c, h;
8460899ea2b8SJacob Faibussowitsch   DMPlexInterpolatedFlag interpEnum;
84619bf0dad6SMatthew G. Knepley 
84629bf0dad6SMatthew G. Knepley   PetscFunctionBegin;
84639bf0dad6SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
84648f6815adSVaclav Hapla   PetscCall(DMPlexIsInterpolatedCollective(dm, &interpEnum));
846545da879fSVaclav Hapla   if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(0);
84668f6815adSVaclav Hapla   if (interpEnum != DMPLEX_INTERPOLATED_FULL) {
84678f6815adSVaclav Hapla     PetscPrintf(PetscObjectComm((PetscObject)dm), "DMPlexCheckFaces() warning: Mesh is only partially interpolated, this is currently not supported");
84688f6815adSVaclav Hapla     PetscFunctionReturn(0);
8469899ea2b8SJacob Faibussowitsch   }
8470899ea2b8SJacob Faibussowitsch 
84719566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
84729566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
84739566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
8474ab91121cSMatthew G. Knepley   for (h = cellHeight; h < PetscMin(depth, dim); ++h) {
84759566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, h, &cStart, &cEnd));
84763554e41dSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
8477412e9a14SMatthew G. Knepley       const PetscInt       *cone, *ornt, *faceSizes, *faces;
8478412e9a14SMatthew G. Knepley       const DMPolytopeType *faceTypes;
8479ba2698f1SMatthew G. Knepley       DMPolytopeType        ct;
8480412e9a14SMatthew G. Knepley       PetscInt              numFaces, coneSize, f;
8481412e9a14SMatthew G. Knepley       PetscInt             *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit;
84829bf0dad6SMatthew G. Knepley 
84839566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, c, &ct));
84849566063dSJacob Faibussowitsch       PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
8485412e9a14SMatthew G. Knepley       if (unsplit) continue;
84869566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
84879566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, c, &cone));
84889566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeOrientation(dm, c, &ornt));
84899566063dSJacob Faibussowitsch       PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
84909bf0dad6SMatthew G. Knepley       for (cl = 0; cl < closureSize * 2; cl += 2) {
84919bf0dad6SMatthew G. Knepley         const PetscInt p = closure[cl];
84929bf0dad6SMatthew G. Knepley         if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p;
84939bf0dad6SMatthew G. Knepley       }
84949566063dSJacob Faibussowitsch       PetscCall(DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces));
849563a3b9bcSJacob 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);
84969bf0dad6SMatthew G. Knepley       for (f = 0; f < numFaces; ++f) {
8497d4961f80SStefano Zampini         DMPolytopeType fct;
84989bf0dad6SMatthew G. Knepley         PetscInt      *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v;
84999bf0dad6SMatthew G. Knepley 
85009566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, cone[f], &fct));
85019566063dSJacob Faibussowitsch         PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure));
85029bf0dad6SMatthew G. Knepley         for (cl = 0; cl < fclosureSize * 2; cl += 2) {
85039bf0dad6SMatthew G. Knepley           const PetscInt p = fclosure[cl];
85049bf0dad6SMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p;
85059bf0dad6SMatthew G. Knepley         }
850663a3b9bcSJacob 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]);
85079bf0dad6SMatthew G. Knepley         for (v = 0; v < fnumCorners; ++v) {
8508b5a892a1SMatthew G. Knepley           if (fclosure[v] != faces[fOff + v]) {
8509b5a892a1SMatthew G. Knepley             PetscInt v1;
8510b5a892a1SMatthew G. Knepley 
85119566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "face closure:"));
851263a3b9bcSJacob Faibussowitsch             for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, fclosure[v1]));
85139566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "\ncell face:"));
851463a3b9bcSJacob Faibussowitsch             for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, faces[fOff + v1]));
85159566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
851663a3b9bcSJacob 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]);
8517b5a892a1SMatthew G. Knepley           }
85189bf0dad6SMatthew G. Knepley         }
85199566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure));
8520412e9a14SMatthew G. Knepley         fOff += faceSizes[f];
85219bf0dad6SMatthew G. Knepley       }
85229566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces));
85239566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
85249bf0dad6SMatthew G. Knepley     }
85253554e41dSMatthew G. Knepley   }
8526552f7358SJed Brown   PetscFunctionReturn(0);
8527552f7358SJed Brown }
85283913d7c8SMatthew G. Knepley 
8529bb6a34a8SMatthew G. Knepley /*@
8530bb6a34a8SMatthew G. Knepley   DMPlexCheckGeometry - Check the geometry of mesh cells
8531bb6a34a8SMatthew G. Knepley 
8532bb6a34a8SMatthew G. Knepley   Input Parameter:
8533bb6a34a8SMatthew G. Knepley . dm - The DMPlex object
8534bb6a34a8SMatthew G. Knepley 
853595eb5ee5SVaclav Hapla   Notes:
853695eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
853795eb5ee5SVaclav Hapla 
853895eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
8539bb6a34a8SMatthew G. Knepley 
8540bb6a34a8SMatthew G. Knepley   Level: developer
8541bb6a34a8SMatthew G. Knepley 
8542db781477SPatrick Sanan .seealso: `DMCreate()`, `DMSetFromOptions()`
8543bb6a34a8SMatthew G. Knepley @*/
85449371c9d4SSatish Balay PetscErrorCode DMPlexCheckGeometry(DM dm) {
8545a2a9e04cSMatthew G. Knepley   Vec       coordinates;
8546bb6a34a8SMatthew G. Knepley   PetscReal detJ, J[9], refVol = 1.0;
8547bb6a34a8SMatthew G. Knepley   PetscReal vol;
854851a74b61SMatthew G. Knepley   PetscInt  dim, depth, dE, d, cStart, cEnd, c;
8549bb6a34a8SMatthew G. Knepley 
8550bb6a34a8SMatthew G. Knepley   PetscFunctionBegin;
85519566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
85529566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dE));
855351a74b61SMatthew G. Knepley   if (dim != dE) PetscFunctionReturn(0);
85549566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
8555bb6a34a8SMatthew G. Knepley   for (d = 0; d < dim; ++d) refVol *= 2.0;
85569566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
8557a2a9e04cSMatthew G. Knepley   /* Make sure local coordinates are created, because that step is collective */
85589566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
8559412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
8560412e9a14SMatthew G. Knepley     DMPolytopeType ct;
8561412e9a14SMatthew G. Knepley     PetscInt       unsplit;
8562412e9a14SMatthew G. Knepley     PetscBool      ignoreZeroVol = PETSC_FALSE;
8563412e9a14SMatthew G. Knepley 
85649566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
8565412e9a14SMatthew G. Knepley     switch (ct) {
8566412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEG_PRISM_TENSOR:
8567412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:
85689371c9d4SSatish Balay     case DM_POLYTOPE_QUAD_PRISM_TENSOR: ignoreZeroVol = PETSC_TRUE; break;
8569412e9a14SMatthew G. Knepley     default: break;
8570412e9a14SMatthew G. Knepley     }
8571412e9a14SMatthew G. Knepley     switch (ct) {
8572412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM:
8573412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:
8574412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
85759371c9d4SSatish Balay     case DM_POLYTOPE_PYRAMID: continue;
8576412e9a14SMatthew G. Knepley     default: break;
8577412e9a14SMatthew G. Knepley     }
85789566063dSJacob Faibussowitsch     PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
8579412e9a14SMatthew G. Knepley     if (unsplit) continue;
85809566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ));
85811dca8a05SBarry 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);
858263a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FEM Volume %g\n", c, (double)(detJ * refVol)));
85836858538eSMatthew G. Knepley     /* This should work with periodicity since DG coordinates should be used */
85846858538eSMatthew G. Knepley     if (depth > 1) {
85859566063dSJacob Faibussowitsch       PetscCall(DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL));
85861dca8a05SBarry 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);
858763a3b9bcSJacob Faibussowitsch       PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FVM Volume %g\n", c, (double)vol));
8588bb6a34a8SMatthew G. Knepley     }
8589bb6a34a8SMatthew G. Knepley   }
8590bb6a34a8SMatthew G. Knepley   PetscFunctionReturn(0);
8591bb6a34a8SMatthew G. Knepley }
8592bb6a34a8SMatthew G. Knepley 
859303da9461SVaclav Hapla /*@
85947726db96SVaclav Hapla   DMPlexCheckPointSF - Check that several necessary conditions are met for the Point SF of this plex.
85957726db96SVaclav Hapla 
85967726db96SVaclav Hapla   Collective
859703da9461SVaclav Hapla 
859803da9461SVaclav Hapla   Input Parameters:
85997726db96SVaclav Hapla + dm - The DMPlex object
8600d7d32a9aSMatthew G. Knepley . pointSF - The Point SF, or NULL for Point SF attached to DM
8601d7d32a9aSMatthew G. Knepley - allowExtraRoots - Flag to allow extra points not present in the DM
860203da9461SVaclav Hapla 
8603e83a0d2dSVaclav Hapla   Notes:
8604e83a0d2dSVaclav Hapla   This is mainly intended for debugging/testing purposes.
860503da9461SVaclav Hapla 
860695eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
860795eb5ee5SVaclav Hapla 
8608d7d32a9aSMatthew G. Knepley   Extra roots can come from priodic cuts, where additional points appear on the boundary
8609d7d32a9aSMatthew G. Knepley 
861003da9461SVaclav Hapla   Level: developer
861103da9461SVaclav Hapla 
8612db781477SPatrick Sanan .seealso: `DMGetPointSF()`, `DMSetFromOptions()`
861303da9461SVaclav Hapla @*/
8614d7d32a9aSMatthew G. Knepley PetscErrorCode DMPlexCheckPointSF(DM dm, PetscSF pointSF, PetscBool allowExtraRoots) {
86157726db96SVaclav Hapla   PetscInt           l, nleaves, nroots, overlap;
86167726db96SVaclav Hapla   const PetscInt    *locals;
86177726db96SVaclav Hapla   const PetscSFNode *remotes;
8618f0cfc026SVaclav Hapla   PetscBool          distributed;
86197726db96SVaclav Hapla   MPI_Comm           comm;
86207726db96SVaclav Hapla   PetscMPIInt        rank;
862103da9461SVaclav Hapla 
862203da9461SVaclav Hapla   PetscFunctionBegin;
862303da9461SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
86247726db96SVaclav Hapla   if (pointSF) PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2);
86257726db96SVaclav Hapla   else pointSF = dm->sf;
86267726db96SVaclav Hapla   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
86277726db96SVaclav Hapla   PetscCheck(pointSF, comm, PETSC_ERR_ARG_WRONGSTATE, "DMPlex must have Point SF attached");
86287726db96SVaclav Hapla   PetscCallMPI(MPI_Comm_rank(comm, &rank));
86297726db96SVaclav Hapla   {
86307726db96SVaclav Hapla     PetscMPIInt mpiFlag;
86317726db96SVaclav Hapla 
86327726db96SVaclav Hapla     PetscCallMPI(MPI_Comm_compare(comm, PetscObjectComm((PetscObject)pointSF), &mpiFlag));
86337726db96SVaclav 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);
86347726db96SVaclav Hapla   }
86357726db96SVaclav Hapla   PetscCall(PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, &remotes));
86369566063dSJacob Faibussowitsch   PetscCall(DMPlexIsDistributed(dm, &distributed));
86377726db96SVaclav Hapla   if (!distributed) {
86387726db96SVaclav 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);
86398918e3e2SVaclav Hapla     PetscFunctionReturn(0);
86408918e3e2SVaclav Hapla   }
86417726db96SVaclav 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);
86427726db96SVaclav Hapla   PetscCall(DMPlexGetOverlap(dm, &overlap));
864303da9461SVaclav Hapla 
86447726db96SVaclav Hapla   /* Check SF graph is compatible with DMPlex chart */
86457726db96SVaclav Hapla   {
86467726db96SVaclav Hapla     PetscInt pStart, pEnd, maxLeaf;
86477726db96SVaclav Hapla 
86487726db96SVaclav Hapla     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
86497726db96SVaclav Hapla     PetscCall(PetscSFGetLeafRange(pointSF, NULL, &maxLeaf));
8650d7d32a9aSMatthew G. Knepley     PetscCheck(allowExtraRoots || pEnd - pStart == nroots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "pEnd - pStart = %" PetscInt_FMT " != nroots = %" PetscInt_FMT, pEnd - pStart, nroots);
86517726db96SVaclav Hapla     PetscCheck(maxLeaf < pEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "maxLeaf = %" PetscInt_FMT " >= pEnd = %" PetscInt_FMT, maxLeaf, pEnd);
86527726db96SVaclav Hapla   }
86537726db96SVaclav Hapla 
86547726db96SVaclav Hapla   /* Check Point SF has no local points referenced */
86557726db96SVaclav Hapla   for (l = 0; l < nleaves; l++) {
86567726db96SVaclav 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);
86577726db96SVaclav Hapla   }
86587726db96SVaclav Hapla 
86597726db96SVaclav Hapla   /* Check there are no cells in interface */
86607726db96SVaclav Hapla   if (!overlap) {
86617726db96SVaclav Hapla     PetscInt cellHeight, cStart, cEnd;
86627726db96SVaclav Hapla 
86639566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
86649566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
8665f5869d18SMatthew G. Knepley     for (l = 0; l < nleaves; ++l) {
86667726db96SVaclav Hapla       const PetscInt point = locals ? locals[l] : l;
8667f5869d18SMatthew G. Knepley 
86687726db96SVaclav Hapla       PetscCheck(point < cStart || point >= cEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %" PetscInt_FMT " which is a cell", point);
86697726db96SVaclav Hapla     }
867003da9461SVaclav Hapla   }
8671ece87651SVaclav Hapla 
86727726db96SVaclav Hapla   /* If some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */
86737726db96SVaclav Hapla   {
86747726db96SVaclav Hapla     const PetscInt *rootdegree;
86757726db96SVaclav Hapla 
86767726db96SVaclav Hapla     PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree));
86777726db96SVaclav Hapla     PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree));
8678f5869d18SMatthew G. Knepley     for (l = 0; l < nleaves; ++l) {
86797726db96SVaclav Hapla       const PetscInt  point = locals ? locals[l] : l;
8680f5869d18SMatthew G. Knepley       const PetscInt *cone;
8681f5869d18SMatthew G. Knepley       PetscInt        coneSize, c, idx;
8682f5869d18SMatthew G. Knepley 
86839566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, point, &coneSize));
86849566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, point, &cone));
8685f5869d18SMatthew G. Knepley       for (c = 0; c < coneSize; ++c) {
8686f5869d18SMatthew G. Knepley         if (!rootdegree[cone[c]]) {
86877726db96SVaclav Hapla           if (locals) {
86889566063dSJacob Faibussowitsch             PetscCall(PetscFindInt(cone[c], nleaves, locals, &idx));
86897726db96SVaclav Hapla           } else {
86907726db96SVaclav Hapla             idx = (cone[c] < nleaves) ? cone[c] : -1;
86917726db96SVaclav Hapla           }
869263a3b9bcSJacob 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]);
8693f5869d18SMatthew G. Knepley         }
8694f5869d18SMatthew G. Knepley       }
8695ece87651SVaclav Hapla     }
86967726db96SVaclav Hapla   }
869703da9461SVaclav Hapla   PetscFunctionReturn(0);
869803da9461SVaclav Hapla }
869903da9461SVaclav Hapla 
87007f9d8d6cSVaclav Hapla /*@
87017f9d8d6cSVaclav Hapla   DMPlexCheck - Perform various checks of Plex sanity
87027f9d8d6cSVaclav Hapla 
87037f9d8d6cSVaclav Hapla   Input Parameter:
87047f9d8d6cSVaclav Hapla . dm - The DMPlex object
87057f9d8d6cSVaclav Hapla 
87067f9d8d6cSVaclav Hapla   Notes:
87077f9d8d6cSVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
87087f9d8d6cSVaclav Hapla 
87097f9d8d6cSVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
87107f9d8d6cSVaclav Hapla 
87117f9d8d6cSVaclav Hapla   Currently does not include DMPlexCheckCellShape().
87127f9d8d6cSVaclav Hapla 
87137f9d8d6cSVaclav Hapla   Level: developer
87147f9d8d6cSVaclav Hapla 
87157f9d8d6cSVaclav Hapla .seealso: DMCreate(), DMSetFromOptions()
87167f9d8d6cSVaclav Hapla @*/
87179371c9d4SSatish Balay PetscErrorCode DMPlexCheck(DM dm) {
87187f9d8d6cSVaclav Hapla   PetscInt cellHeight;
87197f9d8d6cSVaclav Hapla 
8720b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
87217f9d8d6cSVaclav Hapla   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
87229566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckSymmetry(dm));
87239566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckSkeleton(dm, cellHeight));
87249566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckFaces(dm, cellHeight));
87259566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckGeometry(dm));
8726d7d32a9aSMatthew G. Knepley   PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE));
87279566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckInterfaceCones(dm));
8728b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
8729b5a892a1SMatthew G. Knepley }
8730b5a892a1SMatthew G. Knepley 
87319371c9d4SSatish Balay typedef struct cell_stats {
8732068a5610SStefano Zampini   PetscReal min, max, sum, squaresum;
8733068a5610SStefano Zampini   PetscInt  count;
8734068a5610SStefano Zampini } cell_stats_t;
8735068a5610SStefano Zampini 
87369371c9d4SSatish Balay static void MPIAPI cell_stats_reduce(void *a, void *b, int *len, MPI_Datatype *datatype) {
8737068a5610SStefano Zampini   PetscInt i, N = *len;
8738068a5610SStefano Zampini 
8739068a5610SStefano Zampini   for (i = 0; i < N; i++) {
8740068a5610SStefano Zampini     cell_stats_t *A = (cell_stats_t *)a;
8741068a5610SStefano Zampini     cell_stats_t *B = (cell_stats_t *)b;
8742068a5610SStefano Zampini 
8743068a5610SStefano Zampini     B->min = PetscMin(A->min, B->min);
8744068a5610SStefano Zampini     B->max = PetscMax(A->max, B->max);
8745068a5610SStefano Zampini     B->sum += A->sum;
8746068a5610SStefano Zampini     B->squaresum += A->squaresum;
8747068a5610SStefano Zampini     B->count += A->count;
8748068a5610SStefano Zampini   }
8749068a5610SStefano Zampini }
8750068a5610SStefano Zampini 
8751068a5610SStefano Zampini /*@
875243fa8764SMatthew G. Knepley   DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics.
8753068a5610SStefano Zampini 
87548261a58bSMatthew G. Knepley   Collective on dm
87558261a58bSMatthew G. Knepley 
8756068a5610SStefano Zampini   Input Parameters:
8757068a5610SStefano Zampini + dm        - The DMPlex object
875843fa8764SMatthew G. Knepley . output    - If true, statistics will be displayed on stdout
875943fa8764SMatthew G. Knepley - condLimit - Display all cells above this condition number, or PETSC_DETERMINE for no cell output
8760068a5610SStefano Zampini 
876195eb5ee5SVaclav Hapla   Notes:
876295eb5ee5SVaclav Hapla   This is mainly intended for debugging/testing purposes.
876395eb5ee5SVaclav Hapla 
876495eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
8765068a5610SStefano Zampini 
8766068a5610SStefano Zampini   Level: developer
8767068a5610SStefano Zampini 
8768db781477SPatrick Sanan .seealso: `DMSetFromOptions()`, `DMPlexComputeOrthogonalQuality()`
8769068a5610SStefano Zampini @*/
87709371c9d4SSatish Balay PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit) {
8771068a5610SStefano Zampini   DM           dmCoarse;
877243fa8764SMatthew G. Knepley   cell_stats_t stats, globalStats;
877343fa8764SMatthew G. Knepley   MPI_Comm     comm = PetscObjectComm((PetscObject)dm);
877443fa8764SMatthew G. Knepley   PetscReal   *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0;
877543fa8764SMatthew G. Knepley   PetscReal    limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL;
8776412e9a14SMatthew G. Knepley   PetscInt     cdim, cStart, cEnd, c, eStart, eEnd, count = 0;
877743fa8764SMatthew G. Knepley   PetscMPIInt  rank, size;
8778068a5610SStefano Zampini 
8779068a5610SStefano Zampini   PetscFunctionBegin;
8780068a5610SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8781068a5610SStefano Zampini   stats.min = PETSC_MAX_REAL;
8782068a5610SStefano Zampini   stats.max = PETSC_MIN_REAL;
8783068a5610SStefano Zampini   stats.sum = stats.squaresum = 0.;
8784068a5610SStefano Zampini   stats.count                 = 0;
8785068a5610SStefano Zampini 
87869566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
87879566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
87889566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
87899566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ));
87909566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd));
87919566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd));
8792412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; c++) {
8793068a5610SStefano Zampini     PetscInt  i;
8794068a5610SStefano Zampini     PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ;
8795068a5610SStefano Zampini 
87969566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellGeometryAffineFEM(dm, c, NULL, J, invJ, &detJ));
879763a3b9bcSJacob Faibussowitsch     PetscCheck(detJ >= 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " is inverted", c);
879843fa8764SMatthew G. Knepley     for (i = 0; i < PetscSqr(cdim); ++i) {
8799068a5610SStefano Zampini       frobJ += J[i] * J[i];
8800068a5610SStefano Zampini       frobInvJ += invJ[i] * invJ[i];
8801068a5610SStefano Zampini     }
8802068a5610SStefano Zampini     cond2 = frobJ * frobInvJ;
8803068a5610SStefano Zampini     cond  = PetscSqrtReal(cond2);
8804068a5610SStefano Zampini 
8805068a5610SStefano Zampini     stats.min = PetscMin(stats.min, cond);
8806068a5610SStefano Zampini     stats.max = PetscMax(stats.max, cond);
8807068a5610SStefano Zampini     stats.sum += cond;
8808068a5610SStefano Zampini     stats.squaresum += cond2;
8809068a5610SStefano Zampini     stats.count++;
88108261a58bSMatthew G. Knepley     if (output && cond > limit) {
881143fa8764SMatthew G. Knepley       PetscSection coordSection;
881243fa8764SMatthew G. Knepley       Vec          coordsLocal;
881343fa8764SMatthew G. Knepley       PetscScalar *coords = NULL;
881443fa8764SMatthew G. Knepley       PetscInt     Nv, d, clSize, cl, *closure = NULL;
881543fa8764SMatthew G. Knepley 
88169566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal));
88179566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinateSection(dm, &coordSection));
88189566063dSJacob Faibussowitsch       PetscCall(DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords));
881963a3b9bcSJacob Faibussowitsch       PetscCall(PetscSynchronizedPrintf(comm, "[%d] Cell %" PetscInt_FMT " cond %g\n", rank, c, (double)cond));
882043fa8764SMatthew G. Knepley       for (i = 0; i < Nv / cdim; ++i) {
882163a3b9bcSJacob Faibussowitsch         PetscCall(PetscSynchronizedPrintf(comm, "  Vertex %" PetscInt_FMT ": (", i));
882243fa8764SMatthew G. Knepley         for (d = 0; d < cdim; ++d) {
88239566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscSynchronizedPrintf(comm, ", "));
88249566063dSJacob Faibussowitsch           PetscCall(PetscSynchronizedPrintf(comm, "%g", (double)PetscRealPart(coords[i * cdim + d])));
882543fa8764SMatthew G. Knepley         }
88269566063dSJacob Faibussowitsch         PetscCall(PetscSynchronizedPrintf(comm, ")\n"));
882743fa8764SMatthew G. Knepley       }
88289566063dSJacob Faibussowitsch       PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure));
882943fa8764SMatthew G. Knepley       for (cl = 0; cl < clSize * 2; cl += 2) {
883043fa8764SMatthew G. Knepley         const PetscInt edge = closure[cl];
883143fa8764SMatthew G. Knepley 
883243fa8764SMatthew G. Knepley         if ((edge >= eStart) && (edge < eEnd)) {
883343fa8764SMatthew G. Knepley           PetscReal len;
883443fa8764SMatthew G. Knepley 
88359566063dSJacob Faibussowitsch           PetscCall(DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL));
883663a3b9bcSJacob Faibussowitsch           PetscCall(PetscSynchronizedPrintf(comm, "  Edge %" PetscInt_FMT ": length %g\n", edge, (double)len));
883743fa8764SMatthew G. Knepley         }
883843fa8764SMatthew G. Knepley       }
88399566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure));
88409566063dSJacob Faibussowitsch       PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords));
884143fa8764SMatthew G. Knepley     }
8842068a5610SStefano Zampini   }
88439566063dSJacob Faibussowitsch   if (output) PetscCall(PetscSynchronizedFlush(comm, NULL));
8844068a5610SStefano Zampini 
8845068a5610SStefano Zampini   if (size > 1) {
8846068a5610SStefano Zampini     PetscMPIInt  blockLengths[2] = {4, 1};
8847068a5610SStefano Zampini     MPI_Aint     blockOffsets[2] = {offsetof(cell_stats_t, min), offsetof(cell_stats_t, count)};
8848068a5610SStefano Zampini     MPI_Datatype blockTypes[2]   = {MPIU_REAL, MPIU_INT}, statType;
8849068a5610SStefano Zampini     MPI_Op       statReduce;
8850068a5610SStefano Zampini 
88519566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_create_struct(2, blockLengths, blockOffsets, blockTypes, &statType));
88529566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_commit(&statType));
88539566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce));
88549566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&stats, &globalStats, 1, statType, statReduce, 0, comm));
88559566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Op_free(&statReduce));
88569566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_free(&statType));
8857068a5610SStefano Zampini   } else {
88589566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(&globalStats, &stats, 1));
8859068a5610SStefano Zampini   }
8860dd400576SPatrick Sanan   if (rank == 0) {
8861068a5610SStefano Zampini     count = globalStats.count;
8862068a5610SStefano Zampini     min   = globalStats.min;
8863068a5610SStefano Zampini     max   = globalStats.max;
8864068a5610SStefano Zampini     mean  = globalStats.sum / globalStats.count;
8865068a5610SStefano Zampini     stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1), 0)) : 0.0;
8866068a5610SStefano Zampini   }
8867068a5610SStefano Zampini 
886848a46eb9SPierre Jolivet   if (output) 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));
88699566063dSJacob Faibussowitsch   PetscCall(PetscFree2(J, invJ));
8870068a5610SStefano Zampini 
88719566063dSJacob Faibussowitsch   PetscCall(DMGetCoarseDM(dm, &dmCoarse));
8872068a5610SStefano Zampini   if (dmCoarse) {
8873068a5610SStefano Zampini     PetscBool isplex;
8874068a5610SStefano Zampini 
88759566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)dmCoarse, DMPLEX, &isplex));
88761baa6e33SBarry Smith     if (isplex) PetscCall(DMPlexCheckCellShape(dmCoarse, output, condLimit));
8877068a5610SStefano Zampini   }
8878068a5610SStefano Zampini   PetscFunctionReturn(0);
8879068a5610SStefano Zampini }
8880068a5610SStefano Zampini 
8881f108dbd7SJacob Faibussowitsch /*@
8882f108dbd7SJacob Faibussowitsch   DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with
8883f108dbd7SJacob Faibussowitsch   orthogonal quality below given tolerance.
8884f108dbd7SJacob Faibussowitsch 
88856ed19f2fSJacob Faibussowitsch   Collective on dm
8886f108dbd7SJacob Faibussowitsch 
8887f108dbd7SJacob Faibussowitsch   Input Parameters:
8888f108dbd7SJacob Faibussowitsch + dm   - The DMPlex object
8889f108dbd7SJacob Faibussowitsch . fv   - Optional PetscFV object for pre-computed cell/face centroid information
8890f108dbd7SJacob Faibussowitsch - atol - [0, 1] Absolute tolerance for tagging cells.
8891f108dbd7SJacob Faibussowitsch 
8892f108dbd7SJacob Faibussowitsch   Output Parameters:
8893f108dbd7SJacob Faibussowitsch + OrthQual      - Vec containing orthogonal quality per cell
8894f108dbd7SJacob Faibussowitsch - OrthQualLabel - DMLabel tagging cells below atol with DM_ADAPT_REFINE
8895f108dbd7SJacob Faibussowitsch 
8896f108dbd7SJacob Faibussowitsch   Options Database Keys:
8897f108dbd7SJacob Faibussowitsch + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only PETSCVIEWERASCII is
8898f108dbd7SJacob Faibussowitsch supported.
8899f108dbd7SJacob Faibussowitsch - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector.
8900f108dbd7SJacob Faibussowitsch 
8901f108dbd7SJacob Faibussowitsch   Notes:
8902f108dbd7SJacob Faibussowitsch   Orthogonal quality is given by the following formula:
8903f108dbd7SJacob Faibussowitsch 
8904f108dbd7SJacob Faibussowitsch   \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right]
8905f108dbd7SJacob Faibussowitsch 
8906f108dbd7SJacob 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
8907f108dbd7SJacob Faibussowitsch   is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the
8908f108dbd7SJacob Faibussowitsch   current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by
8909f108dbd7SJacob Faibussowitsch   calculating the cosine of the angle between these vectors.
8910f108dbd7SJacob Faibussowitsch 
8911f108dbd7SJacob Faibussowitsch   Orthogonal quality ranges from 1 (best) to 0 (worst).
8912f108dbd7SJacob Faibussowitsch 
8913f108dbd7SJacob Faibussowitsch   This routine is mainly useful for FVM, however is not restricted to only FVM. The PetscFV object is optionally used to check for
8914f108dbd7SJacob Faibussowitsch   pre-computed FVM cell data, but if it is not passed in then this data will be computed.
8915f108dbd7SJacob Faibussowitsch 
8916f108dbd7SJacob Faibussowitsch   Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance.
8917f108dbd7SJacob Faibussowitsch 
8918f108dbd7SJacob Faibussowitsch   Level: intermediate
8919f108dbd7SJacob Faibussowitsch 
8920db781477SPatrick Sanan .seealso: `DMPlexCheckCellShape()`, `DMCreateLabel()`
8921f108dbd7SJacob Faibussowitsch @*/
89229371c9d4SSatish Balay PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel) {
89236ed19f2fSJacob Faibussowitsch   PetscInt               nc, cellHeight, cStart, cEnd, cell, cellIter = 0;
89246ed19f2fSJacob Faibussowitsch   PetscInt              *idx;
89256ed19f2fSJacob Faibussowitsch   PetscScalar           *oqVals;
8926f108dbd7SJacob Faibussowitsch   const PetscScalar     *cellGeomArr, *faceGeomArr;
89276ed19f2fSJacob Faibussowitsch   PetscReal             *ci, *fi, *Ai;
8928f108dbd7SJacob Faibussowitsch   MPI_Comm               comm;
8929f108dbd7SJacob Faibussowitsch   Vec                    cellgeom, facegeom;
8930f108dbd7SJacob Faibussowitsch   DM                     dmFace, dmCell;
8931f108dbd7SJacob Faibussowitsch   IS                     glob;
8932f108dbd7SJacob Faibussowitsch   ISLocalToGlobalMapping ltog;
8933f108dbd7SJacob Faibussowitsch   PetscViewer            vwr;
8934f108dbd7SJacob Faibussowitsch 
8935f108dbd7SJacob Faibussowitsch   PetscFunctionBegin;
8936f108dbd7SJacob Faibussowitsch   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8937ad540459SPierre Jolivet   if (fv) PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2);
8938f108dbd7SJacob Faibussowitsch   PetscValidPointer(OrthQual, 4);
89396bdcaf15SBarry Smith   PetscCheck(atol >= 0.0 && atol <= 1.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g not in [0,1]", (double)atol);
89409566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
89419566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &nc));
894263a3b9bcSJacob Faibussowitsch   PetscCheck(nc >= 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %" PetscInt_FMT ")", nc);
89436ed19f2fSJacob Faibussowitsch   {
89446ed19f2fSJacob Faibussowitsch     DMPlexInterpolatedFlag interpFlag;
89456ed19f2fSJacob Faibussowitsch 
89469566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated(dm, &interpFlag));
8947f108dbd7SJacob Faibussowitsch     if (interpFlag != DMPLEX_INTERPOLATED_FULL) {
8948f108dbd7SJacob Faibussowitsch       PetscMPIInt rank;
8949f108dbd7SJacob Faibussowitsch 
89509566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(comm, &rank));
895198921bdaSJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank);
8952f108dbd7SJacob Faibussowitsch     }
89536ed19f2fSJacob Faibussowitsch   }
8954f108dbd7SJacob Faibussowitsch   if (OrthQualLabel) {
8955f108dbd7SJacob Faibussowitsch     PetscValidPointer(OrthQualLabel, 5);
89569566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(dm, "Orthogonal_Quality"));
89579566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel));
89589371c9d4SSatish Balay   } else {
89599371c9d4SSatish Balay     *OrthQualLabel = NULL;
89609371c9d4SSatish Balay   }
89619566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
89629566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
89639566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob));
89649566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreateIS(glob, &ltog));
89659566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH));
89669566063dSJacob Faibussowitsch   PetscCall(VecCreate(comm, OrthQual));
89679566063dSJacob Faibussowitsch   PetscCall(VecSetType(*OrthQual, VECSTANDARD));
89689566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(*OrthQual, cEnd - cStart, PETSC_DETERMINE));
89699566063dSJacob Faibussowitsch   PetscCall(VecSetLocalToGlobalMapping(*OrthQual, ltog));
89709566063dSJacob Faibussowitsch   PetscCall(VecSetUp(*OrthQual));
89719566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&glob));
89729566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&ltog));
89739566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL));
89749566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(cellgeom, &cellGeomArr));
89759566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(facegeom, &faceGeomArr));
89769566063dSJacob Faibussowitsch   PetscCall(VecGetDM(cellgeom, &dmCell));
89779566063dSJacob Faibussowitsch   PetscCall(VecGetDM(facegeom, &dmFace));
89789566063dSJacob Faibussowitsch   PetscCall(PetscMalloc5(cEnd - cStart, &idx, cEnd - cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai));
89796ed19f2fSJacob Faibussowitsch   for (cell = cStart; cell < cEnd; cellIter++, cell++) {
89806ed19f2fSJacob Faibussowitsch     PetscInt         cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE;
8981f108dbd7SJacob Faibussowitsch     PetscInt         cellarr[2], *adj = NULL;
8982f108dbd7SJacob Faibussowitsch     PetscScalar     *cArr, *fArr;
8983898cd552SSatish Balay     PetscReal        minvalc = 1.0, minvalf = 1.0;
8984f108dbd7SJacob Faibussowitsch     PetscFVCellGeom *cg;
8985f108dbd7SJacob Faibussowitsch 
89866ed19f2fSJacob Faibussowitsch     idx[cellIter] = cell - cStart;
8987f108dbd7SJacob Faibussowitsch     cellarr[0]    = cell;
8988f108dbd7SJacob Faibussowitsch     /* Make indexing into cellGeom easier */
89899566063dSJacob Faibussowitsch     PetscCall(DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg));
89909566063dSJacob Faibussowitsch     PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj));
8991f108dbd7SJacob Faibussowitsch     /* Technically 1 too big, but easier than fiddling with empty adjacency array */
89929566063dSJacob Faibussowitsch     PetscCall(PetscCalloc2(adjSize, &cArr, adjSize, &fArr));
89936ed19f2fSJacob Faibussowitsch     for (cellneigh = 0; cellneigh < adjSize; cellneighiter++, cellneigh++) {
89946ed19f2fSJacob Faibussowitsch       PetscInt         i;
89956ed19f2fSJacob Faibussowitsch       const PetscInt   neigh  = adj[cellneigh];
8996f108dbd7SJacob Faibussowitsch       PetscReal        normci = 0, normfi = 0, normai = 0;
8997f108dbd7SJacob Faibussowitsch       PetscFVCellGeom *cgneigh;
8998f108dbd7SJacob Faibussowitsch       PetscFVFaceGeom *fg;
8999f108dbd7SJacob Faibussowitsch 
9000f108dbd7SJacob Faibussowitsch       /* Don't count ourselves in the neighbor list */
9001f108dbd7SJacob Faibussowitsch       if (neigh == cell) continue;
90029566063dSJacob Faibussowitsch       PetscCall(DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh));
9003f108dbd7SJacob Faibussowitsch       cellarr[1] = neigh;
90046ed19f2fSJacob Faibussowitsch       {
90056ed19f2fSJacob Faibussowitsch         PetscInt        numcovpts;
90066ed19f2fSJacob Faibussowitsch         const PetscInt *covpts;
90076ed19f2fSJacob Faibussowitsch 
90089566063dSJacob Faibussowitsch         PetscCall(DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts));
90099566063dSJacob Faibussowitsch         PetscCall(DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg));
90109566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts));
90116ed19f2fSJacob Faibussowitsch       }
9012f108dbd7SJacob Faibussowitsch 
9013f108dbd7SJacob Faibussowitsch       /* Compute c_i, f_i and their norms */
9014f108dbd7SJacob Faibussowitsch       for (i = 0; i < nc; i++) {
9015f108dbd7SJacob Faibussowitsch         ci[i] = cgneigh->centroid[i] - cg->centroid[i];
9016f108dbd7SJacob Faibussowitsch         fi[i] = fg->centroid[i] - cg->centroid[i];
9017f108dbd7SJacob Faibussowitsch         Ai[i] = fg->normal[i];
9018addd1e01SJunchao Zhang         normci += PetscPowReal(ci[i], 2);
9019addd1e01SJunchao Zhang         normfi += PetscPowReal(fi[i], 2);
9020addd1e01SJunchao Zhang         normai += PetscPowReal(Ai[i], 2);
9021f108dbd7SJacob Faibussowitsch       }
9022addd1e01SJunchao Zhang       normci = PetscSqrtReal(normci);
9023addd1e01SJunchao Zhang       normfi = PetscSqrtReal(normfi);
9024addd1e01SJunchao Zhang       normai = PetscSqrtReal(normai);
9025f108dbd7SJacob Faibussowitsch 
9026f108dbd7SJacob Faibussowitsch       /* Normalize and compute for each face-cell-normal pair */
9027f108dbd7SJacob Faibussowitsch       for (i = 0; i < nc; i++) {
9028f108dbd7SJacob Faibussowitsch         ci[i] = ci[i] / normci;
9029f108dbd7SJacob Faibussowitsch         fi[i] = fi[i] / normfi;
9030f108dbd7SJacob Faibussowitsch         Ai[i] = Ai[i] / normai;
9031f108dbd7SJacob Faibussowitsch         /* PetscAbs because I don't know if normals are guaranteed to point out */
9032f108dbd7SJacob Faibussowitsch         cArr[cellneighiter] += PetscAbs(Ai[i] * ci[i]);
9033f108dbd7SJacob Faibussowitsch         fArr[cellneighiter] += PetscAbs(Ai[i] * fi[i]);
9034f108dbd7SJacob Faibussowitsch       }
9035ad540459SPierre Jolivet       if (PetscRealPart(cArr[cellneighiter]) < minvalc) minvalc = PetscRealPart(cArr[cellneighiter]);
9036ad540459SPierre Jolivet       if (PetscRealPart(fArr[cellneighiter]) < minvalf) minvalf = PetscRealPart(fArr[cellneighiter]);
9037f108dbd7SJacob Faibussowitsch     }
90389566063dSJacob Faibussowitsch     PetscCall(PetscFree(adj));
90399566063dSJacob Faibussowitsch     PetscCall(PetscFree2(cArr, fArr));
9040f108dbd7SJacob Faibussowitsch     /* Defer to cell if they're equal */
90416ed19f2fSJacob Faibussowitsch     oqVals[cellIter] = PetscMin(minvalf, minvalc);
9042f108dbd7SJacob Faibussowitsch     if (OrthQualLabel) {
90439566063dSJacob Faibussowitsch       if (PetscRealPart(oqVals[cellIter]) <= atol) PetscCall(DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE));
9044f108dbd7SJacob Faibussowitsch     }
9045f108dbd7SJacob Faibussowitsch   }
90469566063dSJacob Faibussowitsch   PetscCall(VecSetValuesLocal(*OrthQual, cEnd - cStart, idx, oqVals, INSERT_VALUES));
90479566063dSJacob Faibussowitsch   PetscCall(VecAssemblyBegin(*OrthQual));
90489566063dSJacob Faibussowitsch   PetscCall(VecAssemblyEnd(*OrthQual));
90499566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(cellgeom, &cellGeomArr));
90509566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(facegeom, &faceGeomArr));
90519566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL));
9052f108dbd7SJacob Faibussowitsch   if (OrthQualLabel) {
90539566063dSJacob Faibussowitsch     if (vwr) PetscCall(DMLabelView(*OrthQualLabel, vwr));
9054f108dbd7SJacob Faibussowitsch   }
90559566063dSJacob Faibussowitsch   PetscCall(PetscFree5(idx, oqVals, ci, fi, Ai));
90569566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(&vwr));
90579566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view"));
9058f108dbd7SJacob Faibussowitsch   PetscFunctionReturn(0);
9059f108dbd7SJacob Faibussowitsch }
9060f108dbd7SJacob Faibussowitsch 
90611eb70e55SToby Isaac /* this is here insead of DMGetOutputDM because output DM still has constraints in the local indices that affect
90621eb70e55SToby Isaac  * interpolator construction */
90639371c9d4SSatish Balay static PetscErrorCode DMGetFullDM(DM dm, DM *odm) {
90641eb70e55SToby Isaac   PetscSection section, newSection, gsection;
90651eb70e55SToby Isaac   PetscSF      sf;
90661eb70e55SToby Isaac   PetscBool    hasConstraints, ghasConstraints;
90671eb70e55SToby Isaac 
90681eb70e55SToby Isaac   PetscFunctionBegin;
90691eb70e55SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
90701eb70e55SToby Isaac   PetscValidPointer(odm, 2);
90719566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
90729566063dSJacob Faibussowitsch   PetscCall(PetscSectionHasConstraints(section, &hasConstraints));
90739566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm)));
90741eb70e55SToby Isaac   if (!ghasConstraints) {
90759566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm));
90761eb70e55SToby Isaac     *odm = dm;
90771eb70e55SToby Isaac     PetscFunctionReturn(0);
90781eb70e55SToby Isaac   }
90799566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, odm));
90809566063dSJacob Faibussowitsch   PetscCall(DMCopyFields(dm, *odm));
90819566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(*odm, &newSection));
90829566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(*odm, &sf));
90839566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_FALSE, &gsection));
90849566063dSJacob Faibussowitsch   PetscCall(DMSetGlobalSection(*odm, gsection));
90859566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&gsection));
90861eb70e55SToby Isaac   PetscFunctionReturn(0);
90871eb70e55SToby Isaac }
90881eb70e55SToby Isaac 
90899371c9d4SSatish Balay static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift) {
90901eb70e55SToby Isaac   DM        dmco, dmfo;
90911eb70e55SToby Isaac   Mat       interpo;
90921eb70e55SToby Isaac   Vec       rscale;
90931eb70e55SToby Isaac   Vec       cglobalo, clocal;
90941eb70e55SToby Isaac   Vec       fglobal, fglobalo, flocal;
90951eb70e55SToby Isaac   PetscBool regular;
90961eb70e55SToby Isaac 
90971eb70e55SToby Isaac   PetscFunctionBegin;
90989566063dSJacob Faibussowitsch   PetscCall(DMGetFullDM(dmc, &dmco));
90999566063dSJacob Faibussowitsch   PetscCall(DMGetFullDM(dmf, &dmfo));
91009566063dSJacob Faibussowitsch   PetscCall(DMSetCoarseDM(dmfo, dmco));
91019566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRegularRefinement(dmf, &regular));
91029566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRegularRefinement(dmfo, regular));
91039566063dSJacob Faibussowitsch   PetscCall(DMCreateInterpolation(dmco, dmfo, &interpo, &rscale));
91049566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmco, &cglobalo));
91059566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dmc, &clocal));
91069566063dSJacob Faibussowitsch   PetscCall(VecSet(cglobalo, 0.));
91079566063dSJacob Faibussowitsch   PetscCall(VecSet(clocal, 0.));
91089566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmf, &fglobal));
91099566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmfo, &fglobalo));
91109566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dmf, &flocal));
91119566063dSJacob Faibussowitsch   PetscCall(VecSet(fglobal, 0.));
91129566063dSJacob Faibussowitsch   PetscCall(VecSet(fglobalo, 0.));
91139566063dSJacob Faibussowitsch   PetscCall(VecSet(flocal, 0.));
91149566063dSJacob Faibussowitsch   PetscCall(DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL));
91159566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo));
91169566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo));
91179566063dSJacob Faibussowitsch   PetscCall(MatMult(interpo, cglobalo, fglobalo));
91189566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal));
91199566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal));
91209566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal));
91219566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal));
91221eb70e55SToby Isaac   *shift = fglobal;
91239566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&flocal));
91249566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&fglobalo));
91259566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&clocal));
91269566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&cglobalo));
91279566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&rscale));
91289566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&interpo));
91299566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmfo));
91309566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmco));
91311eb70e55SToby Isaac   PetscFunctionReturn(0);
91321eb70e55SToby Isaac }
91331eb70e55SToby Isaac 
91349371c9d4SSatish Balay PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol) {
91351eb70e55SToby Isaac   PetscObject shifto;
91361eb70e55SToby Isaac   Vec         shift;
91371eb70e55SToby Isaac 
91381eb70e55SToby Isaac   PetscFunctionBegin;
91391eb70e55SToby Isaac   if (!interp) {
91401eb70e55SToby Isaac     Vec rscale;
91411eb70e55SToby Isaac 
91429566063dSJacob Faibussowitsch     PetscCall(DMCreateInterpolation(coarse, fine, &interp, &rscale));
91439566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&rscale));
91441eb70e55SToby Isaac   } else {
91459566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)interp));
91461eb70e55SToby Isaac   }
91479566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto));
91481eb70e55SToby Isaac   if (!shifto) {
91499566063dSJacob Faibussowitsch     PetscCall(DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift));
91509566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject)shift));
91511eb70e55SToby Isaac     shifto = (PetscObject)shift;
91529566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&shift));
91531eb70e55SToby Isaac   }
91541eb70e55SToby Isaac   shift = (Vec)shifto;
91559566063dSJacob Faibussowitsch   PetscCall(MatInterpolate(interp, coarseSol, fineSol));
91569566063dSJacob Faibussowitsch   PetscCall(VecAXPY(fineSol, 1.0, shift));
91579566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&interp));
91581eb70e55SToby Isaac   PetscFunctionReturn(0);
91591eb70e55SToby Isaac }
91601eb70e55SToby Isaac 
9161bceba477SMatthew G. Knepley /* Pointwise interpolation
9162bceba477SMatthew G. Knepley      Just code FEM for now
9163bceba477SMatthew G. Knepley      u^f = I u^c
91644ca5e9f5SMatthew G. Knepley      sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j
91654ca5e9f5SMatthew G. Knepley      u^f_i = sum_j psi^f_i I phi^c_j u^c_j
91664ca5e9f5SMatthew G. Knepley      I_{ij} = psi^f_i phi^c_j
9167bceba477SMatthew G. Knepley */
91689371c9d4SSatish Balay PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) {
9169bceba477SMatthew G. Knepley   PetscSection gsc, gsf;
9170bceba477SMatthew G. Knepley   PetscInt     m, n;
9171a063dac3SMatthew G. Knepley   void        *ctx;
917268132eb9SMatthew G. Knepley   DM           cdm;
9173cf51de39SMatthew G. Knepley   PetscBool    regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE;
9174bceba477SMatthew G. Knepley 
9175bceba477SMatthew G. Knepley   PetscFunctionBegin;
91769566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmFine, &gsf));
91779566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m));
91789566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmCoarse, &gsc));
91799566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n));
918068132eb9SMatthew G. Knepley 
91819566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis));
91829566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), interpolation));
91839566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE));
91849566063dSJacob Faibussowitsch   PetscCall(MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype));
91859566063dSJacob Faibussowitsch   PetscCall(DMGetApplicationContext(dmFine, &ctx));
918668132eb9SMatthew G. Knepley 
91879566063dSJacob Faibussowitsch   PetscCall(DMGetCoarseDM(dmFine, &cdm));
91889566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRegularRefinement(dmFine, &regular));
91899566063dSJacob Faibussowitsch   if (!isRefined || (regular && cdm == dmCoarse)) PetscCall(DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx));
91909566063dSJacob Faibussowitsch   else PetscCall(DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx));
91919566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view"));
91924db47ee9SStefano Zampini   if (scaling) {
91935d1c2e58SMatthew G. Knepley     /* Use naive scaling */
91949566063dSJacob Faibussowitsch     PetscCall(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling));
91954db47ee9SStefano Zampini   }
9196a063dac3SMatthew G. Knepley   PetscFunctionReturn(0);
9197a063dac3SMatthew G. Knepley }
9198bceba477SMatthew G. Knepley 
91999371c9d4SSatish Balay PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) {
92006dbf9973SLawrence Mitchell   VecScatter ctx;
920190748bafSMatthew G. Knepley 
9202a063dac3SMatthew G. Knepley   PetscFunctionBegin;
92039566063dSJacob Faibussowitsch   PetscCall(DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL));
92049566063dSJacob Faibussowitsch   PetscCall(MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat));
92059566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&ctx));
9206bceba477SMatthew G. Knepley   PetscFunctionReturn(0);
9207bceba477SMatthew G. Knepley }
9208bceba477SMatthew G. Knepley 
92099371c9d4SSatish Balay static void g0_identity_private(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]) {
921000635df3SMatthew G. Knepley   const PetscInt Nc = uOff[1] - uOff[0];
921100635df3SMatthew G. Knepley   PetscInt       c;
921200635df3SMatthew G. Knepley   for (c = 0; c < Nc; ++c) g0[c * Nc + c] = 1.0;
92133e9753d6SMatthew G. Knepley }
92143e9753d6SMatthew G. Knepley 
92159371c9d4SSatish Balay PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *mass) {
9216b4937a87SMatthew G. Knepley   DM           dmc;
9217b4937a87SMatthew G. Knepley   PetscDS      ds;
9218b4937a87SMatthew G. Knepley   Vec          ones, locmass;
9219b4937a87SMatthew G. Knepley   IS           cellIS;
9220b4937a87SMatthew G. Knepley   PetscFormKey key;
9221b4937a87SMatthew G. Knepley   PetscInt     depth;
9222b4937a87SMatthew G. Knepley 
9223b4937a87SMatthew G. Knepley   PetscFunctionBegin;
92249566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &dmc));
92259566063dSJacob Faibussowitsch   PetscCall(DMCopyDisc(dm, dmc));
92269566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dmc, &ds));
92279566063dSJacob Faibussowitsch   PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL));
92289566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmc, mass));
92299566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dmc, &ones));
92309566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dmc, &locmass));
92319566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmc, &depth));
92329566063dSJacob Faibussowitsch   PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS));
92339566063dSJacob Faibussowitsch   PetscCall(VecSet(locmass, 0.0));
92349566063dSJacob Faibussowitsch   PetscCall(VecSet(ones, 1.0));
9235b4937a87SMatthew G. Knepley   key.label = NULL;
9236b4937a87SMatthew G. Knepley   key.value = 0;
9237b4937a87SMatthew G. Knepley   key.field = 0;
9238b4937a87SMatthew G. Knepley   key.part  = 0;
92399566063dSJacob Faibussowitsch   PetscCall(DMPlexComputeJacobian_Action_Internal(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL));
92409566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&cellIS));
92419566063dSJacob Faibussowitsch   PetscCall(VecSet(*mass, 0.0));
92429566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmc, locmass, ADD_VALUES, *mass));
92439566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmc, locmass, ADD_VALUES, *mass));
92449566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dmc, &ones));
92459566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dmc, &locmass));
92469566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmc));
9247b4937a87SMatthew G. Knepley   PetscFunctionReturn(0);
9248b4937a87SMatthew G. Knepley }
9249b4937a87SMatthew G. Knepley 
92509371c9d4SSatish Balay PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass) {
9251bd041c0cSMatthew G. Knepley   PetscSection gsc, gsf;
9252bd041c0cSMatthew G. Knepley   PetscInt     m, n;
9253bd041c0cSMatthew G. Knepley   void        *ctx;
9254bd041c0cSMatthew G. Knepley   DM           cdm;
9255bd041c0cSMatthew G. Knepley   PetscBool    regular;
9256bd041c0cSMatthew G. Knepley 
9257bd041c0cSMatthew G. Knepley   PetscFunctionBegin;
92583e9753d6SMatthew G. Knepley   if (dmFine == dmCoarse) {
92593e9753d6SMatthew G. Knepley     DM            dmc;
92603e9753d6SMatthew G. Knepley     PetscDS       ds;
9261b4937a87SMatthew G. Knepley     PetscWeakForm wf;
92623e9753d6SMatthew G. Knepley     Vec           u;
92633e9753d6SMatthew G. Knepley     IS            cellIS;
926406ad1575SMatthew G. Knepley     PetscFormKey  key;
92653e9753d6SMatthew G. Knepley     PetscInt      depth;
92663e9753d6SMatthew G. Knepley 
92679566063dSJacob Faibussowitsch     PetscCall(DMClone(dmFine, &dmc));
92689566063dSJacob Faibussowitsch     PetscCall(DMCopyDisc(dmFine, dmc));
92699566063dSJacob Faibussowitsch     PetscCall(DMGetDS(dmc, &ds));
92709566063dSJacob Faibussowitsch     PetscCall(PetscDSGetWeakForm(ds, &wf));
92719566063dSJacob Faibussowitsch     PetscCall(PetscWeakFormClear(wf));
92729566063dSJacob Faibussowitsch     PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL));
92739566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(dmc, mass));
92748d94ca23SJed Brown     PetscCall(DMGetLocalVector(dmc, &u));
92759566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dmc, &depth));
92769566063dSJacob Faibussowitsch     PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS));
92779566063dSJacob Faibussowitsch     PetscCall(MatZeroEntries(*mass));
92786528b96dSMatthew G. Knepley     key.label = NULL;
92796528b96dSMatthew G. Knepley     key.value = 0;
92806528b96dSMatthew G. Knepley     key.field = 0;
928106ad1575SMatthew G. Knepley     key.part  = 0;
92829566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL));
92839566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&cellIS));
92848d94ca23SJed Brown     PetscCall(DMRestoreLocalVector(dmc, &u));
92859566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&dmc));
92863e9753d6SMatthew G. Knepley   } else {
92879566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dmFine, &gsf));
92889566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m));
92899566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dmCoarse, &gsc));
92909566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n));
9291bd041c0cSMatthew G. Knepley 
92929566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass));
92939566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE));
92949566063dSJacob Faibussowitsch     PetscCall(MatSetType(*mass, dmCoarse->mattype));
92959566063dSJacob Faibussowitsch     PetscCall(DMGetApplicationContext(dmFine, &ctx));
9296bd041c0cSMatthew G. Knepley 
92979566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dmFine, &cdm));
92989566063dSJacob Faibussowitsch     PetscCall(DMPlexGetRegularRefinement(dmFine, &regular));
92999566063dSJacob Faibussowitsch     if (regular && cdm == dmCoarse) PetscCall(DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx));
93009566063dSJacob Faibussowitsch     else PetscCall(DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx));
93013e9753d6SMatthew G. Knepley   }
93029566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view"));
9303bd041c0cSMatthew G. Knepley   PetscFunctionReturn(0);
9304bd041c0cSMatthew G. Knepley }
9305bd041c0cSMatthew G. Knepley 
93060aef6b92SMatthew G. Knepley /*@
93070aef6b92SMatthew G. Knepley   DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh
93080aef6b92SMatthew G. Knepley 
93090aef6b92SMatthew G. Knepley   Input Parameter:
93100aef6b92SMatthew G. Knepley . dm - The DMPlex object
93110aef6b92SMatthew G. Knepley 
93120aef6b92SMatthew G. Knepley   Output Parameter:
93130aef6b92SMatthew G. Knepley . regular - The flag
93140aef6b92SMatthew G. Knepley 
93150aef6b92SMatthew G. Knepley   Level: intermediate
93160aef6b92SMatthew G. Knepley 
9317db781477SPatrick Sanan .seealso: `DMPlexSetRegularRefinement()`
93180aef6b92SMatthew G. Knepley @*/
93199371c9d4SSatish Balay PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) {
93200aef6b92SMatthew G. Knepley   PetscFunctionBegin;
93210aef6b92SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9322dadcf809SJacob Faibussowitsch   PetscValidBoolPointer(regular, 2);
93230aef6b92SMatthew G. Knepley   *regular = ((DM_Plex *)dm->data)->regularRefinement;
93240aef6b92SMatthew G. Knepley   PetscFunctionReturn(0);
93250aef6b92SMatthew G. Knepley }
93260aef6b92SMatthew G. Knepley 
93270aef6b92SMatthew G. Knepley /*@
93280aef6b92SMatthew G. Knepley   DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh
93290aef6b92SMatthew G. Knepley 
93300aef6b92SMatthew G. Knepley   Input Parameters:
93310aef6b92SMatthew G. Knepley + dm - The DMPlex object
93320aef6b92SMatthew G. Knepley - regular - The flag
93330aef6b92SMatthew G. Knepley 
93340aef6b92SMatthew G. Knepley   Level: intermediate
93350aef6b92SMatthew G. Knepley 
9336db781477SPatrick Sanan .seealso: `DMPlexGetRegularRefinement()`
93370aef6b92SMatthew G. Knepley @*/
93389371c9d4SSatish Balay PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) {
93390aef6b92SMatthew G. Knepley   PetscFunctionBegin;
93400aef6b92SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
93410aef6b92SMatthew G. Knepley   ((DM_Plex *)dm->data)->regularRefinement = regular;
93420aef6b92SMatthew G. Knepley   PetscFunctionReturn(0);
93430aef6b92SMatthew G. Knepley }
93440aef6b92SMatthew G. Knepley 
9345f7c74593SToby Isaac /* anchors */
9346a68b90caSToby Isaac /*@
9347f7c74593SToby Isaac   DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints.  Typically, the user will not have to
9348ebdb1bfaSJed Brown   call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetDefaultConstraints().
9349a68b90caSToby Isaac 
9350e228b242SToby Isaac   not collective
9351a68b90caSToby Isaac 
9352f899ff85SJose E. Roman   Input Parameter:
9353a68b90caSToby Isaac . dm - The DMPlex object
9354a68b90caSToby Isaac 
9355a68b90caSToby Isaac   Output Parameters:
9356a68b90caSToby Isaac + anchorSection - If not NULL, set to the section describing which points anchor the constrained points.
9357a68b90caSToby Isaac - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection
9358a68b90caSToby Isaac 
9359a68b90caSToby Isaac   Level: intermediate
9360a68b90caSToby Isaac 
9361db781477SPatrick Sanan .seealso: `DMPlexSetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()`
9362a68b90caSToby Isaac @*/
93639371c9d4SSatish Balay PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) {
9364a68b90caSToby Isaac   DM_Plex *plex = (DM_Plex *)dm->data;
9365a68b90caSToby Isaac 
9366a68b90caSToby Isaac   PetscFunctionBegin;
9367a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
93689566063dSJacob Faibussowitsch   if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) PetscCall((*plex->createanchors)(dm));
9369a68b90caSToby Isaac   if (anchorSection) *anchorSection = plex->anchorSection;
9370a68b90caSToby Isaac   if (anchorIS) *anchorIS = plex->anchorIS;
9371a68b90caSToby Isaac   PetscFunctionReturn(0);
9372a68b90caSToby Isaac }
9373a68b90caSToby Isaac 
9374a68b90caSToby Isaac /*@
9375f7c74593SToby Isaac   DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints.  Unlike boundary conditions,
9376f7c74593SToby Isaac   when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a
9377a68b90caSToby Isaac   point's degrees of freedom to be a linear combination of other points' degrees of freedom.
9378a68b90caSToby Isaac 
9379a17985deSToby Isaac   After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling
9380ebdb1bfaSJed Brown   DMGetDefaultConstraints() and filling in the entries in the constraint matrix.
9381a68b90caSToby Isaac 
9382e228b242SToby Isaac   collective on dm
9383a68b90caSToby Isaac 
9384a68b90caSToby Isaac   Input Parameters:
9385a68b90caSToby Isaac + dm - The DMPlex object
9386e228b242SToby 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).
9387e228b242SToby Isaac - anchorIS - The list of all anchor points.  Must have a local communicator (PETSC_COMM_SELF or derivative).
9388a68b90caSToby Isaac 
9389a68b90caSToby Isaac   The reference counts of anchorSection and anchorIS are incremented.
9390a68b90caSToby Isaac 
9391a68b90caSToby Isaac   Level: intermediate
9392a68b90caSToby Isaac 
9393db781477SPatrick Sanan .seealso: `DMPlexGetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()`
9394a68b90caSToby Isaac @*/
93959371c9d4SSatish Balay PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) {
9396a68b90caSToby Isaac   DM_Plex    *plex = (DM_Plex *)dm->data;
9397e228b242SToby Isaac   PetscMPIInt result;
9398a68b90caSToby Isaac 
9399a68b90caSToby Isaac   PetscFunctionBegin;
9400a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9401e228b242SToby Isaac   if (anchorSection) {
9402e228b242SToby Isaac     PetscValidHeaderSpecific(anchorSection, PETSC_SECTION_CLASSID, 2);
94039566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorSection), &result));
94041dca8a05SBarry Smith     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor section must have local communicator");
9405e228b242SToby Isaac   }
9406e228b242SToby Isaac   if (anchorIS) {
9407e228b242SToby Isaac     PetscValidHeaderSpecific(anchorIS, IS_CLASSID, 3);
94089566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorIS), &result));
94091dca8a05SBarry Smith     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor IS must have local communicator");
9410e228b242SToby Isaac   }
9411a68b90caSToby Isaac 
94129566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)anchorSection));
94139566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&plex->anchorSection));
9414a68b90caSToby Isaac   plex->anchorSection = anchorSection;
9415a68b90caSToby Isaac 
94169566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)anchorIS));
94179566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&plex->anchorIS));
9418a68b90caSToby Isaac   plex->anchorIS = anchorIS;
9419a68b90caSToby Isaac 
9420cf9c20a2SJed Brown   if (PetscUnlikelyDebug(anchorIS && anchorSection)) {
9421a68b90caSToby Isaac     PetscInt        size, a, pStart, pEnd;
9422a68b90caSToby Isaac     const PetscInt *anchors;
9423a68b90caSToby Isaac 
94249566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd));
94259566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(anchorIS, &size));
94269566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(anchorIS, &anchors));
9427a68b90caSToby Isaac     for (a = 0; a < size; a++) {
9428a68b90caSToby Isaac       PetscInt p;
9429a68b90caSToby Isaac 
9430a68b90caSToby Isaac       p = anchors[a];
9431a68b90caSToby Isaac       if (p >= pStart && p < pEnd) {
9432a68b90caSToby Isaac         PetscInt dof;
9433a68b90caSToby Isaac 
94349566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(anchorSection, p, &dof));
9435a68b90caSToby Isaac         if (dof) {
94369566063dSJacob Faibussowitsch           PetscCall(ISRestoreIndices(anchorIS, &anchors));
943763a3b9bcSJacob Faibussowitsch           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Point %" PetscInt_FMT " cannot be constrained and an anchor", p);
9438a68b90caSToby Isaac         }
9439a68b90caSToby Isaac       }
9440a68b90caSToby Isaac     }
94419566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(anchorIS, &anchors));
9442a68b90caSToby Isaac   }
9443f7c74593SToby Isaac   /* reset the generic constraints */
94449566063dSJacob Faibussowitsch   PetscCall(DMSetDefaultConstraints(dm, NULL, NULL, NULL));
9445a68b90caSToby Isaac   PetscFunctionReturn(0);
9446a68b90caSToby Isaac }
9447a68b90caSToby Isaac 
94489371c9d4SSatish Balay static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) {
9449f7c74593SToby Isaac   PetscSection anchorSection;
94506995de1eSToby Isaac   PetscInt     pStart, pEnd, sStart, sEnd, p, dof, numFields, f;
9451a68b90caSToby Isaac 
9452a68b90caSToby Isaac   PetscFunctionBegin;
9453a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
94549566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL));
94559566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF, cSec));
94569566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
94576995de1eSToby Isaac   if (numFields) {
9458719ab38cSToby Isaac     PetscInt f;
94599566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(*cSec, numFields));
9460719ab38cSToby Isaac 
9461719ab38cSToby Isaac     for (f = 0; f < numFields; f++) {
9462719ab38cSToby Isaac       PetscInt numComp;
9463719ab38cSToby Isaac 
94649566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldComponents(section, f, &numComp));
94659566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldComponents(*cSec, f, numComp));
9466719ab38cSToby Isaac     }
94676995de1eSToby Isaac   }
94689566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd));
94699566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &sStart, &sEnd));
94706995de1eSToby Isaac   pStart = PetscMax(pStart, sStart);
94716995de1eSToby Isaac   pEnd   = PetscMin(pEnd, sEnd);
94726995de1eSToby Isaac   pEnd   = PetscMax(pStart, pEnd);
94739566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*cSec, pStart, pEnd));
9474a68b90caSToby Isaac   for (p = pStart; p < pEnd; p++) {
94759566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(anchorSection, p, &dof));
9476a68b90caSToby Isaac     if (dof) {
94779566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, p, &dof));
94789566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(*cSec, p, dof));
9479a68b90caSToby Isaac       for (f = 0; f < numFields; f++) {
94809566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(section, p, f, &dof));
94819566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetFieldDof(*cSec, p, f, dof));
9482a68b90caSToby Isaac       }
9483a68b90caSToby Isaac     }
9484a68b90caSToby Isaac   }
94859566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(*cSec));
94869566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*cSec, "Constraint Section"));
9487a68b90caSToby Isaac   PetscFunctionReturn(0);
9488a68b90caSToby Isaac }
9489a68b90caSToby Isaac 
94909371c9d4SSatish Balay static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) {
9491f7c74593SToby Isaac   PetscSection    aSec;
9492ae65431dSMatthew G. Knepley   PetscInt        pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j;
94930ac89760SToby Isaac   const PetscInt *anchors;
94940ac89760SToby Isaac   PetscInt        numFields, f;
949566ad2231SToby Isaac   IS              aIS;
9496e19f7ee6SMark Adams   MatType         mtype;
9497e19f7ee6SMark Adams   PetscBool       iscuda, iskokkos;
94980ac89760SToby Isaac 
94990ac89760SToby Isaac   PetscFunctionBegin;
95000ac89760SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
95019566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(cSec, &m));
95029566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(section, &n));
95039566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_SELF, cMat));
95049566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*cMat, m, n, m, n));
95059566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJCUSPARSE, &iscuda));
95069566063dSJacob Faibussowitsch   if (!iscuda) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJCUSPARSE, &iscuda));
95079566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJKOKKOS, &iskokkos));
95089566063dSJacob Faibussowitsch   if (!iskokkos) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJKOKKOS, &iskokkos));
9509e19f7ee6SMark Adams   if (iscuda) mtype = MATSEQAIJCUSPARSE;
9510e19f7ee6SMark Adams   else if (iskokkos) mtype = MATSEQAIJKOKKOS;
9511e19f7ee6SMark Adams   else mtype = MATSEQAIJ;
95129566063dSJacob Faibussowitsch   PetscCall(MatSetType(*cMat, mtype));
95139566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS));
95149566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(aIS, &anchors));
95156995de1eSToby Isaac   /* cSec will be a subset of aSec and section */
95169566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(cSec, &pStart, &pEnd));
95179566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &sStart, &sEnd));
95189566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m + 1, &i));
95190ac89760SToby Isaac   i[0] = 0;
95209566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
95210ac89760SToby Isaac   for (p = pStart; p < pEnd; p++) {
9522f19733c5SToby Isaac     PetscInt rDof, rOff, r;
9523f19733c5SToby Isaac 
95249566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(aSec, p, &rDof));
9525f19733c5SToby Isaac     if (!rDof) continue;
95269566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(aSec, p, &rOff));
95270ac89760SToby Isaac     if (numFields) {
95280ac89760SToby Isaac       for (f = 0; f < numFields; f++) {
95290ac89760SToby Isaac         annz = 0;
9530f19733c5SToby Isaac         for (r = 0; r < rDof; r++) {
9531f19733c5SToby Isaac           a = anchors[rOff + r];
9532ae65431dSMatthew G. Knepley           if (a < sStart || a >= sEnd) continue;
95339566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof));
95340ac89760SToby Isaac           annz += aDof;
95350ac89760SToby Isaac         }
95369566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof));
95379566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldOffset(cSec, p, f, &off));
9538ad540459SPierre Jolivet         for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz;
95390ac89760SToby Isaac       }
95402f7452b8SBarry Smith     } else {
95410ac89760SToby Isaac       annz = 0;
95429566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
95430ac89760SToby Isaac       for (q = 0; q < dof; q++) {
9544ae65431dSMatthew G. Knepley         a = anchors[rOff + q];
9545ae65431dSMatthew G. Knepley         if (a < sStart || a >= sEnd) continue;
95469566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, a, &aDof));
95470ac89760SToby Isaac         annz += aDof;
95480ac89760SToby Isaac       }
95499566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
95509566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(cSec, p, &off));
9551ad540459SPierre Jolivet       for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz;
95520ac89760SToby Isaac     }
95530ac89760SToby Isaac   }
95540ac89760SToby Isaac   nnz = i[m];
95559566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nnz, &j));
95560ac89760SToby Isaac   offset = 0;
95570ac89760SToby Isaac   for (p = pStart; p < pEnd; p++) {
95580ac89760SToby Isaac     if (numFields) {
95590ac89760SToby Isaac       for (f = 0; f < numFields; f++) {
95609566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof));
95610ac89760SToby Isaac         for (q = 0; q < dof; q++) {
95620ac89760SToby Isaac           PetscInt rDof, rOff, r;
95639566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(aSec, p, &rDof));
95649566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(aSec, p, &rOff));
95650ac89760SToby Isaac           for (r = 0; r < rDof; r++) {
95660ac89760SToby Isaac             PetscInt s;
95670ac89760SToby Isaac 
95680ac89760SToby Isaac             a = anchors[rOff + r];
9569ae65431dSMatthew G. Knepley             if (a < sStart || a >= sEnd) continue;
95709566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof));
95719566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldOffset(section, a, f, &aOff));
9572ad540459SPierre Jolivet             for (s = 0; s < aDof; s++) j[offset++] = aOff + s;
95730ac89760SToby Isaac           }
95740ac89760SToby Isaac         }
95750ac89760SToby Isaac       }
95762f7452b8SBarry Smith     } else {
95779566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
95780ac89760SToby Isaac       for (q = 0; q < dof; q++) {
95790ac89760SToby Isaac         PetscInt rDof, rOff, r;
95809566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(aSec, p, &rDof));
95819566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, p, &rOff));
95820ac89760SToby Isaac         for (r = 0; r < rDof; r++) {
95830ac89760SToby Isaac           PetscInt s;
95840ac89760SToby Isaac 
95850ac89760SToby Isaac           a = anchors[rOff + r];
9586ae65431dSMatthew G. Knepley           if (a < sStart || a >= sEnd) continue;
95879566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section, a, &aDof));
95889566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(section, a, &aOff));
9589ad540459SPierre Jolivet           for (s = 0; s < aDof; s++) j[offset++] = aOff + s;
95900ac89760SToby Isaac         }
95910ac89760SToby Isaac       }
95920ac89760SToby Isaac     }
95930ac89760SToby Isaac   }
95949566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocationCSR(*cMat, i, j, NULL));
95959566063dSJacob Faibussowitsch   PetscCall(PetscFree(i));
95969566063dSJacob Faibussowitsch   PetscCall(PetscFree(j));
95979566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(aIS, &anchors));
95980ac89760SToby Isaac   PetscFunctionReturn(0);
95990ac89760SToby Isaac }
96000ac89760SToby Isaac 
96019371c9d4SSatish Balay PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) {
9602f7c74593SToby Isaac   DM_Plex     *plex = (DM_Plex *)dm->data;
9603f7c74593SToby Isaac   PetscSection anchorSection, section, cSec;
960466ad2231SToby Isaac   Mat          cMat;
960566ad2231SToby Isaac 
960666ad2231SToby Isaac   PetscFunctionBegin;
960766ad2231SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
96089566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL));
960966ad2231SToby Isaac   if (anchorSection) {
961044a7f3ddSMatthew G. Knepley     PetscInt Nf;
9611e228b242SToby Isaac 
96129566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
96139566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateConstraintSection_Anchors(dm, section, &cSec));
96149566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateConstraintMatrix_Anchors(dm, section, cSec, &cMat));
96159566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
96169566063dSJacob Faibussowitsch     if (Nf && plex->computeanchormatrix) PetscCall((*plex->computeanchormatrix)(dm, section, cSec, cMat));
96179566063dSJacob Faibussowitsch     PetscCall(DMSetDefaultConstraints(dm, cSec, cMat, NULL));
96189566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&cSec));
96199566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&cMat));
962066ad2231SToby Isaac   }
962166ad2231SToby Isaac   PetscFunctionReturn(0);
962266ad2231SToby Isaac }
9623a93c429eSMatthew G. Knepley 
96249371c9d4SSatish Balay PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm) {
9625a93c429eSMatthew G. Knepley   IS           subis;
9626a93c429eSMatthew G. Knepley   PetscSection section, subsection;
9627a93c429eSMatthew G. Knepley 
9628a93c429eSMatthew G. Knepley   PetscFunctionBegin;
96299566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
963028b400f6SJacob Faibussowitsch   PetscCheck(section, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain");
963128b400f6SJacob Faibussowitsch   PetscCheck(subdm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain");
9632a93c429eSMatthew G. Knepley   /* Create subdomain */
96339566063dSJacob Faibussowitsch   PetscCall(DMPlexFilter(dm, label, value, subdm));
9634a93c429eSMatthew G. Knepley   /* Create submodel */
96359566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSubpointIS(*subdm, &subis));
96369566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreateSubmeshSection(section, subis, &subsection));
96379566063dSJacob Faibussowitsch   PetscCall(DMSetLocalSection(*subdm, subsection));
96389566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&subsection));
96399566063dSJacob Faibussowitsch   PetscCall(DMCopyDisc(dm, *subdm));
9640a93c429eSMatthew G. Knepley   /* Create map from submodel to global model */
9641a93c429eSMatthew G. Knepley   if (is) {
9642a93c429eSMatthew G. Knepley     PetscSection    sectionGlobal, subsectionGlobal;
9643a93c429eSMatthew G. Knepley     IS              spIS;
9644a93c429eSMatthew G. Knepley     const PetscInt *spmap;
9645a93c429eSMatthew G. Knepley     PetscInt       *subIndices;
9646a93c429eSMatthew G. Knepley     PetscInt        subSize = 0, subOff = 0, pStart, pEnd, p;
9647a93c429eSMatthew G. Knepley     PetscInt        Nf, f, bs = -1, bsLocal[2], bsMinMax[2];
9648a93c429eSMatthew G. Knepley 
96499566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSubpointIS(*subdm, &spIS));
96509566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(spIS, &spmap));
96519566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetNumFields(section, &Nf));
96529566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dm, &sectionGlobal));
96539566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(*subdm, &subsectionGlobal));
96549566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(subsection, &pStart, &pEnd));
9655a93c429eSMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
9656a93c429eSMatthew G. Knepley       PetscInt gdof, pSubSize = 0;
9657a93c429eSMatthew G. Knepley 
96589566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof));
9659a93c429eSMatthew G. Knepley       if (gdof > 0) {
9660a93c429eSMatthew G. Knepley         for (f = 0; f < Nf; ++f) {
9661a93c429eSMatthew G. Knepley           PetscInt fdof, fcdof;
9662a93c429eSMatthew G. Knepley 
96639566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(subsection, p, f, &fdof));
96649566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof));
9665a93c429eSMatthew G. Knepley           pSubSize += fdof - fcdof;
9666a93c429eSMatthew G. Knepley         }
9667a93c429eSMatthew G. Knepley         subSize += pSubSize;
9668a93c429eSMatthew G. Knepley         if (pSubSize) {
9669a93c429eSMatthew G. Knepley           if (bs < 0) {
9670a93c429eSMatthew G. Knepley             bs = pSubSize;
9671a93c429eSMatthew G. Knepley           } else if (bs != pSubSize) {
9672a93c429eSMatthew G. Knepley             /* Layout does not admit a pointwise block size */
9673a93c429eSMatthew G. Knepley             bs = 1;
9674a93c429eSMatthew G. Knepley           }
9675a93c429eSMatthew G. Knepley         }
9676a93c429eSMatthew G. Knepley       }
9677a93c429eSMatthew G. Knepley     }
9678a93c429eSMatthew G. Knepley     /* Must have same blocksize on all procs (some might have no points) */
96799371c9d4SSatish Balay     bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs;
96809371c9d4SSatish Balay     bsLocal[1] = bs;
96819566063dSJacob Faibussowitsch     PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax));
96829371c9d4SSatish Balay     if (bsMinMax[0] != bsMinMax[1]) {
96839371c9d4SSatish Balay       bs = 1;
96849371c9d4SSatish Balay     } else {
96859371c9d4SSatish Balay       bs = bsMinMax[0];
96869371c9d4SSatish Balay     }
96879566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(subSize, &subIndices));
9688a93c429eSMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
9689a93c429eSMatthew G. Knepley       PetscInt gdof, goff;
9690a93c429eSMatthew G. Knepley 
96919566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(subsectionGlobal, p, &gdof));
9692a93c429eSMatthew G. Knepley       if (gdof > 0) {
9693a93c429eSMatthew G. Knepley         const PetscInt point = spmap[p];
9694a93c429eSMatthew G. Knepley 
96959566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(sectionGlobal, point, &goff));
9696a93c429eSMatthew G. Knepley         for (f = 0; f < Nf; ++f) {
9697a93c429eSMatthew G. Knepley           PetscInt fdof, fcdof, fc, f2, poff = 0;
9698a93c429eSMatthew G. Knepley 
9699a93c429eSMatthew G. Knepley           /* Can get rid of this loop by storing field information in the global section */
9700a93c429eSMatthew G. Knepley           for (f2 = 0; f2 < f; ++f2) {
97019566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, p, f2, &fdof));
97029566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof));
9703a93c429eSMatthew G. Knepley             poff += fdof - fcdof;
9704a93c429eSMatthew G. Knepley           }
97059566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof));
97069566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof));
9707ad540459SPierre Jolivet           for (fc = 0; fc < fdof - fcdof; ++fc, ++subOff) subIndices[subOff] = goff + poff + fc;
9708a93c429eSMatthew G. Knepley         }
9709a93c429eSMatthew G. Knepley       }
9710a93c429eSMatthew G. Knepley     }
97119566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(spIS, &spmap));
97129566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is));
9713a93c429eSMatthew G. Knepley     if (bs > 1) {
9714a93c429eSMatthew G. Knepley       /* We need to check that the block size does not come from non-contiguous fields */
9715a93c429eSMatthew G. Knepley       PetscInt i, j, set = 1;
9716a93c429eSMatthew G. Knepley       for (i = 0; i < subSize; i += bs) {
9717a93c429eSMatthew G. Knepley         for (j = 0; j < bs; ++j) {
97189371c9d4SSatish Balay           if (subIndices[i + j] != subIndices[i] + j) {
97199371c9d4SSatish Balay             set = 0;
97209371c9d4SSatish Balay             break;
97219371c9d4SSatish Balay           }
9722a93c429eSMatthew G. Knepley         }
9723a93c429eSMatthew G. Knepley       }
97249566063dSJacob Faibussowitsch       if (set) PetscCall(ISSetBlockSize(*is, bs));
9725a93c429eSMatthew G. Knepley     }
9726a93c429eSMatthew G. Knepley     /* Attach nullspace */
9727a93c429eSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
9728a93c429eSMatthew G. Knepley       (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f];
9729a93c429eSMatthew G. Knepley       if ((*subdm)->nullspaceConstructors[f]) break;
9730a93c429eSMatthew G. Knepley     }
9731a93c429eSMatthew G. Knepley     if (f < Nf) {
9732a93c429eSMatthew G. Knepley       MatNullSpace nullSpace;
97339566063dSJacob Faibussowitsch       PetscCall((*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace));
97346823f3c5SBlaise Bourdin 
97359566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)*is, "nullspace", (PetscObject)nullSpace));
97369566063dSJacob Faibussowitsch       PetscCall(MatNullSpaceDestroy(&nullSpace));
9737a93c429eSMatthew G. Knepley     }
9738a93c429eSMatthew G. Knepley   }
9739a93c429eSMatthew G. Knepley   PetscFunctionReturn(0);
9740a93c429eSMatthew G. Knepley }
9741c0f0dcc3SMatthew G. Knepley 
9742c0f0dcc3SMatthew G. Knepley /*@
9743c0f0dcc3SMatthew G. Knepley   DMPlexMonitorThroughput - Report the cell throughput of FE integration
9744c0f0dcc3SMatthew G. Knepley 
9745c0f0dcc3SMatthew G. Knepley   Input Parameter:
9746c0f0dcc3SMatthew G. Knepley - dm - The DM
9747c0f0dcc3SMatthew G. Knepley 
9748c0f0dcc3SMatthew G. Knepley   Level: developer
9749c0f0dcc3SMatthew G. Knepley 
9750c0f0dcc3SMatthew G. Knepley   Options Database Keys:
9751c0f0dcc3SMatthew G. Knepley . -dm_plex_monitor_throughput - Activate the monitor
9752c0f0dcc3SMatthew G. Knepley 
9753db781477SPatrick Sanan .seealso: `DMSetFromOptions()`, `DMPlexCreate()`
9754c0f0dcc3SMatthew G. Knepley @*/
97559371c9d4SSatish Balay PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy) {
9756e5ed2c37SJose E. Roman #if defined(PETSC_USE_LOG)
9757c0f0dcc3SMatthew G. Knepley   PetscStageLog      stageLog;
9758c0f0dcc3SMatthew G. Knepley   PetscLogEvent      event;
9759c0f0dcc3SMatthew G. Knepley   PetscLogStage      stage;
9760c0f0dcc3SMatthew G. Knepley   PetscEventPerfInfo eventInfo;
9761c0f0dcc3SMatthew G. Knepley   PetscReal          cellRate, flopRate;
9762c0f0dcc3SMatthew G. Knepley   PetscInt           cStart, cEnd, Nf, N;
9763c0f0dcc3SMatthew G. Knepley   const char        *name;
9764e5ed2c37SJose E. Roman #endif
9765c0f0dcc3SMatthew G. Knepley 
9766c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
9767c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9768c0f0dcc3SMatthew G. Knepley #if defined(PETSC_USE_LOG)
97699566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)dm, &name));
97709566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
97719566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
97729566063dSJacob Faibussowitsch   PetscCall(PetscLogGetStageLog(&stageLog));
97739566063dSJacob Faibussowitsch   PetscCall(PetscStageLogGetCurrent(stageLog, &stage));
97749566063dSJacob Faibussowitsch   PetscCall(PetscLogEventGetId("DMPlexResidualFE", &event));
97759566063dSJacob Faibussowitsch   PetscCall(PetscLogEventGetPerfInfo(stage, event, &eventInfo));
9776c0f0dcc3SMatthew G. Knepley   N        = (cEnd - cStart) * Nf * eventInfo.count;
9777c0f0dcc3SMatthew G. Knepley   flopRate = eventInfo.flops / eventInfo.time;
9778c0f0dcc3SMatthew G. Knepley   cellRate = N / eventInfo.time;
977963a3b9bcSJacob 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)));
9780c0f0dcc3SMatthew G. Knepley #else
9781c0f0dcc3SMatthew G. Knepley   SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Plex Throughput Monitor is not supported if logging is turned off. Reconfigure using --with-log.");
9782c0f0dcc3SMatthew G. Knepley #endif
9783c0f0dcc3SMatthew G. Knepley   PetscFunctionReturn(0);
9784c0f0dcc3SMatthew G. Knepley }
9785