xref: /petsc/src/dm/impls/plex/plex.c (revision 252a1336e0c9cad43c46000f8c024cecaf00900c)
1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h>   /*I      "petscdmplex.h"   I*/
2af0996ceSBarry Smith #include <petsc/private/isimpl.h>
3e5c6e791SKarl Rupp #include <petsc/private/vecimpl.h>
48135c375SStefano Zampini #include <petsc/private/glvisvecimpl.h>
50c312b8eSJed Brown #include <petscsf.h>
6e228b242SToby Isaac #include <petscds.h>
7e412dcbdSMatthew G. Knepley #include <petscdraw.h>
8f19dbd58SToby Isaac #include <petscdmfield.h>
9012bc364SMatthew G. Knepley #include <petscdmplextransform.h>
10552f7358SJed Brown 
11552f7358SJed Brown /* Logging support */
1202f7d72cSksagiyam PetscLogEvent DMPLEX_Interpolate, DMPLEX_Partition, DMPLEX_Distribute, DMPLEX_DistributeCones, DMPLEX_DistributeLabels, DMPLEX_DistributeSF, DMPLEX_DistributeOverlap, DMPLEX_DistributeField, DMPLEX_DistributeData, DMPLEX_Migrate, DMPLEX_InterpolateSF, DMPLEX_GlobalToNaturalBegin, DMPLEX_GlobalToNaturalEnd, DMPLEX_NaturalToGlobalBegin, DMPLEX_NaturalToGlobalEnd, DMPLEX_Stratify, DMPLEX_Symmetrize, DMPLEX_Preallocate, DMPLEX_ResidualFEM, DMPLEX_JacobianFEM, DMPLEX_InterpolatorFEM, DMPLEX_InjectorFEM, DMPLEX_IntegralFEM, DMPLEX_CreateGmsh, DMPLEX_RebalanceSharedPoints, DMPLEX_PartSelf, DMPLEX_PartLabelInvert, DMPLEX_PartLabelCreateSF, DMPLEX_PartStratSF, DMPLEX_CreatePointSF,DMPLEX_LocatePoints,DMPLEX_TopologyView,DMPLEX_LabelsView,DMPLEX_CoordinatesView,DMPLEX_SectionView,DMPLEX_GlobalVectorView,DMPLEX_LocalVectorView,DMPLEX_TopologyLoad,DMPLEX_LabelsLoad,DMPLEX_CoordinatesLoad,DMPLEX_SectionLoad,DMPLEX_GlobalVectorLoad,DMPLEX_LocalVectorLoad;
13*252a1336SBarry Smith PetscLogEvent DMPLEX_RebalBuildGraph,DMPLEX_RebalRewriteSF,DMPLEX_RebalGatherGraph, DMPLEX_RebalPartition, DMPLEX_RebalScatterPart;
14552f7358SJed Brown 
155a576424SJed Brown PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer);
16552f7358SJed Brown 
17e5337592SStefano Zampini /*@
189318fe57SMatthew G. Knepley   DMPlexIsSimplex - Is the first cell in this mesh a simplex?
199318fe57SMatthew G. Knepley 
209318fe57SMatthew G. Knepley   Input Parameter:
219318fe57SMatthew G. Knepley . dm      - The DMPlex object
229318fe57SMatthew G. Knepley 
239318fe57SMatthew G. Knepley   Output Parameter:
249318fe57SMatthew G. Knepley . simplex - Flag checking for a simplex
259318fe57SMatthew G. Knepley 
269318fe57SMatthew 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.
279318fe57SMatthew G. Knepley   If the mesh has no cells, this returns PETSC_FALSE.
289318fe57SMatthew G. Knepley 
299318fe57SMatthew G. Knepley   Level: intermediate
309318fe57SMatthew G. Knepley 
31db781477SPatrick Sanan .seealso `DMPlexGetSimplexOrBoxCells()`, `DMPlexGetCellType()`, `DMPlexGetHeightStratum()`, `DMPolytopeTypeGetNumVertices()`
329318fe57SMatthew G. Knepley @*/
339318fe57SMatthew G. Knepley PetscErrorCode DMPlexIsSimplex(DM dm, PetscBool *simplex)
349318fe57SMatthew G. Knepley {
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));
409318fe57SMatthew G. Knepley   if (cEnd <= cStart) {*simplex = PETSC_FALSE; PetscFunctionReturn(0);}
419566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cStart, &ct));
429318fe57SMatthew G. Knepley   *simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE;
439318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
449318fe57SMatthew G. Knepley }
459318fe57SMatthew G. Knepley 
469318fe57SMatthew G. Knepley /*@
47412e9a14SMatthew G. Knepley   DMPlexGetSimplexOrBoxCells - Get the range of cells which are neither prisms nor ghost FV cells
48e5337592SStefano Zampini 
49d8d19677SJose E. Roman   Input Parameters:
50412e9a14SMatthew G. Knepley + dm     - The DMPlex object
51412e9a14SMatthew G. Knepley - height - The cell height in the Plex, 0 is the default
52e5337592SStefano Zampini 
53e5337592SStefano Zampini   Output Parameters:
54412e9a14SMatthew G. Knepley + cStart - The first "normal" cell
55412e9a14SMatthew G. Knepley - cEnd   - The upper bound on "normal"" cells
56e5337592SStefano Zampini 
57412e9a14SMatthew G. Knepley   Note: This just gives the first range of cells found. If the mesh has several cell types, it will only give the first.
58e5337592SStefano Zampini 
59412e9a14SMatthew G. Knepley   Level: developer
60e5337592SStefano Zampini 
61db781477SPatrick Sanan .seealso `DMPlexConstructGhostCells()`, `DMPlexGetGhostCellStratum()`
62e5337592SStefano Zampini @*/
63412e9a14SMatthew G. Knepley PetscErrorCode DMPlexGetSimplexOrBoxCells(DM dm, PetscInt height, PetscInt *cStart, PetscInt *cEnd)
64e5337592SStefano Zampini {
65412e9a14SMatthew G. Knepley   DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
66412e9a14SMatthew G. Knepley   PetscInt       cS, cE, c;
67e5337592SStefano Zampini 
68e5337592SStefano Zampini   PetscFunctionBegin;
699566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, PetscMax(height, 0), &cS, &cE));
70412e9a14SMatthew G. Knepley   for (c = cS; c < cE; ++c) {
71412e9a14SMatthew G. Knepley     DMPolytopeType cct;
72412e9a14SMatthew G. Knepley 
739566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &cct));
74412e9a14SMatthew G. Knepley     if ((PetscInt) cct < 0) break;
75412e9a14SMatthew G. Knepley     switch (cct) {
76ba2698f1SMatthew G. Knepley       case DM_POLYTOPE_POINT:
77ba2698f1SMatthew G. Knepley       case DM_POLYTOPE_SEGMENT:
78ba2698f1SMatthew G. Knepley       case DM_POLYTOPE_TRIANGLE:
79ba2698f1SMatthew G. Knepley       case DM_POLYTOPE_QUADRILATERAL:
80ba2698f1SMatthew G. Knepley       case DM_POLYTOPE_TETRAHEDRON:
81ba2698f1SMatthew G. Knepley       case DM_POLYTOPE_HEXAHEDRON:
82412e9a14SMatthew G. Knepley         ct = cct;
83e5337592SStefano Zampini         break;
84412e9a14SMatthew G. Knepley       default: break;
85e5337592SStefano Zampini     }
86412e9a14SMatthew G. Knepley     if (ct != DM_POLYTOPE_UNKNOWN) break;
87e5337592SStefano Zampini   }
88412e9a14SMatthew G. Knepley   if (ct != DM_POLYTOPE_UNKNOWN) {
89412e9a14SMatthew G. Knepley     DMLabel ctLabel;
90412e9a14SMatthew G. Knepley 
919566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel));
929566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumBounds(ctLabel, ct, &cS, &cE));
93e5337592SStefano Zampini   }
94412e9a14SMatthew G. Knepley   if (cStart) *cStart = cS;
95412e9a14SMatthew G. Knepley   if (cEnd)   *cEnd   = cE;
96e5337592SStefano Zampini   PetscFunctionReturn(0);
97e5337592SStefano Zampini }
98e5337592SStefano Zampini 
997afe7537SMatthew G. Knepley PetscErrorCode DMPlexGetFieldType_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *sStart, PetscInt *sEnd, PetscViewerVTKFieldType *ft)
1007e42fee7SMatthew G. Knepley {
101412e9a14SMatthew G. Knepley   PetscInt       cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd;
102a99a26bcSAdrian Croucher   PetscInt       vcdof[2] = {0,0}, globalvcdof[2];
1037e42fee7SMatthew G. Knepley 
1047e42fee7SMatthew G. Knepley   PetscFunctionBegin;
105e630c359SToby Isaac   *ft  = PETSC_VTK_INVALID;
1069566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
1079566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
1089566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd));
1099566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
1107e42fee7SMatthew G. Knepley   if (field >= 0) {
1119566063dSJacob Faibussowitsch     if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, vStart, field, &vcdof[0]));
1129566063dSJacob Faibussowitsch     if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, cStart, field, &vcdof[1]));
1137e42fee7SMatthew G. Knepley   } else {
1149566063dSJacob Faibussowitsch     if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetDof(section, vStart, &vcdof[0]));
1159566063dSJacob Faibussowitsch     if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetDof(section, cStart, &vcdof[1]));
1167e42fee7SMatthew G. Knepley   }
1179566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allreduce(vcdof, globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
118a99a26bcSAdrian Croucher   if (globalvcdof[0]) {
1197e42fee7SMatthew G. Knepley     *sStart = vStart;
1207e42fee7SMatthew G. Knepley     *sEnd   = vEnd;
121f094498dSMatthew G. Knepley     if (globalvcdof[0] == cdim) *ft = PETSC_VTK_POINT_VECTOR_FIELD;
1227e42fee7SMatthew G. Knepley     else                        *ft = PETSC_VTK_POINT_FIELD;
123a99a26bcSAdrian Croucher   } else if (globalvcdof[1]) {
1247e42fee7SMatthew G. Knepley     *sStart = cStart;
1257e42fee7SMatthew G. Knepley     *sEnd   = cEnd;
126f094498dSMatthew G. Knepley     if (globalvcdof[1] == cdim) *ft = PETSC_VTK_CELL_VECTOR_FIELD;
1277e42fee7SMatthew G. Knepley     else                        *ft = PETSC_VTK_CELL_FIELD;
128e630c359SToby Isaac   } else {
129e630c359SToby Isaac     if (field >= 0) {
130e630c359SToby Isaac       const char *fieldname;
131e630c359SToby Isaac 
1329566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldName(section, field, &fieldname));
13363a3b9bcSJacob Faibussowitsch       PetscCall(PetscInfo((PetscObject) dm, "Could not classify VTK output type of section field %" PetscInt_FMT " \"%s\"\n", field, fieldname));
134e630c359SToby Isaac     } else {
13563a3b9bcSJacob Faibussowitsch       PetscCall(PetscInfo((PetscObject) dm, "Could not classify VTK output type of section\n"));
136e630c359SToby Isaac     }
137e630c359SToby Isaac   }
1387e42fee7SMatthew G. Knepley   PetscFunctionReturn(0);
1397e42fee7SMatthew G. Knepley }
1407e42fee7SMatthew G. Knepley 
1416913077dSMatthew G. Knepley /*@
1426913077dSMatthew G. Knepley   DMPlexVecView1D - Plot many 1D solutions on the same line graph
1436913077dSMatthew G. Knepley 
1446913077dSMatthew G. Knepley   Collective on dm
1456913077dSMatthew G. Knepley 
1466913077dSMatthew G. Knepley   Input Parameters:
1476913077dSMatthew G. Knepley + dm - The DMPlex
1486913077dSMatthew G. Knepley . n  - The number of vectors
1496913077dSMatthew G. Knepley . u  - The array of local vectors
1506913077dSMatthew G. Knepley - viewer - The Draw viewer
1516913077dSMatthew G. Knepley 
1526913077dSMatthew G. Knepley   Level: advanced
1536913077dSMatthew G. Knepley 
154db781477SPatrick Sanan .seealso: `VecViewFromOptions()`, `VecView()`
1556913077dSMatthew G. Knepley @*/
1566913077dSMatthew G. Knepley PetscErrorCode DMPlexVecView1D(DM dm, PetscInt n, Vec u[], PetscViewer viewer)
1576913077dSMatthew G. Knepley {
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 
2256913077dSMatthew G. Knepley static PetscErrorCode VecView_Plex_Local_Draw_1D(Vec u, PetscViewer viewer)
2266913077dSMatthew G. Knepley {
2276913077dSMatthew G. Knepley   DM             dm;
2286913077dSMatthew G. Knepley 
2296913077dSMatthew G. Knepley   PetscFunctionBegin;
2309566063dSJacob Faibussowitsch   PetscCall(VecGetDM(u, &dm));
2319566063dSJacob Faibussowitsch   PetscCall(DMPlexVecView1D(dm, 1, &u, viewer));
2326913077dSMatthew G. Knepley   PetscFunctionReturn(0);
2336913077dSMatthew G. Knepley }
2346913077dSMatthew G. Knepley 
2356913077dSMatthew G. Knepley static PetscErrorCode VecView_Plex_Local_Draw_2D(Vec v, PetscViewer viewer)
236e412dcbdSMatthew G. Knepley {
237e412dcbdSMatthew G. Knepley   DM                 dm;
238d1df6f1dSMatthew G. Knepley   PetscSection       s;
239e412dcbdSMatthew G. Knepley   PetscDraw          draw, popup;
240e412dcbdSMatthew G. Knepley   DM                 cdm;
241e412dcbdSMatthew G. Knepley   PetscSection       coordSection;
242e412dcbdSMatthew G. Knepley   Vec                coordinates;
243e412dcbdSMatthew G. Knepley   const PetscScalar *coords, *array;
244e412dcbdSMatthew G. Knepley   PetscReal          bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL};
245339e3443SMatthew G. Knepley   PetscReal          vbound[2], time;
2466913077dSMatthew G. Knepley   PetscBool          flg;
247d1df6f1dSMatthew G. Knepley   PetscInt           dim, Nf, f, Nc, comp, vStart, vEnd, cStart, cEnd, c, N, level, step, w = 0;
248e412dcbdSMatthew G. Knepley   const char        *name;
249339e3443SMatthew G. Knepley   char               title[PETSC_MAX_PATH_LEN];
250e412dcbdSMatthew G. Knepley 
251e412dcbdSMatthew G. Knepley   PetscFunctionBegin;
2529566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
2539566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
2549566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dim));
2559566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &s));
2569566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(s, &Nf));
2579566063dSJacob Faibussowitsch   PetscCall(DMGetCoarsenLevel(dm, &level));
2589566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
2599566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(cdm, &coordSection));
2609566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
2619566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
2629566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
263e412dcbdSMatthew G. Knepley 
2649566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject) v, &name));
2659566063dSJacob Faibussowitsch   PetscCall(DMGetOutputSequenceNumber(dm, &step, &time));
266e412dcbdSMatthew G. Knepley 
2679566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(coordinates, &N));
2689566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(coordinates, &coords));
269e412dcbdSMatthew G. Knepley   for (c = 0; c < N; c += dim) {
2700c81f2a8SMatthew G. Knepley     bound[0] = PetscMin(bound[0], PetscRealPart(coords[c]));   bound[2] = PetscMax(bound[2], PetscRealPart(coords[c]));
2710c81f2a8SMatthew G. Knepley     bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); 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)));
288d1df6f1dSMatthew G. Knepley     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 
3716913077dSMatthew G. Knepley static PetscErrorCode VecView_Plex_Local_Draw(Vec v, PetscViewer viewer)
3726913077dSMatthew G. Knepley {
3736913077dSMatthew G. Knepley   DM        dm;
3746913077dSMatthew G. Knepley   PetscDraw draw;
3756913077dSMatthew G. Knepley   PetscInt  dim;
3766913077dSMatthew G. Knepley   PetscBool isnull;
3776913077dSMatthew G. Knepley 
3786913077dSMatthew G. Knepley   PetscFunctionBegin;
3799566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
3809566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
3816913077dSMatthew G. Knepley   if (isnull) PetscFunctionReturn(0);
3826913077dSMatthew G. Knepley 
3839566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
3849566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dim));
3856913077dSMatthew G. Knepley   switch (dim) {
3869566063dSJacob Faibussowitsch   case 1: PetscCall(VecView_Plex_Local_Draw_1D(v, viewer));break;
3879566063dSJacob Faibussowitsch   case 2: PetscCall(VecView_Plex_Local_Draw_2D(v, viewer));break;
3885f80ce2aSJacob Faibussowitsch   default: SETERRQ(PetscObjectComm((PetscObject) v), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT ". Try PETSCVIEWERGLVIS", dim);
3896913077dSMatthew G. Knepley   }
3906913077dSMatthew G. Knepley   PetscFunctionReturn(0);
3916913077dSMatthew G. Knepley }
3926913077dSMatthew G. Knepley 
393684b87d9SLisandro Dalcin static PetscErrorCode VecView_Plex_Local_VTK(Vec v, PetscViewer viewer)
394684b87d9SLisandro Dalcin {
395684b87d9SLisandro Dalcin   DM                      dm;
396684b87d9SLisandro Dalcin   Vec                     locv;
397684b87d9SLisandro Dalcin   const char              *name;
398684b87d9SLisandro Dalcin   PetscSection            section;
399684b87d9SLisandro Dalcin   PetscInt                pStart, pEnd;
400e630c359SToby Isaac   PetscInt                numFields;
401684b87d9SLisandro Dalcin   PetscViewerVTKFieldType ft;
402684b87d9SLisandro Dalcin 
403684b87d9SLisandro Dalcin   PetscFunctionBegin;
4049566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
4059566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dm, &locv)); /* VTK viewer requires exclusive ownership of the vector */
4069566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject) v, &name));
4079566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject) locv, name));
4089566063dSJacob Faibussowitsch   PetscCall(VecCopy(v, locv));
4099566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
4109566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
411e630c359SToby Isaac   if (!numFields) {
4129566063dSJacob Faibussowitsch     PetscCall(DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft));
4139566063dSJacob Faibussowitsch     PetscCall(PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, PETSC_TRUE,(PetscObject) locv));
414e630c359SToby Isaac   } else {
415e630c359SToby Isaac     PetscInt f;
416e630c359SToby Isaac 
417e630c359SToby Isaac     for (f = 0; f < numFields; f++) {
4189566063dSJacob Faibussowitsch       PetscCall(DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft));
419e630c359SToby Isaac       if (ft == PETSC_VTK_INVALID) continue;
4209566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)locv));
4219566063dSJacob Faibussowitsch       PetscCall(PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE,(PetscObject) locv));
422e630c359SToby Isaac     }
4239566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&locv));
424e630c359SToby Isaac   }
425684b87d9SLisandro Dalcin   PetscFunctionReturn(0);
426684b87d9SLisandro Dalcin }
427684b87d9SLisandro Dalcin 
428552f7358SJed Brown PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer)
429552f7358SJed Brown {
430552f7358SJed Brown   DM             dm;
431684b87d9SLisandro Dalcin   PetscBool      isvtk, ishdf5, isdraw, isglvis;
432552f7358SJed Brown 
433552f7358SJed Brown   PetscFunctionBegin;
4349566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
43528b400f6SJacob Faibussowitsch   PetscCheck(dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
4369566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK,   &isvtk));
4379566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,  &ishdf5));
4389566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW,  &isdraw));
4399566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS, &isglvis));
440684b87d9SLisandro Dalcin   if (isvtk || ishdf5 || isdraw || isglvis) {
441684b87d9SLisandro Dalcin     PetscInt    i,numFields;
442684b87d9SLisandro Dalcin     PetscObject fe;
443ef31f671SMatthew G. Knepley     PetscBool   fem = PETSC_FALSE;
444684b87d9SLisandro Dalcin     Vec         locv = v;
445684b87d9SLisandro Dalcin     const char  *name;
446684b87d9SLisandro Dalcin     PetscInt    step;
447684b87d9SLisandro Dalcin     PetscReal   time;
448ef31f671SMatthew G. Knepley 
4499566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &numFields));
450684b87d9SLisandro Dalcin     for (i=0; i<numFields; i++) {
4519566063dSJacob Faibussowitsch       PetscCall(DMGetField(dm, i, NULL, &fe));
452684b87d9SLisandro Dalcin       if (fe->classid == PETSCFE_CLASSID) { fem = PETSC_TRUE; break; }
453ef31f671SMatthew G. Knepley     }
454684b87d9SLisandro Dalcin     if (fem) {
455798534f6SMatthew G. Knepley       PetscObject isZero;
456798534f6SMatthew G. Knepley 
4579566063dSJacob Faibussowitsch       PetscCall(DMGetLocalVector(dm, &locv));
4589566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject) v, &name));
4599566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject) locv, name));
4609566063dSJacob Faibussowitsch       PetscCall(PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero));
4619566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero));
4629566063dSJacob Faibussowitsch       PetscCall(VecCopy(v, locv));
4639566063dSJacob Faibussowitsch       PetscCall(DMGetOutputSequenceNumber(dm, NULL, &time));
4649566063dSJacob Faibussowitsch       PetscCall(DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL));
465ef31f671SMatthew G. Knepley     }
466552f7358SJed Brown     if (isvtk) {
4679566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_VTK(locv, viewer));
468b136c2c9SMatthew G. Knepley     } else if (ishdf5) {
469b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
4709566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_HDF5_Internal(locv, viewer));
471b136c2c9SMatthew G. Knepley #else
472b136c2c9SMatthew G. Knepley       SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
473b136c2c9SMatthew G. Knepley #endif
474f13a32a3SMatthew G. Knepley     } else if (isdraw) {
4759566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_Draw(locv, viewer));
476684b87d9SLisandro Dalcin     } else if (isglvis) {
4779566063dSJacob Faibussowitsch       PetscCall(DMGetOutputSequenceNumber(dm, &step, NULL));
4789566063dSJacob Faibussowitsch       PetscCall(PetscViewerGLVisSetSnapId(viewer, step));
4799566063dSJacob Faibussowitsch       PetscCall(VecView_GLVis(locv, viewer));
480684b87d9SLisandro Dalcin     }
481798534f6SMatthew G. Knepley     if (fem) {
4829566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL));
4839566063dSJacob Faibussowitsch       PetscCall(DMRestoreLocalVector(dm, &locv));
484798534f6SMatthew G. Knepley     }
485552f7358SJed Brown   } else {
486684b87d9SLisandro Dalcin     PetscBool isseq;
487684b87d9SLisandro Dalcin 
4889566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq));
4899566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
4909566063dSJacob Faibussowitsch     else       PetscCall(VecView_MPI(v, viewer));
491552f7358SJed Brown   }
492552f7358SJed Brown   PetscFunctionReturn(0);
493552f7358SJed Brown }
494552f7358SJed Brown 
495552f7358SJed Brown PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer)
496552f7358SJed Brown {
497552f7358SJed Brown   DM        dm;
4986823f3c5SBlaise Bourdin   PetscBool isvtk, ishdf5, isdraw, isglvis, isexodusii;
499552f7358SJed Brown 
500552f7358SJed Brown   PetscFunctionBegin;
5019566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
50228b400f6SJacob Faibussowitsch   PetscCheck(dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
5039566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK,      &isvtk));
5049566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,     &ishdf5));
5059566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW,     &isdraw));
5069566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS,    &isglvis));
5079566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii));
508684b87d9SLisandro Dalcin   if (isvtk || isdraw || isglvis) {
509552f7358SJed Brown     Vec         locv;
510798534f6SMatthew G. Knepley     PetscObject isZero;
511552f7358SJed Brown     const char *name;
512552f7358SJed Brown 
5139566063dSJacob Faibussowitsch     PetscCall(DMGetLocalVector(dm, &locv));
5149566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject) v, &name));
5159566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject) locv, name));
5169566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv));
5179566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv));
5189566063dSJacob Faibussowitsch     PetscCall(PetscObjectQuery((PetscObject) v, "__Vec_bc_zero__", &isZero));
5199566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", isZero));
5209566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_Local(locv, viewer));
5219566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject) locv, "__Vec_bc_zero__", NULL));
5229566063dSJacob Faibussowitsch     PetscCall(DMRestoreLocalVector(dm, &locv));
523b136c2c9SMatthew G. Knepley   } else if (ishdf5) {
524b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
5259566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_HDF5_Internal(v, viewer));
526b136c2c9SMatthew G. Knepley #else
527b136c2c9SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
528b136c2c9SMatthew G. Knepley #endif
5296823f3c5SBlaise Bourdin   } else if (isexodusii) {
5306823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII)
5319566063dSJacob Faibussowitsch     PetscCall(VecView_PlexExodusII_Internal(v, viewer));
5326823f3c5SBlaise Bourdin #else
5336823f3c5SBlaise Bourdin     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii");
5346823f3c5SBlaise Bourdin #endif
535552f7358SJed Brown   } else {
536684b87d9SLisandro Dalcin     PetscBool isseq;
537684b87d9SLisandro Dalcin 
5389566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq));
5399566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
5409566063dSJacob Faibussowitsch     else       PetscCall(VecView_MPI(v, viewer));
541552f7358SJed Brown   }
542552f7358SJed Brown   PetscFunctionReturn(0);
543552f7358SJed Brown }
544552f7358SJed Brown 
545d930f514SMatthew G. Knepley PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer)
546d930f514SMatthew G. Knepley {
547d930f514SMatthew G. Knepley   DM                dm;
548d930f514SMatthew G. Knepley   MPI_Comm          comm;
549d930f514SMatthew G. Knepley   PetscViewerFormat format;
550d930f514SMatthew G. Knepley   Vec               v;
551d930f514SMatthew G. Knepley   PetscBool         isvtk, ishdf5;
552d930f514SMatthew G. Knepley 
553d930f514SMatthew G. Knepley   PetscFunctionBegin;
5549566063dSJacob Faibussowitsch   PetscCall(VecGetDM(originalv, &dm));
5559566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject) originalv, &comm));
55628b400f6SJacob Faibussowitsch   PetscCheck(dm,comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
5579566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
5589566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
5599566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK,  &isvtk));
560d930f514SMatthew G. Knepley   if (format == PETSC_VIEWER_NATIVE) {
561a8ad634aSStefano Zampini     /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */
562a8ad634aSStefano Zampini     /* this need a better fix */
563a8ad634aSStefano Zampini     if (dm->useNatural) {
564a8ad634aSStefano Zampini       if (dm->sfNatural) {
565d930f514SMatthew G. Knepley         const char *vecname;
566d930f514SMatthew G. Knepley         PetscInt    n, nroots;
567d930f514SMatthew G. Knepley 
5689566063dSJacob Faibussowitsch         PetscCall(VecGetLocalSize(originalv, &n));
5699566063dSJacob Faibussowitsch         PetscCall(PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL));
570d930f514SMatthew G. Knepley         if (n == nroots) {
5719566063dSJacob Faibussowitsch           PetscCall(DMGetGlobalVector(dm, &v));
5729566063dSJacob Faibussowitsch           PetscCall(DMPlexGlobalToNaturalBegin(dm, originalv, v));
5739566063dSJacob Faibussowitsch           PetscCall(DMPlexGlobalToNaturalEnd(dm, originalv, v));
5749566063dSJacob Faibussowitsch           PetscCall(PetscObjectGetName((PetscObject) originalv, &vecname));
5759566063dSJacob Faibussowitsch           PetscCall(PetscObjectSetName((PetscObject) v, vecname));
576d930f514SMatthew G. Knepley         } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors");
577d930f514SMatthew G. Knepley       } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created");
578a8ad634aSStefano Zampini     } else v = originalv;
579a8ad634aSStefano Zampini   } else v = originalv;
580a8ad634aSStefano Zampini 
581d930f514SMatthew G. Knepley   if (ishdf5) {
582d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
5839566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_HDF5_Native_Internal(v, viewer));
584d930f514SMatthew G. Knepley #else
585d930f514SMatthew G. Knepley     SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
586d930f514SMatthew G. Knepley #endif
587d930f514SMatthew G. Knepley   } else if (isvtk) {
588d930f514SMatthew G. Knepley     SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5.");
589d930f514SMatthew G. Knepley   } else {
590d930f514SMatthew G. Knepley     PetscBool isseq;
591d930f514SMatthew G. Knepley 
5929566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq));
5939566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
5949566063dSJacob Faibussowitsch     else       PetscCall(VecView_MPI(v, viewer));
595d930f514SMatthew G. Knepley   }
5969566063dSJacob Faibussowitsch   if (v != originalv) PetscCall(DMRestoreGlobalVector(dm, &v));
597d930f514SMatthew G. Knepley   PetscFunctionReturn(0);
598d930f514SMatthew G. Knepley }
599d930f514SMatthew G. Knepley 
6002c40f234SMatthew G. Knepley PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer)
6012c40f234SMatthew G. Knepley {
6022c40f234SMatthew G. Knepley   DM             dm;
6032c40f234SMatthew G. Knepley   PetscBool      ishdf5;
6042c40f234SMatthew G. Knepley 
6052c40f234SMatthew G. Knepley   PetscFunctionBegin;
6069566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
60728b400f6SJacob Faibussowitsch   PetscCheck(dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
6089566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
6092c40f234SMatthew G. Knepley   if (ishdf5) {
6102c40f234SMatthew G. Knepley     DM          dmBC;
6112c40f234SMatthew G. Knepley     Vec         gv;
6122c40f234SMatthew G. Knepley     const char *name;
6132c40f234SMatthew G. Knepley 
6149566063dSJacob Faibussowitsch     PetscCall(DMGetOutputDM(dm, &dmBC));
6159566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalVector(dmBC, &gv));
6169566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject) v, &name));
6179566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject) gv, name));
6189566063dSJacob Faibussowitsch     PetscCall(VecLoad_Default(gv, viewer));
6199566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v));
6209566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v));
6219566063dSJacob Faibussowitsch     PetscCall(DMRestoreGlobalVector(dmBC, &gv));
6221baa6e33SBarry Smith   } else PetscCall(VecLoad_Default(v, viewer));
6232c40f234SMatthew G. Knepley   PetscFunctionReturn(0);
6242c40f234SMatthew G. Knepley }
6252c40f234SMatthew G. Knepley 
6262c40f234SMatthew G. Knepley PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer)
6272c40f234SMatthew G. Knepley {
6282c40f234SMatthew G. Knepley   DM             dm;
6296823f3c5SBlaise Bourdin   PetscBool      ishdf5,isexodusii;
6302c40f234SMatthew G. Knepley 
6312c40f234SMatthew G. Knepley   PetscFunctionBegin;
6329566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
63328b400f6SJacob Faibussowitsch   PetscCheck(dm,PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
6349566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,     &ishdf5));
6359566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodusii));
6362c40f234SMatthew G. Knepley   if (ishdf5) {
637878b459fSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
6389566063dSJacob Faibussowitsch     PetscCall(VecLoad_Plex_HDF5_Internal(v, viewer));
639b136c2c9SMatthew G. Knepley #else
640b136c2c9SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
641878b459fSMatthew G. Knepley #endif
6426823f3c5SBlaise Bourdin   } else if (isexodusii) {
6436823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII)
6449566063dSJacob Faibussowitsch     PetscCall(VecLoad_PlexExodusII_Internal(v, viewer));
6456823f3c5SBlaise Bourdin #else
6466823f3c5SBlaise Bourdin     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii");
6476823f3c5SBlaise Bourdin #endif
6481baa6e33SBarry Smith   } else PetscCall(VecLoad_Default(v, viewer));
649552f7358SJed Brown   PetscFunctionReturn(0);
650552f7358SJed Brown }
651552f7358SJed Brown 
652d930f514SMatthew G. Knepley PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer)
653d930f514SMatthew G. Knepley {
654d930f514SMatthew G. Knepley   DM                dm;
655d930f514SMatthew G. Knepley   PetscViewerFormat format;
656d930f514SMatthew G. Knepley   PetscBool         ishdf5;
657d930f514SMatthew G. Knepley 
658d930f514SMatthew G. Knepley   PetscFunctionBegin;
6599566063dSJacob Faibussowitsch   PetscCall(VecGetDM(originalv, &dm));
66028b400f6SJacob Faibussowitsch   PetscCheck(dm,PetscObjectComm((PetscObject) originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
6619566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
6629566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
663d930f514SMatthew G. Knepley   if (format == PETSC_VIEWER_NATIVE) {
664a8ad634aSStefano Zampini     if (dm->useNatural) {
665d930f514SMatthew G. Knepley       if (dm->sfNatural) {
666d930f514SMatthew G. Knepley         if (ishdf5) {
667d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
668d930f514SMatthew G. Knepley           Vec         v;
669d930f514SMatthew G. Knepley           const char *vecname;
670d930f514SMatthew G. Knepley 
6719566063dSJacob Faibussowitsch           PetscCall(DMGetGlobalVector(dm, &v));
6729566063dSJacob Faibussowitsch           PetscCall(PetscObjectGetName((PetscObject) originalv, &vecname));
6739566063dSJacob Faibussowitsch           PetscCall(PetscObjectSetName((PetscObject) v, vecname));
6749566063dSJacob Faibussowitsch           PetscCall(VecLoad_Plex_HDF5_Native_Internal(v, viewer));
6759566063dSJacob Faibussowitsch           PetscCall(DMPlexNaturalToGlobalBegin(dm, v, originalv));
6769566063dSJacob Faibussowitsch           PetscCall(DMPlexNaturalToGlobalEnd(dm, v, originalv));
6779566063dSJacob Faibussowitsch           PetscCall(DMRestoreGlobalVector(dm, &v));
678d930f514SMatthew G. Knepley #else
679d930f514SMatthew G. Knepley           SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
680d930f514SMatthew G. Knepley #endif
681d930f514SMatthew G. Knepley         } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5.");
682d930f514SMatthew G. Knepley       }
6831baa6e33SBarry Smith     } else PetscCall(VecLoad_Default(originalv, viewer));
684d930f514SMatthew G. Knepley   }
685d930f514SMatthew G. Knepley   PetscFunctionReturn(0);
686d930f514SMatthew G. Knepley }
687d930f514SMatthew G. Knepley 
6887cd05799SMatthew G. Knepley PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer)
689731e8ddeSMatthew G. Knepley {
690731e8ddeSMatthew G. Knepley   PetscSection       coordSection;
691731e8ddeSMatthew G. Knepley   Vec                coordinates;
692ba2698f1SMatthew G. Knepley   DMLabel            depthLabel, celltypeLabel;
693731e8ddeSMatthew G. Knepley   const char        *name[4];
694731e8ddeSMatthew G. Knepley   const PetscScalar *a;
695731e8ddeSMatthew G. Knepley   PetscInt           dim, pStart, pEnd, cStart, cEnd, c;
696731e8ddeSMatthew G. Knepley 
697731e8ddeSMatthew G. Knepley   PetscFunctionBegin;
6989566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
6999566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
7009566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
7019566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
7029566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &celltypeLabel));
7039566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
7049566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(coordSection, &pStart, &pEnd));
7059566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(coordinates, &a));
706731e8ddeSMatthew G. Knepley   name[0]     = "vertex";
707731e8ddeSMatthew G. Knepley   name[1]     = "edge";
708731e8ddeSMatthew G. Knepley   name[dim-1] = "face";
709731e8ddeSMatthew G. Knepley   name[dim]   = "cell";
710731e8ddeSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
711731e8ddeSMatthew G. Knepley     PetscInt *closure = NULL;
712ba2698f1SMatthew G. Knepley     PetscInt  closureSize, cl, ct;
713731e8ddeSMatthew G. Knepley 
7149566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(celltypeLabel, c, &ct));
71563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Geometry for cell %" PetscInt_FMT " polytope type %s:\n", c, DMPolytopeTypes[ct]));
7169566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
7179566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
718731e8ddeSMatthew G. Knepley     for (cl = 0; cl < closureSize*2; cl += 2) {
719731e8ddeSMatthew G. Knepley       PetscInt point = closure[cl], depth, dof, off, d, p;
720731e8ddeSMatthew G. Knepley 
721731e8ddeSMatthew G. Knepley       if ((point < pStart) || (point >= pEnd)) continue;
7229566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(coordSection, point, &dof));
723731e8ddeSMatthew G. Knepley       if (!dof) continue;
7249566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(depthLabel, point, &depth));
7259566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, point, &off));
72663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s %" PetscInt_FMT " coords:", name[depth], point));
727731e8ddeSMatthew G. Knepley       for (p = 0; p < dof/dim; ++p) {
7289566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " ("));
729731e8ddeSMatthew G. Knepley         for (d = 0; d < dim; ++d) {
7309566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
7319566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "%g", (double) PetscRealPart(a[off+p*dim+d])));
732731e8ddeSMatthew G. Knepley         }
7339566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, ")"));
734731e8ddeSMatthew G. Knepley       }
7359566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
736731e8ddeSMatthew G. Knepley     }
7379566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
7389566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
739731e8ddeSMatthew G. Knepley   }
7409566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(coordinates, &a));
741731e8ddeSMatthew G. Knepley   PetscFunctionReturn(0);
742731e8ddeSMatthew G. Knepley }
743731e8ddeSMatthew G. Knepley 
74419ad8254SMatthew G. Knepley typedef enum {CS_CARTESIAN, CS_POLAR, CS_CYLINDRICAL, CS_SPHERICAL} CoordSystem;
74519ad8254SMatthew G. Knepley const char *CoordSystems[] = {"cartesian", "polar", "cylindrical", "spherical", "CoordSystem", "CS_", NULL};
74619ad8254SMatthew G. Knepley 
74719ad8254SMatthew G. Knepley static PetscErrorCode DMPlexView_Ascii_Coordinates(PetscViewer viewer, CoordSystem cs, PetscInt dim, const PetscScalar x[])
74819ad8254SMatthew G. Knepley {
74919ad8254SMatthew G. Knepley   PetscInt       i;
75019ad8254SMatthew G. Knepley 
75119ad8254SMatthew G. Knepley   PetscFunctionBegin;
75219ad8254SMatthew G. Knepley   if (dim > 3) {
7539566063dSJacob Faibussowitsch     for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double) PetscRealPart(x[i])));
75419ad8254SMatthew G. Knepley   } else {
755bd83fdcbSStefano Zampini     PetscReal coords[3], trcoords[3] = {0., 0., 0.};
75619ad8254SMatthew G. Knepley 
75719ad8254SMatthew G. Knepley     for (i = 0; i < dim; ++i) coords[i] = PetscRealPart(x[i]);
75819ad8254SMatthew G. Knepley     switch (cs) {
75919ad8254SMatthew G. Knepley       case CS_CARTESIAN: for (i = 0; i < dim; ++i) trcoords[i] = coords[i];break;
76019ad8254SMatthew G. Knepley       case CS_POLAR:
76163a3b9bcSJacob Faibussowitsch         PetscCheck(dim == 2,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Polar coordinates are for 2 dimension, not %" PetscInt_FMT, dim);
76219ad8254SMatthew G. Knepley         trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]));
76319ad8254SMatthew G. Knepley         trcoords[1] = PetscAtan2Real(coords[1], coords[0]);
76419ad8254SMatthew G. Knepley         break;
76519ad8254SMatthew G. Knepley       case CS_CYLINDRICAL:
76663a3b9bcSJacob Faibussowitsch         PetscCheck(dim == 3,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cylindrical coordinates are for 3 dimension, not %" PetscInt_FMT, dim);
76719ad8254SMatthew G. Knepley         trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]));
76819ad8254SMatthew G. Knepley         trcoords[1] = PetscAtan2Real(coords[1], coords[0]);
76919ad8254SMatthew G. Knepley         trcoords[2] = coords[2];
77019ad8254SMatthew G. Knepley         break;
77119ad8254SMatthew G. Knepley       case CS_SPHERICAL:
77263a3b9bcSJacob Faibussowitsch         PetscCheck(dim == 3,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Spherical coordinates are for 3 dimension, not %" PetscInt_FMT, dim);
77319ad8254SMatthew G. Knepley         trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]) + PetscSqr(coords[2]));
77419ad8254SMatthew G. Knepley         trcoords[1] = PetscAtan2Real(PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])), coords[2]);
77519ad8254SMatthew G. Knepley         trcoords[2] = PetscAtan2Real(coords[1], coords[0]);
77619ad8254SMatthew G. Knepley         break;
77719ad8254SMatthew G. Knepley     }
7789566063dSJacob Faibussowitsch     for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double) trcoords[i]));
77919ad8254SMatthew G. Knepley   }
78019ad8254SMatthew G. Knepley   PetscFunctionReturn(0);
78119ad8254SMatthew G. Knepley }
78219ad8254SMatthew G. Knepley 
7837cd05799SMatthew G. Knepley static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer)
784552f7358SJed Brown {
785552f7358SJed Brown   DM_Plex          *mesh = (DM_Plex*) dm->data;
7866858538eSMatthew G. Knepley   DM                cdm, cdmCell;
7876858538eSMatthew G. Knepley   PetscSection      coordSection, coordSectionCell;
7886858538eSMatthew G. Knepley   Vec               coordinates, coordinatesCell;
789552f7358SJed Brown   PetscViewerFormat format;
790552f7358SJed Brown 
791552f7358SJed Brown   PetscFunctionBegin;
7929566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
7936858538eSMatthew G. Knepley   PetscCall(DMGetCoordinateSection(dm, &coordSection));
7949566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
7956858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dm, &cdmCell));
7966858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell));
7976858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell));
7989566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
799552f7358SJed Brown   if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
800552f7358SJed Brown     const char *name;
801f73eea6eSMatthew G. Knepley     PetscInt    dim, cellHeight, maxConeSize, maxSupportSize;
8029318fe57SMatthew G. Knepley     PetscInt    pStart, pEnd, p, numLabels, l;
803552f7358SJed Brown     PetscMPIInt rank, size;
804552f7358SJed Brown 
8059566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
8069566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
8079566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject) dm, &name));
8089566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
8099566063dSJacob Faibussowitsch     PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
8109566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
8119566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
81263a3b9bcSJacob Faibussowitsch     if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s"));
81363a3b9bcSJacob Faibussowitsch     else      PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s"));
81463a3b9bcSJacob Faibussowitsch     if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, "  Cells are at height %" PetscInt_FMT "\n", cellHeight));
81563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Supports:\n"));
8169566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
81763a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %" PetscInt_FMT "\n", rank, maxSupportSize));
818552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
819552f7358SJed Brown       PetscInt dof, off, s;
820552f7358SJed Brown 
8219566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
8229566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
823552f7358SJed Brown       for (s = off; s < off+dof; ++s) {
82463a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " ----> %" PetscInt_FMT "\n", rank, p, mesh->supports[s]));
825552f7358SJed Brown       }
826552f7358SJed Brown     }
8279566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
82863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Cones:\n"));
82963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %" PetscInt_FMT "\n", rank, maxConeSize));
830552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
831552f7358SJed Brown       PetscInt dof, off, c;
832552f7358SJed Brown 
8339566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
8349566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
835552f7358SJed Brown       for (c = off; c < off+dof; ++c) {
83663a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " <---- %" PetscInt_FMT " (%" PetscInt_FMT ")\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]));
837552f7358SJed Brown       }
838552f7358SJed Brown     }
8399566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
8409566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
8413d2e540fSStefano Zampini     if (coordSection && coordinates) {
84219ad8254SMatthew G. Knepley       CoordSystem        cs = CS_CARTESIAN;
8436858538eSMatthew G. Knepley       const PetscScalar *array, *arrayCell = NULL;
8446858538eSMatthew G. Knepley       PetscInt           Nf, Nc, pvStart, pvEnd, pcStart = PETSC_MAX_INT, pcEnd = PETSC_MIN_INT, pStart, pEnd, p;
84519ad8254SMatthew G. Knepley       PetscMPIInt        rank;
84619ad8254SMatthew G. Knepley       const char        *name;
84719ad8254SMatthew G. Knepley 
8489566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetEnum(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_coord_system", CoordSystems, (PetscEnum *) &cs, NULL));
8499566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
8509566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetNumFields(coordSection, &Nf));
85163a3b9bcSJacob Faibussowitsch       PetscCheck(Nf == 1,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate section should have 1 field, not %" PetscInt_FMT, Nf);
8529566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldComponents(coordSection, 0, &Nc));
8536858538eSMatthew G. Knepley       PetscCall(PetscSectionGetChart(coordSection, &pvStart, &pvEnd));
8546858538eSMatthew G. Knepley       if (coordSectionCell) PetscCall(PetscSectionGetChart(coordSectionCell, &pcStart, &pcEnd));
8556858538eSMatthew G. Knepley       pStart =  PetscMin(pvStart, pcStart);
8566858538eSMatthew G. Knepley       pEnd   =  PetscMax(pvEnd,   pcEnd);
8579566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject) coordinates, &name));
85863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s with %" PetscInt_FMT " fields\n", name, Nf));
85963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  field 0 with %" PetscInt_FMT " components\n", Nc));
8609566063dSJacob Faibussowitsch       if (cs != CS_CARTESIAN) PetscCall(PetscViewerASCIIPrintf(viewer, "  output coordinate system: %s\n", CoordSystems[cs]));
86119ad8254SMatthew G. Knepley 
8629566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(coordinates, &array));
8636858538eSMatthew G. Knepley       if (coordinatesCell) PetscCall(VecGetArrayRead(coordinatesCell, &arrayCell));
8649566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushSynchronized(viewer));
8659566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank));
86619ad8254SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
86719ad8254SMatthew G. Knepley         PetscInt dof, off;
86819ad8254SMatthew G. Knepley 
8696858538eSMatthew G. Knepley         if (p >= pvStart && p < pvEnd) {
8709566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(coordSection, p, &dof));
8719566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(coordSection, p, &off));
8726858538eSMatthew G. Knepley           if (dof) {
87363a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "  (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off));
8749566063dSJacob Faibussowitsch             PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &array[off]));
8759566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
87619ad8254SMatthew G. Knepley           }
8776858538eSMatthew G. Knepley         }
8786858538eSMatthew G. Knepley         if (cdmCell && p >= pcStart && p < pcEnd) {
8796858538eSMatthew G. Knepley           PetscCall(PetscSectionGetDof(coordSectionCell, p, &dof));
8806858538eSMatthew G. Knepley           PetscCall(PetscSectionGetOffset(coordSectionCell, p, &off));
8816858538eSMatthew G. Knepley           if (dof) {
8826858538eSMatthew G. Knepley             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "  (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off));
8836858538eSMatthew G. Knepley             PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &arrayCell[off]));
8846858538eSMatthew G. Knepley             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
8856858538eSMatthew G. Knepley           }
8866858538eSMatthew G. Knepley         }
8876858538eSMatthew G. Knepley       }
8889566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
8899566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopSynchronized(viewer));
8909566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(coordinates, &array));
8916858538eSMatthew G. Knepley       if (coordinatesCell) PetscCall(VecRestoreArrayRead(coordinatesCell, &arrayCell));
8923d2e540fSStefano Zampini     }
8939566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
8949566063dSJacob Faibussowitsch     if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n"));
8959318fe57SMatthew G. Knepley     for (l = 0; l < numLabels; ++l) {
8969318fe57SMatthew G. Knepley       DMLabel     label;
8979318fe57SMatthew G. Knepley       PetscBool   isdepth;
8989318fe57SMatthew G. Knepley       const char *name;
8999318fe57SMatthew G. Knepley 
9009566063dSJacob Faibussowitsch       PetscCall(DMGetLabelName(dm, l, &name));
9019566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "depth", &isdepth));
9029318fe57SMatthew G. Knepley       if (isdepth) continue;
9039566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, name, &label));
9049566063dSJacob Faibussowitsch       PetscCall(DMLabelView(label, viewer));
9059318fe57SMatthew G. Knepley     }
906552f7358SJed Brown     if (size > 1) {
907552f7358SJed Brown       PetscSF sf;
908552f7358SJed Brown 
9099566063dSJacob Faibussowitsch       PetscCall(DMGetPointSF(dm, &sf));
9109566063dSJacob Faibussowitsch       PetscCall(PetscSFView(sf, viewer));
911552f7358SJed Brown     }
9129566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
913552f7358SJed Brown   } else if (format == PETSC_VIEWER_ASCII_LATEX) {
9140588280cSMatthew G. Knepley     const char  *name, *color;
9150588280cSMatthew G. Knepley     const char  *defcolors[3]  = {"gray", "orange", "green"};
9160588280cSMatthew G. Knepley     const char  *deflcolors[4] = {"blue", "cyan", "red", "magenta"};
917fe1cc32dSStefano Zampini     char         lname[PETSC_MAX_PATH_LEN];
918552f7358SJed Brown     PetscReal    scale         = 2.0;
91978081901SStefano Zampini     PetscReal    tikzscale     = 1.0;
920b7f6ffafSMatthew G. Knepley     PetscBool    useNumbers    = PETSC_TRUE, drawNumbers[4], drawColors[4], useLabels, useColors, plotEdges, drawHasse = PETSC_FALSE;
9210588280cSMatthew G. Knepley     double       tcoords[3];
922552f7358SJed Brown     PetscScalar *coords;
923b7f6ffafSMatthew G. Knepley     PetscInt     numLabels, l, numColors, numLColors, dim, d, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p, n;
924552f7358SJed Brown     PetscMPIInt  rank, size;
9250588280cSMatthew G. Knepley     char         **names, **colors, **lcolors;
926b7f6ffafSMatthew G. Knepley     PetscBool    flg, lflg;
927fe1cc32dSStefano Zampini     PetscBT      wp = NULL;
928fe1cc32dSStefano Zampini     PetscInt     pEnd, pStart;
929552f7358SJed Brown 
9309566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
9319566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dm, &depth));
9329566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
9330588280cSMatthew G. Knepley     numLabels  = PetscMax(numLabels, 10);
9340588280cSMatthew G. Knepley     numColors  = 10;
9350588280cSMatthew G. Knepley     numLColors = 10;
9369566063dSJacob Faibussowitsch     PetscCall(PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors));
9379566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_scale", &scale, NULL));
9389566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetReal(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL));
9399566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL));
940b7f6ffafSMatthew G. Knepley     for (d = 0; d < 4; ++d) drawNumbers[d] = useNumbers;
941b7f6ffafSMatthew G. Knepley     for (d = 0; d < 4; ++d) drawColors[d]  = PETSC_TRUE;
942b7f6ffafSMatthew G. Knepley     n = 4;
9439566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBoolArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers_depth", drawNumbers, &n, &flg));
9441dca8a05SBarry 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);
9459566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBoolArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors_depth", drawColors, &n, &flg));
9461dca8a05SBarry 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);
9479566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels));
9480588280cSMatthew G. Knepley     if (!useLabels) numLabels = 0;
9499566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors));
9500588280cSMatthew G. Knepley     if (!useColors) {
9510588280cSMatthew G. Knepley       numColors = 3;
9529566063dSJacob Faibussowitsch       for (c = 0; c < numColors; ++c) PetscCall(PetscStrallocpy(defcolors[c], &colors[c]));
9530588280cSMatthew G. Knepley     }
9549566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors));
9550588280cSMatthew G. Knepley     if (!useColors) {
9560588280cSMatthew G. Knepley       numLColors = 4;
9579566063dSJacob Faibussowitsch       for (c = 0; c < numLColors; ++c) PetscCall(PetscStrallocpy(deflcolors[c], &lcolors[c]));
9580588280cSMatthew G. Knepley     }
9599566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetString(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg));
960b7f6ffafSMatthew G. Knepley     plotEdges = (PetscBool)(depth > 1 && drawNumbers[1] && dim < 3);
9619566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg));
9621dca8a05SBarry Smith     PetscCheck(!flg || !plotEdges || depth >= dim,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Mesh must be interpolated");
963202fd40aSStefano Zampini     if (depth < dim) plotEdges = PETSC_FALSE;
9649566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject) viewer)->options, ((PetscObject) viewer)->prefix, "-dm_plex_view_hasse", &drawHasse, NULL));
965fe1cc32dSStefano Zampini 
966fe1cc32dSStefano Zampini     /* filter points with labelvalue != labeldefaultvalue */
9679566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
9689566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
9699566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd));
9709566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
971fe1cc32dSStefano Zampini     if (lflg) {
972fe1cc32dSStefano Zampini       DMLabel lbl;
973fe1cc32dSStefano Zampini 
9749566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, lname, &lbl));
975fe1cc32dSStefano Zampini       if (lbl) {
976fe1cc32dSStefano Zampini         PetscInt val, defval;
977fe1cc32dSStefano Zampini 
9789566063dSJacob Faibussowitsch         PetscCall(DMLabelGetDefaultValue(lbl, &defval));
9799566063dSJacob Faibussowitsch         PetscCall(PetscBTCreate(pEnd-pStart, &wp));
980fe1cc32dSStefano Zampini         for (c = pStart;  c < pEnd; c++) {
981fe1cc32dSStefano Zampini           PetscInt *closure = NULL;
982fe1cc32dSStefano Zampini           PetscInt  closureSize;
983fe1cc32dSStefano Zampini 
9849566063dSJacob Faibussowitsch           PetscCall(DMLabelGetValue(lbl, c, &val));
985fe1cc32dSStefano Zampini           if (val == defval) continue;
986fe1cc32dSStefano Zampini 
9879566063dSJacob Faibussowitsch           PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
988fe1cc32dSStefano Zampini           for (p = 0; p < closureSize*2; p += 2) {
9899566063dSJacob Faibussowitsch             PetscCall(PetscBTSet(wp, closure[p] - pStart));
990fe1cc32dSStefano Zampini           }
9919566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
992fe1cc32dSStefano Zampini         }
993fe1cc32dSStefano Zampini       }
994fe1cc32dSStefano Zampini     }
995fe1cc32dSStefano Zampini 
9969566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
9979566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
9989566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject) dm, &name));
9999566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\
10000588280cSMatthew G. Knepley \\documentclass[tikz]{standalone}\n\n\
1001552f7358SJed Brown \\usepackage{pgflibraryshapes}\n\
1002552f7358SJed Brown \\usetikzlibrary{backgrounds}\n\
1003552f7358SJed Brown \\usetikzlibrary{arrows}\n\
10045f80ce2aSJacob Faibussowitsch \\begin{document}\n"));
10050588280cSMatthew G. Knepley     if (size > 1) {
10069566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s for process ", name));
1007770b213bSMatthew G Knepley       for (p = 0; p < size; ++p) {
100863a3b9bcSJacob Faibussowitsch         if (p) PetscCall(PetscViewerASCIIPrintf(viewer, (p == size-1) ? ", and " :  ", "));
100963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%" PetscInt_FMT "}", colors[p%numColors], p));
1010770b213bSMatthew G Knepley       }
10119566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, ".\n\n\n"));
10120588280cSMatthew G. Knepley     }
1013b7f6ffafSMatthew G. Knepley     if (drawHasse) {
1014b7f6ffafSMatthew G. Knepley       PetscInt maxStratum = PetscMax(vEnd-vStart, PetscMax(eEnd-eStart, cEnd-cStart));
1015b7f6ffafSMatthew G. Knepley 
101663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vStart}{%" PetscInt_FMT "}\n", vStart));
101763a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vEnd}{%" PetscInt_FMT "}\n", vEnd-1));
101863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numVertices}{%" PetscInt_FMT "}\n", vEnd-vStart));
10199566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vShift}{%.2f}\n", 3 + (maxStratum-(vEnd-vStart))/2.));
102063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eStart}{%" PetscInt_FMT "}\n", eStart));
102163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eEnd}{%" PetscInt_FMT "}\n", eEnd-1));
10229566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eShift}{%.2f}\n", 3 + (maxStratum-(eEnd-eStart))/2.));
102363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numEdges}{%" PetscInt_FMT "}\n", eEnd-eStart));
102463a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cStart}{%" PetscInt_FMT "}\n", cStart));
102563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cEnd}{%" PetscInt_FMT "}\n", cEnd-1));
102663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numCells}{%" PetscInt_FMT "}\n", cEnd-cStart));
10279566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cShift}{%.2f}\n", 3 + (maxStratum-(cEnd-cStart))/2.));
1028b7f6ffafSMatthew G. Knepley     }
10299566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double) tikzscale));
1030fe1cc32dSStefano Zampini 
1031552f7358SJed Brown     /* Plot vertices */
10329566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
10339566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
1034552f7358SJed Brown     for (v = vStart; v < vEnd; ++v) {
1035552f7358SJed Brown       PetscInt  off, dof, d;
10360588280cSMatthew G. Knepley       PetscBool isLabeled = PETSC_FALSE;
1037552f7358SJed Brown 
1038fe1cc32dSStefano Zampini       if (wp && !PetscBTLookup(wp,v - pStart)) continue;
10399566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(coordSection, v, &dof));
10409566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, v, &off));
10419566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path ("));
104263a3b9bcSJacob Faibussowitsch       PetscCheck(dof <= 3,PETSC_COMM_SELF,PETSC_ERR_PLIB,"coordSection vertex %" PetscInt_FMT " has dof %" PetscInt_FMT " > 3",v,dof);
10430588280cSMatthew G. Knepley       for (d = 0; d < dof; ++d) {
10440588280cSMatthew G. Knepley         tcoords[d] = (double) (scale*PetscRealPart(coords[off+d]));
1045c068d9bbSLisandro Dalcin         tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
10460588280cSMatthew G. Knepley       }
10470588280cSMatthew G. Knepley       /* Rotate coordinates since PGF makes z point out of the page instead of up */
10480588280cSMatthew G. Knepley       if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;}
1049552f7358SJed Brown       for (d = 0; d < dof; ++d) {
10509566063dSJacob Faibussowitsch         if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
10519566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) tcoords[d]));
1052552f7358SJed Brown       }
1053b7f6ffafSMatthew G. Knepley       if (drawHasse) color = colors[0%numColors];
1054b7f6ffafSMatthew G. Knepley       else           color = colors[rank%numColors];
10550588280cSMatthew G. Knepley       for (l = 0; l < numLabels; ++l) {
10560588280cSMatthew G. Knepley         PetscInt val;
10579566063dSJacob Faibussowitsch         PetscCall(DMGetLabelValue(dm, names[l], v, &val));
10580588280cSMatthew G. Knepley         if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;}
10590588280cSMatthew G. Knepley       }
1060b7f6ffafSMatthew G. Knepley       if (drawNumbers[0]) {
106163a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", v, rank, color, v));
1062b7f6ffafSMatthew G. Knepley       } else if (drawColors[0]) {
106363a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color));
10641baa6e33SBarry Smith       } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", v, rank));
1065552f7358SJed Brown     }
10669566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
10679566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
1068b7f6ffafSMatthew G. Knepley     /* Plot edges */
1069b7f6ffafSMatthew G. Knepley     if (plotEdges) {
10709566063dSJacob Faibussowitsch       PetscCall(VecGetArray(coordinates, &coords));
10719566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\path\n"));
1072b7f6ffafSMatthew G. Knepley       for (e = eStart; e < eEnd; ++e) {
1073b7f6ffafSMatthew G. Knepley         const PetscInt *cone;
1074b7f6ffafSMatthew G. Knepley         PetscInt        coneSize, offA, offB, dof, d;
1075b7f6ffafSMatthew G. Knepley 
1076b7f6ffafSMatthew G. Knepley         if (wp && !PetscBTLookup(wp,e - pStart)) continue;
10779566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, e, &coneSize));
107863a3b9bcSJacob Faibussowitsch         PetscCheck(coneSize == 2,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %" PetscInt_FMT " cone should have two vertices, not %" PetscInt_FMT, e, coneSize);
10799566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, e, &cone));
10809566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(coordSection, cone[0], &dof));
10819566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(coordSection, cone[0], &offA));
10829566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(coordSection, cone[1], &offB));
10839566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "("));
1084b7f6ffafSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
1085b7f6ffafSMatthew G. Knepley           tcoords[d] = (double) (0.5*scale*PetscRealPart(coords[offA+d]+coords[offB+d]));
1086b7f6ffafSMatthew G. Knepley           tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
1087b7f6ffafSMatthew G. Knepley         }
1088b7f6ffafSMatthew G. Knepley         /* Rotate coordinates since PGF makes z point out of the page instead of up */
1089b7f6ffafSMatthew G. Knepley         if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;}
1090b7f6ffafSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
10919566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
10929566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d]));
1093b7f6ffafSMatthew G. Knepley         }
1094b7f6ffafSMatthew G. Knepley         if (drawHasse) color = colors[1%numColors];
1095b7f6ffafSMatthew G. Knepley         else           color = colors[rank%numColors];
1096b7f6ffafSMatthew G. Knepley         for (l = 0; l < numLabels; ++l) {
1097b7f6ffafSMatthew G. Knepley           PetscInt val;
10989566063dSJacob Faibussowitsch           PetscCall(DMGetLabelValue(dm, names[l], v, &val));
1099b7f6ffafSMatthew G. Knepley           if (val >= 0) {color = lcolors[l%numLColors]; break;}
1100b7f6ffafSMatthew G. Knepley         }
110163a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "} --\n", e, rank, color, e));
1102b7f6ffafSMatthew G. Knepley       }
11039566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(coordinates, &coords));
11049566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
11059566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "(0,0);\n"));
1106b7f6ffafSMatthew G. Knepley     }
1107846a3e8bSMatthew G. Knepley     /* Plot cells */
1108b7f6ffafSMatthew G. Knepley     if (dim == 3 || !drawNumbers[1]) {
1109846a3e8bSMatthew G. Knepley       for (e = eStart; e < eEnd; ++e) {
1110846a3e8bSMatthew G. Knepley         const PetscInt *cone;
1111846a3e8bSMatthew G. Knepley 
1112fe1cc32dSStefano Zampini         if (wp && !PetscBTLookup(wp,e - pStart)) continue;
1113846a3e8bSMatthew G. Knepley         color = colors[rank%numColors];
1114846a3e8bSMatthew G. Knepley         for (l = 0; l < numLabels; ++l) {
1115846a3e8bSMatthew G. Knepley           PetscInt val;
11169566063dSJacob Faibussowitsch           PetscCall(DMGetLabelValue(dm, names[l], e, &val));
1117846a3e8bSMatthew G. Knepley           if (val >= 0) {color = lcolors[l%numLColors]; break;}
1118846a3e8bSMatthew G. Knepley         }
11199566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, e, &cone));
112063a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", color, cone[0], rank, cone[1], rank));
1121846a3e8bSMatthew G. Knepley       }
1122846a3e8bSMatthew G. Knepley     } else {
1123b7f6ffafSMatthew G. Knepley        DMPolytopeType ct;
1124846a3e8bSMatthew G. Knepley 
1125b7f6ffafSMatthew G. Knepley       /* Drawing a 2D polygon */
1126b7f6ffafSMatthew G. Knepley       for (c = cStart; c < cEnd; ++c) {
1127fe1cc32dSStefano Zampini         if (wp && !PetscBTLookup(wp, c - pStart)) continue;
11289566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, c, &ct));
1129b7f6ffafSMatthew G. Knepley         if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR ||
1130b7f6ffafSMatthew G. Knepley             ct == DM_POLYTOPE_TRI_PRISM_TENSOR ||
1131b7f6ffafSMatthew G. Knepley             ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) {
1132b7f6ffafSMatthew G. Knepley           const PetscInt *cone;
1133b7f6ffafSMatthew G. Knepley           PetscInt        coneSize, e;
1134b7f6ffafSMatthew G. Knepley 
11359566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCone(dm, c, &cone));
11369566063dSJacob Faibussowitsch           PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
1137b7f6ffafSMatthew G. Knepley           for (e = 0; e < coneSize; ++e) {
1138b7f6ffafSMatthew G. Knepley             const PetscInt *econe;
1139b7f6ffafSMatthew G. Knepley 
11409566063dSJacob Faibussowitsch             PetscCall(DMPlexGetCone(dm, cone[e], &econe));
114163a3b9bcSJacob 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));
1142b7f6ffafSMatthew G. Knepley           }
1143b7f6ffafSMatthew G. Knepley         } else {
1144b7f6ffafSMatthew G. Knepley           PetscInt *closure = NULL;
1145b7f6ffafSMatthew G. Knepley           PetscInt  closureSize, Nv = 0, v;
1146b7f6ffafSMatthew G. Knepley 
11479566063dSJacob Faibussowitsch           PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1148846a3e8bSMatthew G. Knepley           for (p = 0; p < closureSize*2; p += 2) {
1149846a3e8bSMatthew G. Knepley             const PetscInt point = closure[p];
1150846a3e8bSMatthew G. Knepley 
1151b7f6ffafSMatthew G. Knepley             if ((point >= vStart) && (point < vEnd)) closure[Nv++] = point;
1152846a3e8bSMatthew G. Knepley           }
11539566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]));
1154b7f6ffafSMatthew G. Knepley           for (v = 0; v <= Nv; ++v) {
1155b7f6ffafSMatthew G. Knepley             const PetscInt vertex = closure[v%Nv];
1156b7f6ffafSMatthew G. Knepley 
1157b7f6ffafSMatthew G. Knepley             if (v > 0) {
1158b7f6ffafSMatthew G. Knepley               if (plotEdges) {
1159b7f6ffafSMatthew G. Knepley                 const PetscInt *edge;
1160b7f6ffafSMatthew G. Knepley                 PetscInt        endpoints[2], ne;
1161b7f6ffafSMatthew G. Knepley 
1162b7f6ffafSMatthew G. Knepley                 endpoints[0] = closure[v-1]; endpoints[1] = vertex;
11639566063dSJacob Faibussowitsch                 PetscCall(DMPlexGetJoin(dm, 2, endpoints, &ne, &edge));
116463a3b9bcSJacob Faibussowitsch                 PetscCheck(ne == 1,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find edge for vertices %" PetscInt_FMT ", %" PetscInt_FMT, endpoints[0], endpoints[1]);
116563a3b9bcSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- (%" PetscInt_FMT "_%d) -- ", edge[0], rank));
11669566063dSJacob Faibussowitsch                 PetscCall(DMPlexRestoreJoin(dm, 2, endpoints, &ne, &edge));
11671baa6e33SBarry Smith               } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- "));
1168b7f6ffafSMatthew G. Knepley             }
116963a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(%" PetscInt_FMT "_%d)", vertex, rank));
1170b7f6ffafSMatthew G. Knepley           }
11719566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ";\n"));
11729566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1173846a3e8bSMatthew G. Knepley         }
1174846a3e8bSMatthew G. Knepley       }
1175b7f6ffafSMatthew G. Knepley     }
11769566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
1177846a3e8bSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
1178846a3e8bSMatthew G. Knepley       double    ccoords[3] = {0.0, 0.0, 0.0};
1179846a3e8bSMatthew G. Knepley       PetscBool isLabeled  = PETSC_FALSE;
1180846a3e8bSMatthew G. Knepley       PetscInt *closure    = NULL;
1181846a3e8bSMatthew G. Knepley       PetscInt  closureSize, dof, d, n = 0;
1182846a3e8bSMatthew G. Knepley 
1183fe1cc32dSStefano Zampini       if (wp && !PetscBTLookup(wp,c - pStart)) continue;
11849566063dSJacob Faibussowitsch       PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
11859566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path ("));
1186846a3e8bSMatthew G. Knepley       for (p = 0; p < closureSize*2; p += 2) {
1187846a3e8bSMatthew G. Knepley         const PetscInt point = closure[p];
1188846a3e8bSMatthew G. Knepley         PetscInt       off;
1189846a3e8bSMatthew G. Knepley 
1190846a3e8bSMatthew G. Knepley         if ((point < vStart) || (point >= vEnd)) continue;
11919566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(coordSection, point, &dof));
11929566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(coordSection, point, &off));
1193846a3e8bSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
1194846a3e8bSMatthew G. Knepley           tcoords[d] = (double) (scale*PetscRealPart(coords[off+d]));
1195846a3e8bSMatthew G. Knepley           tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
1196846a3e8bSMatthew G. Knepley         }
1197846a3e8bSMatthew G. Knepley         /* Rotate coordinates since PGF makes z point out of the page instead of up */
1198846a3e8bSMatthew G. Knepley         if (dof == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;}
1199846a3e8bSMatthew G. Knepley         for (d = 0; d < dof; ++d) {ccoords[d] += tcoords[d];}
1200846a3e8bSMatthew G. Knepley         ++n;
1201846a3e8bSMatthew G. Knepley       }
1202846a3e8bSMatthew G. Knepley       for (d = 0; d < dof; ++d) {ccoords[d] /= n;}
12039566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1204846a3e8bSMatthew G. Knepley       for (d = 0; d < dof; ++d) {
12059566063dSJacob Faibussowitsch         if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
12069566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double) ccoords[d]));
1207846a3e8bSMatthew G. Knepley       }
1208b7f6ffafSMatthew G. Knepley       if (drawHasse) color = colors[depth%numColors];
1209b7f6ffafSMatthew G. Knepley       else           color = colors[rank%numColors];
1210846a3e8bSMatthew G. Knepley       for (l = 0; l < numLabels; ++l) {
1211846a3e8bSMatthew G. Knepley         PetscInt val;
12129566063dSJacob Faibussowitsch         PetscCall(DMGetLabelValue(dm, names[l], c, &val));
1213846a3e8bSMatthew G. Knepley         if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;}
1214846a3e8bSMatthew G. Knepley       }
1215b7f6ffafSMatthew G. Knepley       if (drawNumbers[dim]) {
121663a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", c, rank, color, c));
1217b7f6ffafSMatthew G. Knepley       } else if (drawColors[dim]) {
121863a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color));
12191baa6e33SBarry Smith       } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", c, rank));
1220846a3e8bSMatthew G. Knepley     }
12219566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
1222b7f6ffafSMatthew G. Knepley     if (drawHasse) {
1223b7f6ffafSMatthew G. Knepley       color = colors[depth%numColors];
12249566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Cells\n"));
12259566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\c in {\\cStart,...,\\cEnd}\n"));
12269566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
12279566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\c_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\cShift+\\c-\\cStart,0) {\\c};\n", rank, color));
12289566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1229552f7358SJed Brown 
1230b7f6ffafSMatthew G. Knepley       color = colors[1%numColors];
12319566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Edges\n"));
12329566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\e in {\\eStart,...,\\eEnd}\n"));
12339566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
12349566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\e_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\eShift+\\e-\\eStart,1) {\\e};\n", rank, color));
12359566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1236b7f6ffafSMatthew G. Knepley 
1237b7f6ffafSMatthew G. Knepley       color = colors[0%numColors];
12389566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Vertices\n"));
12399566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\v in {\\vStart,...,\\vEnd}\n"));
12409566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
12419566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\v_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\vShift+\\v-\\vStart,2) {\\v};\n", rank, color));
12429566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1243b7f6ffafSMatthew G. Knepley 
1244b7f6ffafSMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
1245b7f6ffafSMatthew G. Knepley         const PetscInt *cone;
1246b7f6ffafSMatthew G. Knepley         PetscInt        coneSize, cp;
1247b7f6ffafSMatthew G. Knepley 
12489566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, p, &cone));
12499566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
1250b7f6ffafSMatthew G. Knepley         for (cp = 0; cp < coneSize; ++cp) {
125163a3b9bcSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "\\draw[->, shorten >=1pt] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", cone[cp], rank, p, rank));
1252552f7358SJed Brown         }
12530588280cSMatthew G. Knepley       }
12540588280cSMatthew G. Knepley     }
12559566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
12569566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
12579566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n"));
125863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{document}\n"));
12599566063dSJacob Faibussowitsch     for (l = 0; l < numLabels;  ++l) PetscCall(PetscFree(names[l]));
12609566063dSJacob Faibussowitsch     for (c = 0; c < numColors;  ++c) PetscCall(PetscFree(colors[c]));
12619566063dSJacob Faibussowitsch     for (c = 0; c < numLColors; ++c) PetscCall(PetscFree(lcolors[c]));
12629566063dSJacob Faibussowitsch     PetscCall(PetscFree3(names, colors, lcolors));
12639566063dSJacob Faibussowitsch     PetscCall(PetscBTDestroy(&wp));
12640f7d6e4aSStefano Zampini   } else if (format == PETSC_VIEWER_LOAD_BALANCE) {
12650f7d6e4aSStefano Zampini     Vec                    cown,acown;
12660f7d6e4aSStefano Zampini     VecScatter             sct;
12670f7d6e4aSStefano Zampini     ISLocalToGlobalMapping g2l;
12680f7d6e4aSStefano Zampini     IS                     gid,acis;
12690f7d6e4aSStefano Zampini     MPI_Comm               comm,ncomm = MPI_COMM_NULL;
12700f7d6e4aSStefano Zampini     MPI_Group              ggroup,ngroup;
12710f7d6e4aSStefano Zampini     PetscScalar            *array,nid;
12720f7d6e4aSStefano Zampini     const PetscInt         *idxs;
12730f7d6e4aSStefano Zampini     PetscInt               *idxs2,*start,*adjacency,*work;
12740f7d6e4aSStefano Zampini     PetscInt64             lm[3],gm[3];
12750f7d6e4aSStefano Zampini     PetscInt               i,c,cStart,cEnd,cum,numVertices,ect,ectn,cellHeight;
12760f7d6e4aSStefano Zampini     PetscMPIInt            d1,d2,rank;
12770f7d6e4aSStefano Zampini 
12789566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)dm,&comm));
12799566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm,&rank));
1280b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
12819566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_split_type(comm,MPI_COMM_TYPE_SHARED,rank,MPI_INFO_NULL,&ncomm));
12820f7d6e4aSStefano Zampini #endif
12830f7d6e4aSStefano Zampini     if (ncomm != MPI_COMM_NULL) {
12849566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_group(comm,&ggroup));
12859566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_group(ncomm,&ngroup));
12860f7d6e4aSStefano Zampini       d1   = 0;
12879566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_translate_ranks(ngroup,1,&d1,ggroup,&d2));
12880f7d6e4aSStefano Zampini       nid  = d2;
12899566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_free(&ggroup));
12909566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_free(&ngroup));
12919566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_free(&ncomm));
12920f7d6e4aSStefano Zampini     } else nid = 0.0;
12930f7d6e4aSStefano Zampini 
12940f7d6e4aSStefano Zampini     /* Get connectivity */
12959566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm,&cellHeight));
12969566063dSJacob Faibussowitsch     PetscCall(DMPlexCreatePartitionerGraph(dm,cellHeight,&numVertices,&start,&adjacency,&gid));
12970f7d6e4aSStefano Zampini 
12980f7d6e4aSStefano Zampini     /* filter overlapped local cells */
12999566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm,cellHeight,&cStart,&cEnd));
13009566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(gid,&idxs));
13019566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(gid,&cum));
13029566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(cum,&idxs2));
13030f7d6e4aSStefano Zampini     for (c = cStart, cum = 0; c < cEnd; c++) {
13040f7d6e4aSStefano Zampini       if (idxs[c-cStart] < 0) continue;
13050f7d6e4aSStefano Zampini       idxs2[cum++] = idxs[c-cStart];
13060f7d6e4aSStefano Zampini     }
13079566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(gid,&idxs));
130863a3b9bcSJacob Faibussowitsch     PetscCheck(numVertices == cum,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected %" PetscInt_FMT " != %" PetscInt_FMT,numVertices,cum);
13099566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&gid));
13109566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm,numVertices,idxs2,PETSC_OWN_POINTER,&gid));
13110f7d6e4aSStefano Zampini 
13120f7d6e4aSStefano Zampini     /* support for node-aware cell locality */
13139566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm,start[numVertices],adjacency,PETSC_USE_POINTER,&acis));
13149566063dSJacob Faibussowitsch     PetscCall(VecCreateSeq(PETSC_COMM_SELF,start[numVertices],&acown));
13159566063dSJacob Faibussowitsch     PetscCall(VecCreateMPI(comm,numVertices,PETSC_DECIDE,&cown));
13169566063dSJacob Faibussowitsch     PetscCall(VecGetArray(cown,&array));
13170f7d6e4aSStefano Zampini     for (c = 0; c < numVertices; c++) array[c] = nid;
13189566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(cown,&array));
13199566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(cown,acis,acown,NULL,&sct));
13209566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD));
13219566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(sct,cown,acown,INSERT_VALUES,SCATTER_FORWARD));
13229566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&acis));
13239566063dSJacob Faibussowitsch     PetscCall(VecScatterDestroy(&sct));
13249566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&cown));
13250f7d6e4aSStefano Zampini 
13260f7d6e4aSStefano Zampini     /* compute edgeCut */
13270f7d6e4aSStefano Zampini     for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum,start[c+1]-start[c]);
13289566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(cum,&work));
13299566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(gid,&g2l));
13309566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingSetType(g2l,ISLOCALTOGLOBALMAPPINGHASH));
13319566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&gid));
13329566063dSJacob Faibussowitsch     PetscCall(VecGetArray(acown,&array));
13330f7d6e4aSStefano Zampini     for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) {
13340f7d6e4aSStefano Zampini       PetscInt totl;
13350f7d6e4aSStefano Zampini 
13360f7d6e4aSStefano Zampini       totl = start[c+1]-start[c];
13379566063dSJacob Faibussowitsch       PetscCall(ISGlobalToLocalMappingApply(g2l,IS_GTOLM_MASK,totl,adjacency+start[c],NULL,work));
13380f7d6e4aSStefano Zampini       for (i = 0; i < totl; i++) {
13390f7d6e4aSStefano Zampini         if (work[i] < 0) {
13400f7d6e4aSStefano Zampini           ect  += 1;
13410f7d6e4aSStefano Zampini           ectn += (array[i + start[c]] != nid) ? 0 : 1;
13420f7d6e4aSStefano Zampini         }
13430f7d6e4aSStefano Zampini       }
13440f7d6e4aSStefano Zampini     }
13459566063dSJacob Faibussowitsch     PetscCall(PetscFree(work));
13469566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(acown,&array));
13470f7d6e4aSStefano Zampini     lm[0] = numVertices > 0 ?  numVertices : PETSC_MAX_INT;
13480f7d6e4aSStefano Zampini     lm[1] = -numVertices;
13491c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(lm,gm,2,MPIU_INT64,MPI_MIN,comm));
135063a3b9bcSJacob 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]));
13510f7d6e4aSStefano Zampini     lm[0] = ect; /* edgeCut */
13520f7d6e4aSStefano Zampini     lm[1] = ectn; /* node-aware edgeCut */
13530f7d6e4aSStefano Zampini     lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */
13541c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(lm,gm,3,MPIU_INT64,MPI_SUM,comm));
135563a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,", empty %" PetscInt_FMT ")\n",(PetscInt)gm[2]));
1356b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
135763a3b9bcSJacob 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.));
13580f7d6e4aSStefano Zampini #else
135963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer,"  Edge Cut: %" PetscInt_FMT " (on node %.3f)\n",(PetscInt)(gm[0]/2),0.0));
13600f7d6e4aSStefano Zampini #endif
13619566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&g2l));
13629566063dSJacob Faibussowitsch     PetscCall(PetscFree(start));
13639566063dSJacob Faibussowitsch     PetscCall(PetscFree(adjacency));
13649566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&acown));
1365552f7358SJed Brown   } else {
1366412e9a14SMatthew G. Knepley     const char    *name;
1367d80ece95SMatthew G. Knepley     PetscInt      *sizes, *hybsizes, *ghostsizes;
1368412e9a14SMatthew G. Knepley     PetscInt       locDepth, depth, cellHeight, dim, d;
1369d80ece95SMatthew G. Knepley     PetscInt       pStart, pEnd, p, gcStart, gcEnd, gcNum;
1370ca7bf7eeSMatthew G. Knepley     PetscInt       numLabels, l, maxSize = 17;
13719318fe57SMatthew G. Knepley     DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN;
1372412e9a14SMatthew G. Knepley     MPI_Comm       comm;
1373412e9a14SMatthew G. Knepley     PetscMPIInt    size, rank;
1374552f7358SJed Brown 
13759566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject) dm, &comm));
13769566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(comm, &size));
13779566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
13789566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
13799566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
13809566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject) dm, &name));
138163a3b9bcSJacob Faibussowitsch     if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s"));
138263a3b9bcSJacob Faibussowitsch     else      PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s"));
138363a3b9bcSJacob Faibussowitsch     if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, "  Cells are at height %" PetscInt_FMT "\n", cellHeight));
13849566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dm, &locDepth));
13851c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm));
13869566063dSJacob Faibussowitsch     PetscCall(DMPlexGetGhostCellStratum(dm, &gcStart, &gcEnd));
1387d80ece95SMatthew G. Knepley     gcNum = gcEnd - gcStart;
13889566063dSJacob Faibussowitsch     if (size < maxSize) PetscCall(PetscCalloc3(size, &sizes, size, &hybsizes, size, &ghostsizes));
13899566063dSJacob Faibussowitsch     else                PetscCall(PetscCalloc3(3,    &sizes, 3,    &hybsizes, 3,    &ghostsizes));
1390412e9a14SMatthew G. Knepley     for (d = 0; d <= depth; d++) {
1391412e9a14SMatthew G. Knepley       PetscInt Nc[2] = {0, 0}, ict;
1392412e9a14SMatthew G. Knepley 
13939566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
13949566063dSJacob Faibussowitsch       if (pStart < pEnd) PetscCall(DMPlexGetCellType(dm, pStart, &ct0));
1395412e9a14SMatthew G. Knepley       ict  = ct0;
13969566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Bcast(&ict, 1, MPIU_INT, 0, comm));
1397412e9a14SMatthew G. Knepley       ct0  = (DMPolytopeType) ict;
1398412e9a14SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
1399412e9a14SMatthew G. Knepley         DMPolytopeType ct;
1400412e9a14SMatthew G. Knepley 
14019566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, p, &ct));
1402412e9a14SMatthew G. Knepley         if (ct == ct0) ++Nc[0];
1403412e9a14SMatthew G. Knepley         else           ++Nc[1];
1404412e9a14SMatthew G. Knepley       }
1405ca7bf7eeSMatthew G. Knepley       if (size < maxSize) {
14069566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Gather(&Nc[0], 1, MPIU_INT, sizes,    1, MPIU_INT, 0, comm));
14079566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm));
14089566063dSJacob Faibussowitsch         if (d == depth) PetscCallMPI(MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm));
140963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Number of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d));
1410834065abSMatthew G. Knepley         for (p = 0; p < size; ++p) {
1411dd400576SPatrick Sanan           if (rank == 0) {
141263a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sizes[p]+hybsizes[p]));
141363a3b9bcSJacob Faibussowitsch             if (hybsizes[p]   > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ")", hybsizes[p]));
141463a3b9bcSJacob Faibussowitsch             if (ghostsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "]", ghostsizes[p]));
1415834065abSMatthew G. Knepley           }
1416cbb7f117SMark Adams         }
1417ca7bf7eeSMatthew G. Knepley       } else {
1418ca7bf7eeSMatthew G. Knepley         PetscInt locMinMax[2];
1419ca7bf7eeSMatthew G. Knepley 
1420ca7bf7eeSMatthew G. Knepley         locMinMax[0] = Nc[0]+Nc[1]; locMinMax[1] = Nc[0]+Nc[1];
14219566063dSJacob Faibussowitsch         PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, sizes));
1422ca7bf7eeSMatthew G. Knepley         locMinMax[0] = Nc[1]; locMinMax[1] = Nc[1];
14239566063dSJacob Faibussowitsch         PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, hybsizes));
1424ca7bf7eeSMatthew G. Knepley         if (d == depth) {
1425ca7bf7eeSMatthew G. Knepley           locMinMax[0] = gcNum; locMinMax[1] = gcNum;
14269566063dSJacob Faibussowitsch           PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, ghostsizes));
1427ca7bf7eeSMatthew G. Knepley         }
142863a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Min/Max of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d));
14299566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1]));
14309566063dSJacob Faibussowitsch         if (hybsizes[0]   > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT "/%" PetscInt_FMT ")", hybsizes[0], hybsizes[1]));
14319566063dSJacob Faibussowitsch         if (ghostsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "/%" PetscInt_FMT "]", ghostsizes[0], ghostsizes[1]));
1432ca7bf7eeSMatthew G. Knepley       }
14339566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
1434552f7358SJed Brown     }
14359566063dSJacob Faibussowitsch     PetscCall(PetscFree3(sizes, hybsizes, ghostsizes));
14369318fe57SMatthew G. Knepley     {
14379318fe57SMatthew G. Knepley       const PetscReal *maxCell;
14389318fe57SMatthew G. Knepley       const PetscReal *L;
14396858538eSMatthew G. Knepley       PetscBool        localized;
14409318fe57SMatthew G. Knepley 
14416858538eSMatthew G. Knepley       PetscCall(DMGetPeriodicity(dm, &maxCell, &L));
14429566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocalized(dm, &localized));
14436858538eSMatthew G. Knepley       if (L || localized) {
14446858538eSMatthew G. Knepley         PetscCall(PetscViewerASCIIPrintf(viewer, "Periodic mesh"));
14459566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
14466858538eSMatthew G. Knepley         if (L) {
14476858538eSMatthew G. Knepley           PetscCall(PetscViewerASCIIPrintf(viewer, " ("));
14489318fe57SMatthew G. Knepley           for (d = 0; d < dim; ++d) {
14496858538eSMatthew G. Knepley             if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
14506858538eSMatthew G. Knepley             PetscCall(PetscViewerASCIIPrintf(viewer, "%s", L[d] > 0.0 ? "PERIODIC" : "NONE"));
14519318fe57SMatthew G. Knepley           }
14526858538eSMatthew G. Knepley           PetscCall(PetscViewerASCIIPrintf(viewer, ")"));
14536858538eSMatthew G. Knepley         }
14546858538eSMatthew G. Knepley         PetscCall(PetscViewerASCIIPrintf(viewer, " coordinates %s\n", localized ? "localized" : "not localized"));
14559566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
14569318fe57SMatthew G. Knepley       }
14579318fe57SMatthew G. Knepley     }
14589566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
14599566063dSJacob Faibussowitsch     if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n"));
1460a57dd577SMatthew G Knepley     for (l = 0; l < numLabels; ++l) {
1461a57dd577SMatthew G Knepley       DMLabel         label;
1462a57dd577SMatthew G Knepley       const char     *name;
1463a57dd577SMatthew G Knepley       IS              valueIS;
1464a57dd577SMatthew G Knepley       const PetscInt *values;
1465a57dd577SMatthew G Knepley       PetscInt        numValues, v;
1466a57dd577SMatthew G Knepley 
14679566063dSJacob Faibussowitsch       PetscCall(DMGetLabelName(dm, l, &name));
14689566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, name, &label));
14699566063dSJacob Faibussowitsch       PetscCall(DMLabelGetNumValues(label, &numValues));
147063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  %s: %" PetscInt_FMT " strata with value/size (", name, numValues));
14719566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValueIS(label, &valueIS));
14729566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(valueIS, &values));
14739566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
1474a57dd577SMatthew G Knepley       for (v = 0; v < numValues; ++v) {
1475a57dd577SMatthew G Knepley         PetscInt size;
1476a57dd577SMatthew G Knepley 
14779566063dSJacob Faibussowitsch         PetscCall(DMLabelGetStratumSize(label, values[v], &size));
14789566063dSJacob Faibussowitsch         if (v > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
147963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " (%" PetscInt_FMT ")", values[v], size));
1480a57dd577SMatthew G Knepley       }
14819566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, ")\n"));
14829566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
14839566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(valueIS, &values));
14849566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&valueIS));
1485a57dd577SMatthew G Knepley     }
1486c1cad2e7SMatthew G. Knepley     {
1487c1cad2e7SMatthew G. Knepley       char    **labelNames;
1488c1cad2e7SMatthew G. Knepley       PetscInt  Nl = numLabels;
1489c1cad2e7SMatthew G. Knepley       PetscBool flg;
1490c1cad2e7SMatthew G. Knepley 
14919566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Nl, &labelNames));
14929566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetStringArray(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_plex_view_labels", labelNames, &Nl, &flg));
1493c1cad2e7SMatthew G. Knepley       for (l = 0; l < Nl; ++l) {
1494c1cad2e7SMatthew G. Knepley         DMLabel label;
1495c1cad2e7SMatthew G. Knepley 
14969566063dSJacob Faibussowitsch         PetscCall(DMHasLabel(dm, labelNames[l], &flg));
1497c1cad2e7SMatthew G. Knepley         if (flg) {
14989566063dSJacob Faibussowitsch           PetscCall(DMGetLabel(dm, labelNames[l], &label));
14999566063dSJacob Faibussowitsch           PetscCall(DMLabelView(label, viewer));
1500c1cad2e7SMatthew G. Knepley         }
15019566063dSJacob Faibussowitsch         PetscCall(PetscFree(labelNames[l]));
1502c1cad2e7SMatthew G. Knepley       }
15039566063dSJacob Faibussowitsch       PetscCall(PetscFree(labelNames));
1504c1cad2e7SMatthew G. Knepley     }
150534aa8a36SMatthew G. Knepley     /* If no fields are specified, people do not want to see adjacency */
150634aa8a36SMatthew G. Knepley     if (dm->Nf) {
150734aa8a36SMatthew G. Knepley       PetscInt f;
150834aa8a36SMatthew G. Knepley 
150934aa8a36SMatthew G. Knepley       for (f = 0; f < dm->Nf; ++f) {
151034aa8a36SMatthew G. Knepley         const char *name;
151134aa8a36SMatthew G. Knepley 
15129566063dSJacob Faibussowitsch         PetscCall(PetscObjectGetName(dm->fields[f].disc, &name));
15139566063dSJacob Faibussowitsch         if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Field %s:\n", name));
15149566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
15159566063dSJacob Faibussowitsch         if (dm->fields[f].label) PetscCall(DMLabelView(dm->fields[f].label, viewer));
151634aa8a36SMatthew G. Knepley         if (dm->fields[f].adjacency[0]) {
15179566063dSJacob Faibussowitsch           if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n"));
15189566063dSJacob Faibussowitsch           else                            PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM\n"));
151934aa8a36SMatthew G. Knepley         } else {
15209566063dSJacob Faibussowitsch           if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FEM\n"));
15219566063dSJacob Faibussowitsch           else                            PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n"));
152234aa8a36SMatthew G. Knepley         }
15239566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
152434aa8a36SMatthew G. Knepley       }
152534aa8a36SMatthew G. Knepley     }
15269566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dm, &cdm));
15278e7ff633SMatthew G. Knepley     if (cdm) {
15289566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(viewer));
15299566063dSJacob Faibussowitsch       PetscCall(DMPlexView_Ascii(cdm, viewer));
15309566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(viewer));
15318e7ff633SMatthew G. Knepley     }
1532552f7358SJed Brown   }
1533552f7358SJed Brown   PetscFunctionReturn(0);
1534552f7358SJed Brown }
1535552f7358SJed Brown 
1536e5c487bfSMatthew G. Knepley static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[])
1537e5c487bfSMatthew G. Knepley {
1538e5c487bfSMatthew G. Knepley   DMPolytopeType ct;
1539e5c487bfSMatthew G. Knepley   PetscMPIInt    rank;
1540a12d352dSMatthew G. Knepley   PetscInt       cdim;
1541e5c487bfSMatthew G. Knepley 
1542e5c487bfSMatthew G. Knepley   PetscFunctionBegin;
15439566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank));
15449566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cell, &ct));
15459566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
1546e5c487bfSMatthew G. Knepley   switch (ct) {
1547a12d352dSMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
1548a12d352dSMatthew G. Knepley   case DM_POLYTOPE_POINT_PRISM_TENSOR:
1549a12d352dSMatthew G. Knepley     switch (cdim) {
1550a12d352dSMatthew G. Knepley     case 1:
1551a12d352dSMatthew G. Knepley     {
1552a12d352dSMatthew G. Knepley       const PetscReal y  = 0.5;  /* TODO Put it in the middle of the viewport */
1553a12d352dSMatthew G. Knepley       const PetscReal dy = 0.05; /* TODO Make it a fraction of the total length */
1554a12d352dSMatthew G. Knepley 
15559566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y,    PetscRealPart(coords[1]), y,    PETSC_DRAW_BLACK));
15569566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y+dy, PetscRealPart(coords[0]), y-dy, PETSC_DRAW_BLACK));
15579566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[1]), y+dy, PetscRealPart(coords[1]), y-dy, PETSC_DRAW_BLACK));
1558a12d352dSMatthew G. Knepley     }
1559a12d352dSMatthew G. Knepley     break;
1560a12d352dSMatthew G. Knepley     case 2:
1561a12d352dSMatthew G. Knepley     {
1562a12d352dSMatthew G. Knepley       const PetscReal dx = (PetscRealPart(coords[3]) - PetscRealPart(coords[1]));
1563a12d352dSMatthew G. Knepley       const PetscReal dy = (PetscRealPart(coords[2]) - PetscRealPart(coords[0]));
1564a12d352dSMatthew G. Knepley       const PetscReal l  = 0.1/PetscSqrtReal(dx*dx + dy*dy);
1565a12d352dSMatthew G. Knepley 
15669566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
15679566063dSJacob 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));
15689566063dSJacob 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));
1569a12d352dSMatthew G. Knepley     }
1570a12d352dSMatthew G. Knepley     break;
157163a3b9bcSJacob Faibussowitsch     default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of dimension %" PetscInt_FMT, cdim);
1572a12d352dSMatthew G. Knepley     }
1573a12d352dSMatthew G. Knepley     break;
1574e5c487bfSMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
15759566063dSJacob Faibussowitsch     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]),
1576e5c487bfSMatthew G. Knepley                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2,
1577e5c487bfSMatthew G. Knepley                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2,
15785f80ce2aSJacob Faibussowitsch                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2));
15799566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
15809566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK));
15819566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK));
1582e5c487bfSMatthew G. Knepley     break;
1583e5c487bfSMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
15849566063dSJacob Faibussowitsch     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]),
1585e5c487bfSMatthew G. Knepley                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2,
1586e5c487bfSMatthew G. Knepley                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2,
15875f80ce2aSJacob Faibussowitsch                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2));
15889566063dSJacob Faibussowitsch     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]),
1589e5c487bfSMatthew G. Knepley                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2,
1590e5c487bfSMatthew G. Knepley                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2,
15915f80ce2aSJacob Faibussowitsch                               PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2));
15929566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
15939566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK));
15949566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK));
15959566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK));
1596e5c487bfSMatthew G. Knepley     break;
159798921bdaSJacob Faibussowitsch   default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]);
1598e5c487bfSMatthew G. Knepley   }
1599e5c487bfSMatthew G. Knepley   PetscFunctionReturn(0);
1600e5c487bfSMatthew G. Knepley }
1601e5c487bfSMatthew G. Knepley 
1602e5c487bfSMatthew G. Knepley static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[])
1603e5c487bfSMatthew G. Knepley {
1604e5c487bfSMatthew G. Knepley   DMPolytopeType ct;
1605e5c487bfSMatthew G. Knepley   PetscReal      centroid[2] = {0., 0.};
1606e5c487bfSMatthew G. Knepley   PetscMPIInt    rank;
1607e5c487bfSMatthew G. Knepley   PetscInt       fillColor, v, e, d;
1608e5c487bfSMatthew G. Knepley 
1609e5c487bfSMatthew G. Knepley   PetscFunctionBegin;
16109566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank));
16119566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cell, &ct));
1612e5c487bfSMatthew G. Knepley   fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS-2) + 2;
1613e5c487bfSMatthew G. Knepley   switch (ct) {
1614e5c487bfSMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
1615e5c487bfSMatthew G. Knepley     {
1616e5c487bfSMatthew G. Knepley       PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.};
1617e5c487bfSMatthew G. Knepley 
1618e5c487bfSMatthew G. Knepley       for (v = 0; v < 3; ++v) {centroid[0] += PetscRealPart(coords[v*2+0])/3.;centroid[1] += PetscRealPart(coords[v*2+1])/3.;}
1619e5c487bfSMatthew G. Knepley       for (e = 0; e < 3; ++e) {
1620e5c487bfSMatthew G. Knepley         refCoords[0] = refVertices[e*2+0];
1621e5c487bfSMatthew G. Knepley         refCoords[1] = refVertices[e*2+1];
1622e5c487bfSMatthew G. Knepley         for (d = 1; d <= edgeDiv; ++d) {
1623e5c487bfSMatthew G. Knepley           refCoords[d*2+0] = refCoords[0] + (refVertices[(e+1)%3 * 2 + 0] - refCoords[0])*d/edgeDiv;
1624e5c487bfSMatthew G. Knepley           refCoords[d*2+1] = refCoords[1] + (refVertices[(e+1)%3 * 2 + 1] - refCoords[1])*d/edgeDiv;
1625e5c487bfSMatthew G. Knepley         }
16269566063dSJacob Faibussowitsch         PetscCall(DMPlexReferenceToCoordinates(dm, cell, edgeDiv+1, refCoords, edgeCoords));
1627e5c487bfSMatthew G. Knepley         for (d = 0; d < edgeDiv; ++d) {
16289566063dSJacob 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));
16299566063dSJacob 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));
1630e5c487bfSMatthew G. Knepley         }
1631e5c487bfSMatthew G. Knepley       }
1632e5c487bfSMatthew G. Knepley     }
1633e5c487bfSMatthew G. Knepley     break;
163498921bdaSJacob Faibussowitsch   default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]);
1635e5c487bfSMatthew G. Knepley   }
1636e5c487bfSMatthew G. Knepley   PetscFunctionReturn(0);
1637e5c487bfSMatthew G. Knepley }
1638e5c487bfSMatthew G. Knepley 
16397cd05799SMatthew G. Knepley static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer)
1640e412dcbdSMatthew G. Knepley {
1641e412dcbdSMatthew G. Knepley   PetscDraw          draw;
1642e412dcbdSMatthew G. Knepley   DM                 cdm;
1643e412dcbdSMatthew G. Knepley   PetscSection       coordSection;
1644e412dcbdSMatthew G. Knepley   Vec                coordinates;
1645e412dcbdSMatthew G. Knepley   const PetscScalar *coords;
164629494db1SLisandro Dalcin   PetscReal          xyl[2],xyr[2],bound[4] = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL};
1647e5c487bfSMatthew G. Knepley   PetscReal         *refCoords, *edgeCoords;
1648e5c487bfSMatthew G. Knepley   PetscBool          isnull, drawAffine = PETSC_TRUE;
1649e5c487bfSMatthew G. Knepley   PetscInt           dim, vStart, vEnd, cStart, cEnd, c, N, edgeDiv = 4;
1650e412dcbdSMatthew G. Knepley 
1651e412dcbdSMatthew G. Knepley   PetscFunctionBegin;
16529566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dim));
165363a3b9bcSJacob Faibussowitsch   PetscCheck(dim <= 2,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT, dim);
16549566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL));
16559566063dSJacob Faibussowitsch   if (!drawAffine) PetscCall(PetscMalloc2((edgeDiv+1)*dim, &refCoords, (edgeDiv+1)*dim, &edgeCoords));
16569566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
16579566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(cdm, &coordSection));
16589566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
16599566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
16609566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
1661e412dcbdSMatthew G. Knepley 
16629566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
16639566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
1664e412dcbdSMatthew G. Knepley   if (isnull) PetscFunctionReturn(0);
16659566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "Mesh"));
1666e412dcbdSMatthew G. Knepley 
16679566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(coordinates, &N));
16689566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(coordinates, &coords));
1669e412dcbdSMatthew G. Knepley   for (c = 0; c < N; c += dim) {
16700c81f2a8SMatthew G. Knepley     bound[0] = PetscMin(bound[0], PetscRealPart(coords[c]));   bound[2] = PetscMax(bound[2], PetscRealPart(coords[c]));
16710c81f2a8SMatthew G. Knepley     bound[1] = PetscMin(bound[1], PetscRealPart(coords[c+1])); bound[3] = PetscMax(bound[3], PetscRealPart(coords[c+1]));
1672e412dcbdSMatthew G. Knepley   }
16739566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(coordinates, &coords));
16741c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&bound[0],xyl,2,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)dm)));
16751c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&bound[2],xyr,2,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)dm)));
16769566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1]));
16779566063dSJacob Faibussowitsch   PetscCall(PetscDrawClear(draw));
1678e412dcbdSMatthew G. Knepley 
1679cf3064d3SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1680cf3064d3SMatthew G. Knepley     PetscScalar *coords = NULL;
1681ba2698f1SMatthew G. Knepley     PetscInt     numCoords;
1682cf3064d3SMatthew G. Knepley 
16839566063dSJacob Faibussowitsch     PetscCall(DMPlexVecGetClosureAtDepth_Internal(dm, coordSection, coordinates, c, 0, &numCoords, &coords));
16841baa6e33SBarry Smith     if (drawAffine) PetscCall(DMPlexDrawCell(dm, draw, c, coords));
16851baa6e33SBarry Smith     else PetscCall(DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords));
16869566063dSJacob Faibussowitsch     PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &numCoords, &coords));
1687cf3064d3SMatthew G. Knepley   }
16889566063dSJacob Faibussowitsch   if (!drawAffine) PetscCall(PetscFree2(refCoords, edgeCoords));
16899566063dSJacob Faibussowitsch   PetscCall(PetscDrawFlush(draw));
16909566063dSJacob Faibussowitsch   PetscCall(PetscDrawPause(draw));
16919566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave(draw));
1692e412dcbdSMatthew G. Knepley   PetscFunctionReturn(0);
1693e412dcbdSMatthew G. Knepley }
1694e412dcbdSMatthew G. Knepley 
16951e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII)
16961e50132fSMatthew G. Knepley #include <exodusII.h>
16976823f3c5SBlaise Bourdin #include <petscviewerexodusii.h>
16981e50132fSMatthew G. Knepley #endif
16991e50132fSMatthew G. Knepley 
1700552f7358SJed Brown PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer)
1701552f7358SJed Brown {
17021e50132fSMatthew G. Knepley   PetscBool      iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus;
1703002a2709SMatthew G. Knepley   char           name[PETSC_MAX_PATH_LEN];
1704552f7358SJed Brown 
1705552f7358SJed Brown   PetscFunctionBegin;
1706552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1707552f7358SJed Brown   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
17089566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII,    &iascii));
17099566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK,      &isvtk));
17109566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,     &ishdf5));
17119566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERDRAW,     &isdraw));
17129566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERGLVIS,    &isglvis));
17139566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWEREXODUSII, &isexodus));
1714552f7358SJed Brown   if (iascii) {
17158135c375SStefano Zampini     PetscViewerFormat format;
17169566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
17171baa6e33SBarry Smith     if (format == PETSC_VIEWER_ASCII_GLVIS) PetscCall(DMPlexView_GLVis(dm, viewer));
17181baa6e33SBarry Smith     else PetscCall(DMPlexView_Ascii(dm, viewer));
1719c6ccd67eSMatthew G. Knepley   } else if (ishdf5) {
1720c6ccd67eSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
17219566063dSJacob Faibussowitsch     PetscCall(DMPlexView_HDF5_Internal(dm, viewer));
1722c6ccd67eSMatthew G. Knepley #else
1723c6ccd67eSMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1724552f7358SJed Brown #endif
1725e412dcbdSMatthew G. Knepley   } else if (isvtk) {
17269566063dSJacob Faibussowitsch     PetscCall(DMPlexVTKWriteAll((PetscObject) dm,viewer));
1727e412dcbdSMatthew G. Knepley   } else if (isdraw) {
17289566063dSJacob Faibussowitsch     PetscCall(DMPlexView_Draw(dm, viewer));
17298135c375SStefano Zampini   } else if (isglvis) {
17309566063dSJacob Faibussowitsch     PetscCall(DMPlexView_GLVis(dm, viewer));
17311e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII)
17321e50132fSMatthew G. Knepley   } else if (isexodus) {
17336823f3c5SBlaise Bourdin /*
17346823f3c5SBlaise Bourdin       exodusII requires that all sets be part of exactly one cell set.
17356823f3c5SBlaise Bourdin       If the dm does not have a "Cell Sets" label defined, we create one
17366823f3c5SBlaise Bourdin       with ID 1, containig all cells.
17376823f3c5SBlaise Bourdin       Note that if the Cell Sets label is defined but does not cover all cells,
17386823f3c5SBlaise Bourdin       we may still have a problem. This should probably be checked here or in the viewer;
17396823f3c5SBlaise Bourdin     */
17406823f3c5SBlaise Bourdin     PetscInt numCS;
17419566063dSJacob Faibussowitsch     PetscCall(DMGetLabelSize(dm,"Cell Sets",&numCS));
17426823f3c5SBlaise Bourdin     if (!numCS) {
17431e50132fSMatthew G. Knepley       PetscInt cStart, cEnd, c;
17449566063dSJacob Faibussowitsch       PetscCall(DMCreateLabel(dm, "Cell Sets"));
17459566063dSJacob Faibussowitsch       PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
17469566063dSJacob Faibussowitsch       for (c = cStart; c < cEnd; ++c) PetscCall(DMSetLabelValue(dm, "Cell Sets", c, 1));
17476823f3c5SBlaise Bourdin     }
17489566063dSJacob Faibussowitsch     PetscCall(DMView_PlexExodusII(dm, viewer));
17491e50132fSMatthew G. Knepley #endif
17501baa6e33SBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name);
17511baa6e33SBarry Smith 
1752cb3ba0daSMatthew G. Knepley   /* Optionally view the partition */
17539566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_partition_view", &flg));
1754cb3ba0daSMatthew G. Knepley   if (flg) {
1755cb3ba0daSMatthew G. Knepley     Vec ranks;
17569566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateRankField(dm, &ranks));
17579566063dSJacob Faibussowitsch     PetscCall(VecView(ranks, viewer));
17589566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&ranks));
1759cb3ba0daSMatthew G. Knepley   }
1760002a2709SMatthew G. Knepley   /* Optionally view a label */
17619566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetString(((PetscObject) dm)->options, ((PetscObject) dm)->prefix, "-dm_label_view", name, sizeof(name), &flg));
1762002a2709SMatthew G. Knepley   if (flg) {
1763002a2709SMatthew G. Knepley     DMLabel label;
1764002a2709SMatthew G. Knepley     Vec     val;
1765002a2709SMatthew G. Knepley 
17669566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, name, &label));
176728b400f6SJacob Faibussowitsch     PetscCheck(label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name);
17689566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateLabelField(dm, label, &val));
17699566063dSJacob Faibussowitsch     PetscCall(VecView(val, viewer));
17709566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&val));
1771002a2709SMatthew G. Knepley   }
1772552f7358SJed Brown   PetscFunctionReturn(0);
1773552f7358SJed Brown }
1774552f7358SJed Brown 
17757f96f51bSksagiyam /*@
17767f96f51bSksagiyam   DMPlexTopologyView - Saves a DMPlex topology into a file
17777f96f51bSksagiyam 
17787f96f51bSksagiyam   Collective on DM
17797f96f51bSksagiyam 
17807f96f51bSksagiyam   Input Parameters:
17817f96f51bSksagiyam + dm     - The DM whose topology is to be saved
17827f96f51bSksagiyam - viewer - The PetscViewer for saving
17837f96f51bSksagiyam 
17847f96f51bSksagiyam   Level: advanced
17857f96f51bSksagiyam 
1786db781477SPatrick Sanan .seealso: `DMView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexTopologyLoad()`
17877f96f51bSksagiyam @*/
17887f96f51bSksagiyam PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer)
17897f96f51bSksagiyam {
17907f96f51bSksagiyam   PetscBool      ishdf5;
17917f96f51bSksagiyam 
17927f96f51bSksagiyam   PetscFunctionBegin;
17937f96f51bSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
17947f96f51bSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
17959566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
17969566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_TopologyView,viewer,0,0,0));
17977f96f51bSksagiyam   if (ishdf5) {
17987f96f51bSksagiyam #if defined(PETSC_HAVE_HDF5)
17997f96f51bSksagiyam     PetscViewerFormat format;
18009566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
18017f96f51bSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
18027f96f51bSksagiyam       IS globalPointNumbering;
18037f96f51bSksagiyam 
18049566063dSJacob Faibussowitsch       PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering));
18059566063dSJacob Faibussowitsch       PetscCall(DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer));
18069566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&globalPointNumbering));
180798921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]);
18087f96f51bSksagiyam #else
18097f96f51bSksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
18107f96f51bSksagiyam #endif
18117f96f51bSksagiyam   }
18129566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_TopologyView,viewer,0,0,0));
18137f96f51bSksagiyam   PetscFunctionReturn(0);
18147f96f51bSksagiyam }
18157f96f51bSksagiyam 
181677b8e257Sksagiyam /*@
181777b8e257Sksagiyam   DMPlexCoordinatesView - Saves DMPlex coordinates into a file
181877b8e257Sksagiyam 
181977b8e257Sksagiyam   Collective on DM
182077b8e257Sksagiyam 
182177b8e257Sksagiyam   Input Parameters:
182277b8e257Sksagiyam + dm     - The DM whose coordinates are to be saved
182377b8e257Sksagiyam - viewer - The PetscViewer for saving
182477b8e257Sksagiyam 
182577b8e257Sksagiyam   Level: advanced
182677b8e257Sksagiyam 
1827db781477SPatrick Sanan .seealso: `DMView()`, `DMPlexTopologyView()`, `DMPlexLabelsView()`, `DMPlexCoordinatesLoad()`
182877b8e257Sksagiyam @*/
182977b8e257Sksagiyam PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer)
183077b8e257Sksagiyam {
183177b8e257Sksagiyam   PetscBool      ishdf5;
183277b8e257Sksagiyam 
183377b8e257Sksagiyam   PetscFunctionBegin;
183477b8e257Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
183577b8e257Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
18369566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
18379566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesView,viewer,0,0,0));
183877b8e257Sksagiyam   if (ishdf5) {
183977b8e257Sksagiyam #if defined(PETSC_HAVE_HDF5)
184077b8e257Sksagiyam     PetscViewerFormat format;
18419566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
184277b8e257Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
18439566063dSJacob Faibussowitsch       PetscCall(DMPlexCoordinatesView_HDF5_Internal(dm, viewer));
184498921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
184577b8e257Sksagiyam #else
184677b8e257Sksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
184777b8e257Sksagiyam #endif
184877b8e257Sksagiyam   }
18499566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesView,viewer,0,0,0));
185077b8e257Sksagiyam   PetscFunctionReturn(0);
185177b8e257Sksagiyam }
185277b8e257Sksagiyam 
1853bd6565f1Sksagiyam /*@
1854bd6565f1Sksagiyam   DMPlexLabelsView - Saves DMPlex labels into a file
1855bd6565f1Sksagiyam 
1856bd6565f1Sksagiyam   Collective on DM
1857bd6565f1Sksagiyam 
1858bd6565f1Sksagiyam   Input Parameters:
1859bd6565f1Sksagiyam + dm     - The DM whose labels are to be saved
1860bd6565f1Sksagiyam - viewer - The PetscViewer for saving
1861bd6565f1Sksagiyam 
1862bd6565f1Sksagiyam   Level: advanced
1863bd6565f1Sksagiyam 
1864db781477SPatrick Sanan .seealso: `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsLoad()`
1865bd6565f1Sksagiyam @*/
1866bd6565f1Sksagiyam PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer)
1867bd6565f1Sksagiyam {
1868bd6565f1Sksagiyam   PetscBool      ishdf5;
1869bd6565f1Sksagiyam 
1870bd6565f1Sksagiyam   PetscFunctionBegin;
1871bd6565f1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1872bd6565f1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
18739566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
18749566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LabelsView,viewer,0,0,0));
1875bd6565f1Sksagiyam   if (ishdf5) {
1876bd6565f1Sksagiyam #if defined(PETSC_HAVE_HDF5)
1877bd6565f1Sksagiyam     IS                globalPointNumbering;
1878bd6565f1Sksagiyam     PetscViewerFormat format;
1879bd6565f1Sksagiyam 
18809566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
1881bd6565f1Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
18829566063dSJacob Faibussowitsch       PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering));
18839566063dSJacob Faibussowitsch       PetscCall(DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer));
18849566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&globalPointNumbering));
188598921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
1886bd6565f1Sksagiyam #else
1887bd6565f1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1888bd6565f1Sksagiyam #endif
1889bd6565f1Sksagiyam   }
18909566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LabelsView,viewer,0,0,0));
1891bd6565f1Sksagiyam   PetscFunctionReturn(0);
1892bd6565f1Sksagiyam }
1893bd6565f1Sksagiyam 
1894021affd3Sksagiyam /*@
1895021affd3Sksagiyam   DMPlexSectionView - Saves a section associated with a DMPlex
1896021affd3Sksagiyam 
1897021affd3Sksagiyam   Collective on DM
1898021affd3Sksagiyam 
1899021affd3Sksagiyam   Input Parameters:
1900021affd3Sksagiyam + dm         - The DM that contains the topology on which the section to be saved is defined
1901021affd3Sksagiyam . viewer     - The PetscViewer for saving
1902021affd3Sksagiyam - sectiondm  - The DM that contains the section to be saved
1903021affd3Sksagiyam 
1904021affd3Sksagiyam   Level: advanced
1905021affd3Sksagiyam 
1906021affd3Sksagiyam   Notes:
1907021affd3Sksagiyam   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.
1908021affd3Sksagiyam 
1909021affd3Sksagiyam   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.
1910021affd3Sksagiyam 
1911db781477SPatrick Sanan .seealso: `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, `PetscSectionView()`, `DMPlexSectionLoad()`
1912021affd3Sksagiyam @*/
1913021affd3Sksagiyam PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm)
1914021affd3Sksagiyam {
1915021affd3Sksagiyam   PetscBool      ishdf5;
1916021affd3Sksagiyam 
1917021affd3Sksagiyam   PetscFunctionBegin;
1918021affd3Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1919021affd3Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1920021affd3Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
19219566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5));
19229566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_SectionView,viewer,0,0,0));
1923021affd3Sksagiyam   if (ishdf5) {
1924021affd3Sksagiyam #if defined(PETSC_HAVE_HDF5)
19259566063dSJacob Faibussowitsch     PetscCall(DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm));
1926021affd3Sksagiyam #else
1927021affd3Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1928021affd3Sksagiyam #endif
1929021affd3Sksagiyam   }
19309566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_SectionView,viewer,0,0,0));
1931021affd3Sksagiyam   PetscFunctionReturn(0);
1932021affd3Sksagiyam }
1933021affd3Sksagiyam 
19343e97647fSksagiyam /*@
19353e97647fSksagiyam   DMPlexGlobalVectorView - Saves a global vector
19363e97647fSksagiyam 
19373e97647fSksagiyam   Collective on DM
19383e97647fSksagiyam 
19393e97647fSksagiyam   Input Parameters:
19403e97647fSksagiyam + dm        - The DM that represents the topology
19413e97647fSksagiyam . viewer    - The PetscViewer to save data with
19423e97647fSksagiyam . sectiondm - The DM that contains the global section on which vec is defined
19433e97647fSksagiyam - vec       - The global vector to be saved
19443e97647fSksagiyam 
19453e97647fSksagiyam   Level: advanced
19463e97647fSksagiyam 
19473e97647fSksagiyam   Notes:
19483e97647fSksagiyam   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.
19493e97647fSksagiyam 
19503e97647fSksagiyam   Typical calling sequence
19513e97647fSksagiyam $       DMCreate(PETSC_COMM_WORLD, &dm);
19523e97647fSksagiyam $       DMSetType(dm, DMPLEX);
19533e97647fSksagiyam $       PetscObjectSetName((PetscObject)dm, "topologydm_name");
19543e97647fSksagiyam $       DMClone(dm, &sectiondm);
19553e97647fSksagiyam $       PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
19563e97647fSksagiyam $       PetscSectionCreate(PETSC_COMM_WORLD, &section);
19573e97647fSksagiyam $       DMPlexGetChart(sectiondm, &pStart, &pEnd);
19583e97647fSksagiyam $       PetscSectionSetChart(section, pStart, pEnd);
19593e97647fSksagiyam $       PetscSectionSetUp(section);
19603e97647fSksagiyam $       DMSetLocalSection(sectiondm, section);
19613e97647fSksagiyam $       PetscSectionDestroy(&section);
19623e97647fSksagiyam $       DMGetGlobalVector(sectiondm, &vec);
19633e97647fSksagiyam $       PetscObjectSetName((PetscObject)vec, "vec_name");
19643e97647fSksagiyam $       DMPlexTopologyView(dm, viewer);
19653e97647fSksagiyam $       DMPlexSectionView(dm, viewer, sectiondm);
19663e97647fSksagiyam $       DMPlexGlobalVectorView(dm, viewer, sectiondm, vec);
19673e97647fSksagiyam $       DMRestoreGlobalVector(sectiondm, &vec);
19683e97647fSksagiyam $       DMDestroy(&sectiondm);
19693e97647fSksagiyam $       DMDestroy(&dm);
19703e97647fSksagiyam 
1971db781477SPatrick Sanan .seealso: `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexLocalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`
19723e97647fSksagiyam @*/
19733e97647fSksagiyam PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec)
19743e97647fSksagiyam {
19753e97647fSksagiyam   PetscBool       ishdf5;
19763e97647fSksagiyam 
19773e97647fSksagiyam   PetscFunctionBegin;
19783e97647fSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
19793e97647fSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
19803e97647fSksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
19813e97647fSksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 4);
19823e97647fSksagiyam   /* Check consistency */
19833e97647fSksagiyam   {
19843e97647fSksagiyam     PetscSection  section;
19853e97647fSksagiyam     PetscBool     includesConstraints;
19863e97647fSksagiyam     PetscInt      m, m1;
19873e97647fSksagiyam 
19889566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
19899566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(sectiondm, &section));
19909566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
19919566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
19929566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
199363a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m);
19943e97647fSksagiyam   }
19959566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
19969566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorView,viewer,0,0,0));
19973e97647fSksagiyam   if (ishdf5) {
19983e97647fSksagiyam #if defined(PETSC_HAVE_HDF5)
19999566063dSJacob Faibussowitsch     PetscCall(DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec));
20003e97647fSksagiyam #else
20013e97647fSksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
20023e97647fSksagiyam #endif
20033e97647fSksagiyam   }
20049566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorView,viewer,0,0,0));
20053e97647fSksagiyam   PetscFunctionReturn(0);
20063e97647fSksagiyam }
20073e97647fSksagiyam 
20083e97647fSksagiyam /*@
20093e97647fSksagiyam   DMPlexLocalVectorView - Saves a local vector
20103e97647fSksagiyam 
20113e97647fSksagiyam   Collective on DM
20123e97647fSksagiyam 
20133e97647fSksagiyam   Input Parameters:
20143e97647fSksagiyam + dm        - The DM that represents the topology
20153e97647fSksagiyam . viewer    - The PetscViewer to save data with
20163e97647fSksagiyam . sectiondm - The DM that contains the local section on which vec is defined; may be the same as dm
20173e97647fSksagiyam - vec       - The local vector to be saved
20183e97647fSksagiyam 
20193e97647fSksagiyam   Level: advanced
20203e97647fSksagiyam 
20213e97647fSksagiyam   Notes:
20223e97647fSksagiyam   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.
20233e97647fSksagiyam 
20243e97647fSksagiyam   Typical calling sequence
20253e97647fSksagiyam $       DMCreate(PETSC_COMM_WORLD, &dm);
20263e97647fSksagiyam $       DMSetType(dm, DMPLEX);
20273e97647fSksagiyam $       PetscObjectSetName((PetscObject)dm, "topologydm_name");
20283e97647fSksagiyam $       DMClone(dm, &sectiondm);
20293e97647fSksagiyam $       PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
20303e97647fSksagiyam $       PetscSectionCreate(PETSC_COMM_WORLD, &section);
20313e97647fSksagiyam $       DMPlexGetChart(sectiondm, &pStart, &pEnd);
20323e97647fSksagiyam $       PetscSectionSetChart(section, pStart, pEnd);
20333e97647fSksagiyam $       PetscSectionSetUp(section);
20343e97647fSksagiyam $       DMSetLocalSection(sectiondm, section);
20353e97647fSksagiyam $       DMGetLocalVector(sectiondm, &vec);
20363e97647fSksagiyam $       PetscObjectSetName((PetscObject)vec, "vec_name");
20373e97647fSksagiyam $       DMPlexTopologyView(dm, viewer);
20383e97647fSksagiyam $       DMPlexSectionView(dm, viewer, sectiondm);
20393e97647fSksagiyam $       DMPlexLocalVectorView(dm, viewer, sectiondm, vec);
20403e97647fSksagiyam $       DMRestoreLocalVector(sectiondm, &vec);
20413e97647fSksagiyam $       DMDestroy(&sectiondm);
20423e97647fSksagiyam $       DMDestroy(&dm);
20433e97647fSksagiyam 
2044db781477SPatrick Sanan .seealso: `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexGlobalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`
20453e97647fSksagiyam @*/
20463e97647fSksagiyam PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec)
20473e97647fSksagiyam {
20483e97647fSksagiyam   PetscBool       ishdf5;
20493e97647fSksagiyam 
20503e97647fSksagiyam   PetscFunctionBegin;
20513e97647fSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
20523e97647fSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
20533e97647fSksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
20543e97647fSksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 4);
20553e97647fSksagiyam   /* Check consistency */
20563e97647fSksagiyam   {
20573e97647fSksagiyam     PetscSection  section;
20583e97647fSksagiyam     PetscBool     includesConstraints;
20593e97647fSksagiyam     PetscInt      m, m1;
20603e97647fSksagiyam 
20619566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
20629566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(sectiondm, &section));
20639566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
20649566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
20659566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
206663a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m);
20673e97647fSksagiyam   }
20689566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
20699566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorView,viewer,0,0,0));
20703e97647fSksagiyam   if (ishdf5) {
20713e97647fSksagiyam #if defined(PETSC_HAVE_HDF5)
20729566063dSJacob Faibussowitsch     PetscCall(DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec));
20733e97647fSksagiyam #else
20743e97647fSksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
20753e97647fSksagiyam #endif
20763e97647fSksagiyam   }
20779566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorView,viewer,0,0,0));
20783e97647fSksagiyam   PetscFunctionReturn(0);
20793e97647fSksagiyam }
20803e97647fSksagiyam 
20812c40f234SMatthew G. Knepley PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer)
20822c40f234SMatthew G. Knepley {
2083d4f5a9a0SVaclav Hapla   PetscBool      ishdf5;
20842c40f234SMatthew G. Knepley 
20852c40f234SMatthew G. Knepley   PetscFunctionBegin;
20862c40f234SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
20872c40f234SMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
20889566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,   &ishdf5));
2089d4f5a9a0SVaclav Hapla   if (ishdf5) {
20902c40f234SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
20919c48423bSVaclav Hapla     PetscViewerFormat format;
20929566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
20939c48423bSVaclav Hapla     if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) {
20949566063dSJacob Faibussowitsch       PetscCall(DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer));
2095509517efSVaclav Hapla     } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
20969566063dSJacob Faibussowitsch       PetscCall(DMPlexLoad_HDF5_Internal(dm, viewer));
209798921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2098b458e8f1SJose E. Roman     PetscFunctionReturn(0);
20992c40f234SMatthew G. Knepley #else
21002c40f234SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2101552f7358SJed Brown #endif
210298921bdaSJacob Faibussowitsch   } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name);
2103552f7358SJed Brown }
2104552f7358SJed Brown 
2105ea8e1828Sksagiyam /*@
2106ea8e1828Sksagiyam   DMPlexTopologyLoad - Loads a topology into a DMPlex
2107ea8e1828Sksagiyam 
2108ea8e1828Sksagiyam   Collective on DM
2109ea8e1828Sksagiyam 
2110ea8e1828Sksagiyam   Input Parameters:
2111ea8e1828Sksagiyam + dm     - The DM into which the topology is loaded
2112ea8e1828Sksagiyam - viewer - The PetscViewer for the saved topology
2113ea8e1828Sksagiyam 
2114dec9e869Sksagiyam   Output Parameters:
2115f84dd6b4Sksagiyam . 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
2116dec9e869Sksagiyam 
2117ea8e1828Sksagiyam   Level: advanced
2118ea8e1828Sksagiyam 
2119db781477SPatrick Sanan .seealso: `DMLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`
2120ea8e1828Sksagiyam @*/
2121f84dd6b4Sksagiyam PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF)
2122ea8e1828Sksagiyam {
2123ea8e1828Sksagiyam   PetscBool      ishdf5;
2124ea8e1828Sksagiyam 
2125ea8e1828Sksagiyam   PetscFunctionBegin;
2126ea8e1828Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2127ea8e1828Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2128f84dd6b4Sksagiyam   if (globalToLocalPointSF) PetscValidPointer(globalToLocalPointSF, 3);
21299566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
21309566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_TopologyLoad,viewer,0,0,0));
2131ea8e1828Sksagiyam   if (ishdf5) {
2132ea8e1828Sksagiyam #if defined(PETSC_HAVE_HDF5)
2133ea8e1828Sksagiyam     PetscViewerFormat format;
21349566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
2135ea8e1828Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
21369566063dSJacob Faibussowitsch       PetscCall(DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
213798921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2138ea8e1828Sksagiyam #else
2139ea8e1828Sksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2140ea8e1828Sksagiyam #endif
2141ea8e1828Sksagiyam   }
21429566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_TopologyLoad,viewer,0,0,0));
2143ea8e1828Sksagiyam   PetscFunctionReturn(0);
2144ea8e1828Sksagiyam }
2145ea8e1828Sksagiyam 
21463e701f1cSksagiyam /*@
21473e701f1cSksagiyam   DMPlexCoordinatesLoad - Loads coordinates into a DMPlex
21483e701f1cSksagiyam 
21493e701f1cSksagiyam   Collective on DM
21503e701f1cSksagiyam 
21513e701f1cSksagiyam   Input Parameters:
21523e701f1cSksagiyam + dm     - The DM into which the coordinates are loaded
2153c9ad657eSksagiyam . viewer - The PetscViewer for the saved coordinates
2154c9ad657eSksagiyam - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer
21553e701f1cSksagiyam 
21563e701f1cSksagiyam   Level: advanced
21573e701f1cSksagiyam 
2158db781477SPatrick Sanan .seealso: `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`
21593e701f1cSksagiyam @*/
2160c9ad657eSksagiyam PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF)
21613e701f1cSksagiyam {
21623e701f1cSksagiyam   PetscBool      ishdf5;
21633e701f1cSksagiyam 
21643e701f1cSksagiyam   PetscFunctionBegin;
21653e701f1cSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
21663e701f1cSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2167c9ad657eSksagiyam   PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3);
21689566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
21699566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesLoad,viewer,0,0,0));
21703e701f1cSksagiyam   if (ishdf5) {
21713e701f1cSksagiyam #if defined(PETSC_HAVE_HDF5)
21723e701f1cSksagiyam     PetscViewerFormat format;
21739566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
21743e701f1cSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
21759566063dSJacob Faibussowitsch       PetscCall(DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
217698921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
21773e701f1cSksagiyam #else
21783e701f1cSksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
21793e701f1cSksagiyam #endif
21803e701f1cSksagiyam   }
21819566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesLoad,viewer,0,0,0));
21823e701f1cSksagiyam   PetscFunctionReturn(0);
21833e701f1cSksagiyam }
21843e701f1cSksagiyam 
2185b08ad5deSksagiyam /*@
2186b08ad5deSksagiyam   DMPlexLabelsLoad - Loads labels into a DMPlex
2187b08ad5deSksagiyam 
2188b08ad5deSksagiyam   Collective on DM
2189b08ad5deSksagiyam 
2190b08ad5deSksagiyam   Input Parameters:
2191b08ad5deSksagiyam + dm     - The DM into which the labels are loaded
2192e6368b79SVaclav Hapla . viewer - The PetscViewer for the saved labels
2193e6368b79SVaclav Hapla - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer
2194b08ad5deSksagiyam 
2195b08ad5deSksagiyam   Level: advanced
2196b08ad5deSksagiyam 
2197e6368b79SVaclav Hapla   Notes:
2198e6368b79SVaclav Hapla   The PetscSF argument must not be NULL if the DM is distributed, otherwise an error occurs.
2199e6368b79SVaclav Hapla 
2200db781477SPatrick Sanan .seealso: `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`
2201b08ad5deSksagiyam @*/
2202e6368b79SVaclav Hapla PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF)
2203b08ad5deSksagiyam {
2204b08ad5deSksagiyam   PetscBool      ishdf5;
2205b08ad5deSksagiyam 
2206b08ad5deSksagiyam   PetscFunctionBegin;
2207b08ad5deSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2208b08ad5deSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2209e6368b79SVaclav Hapla   if (globalToLocalPointSF) PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3);
22109566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5));
22119566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LabelsLoad,viewer,0,0,0));
2212b08ad5deSksagiyam   if (ishdf5) {
2213b08ad5deSksagiyam #if defined(PETSC_HAVE_HDF5)
2214b08ad5deSksagiyam     PetscViewerFormat format;
2215b08ad5deSksagiyam 
22169566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
2217b08ad5deSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
22189566063dSJacob Faibussowitsch       PetscCall(DMPlexLabelsLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
221998921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2220b08ad5deSksagiyam #else
2221b08ad5deSksagiyam     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2222b08ad5deSksagiyam #endif
2223b08ad5deSksagiyam   }
22249566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LabelsLoad,viewer,0,0,0));
2225b08ad5deSksagiyam   PetscFunctionReturn(0);
2226b08ad5deSksagiyam }
2227b08ad5deSksagiyam 
2228f84dd6b4Sksagiyam /*@
2229f84dd6b4Sksagiyam   DMPlexSectionLoad - Loads section into a DMPlex
2230f84dd6b4Sksagiyam 
2231f84dd6b4Sksagiyam   Collective on DM
2232f84dd6b4Sksagiyam 
2233f84dd6b4Sksagiyam   Input Parameters:
2234f84dd6b4Sksagiyam + dm          - The DM that represents the topology
2235f84dd6b4Sksagiyam . viewer      - The PetscViewer that represents the on-disk section (sectionA)
2236f84dd6b4Sksagiyam . sectiondm   - The DM into which the on-disk section (sectionA) is migrated
2237f84dd6b4Sksagiyam - globalToLocalPointSF - The SF returned by DMPlexTopologyLoad() when loading dm from viewer
2238f84dd6b4Sksagiyam 
2239f84dd6b4Sksagiyam   Output Parameters
2240f84dd6b4Sksagiyam + 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)
2241f84dd6b4Sksagiyam - 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)
2242f84dd6b4Sksagiyam 
2243f84dd6b4Sksagiyam   Level: advanced
2244f84dd6b4Sksagiyam 
2245f84dd6b4Sksagiyam   Notes:
2246f84dd6b4Sksagiyam   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.
2247f84dd6b4Sksagiyam 
2248f84dd6b4Sksagiyam   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.
2249f84dd6b4Sksagiyam 
2250f84dd6b4Sksagiyam   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.
2251f84dd6b4Sksagiyam 
2252f84dd6b4Sksagiyam   Example using 2 processes:
2253f84dd6b4Sksagiyam $  NX (number of points on dm): 4
2254f84dd6b4Sksagiyam $  sectionA                   : the on-disk section
2255f84dd6b4Sksagiyam $  vecA                       : a vector associated with sectionA
2256f84dd6b4Sksagiyam $  sectionB                   : sectiondm's local section constructed in this function
2257f84dd6b4Sksagiyam $  vecB (local)               : a vector associated with sectiondm's local section
2258f84dd6b4Sksagiyam $  vecB (global)              : a vector associated with sectiondm's global section
2259f84dd6b4Sksagiyam $
2260f84dd6b4Sksagiyam $                                     rank 0    rank 1
2261f84dd6b4Sksagiyam $  vecA (global)                  : [.0 .4 .1 | .2 .3]        <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad()
2262f84dd6b4Sksagiyam $  sectionA->atlasOff             :       0 2 | 1             <- loaded in PetscSectionLoad()
2263f84dd6b4Sksagiyam $  sectionA->atlasDof             :       1 3 | 1             <- loaded in PetscSectionLoad()
2264f84dd6b4Sksagiyam $  sectionA's global point numbers:       0 2 | 3             <- loaded in DMPlexSectionLoad()
2265f84dd6b4Sksagiyam $  [0, NX)                        :       0 1 | 2 3           <- conceptual partition used in globalToLocalPointSF
2266f84dd6b4Sksagiyam $  sectionB's global point numbers:     0 1 3 | 3 2           <- associated with [0, NX) by globalToLocalPointSF
2267f84dd6b4Sksagiyam $  sectionB->atlasDof             :     1 0 1 | 1 3
2268f84dd6b4Sksagiyam $  sectionB->atlasOff (no perm)   :     0 1 1 | 0 1
2269f84dd6b4Sksagiyam $  vecB (local)                   :   [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF
2270f84dd6b4Sksagiyam $  vecB (global)                  :    [.0 .4 | .1 .2 .3]     <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF
2271f84dd6b4Sksagiyam $
2272f84dd6b4Sksagiyam $  where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0.
2273f84dd6b4Sksagiyam 
2274db781477SPatrick Sanan .seealso: `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`, `PetscSectionLoad()`, `DMPlexSectionView()`
2275f84dd6b4Sksagiyam @*/
2276f84dd6b4Sksagiyam PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF globalToLocalPointSF, PetscSF *globalDofSF, PetscSF *localDofSF)
2277f84dd6b4Sksagiyam {
2278f84dd6b4Sksagiyam   PetscBool      ishdf5;
2279f84dd6b4Sksagiyam 
2280f84dd6b4Sksagiyam   PetscFunctionBegin;
2281f84dd6b4Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2282f84dd6b4Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2283f84dd6b4Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
2284f84dd6b4Sksagiyam   PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4);
2285f84dd6b4Sksagiyam   if (globalDofSF) PetscValidPointer(globalDofSF, 5);
2286f84dd6b4Sksagiyam   if (localDofSF) PetscValidPointer(localDofSF, 6);
22879566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5));
22889566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_SectionLoad,viewer,0,0,0));
2289f84dd6b4Sksagiyam   if (ishdf5) {
2290f84dd6b4Sksagiyam #if defined(PETSC_HAVE_HDF5)
22919566063dSJacob Faibussowitsch     PetscCall(DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF));
2292f84dd6b4Sksagiyam #else
2293f84dd6b4Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2294f84dd6b4Sksagiyam #endif
2295f84dd6b4Sksagiyam   }
22969566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_SectionLoad,viewer,0,0,0));
2297f84dd6b4Sksagiyam   PetscFunctionReturn(0);
2298f84dd6b4Sksagiyam }
2299f84dd6b4Sksagiyam 
23008be3dfe1Sksagiyam /*@
23018be3dfe1Sksagiyam   DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector
23028be3dfe1Sksagiyam 
23038be3dfe1Sksagiyam   Collective on DM
23048be3dfe1Sksagiyam 
23058be3dfe1Sksagiyam   Input Parameters:
23068be3dfe1Sksagiyam + dm        - The DM that represents the topology
23078be3dfe1Sksagiyam . viewer    - The PetscViewer that represents the on-disk vector data
23088be3dfe1Sksagiyam . sectiondm - The DM that contains the global section on which vec is defined
23098be3dfe1Sksagiyam . sf        - The SF that migrates the on-disk vector data into vec
23108be3dfe1Sksagiyam - vec       - The global vector to set values of
23118be3dfe1Sksagiyam 
23128be3dfe1Sksagiyam   Level: advanced
23138be3dfe1Sksagiyam 
23148be3dfe1Sksagiyam   Notes:
23158be3dfe1Sksagiyam   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.
23168be3dfe1Sksagiyam 
23178be3dfe1Sksagiyam   Typical calling sequence
23188be3dfe1Sksagiyam $       DMCreate(PETSC_COMM_WORLD, &dm);
23198be3dfe1Sksagiyam $       DMSetType(dm, DMPLEX);
23208be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)dm, "topologydm_name");
23218be3dfe1Sksagiyam $       DMPlexTopologyLoad(dm, viewer, &sfX);
23228be3dfe1Sksagiyam $       DMClone(dm, &sectiondm);
23238be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
23248be3dfe1Sksagiyam $       DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL);
23258be3dfe1Sksagiyam $       DMGetGlobalVector(sectiondm, &vec);
23268be3dfe1Sksagiyam $       PetscObjectSetName((PetscObject)vec, "vec_name");
23278be3dfe1Sksagiyam $       DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec);
23288be3dfe1Sksagiyam $       DMRestoreGlobalVector(sectiondm, &vec);
23298be3dfe1Sksagiyam $       PetscSFDestroy(&gsf);
23308be3dfe1Sksagiyam $       PetscSFDestroy(&sfX);
23318be3dfe1Sksagiyam $       DMDestroy(&sectiondm);
23328be3dfe1Sksagiyam $       DMDestroy(&dm);
23338be3dfe1Sksagiyam 
2334db781477SPatrick Sanan .seealso: `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexLocalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`
23358be3dfe1Sksagiyam @*/
23368be3dfe1Sksagiyam PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec)
23378be3dfe1Sksagiyam {
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 @*/
24088be3dfe1Sksagiyam PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec)
24098be3dfe1Sksagiyam {
24108be3dfe1Sksagiyam   PetscBool       ishdf5;
24118be3dfe1Sksagiyam 
24128be3dfe1Sksagiyam   PetscFunctionBegin;
24138be3dfe1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
24148be3dfe1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
24158be3dfe1Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
24168be3dfe1Sksagiyam   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4);
24178be3dfe1Sksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 5);
24188be3dfe1Sksagiyam   /* Check consistency */
24198be3dfe1Sksagiyam   {
24208be3dfe1Sksagiyam     PetscSection  section;
24218be3dfe1Sksagiyam     PetscBool     includesConstraints;
24228be3dfe1Sksagiyam     PetscInt      m, m1;
24238be3dfe1Sksagiyam 
24249566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
24259566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(sectiondm, &section));
24269566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
24279566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
24289566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
242963a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m);
24308be3dfe1Sksagiyam   }
24319566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5));
24329566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorLoad,viewer,0,0,0));
24338be3dfe1Sksagiyam   if (ishdf5) {
24348be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5)
24359566063dSJacob Faibussowitsch     PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec));
24368be3dfe1Sksagiyam #else
24378be3dfe1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
24388be3dfe1Sksagiyam #endif
24398be3dfe1Sksagiyam   }
24409566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorLoad,viewer,0,0,0));
24418be3dfe1Sksagiyam   PetscFunctionReturn(0);
24428be3dfe1Sksagiyam }
24438be3dfe1Sksagiyam 
2444552f7358SJed Brown PetscErrorCode DMDestroy_Plex(DM dm)
2445552f7358SJed Brown {
2446552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2447552f7358SJed Brown 
2448552f7358SJed Brown   PetscFunctionBegin;
24499566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMSetUpGLVisViewer_C",NULL));
24509566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertBoundaryValues_C", NULL));
24519566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMCreateNeumannOverlap_C", NULL));
24529566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMInterpolateSolution_C", NULL));
24532e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexInsertTimeDerviativeBoundaryValues_C", NULL));
24542e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexGetOverlap_C", NULL));
24552e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexDistributeGetDefault_C", NULL));
24562e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexDistributeSetDefault_C", NULL));
24572e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"MatComputeNeumannOverlap_C",NULL));
24586bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexReorderGetDefault_C", NULL));
24596bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexReorderSetDefault_C", NULL));
2460c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexGetOverlap_C",NULL));
2461c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm,"DMPlexSetOverlap_C",NULL));
24620d644c17SKarl Rupp   if (--mesh->refct > 0) PetscFunctionReturn(0);
24639566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->coneSection));
24649566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->cones));
24659566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->coneOrientations));
24669566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->supportSection));
24679566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->subdomainSection));
24689566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->supports));
24699566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->facesTmp));
24709566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->tetgenOpts));
24719566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->triangleOpts));
24729566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->transformType));
24739566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerDestroy(&mesh->partitioner));
24749566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&mesh->subpointMap));
24759566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->subpointIS));
24769566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->globalVertexNumbers));
24779566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->globalCellNumbers));
24789566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->anchorSection));
24799566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->anchorIS));
24809566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->parentSection));
24819566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->parents));
24829566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->childIDs));
24839566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->childSection));
24849566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->children));
24859566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&mesh->referenceTree));
24869566063dSJacob Faibussowitsch   PetscCall(PetscGridHashDestroy(&mesh->lbox));
24879566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->neighbors));
24889566063dSJacob Faibussowitsch   if (mesh->metricCtx) PetscCall(PetscFree(mesh->metricCtx));
2489552f7358SJed Brown   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
24909566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh));
2491552f7358SJed Brown   PetscFunctionReturn(0);
2492552f7358SJed Brown }
2493552f7358SJed Brown 
2494b412c318SBarry Smith PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J)
2495552f7358SJed Brown {
24968d1174e4SMatthew G. Knepley   PetscSection           sectionGlobal;
2497acd755d7SMatthew G. Knepley   PetscInt               bs = -1, mbs;
24989fca9976SJed Brown   PetscInt               localSize, localStart = 0;
2499837628f4SStefano Zampini   PetscBool              isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS;
2500b412c318SBarry Smith   MatType                mtype;
25011428887cSShri Abhyankar   ISLocalToGlobalMapping ltog;
2502552f7358SJed Brown 
2503552f7358SJed Brown   PetscFunctionBegin;
25049566063dSJacob Faibussowitsch   PetscCall(MatInitializePackage());
2505b412c318SBarry Smith   mtype = dm->mattype;
25069566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dm, &sectionGlobal));
25079566063dSJacob Faibussowitsch   /* PetscCall(PetscSectionGetStorageSize(sectionGlobal, &localSize)); */
25089566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize));
25099fca9976SJed Brown   PetscCallMPI(MPI_Exscan(&localSize, &localStart, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) dm)));
25109566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), J));
25119566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE));
25129566063dSJacob Faibussowitsch   PetscCall(MatSetType(*J, mtype));
25139566063dSJacob Faibussowitsch   PetscCall(MatSetFromOptions(*J));
25149566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(*J, &mbs));
2515acd755d7SMatthew G. Knepley   if (mbs > 1) bs = mbs;
25169566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSHELL, &isShell));
25179566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATBAIJ, &isBlock));
25189566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock));
25199566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock));
25209566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSBAIJ, &isSymBlock));
25219566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock));
25229566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock));
25239566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATIS, &isMatIS));
2524552f7358SJed Brown   if (!isShell) {
2525837628f4SStefano Zampini     PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS);
25269fca9976SJed Brown     PetscInt  *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *pblocks;
2527fad22124SMatthew G Knepley     PetscInt  pStart, pEnd, p, dof, cdof;
2528552f7358SJed Brown 
25299566063dSJacob Faibussowitsch     PetscCall(DMGetLocalToGlobalMapping(dm,&ltog));
25309fca9976SJed Brown 
25319fca9976SJed Brown     PetscCall(PetscCalloc1(localSize, &pblocks));
25329566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(sectionGlobal, &pStart, &pEnd));
2533e432b41dSStefano Zampini     for (p = pStart; p < pEnd; ++p) {
25349fca9976SJed Brown       PetscInt bdof, offset;
2535a9d99c84SMatthew G. Knepley 
25369566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sectionGlobal, p, &dof));
25379fca9976SJed Brown       PetscCall(PetscSectionGetOffset(sectionGlobal, p, &offset));
25389566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetConstraintDof(sectionGlobal, p, &cdof));
25399fca9976SJed Brown       for (PetscInt i=0; i < dof - cdof; i++)
25409fca9976SJed Brown         pblocks[offset - localStart + i] = dof - cdof;
25411d17a0a3SMatthew G. Knepley       dof  = dof < 0 ? -(dof+1) : dof;
25421d17a0a3SMatthew G. Knepley       bdof = cdof && (dof-cdof) ? 1 : dof;
25431d17a0a3SMatthew G. Knepley       if (dof) {
25441d17a0a3SMatthew G. Knepley         if (bs < 0)          {bs = bdof;}
25459fca9976SJed Brown         else if (bs != bdof) {bs = 1;}
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
25699fca9976SJed Brown         for (PetscInt j=1; j<pblocks[i]; j++) {
25709fca9976SJed Brown            PetscCheck(pblocks[i+j] == pblocks[i], PETSC_COMM_SELF, PETSC_ERR_PLIB, "Block of size %" PetscInt_FMT " mismatches entry %" PetscInt_FMT, pblocks[i], pblocks[i+j]);
25719fca9976SJed Brown         }
25729fca9976SJed Brown       }
25739fca9976SJed Brown       PetscCall(MatSetVariableBlockSizes(*J, nblocks, pblocks));
25749fca9976SJed Brown     }
25759fca9976SJed Brown     PetscCall(PetscFree(pblocks));
2576aa0f6e3cSJed Brown   }
25779566063dSJacob Faibussowitsch   PetscCall(MatSetDM(*J, dm));
2578552f7358SJed Brown   PetscFunctionReturn(0);
2579552f7358SJed Brown }
2580552f7358SJed Brown 
25817cd05799SMatthew G. Knepley /*@
2582a8f00d21SMatthew G. Knepley   DMPlexGetSubdomainSection - Returns the section associated with the subdomain
2583be36d101SStefano Zampini 
2584be36d101SStefano Zampini   Not collective
2585be36d101SStefano Zampini 
2586be36d101SStefano Zampini   Input Parameter:
2587be36d101SStefano Zampini . mesh - The DMPlex
2588be36d101SStefano Zampini 
2589be36d101SStefano Zampini   Output Parameters:
2590be36d101SStefano Zampini . subsection - The subdomain section
2591be36d101SStefano Zampini 
2592be36d101SStefano Zampini   Level: developer
2593be36d101SStefano Zampini 
2594be36d101SStefano Zampini .seealso:
25957cd05799SMatthew G. Knepley @*/
2596be36d101SStefano Zampini PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection)
2597be36d101SStefano Zampini {
2598be36d101SStefano Zampini   DM_Plex       *mesh = (DM_Plex*) dm->data;
2599be36d101SStefano Zampini 
2600be36d101SStefano Zampini   PetscFunctionBegin;
2601be36d101SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2602be36d101SStefano Zampini   if (!mesh->subdomainSection) {
2603be36d101SStefano Zampini     PetscSection section;
2604be36d101SStefano Zampini     PetscSF      sf;
2605be36d101SStefano Zampini 
26069566063dSJacob Faibussowitsch     PetscCall(PetscSFCreate(PETSC_COMM_SELF,&sf));
26079566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm,&section));
26089566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreateGlobalSection(section,sf,PETSC_FALSE,PETSC_TRUE,&mesh->subdomainSection));
26099566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sf));
2610be36d101SStefano Zampini   }
2611be36d101SStefano Zampini   *subsection = mesh->subdomainSection;
2612be36d101SStefano Zampini   PetscFunctionReturn(0);
2613be36d101SStefano Zampini }
2614be36d101SStefano Zampini 
2615552f7358SJed Brown /*@
2616552f7358SJed Brown   DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd)
2617552f7358SJed Brown 
2618552f7358SJed Brown   Not collective
2619552f7358SJed Brown 
2620552f7358SJed Brown   Input Parameter:
2621552f7358SJed Brown . mesh - The DMPlex
2622552f7358SJed Brown 
2623552f7358SJed Brown   Output Parameters:
2624552f7358SJed Brown + pStart - The first mesh point
2625552f7358SJed Brown - pEnd   - The upper bound for mesh points
2626552f7358SJed Brown 
2627552f7358SJed Brown   Level: beginner
2628552f7358SJed Brown 
2629db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetChart()`
2630552f7358SJed Brown @*/
2631552f7358SJed Brown PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd)
2632552f7358SJed Brown {
2633552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2634552f7358SJed Brown 
2635552f7358SJed Brown   PetscFunctionBegin;
2636552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
26379566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->coneSection, pStart, pEnd));
2638552f7358SJed Brown   PetscFunctionReturn(0);
2639552f7358SJed Brown }
2640552f7358SJed Brown 
2641552f7358SJed Brown /*@
2642552f7358SJed Brown   DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd)
2643552f7358SJed Brown 
2644552f7358SJed Brown   Not collective
2645552f7358SJed Brown 
2646552f7358SJed Brown   Input Parameters:
2647552f7358SJed Brown + mesh - The DMPlex
2648552f7358SJed Brown . pStart - The first mesh point
2649552f7358SJed Brown - pEnd   - The upper bound for mesh points
2650552f7358SJed Brown 
2651552f7358SJed Brown   Output Parameters:
2652552f7358SJed Brown 
2653552f7358SJed Brown   Level: beginner
2654552f7358SJed Brown 
2655db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetChart()`
2656552f7358SJed Brown @*/
2657552f7358SJed Brown PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd)
2658552f7358SJed Brown {
2659552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2660552f7358SJed Brown 
2661552f7358SJed Brown   PetscFunctionBegin;
2662552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
26639566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(mesh->coneSection, pStart, pEnd));
26649566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(mesh->supportSection, pStart, pEnd));
2665552f7358SJed Brown   PetscFunctionReturn(0);
2666552f7358SJed Brown }
2667552f7358SJed Brown 
2668552f7358SJed Brown /*@
2669eaf898f9SPatrick Sanan   DMPlexGetConeSize - Return the number of in-edges for this point in the DAG
2670552f7358SJed Brown 
2671552f7358SJed Brown   Not collective
2672552f7358SJed Brown 
2673552f7358SJed Brown   Input Parameters:
2674552f7358SJed Brown + mesh - The DMPlex
2675eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
2676552f7358SJed Brown 
2677552f7358SJed Brown   Output Parameter:
2678552f7358SJed Brown . size - The cone size for point p
2679552f7358SJed Brown 
2680552f7358SJed Brown   Level: beginner
2681552f7358SJed Brown 
2682db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`
2683552f7358SJed Brown @*/
2684552f7358SJed Brown PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size)
2685552f7358SJed Brown {
2686552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2687552f7358SJed Brown 
2688552f7358SJed Brown   PetscFunctionBegin;
2689552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2690dadcf809SJacob Faibussowitsch   PetscValidIntPointer(size, 3);
26919566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, size));
2692552f7358SJed Brown   PetscFunctionReturn(0);
2693552f7358SJed Brown }
2694552f7358SJed Brown 
2695552f7358SJed Brown /*@
2696eaf898f9SPatrick Sanan   DMPlexSetConeSize - Set the number of in-edges for this point in the DAG
2697552f7358SJed Brown 
2698552f7358SJed Brown   Not collective
2699552f7358SJed Brown 
2700552f7358SJed Brown   Input Parameters:
2701552f7358SJed Brown + mesh - The DMPlex
2702eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
2703552f7358SJed Brown - size - The cone size for point p
2704552f7358SJed Brown 
2705552f7358SJed Brown   Output Parameter:
2706552f7358SJed Brown 
2707552f7358SJed Brown   Note:
2708552f7358SJed Brown   This should be called after DMPlexSetChart().
2709552f7358SJed Brown 
2710552f7358SJed Brown   Level: beginner
2711552f7358SJed Brown 
2712db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetConeSize()`, `DMPlexSetChart()`
2713552f7358SJed Brown @*/
2714552f7358SJed Brown PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size)
2715552f7358SJed Brown {
2716552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2717552f7358SJed Brown 
2718552f7358SJed Brown   PetscFunctionBegin;
2719552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
27209566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetDof(mesh->coneSection, p, size));
2721552f7358SJed Brown   PetscFunctionReturn(0);
2722552f7358SJed Brown }
2723552f7358SJed Brown 
2724f5a469b9SMatthew G. Knepley /*@
2725eaf898f9SPatrick Sanan   DMPlexAddConeSize - Add the given number of in-edges to this point in the DAG
2726f5a469b9SMatthew G. Knepley 
2727f5a469b9SMatthew G. Knepley   Not collective
2728f5a469b9SMatthew G. Knepley 
2729f5a469b9SMatthew G. Knepley   Input Parameters:
2730f5a469b9SMatthew G. Knepley + mesh - The DMPlex
2731eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
2732f5a469b9SMatthew G. Knepley - size - The additional cone size for point p
2733f5a469b9SMatthew G. Knepley 
2734f5a469b9SMatthew G. Knepley   Output Parameter:
2735f5a469b9SMatthew G. Knepley 
2736f5a469b9SMatthew G. Knepley   Note:
2737f5a469b9SMatthew G. Knepley   This should be called after DMPlexSetChart().
2738f5a469b9SMatthew G. Knepley 
2739f5a469b9SMatthew G. Knepley   Level: beginner
2740f5a469b9SMatthew G. Knepley 
2741db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexGetConeSize()`, `DMPlexSetChart()`
2742f5a469b9SMatthew G. Knepley @*/
2743f5a469b9SMatthew G. Knepley PetscErrorCode DMPlexAddConeSize(DM dm, PetscInt p, PetscInt size)
2744f5a469b9SMatthew G. Knepley {
2745f5a469b9SMatthew G. Knepley   DM_Plex       *mesh = (DM_Plex*) dm->data;
2746f5a469b9SMatthew G. Knepley   PetscFunctionBegin;
2747f5a469b9SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
27489566063dSJacob Faibussowitsch   PetscCall(PetscSectionAddDof(mesh->coneSection, p, size));
2749f5a469b9SMatthew G. Knepley   PetscFunctionReturn(0);
2750f5a469b9SMatthew G. Knepley }
2751f5a469b9SMatthew G. Knepley 
2752552f7358SJed Brown /*@C
2753eaf898f9SPatrick Sanan   DMPlexGetCone - Return the points on the in-edges for this point in the DAG
2754552f7358SJed Brown 
2755552f7358SJed Brown   Not collective
2756552f7358SJed Brown 
2757552f7358SJed Brown   Input Parameters:
2758833c876bSVaclav Hapla + dm - The DMPlex
2759eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
2760552f7358SJed Brown 
2761552f7358SJed Brown   Output Parameter:
2762552f7358SJed Brown . cone - An array of points which are on the in-edges for point p
2763552f7358SJed Brown 
2764552f7358SJed Brown   Level: beginner
2765552f7358SJed Brown 
27663813dfbdSMatthew G Knepley   Fortran Notes:
27673813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
27683813dfbdSMatthew G Knepley   include petsc.h90 in your code.
2769922102d1SVaclav Hapla   You must also call DMPlexRestoreCone() after you finish using the returned array.
2770922102d1SVaclav Hapla   DMPlexRestoreCone() is not needed/available in C.
27713813dfbdSMatthew G Knepley 
2772db781477SPatrick Sanan .seealso: `DMPlexGetConeSize()`, `DMPlexSetCone()`, `DMPlexGetConeTuple()`, `DMPlexSetChart()`
2773552f7358SJed Brown @*/
2774552f7358SJed Brown PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[])
2775552f7358SJed Brown {
2776552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
2777552f7358SJed Brown   PetscInt       off;
2778552f7358SJed Brown 
2779552f7358SJed Brown   PetscFunctionBegin;
2780552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2781552f7358SJed Brown   PetscValidPointer(cone, 3);
27829566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
2783552f7358SJed Brown   *cone = &mesh->cones[off];
2784552f7358SJed Brown   PetscFunctionReturn(0);
2785552f7358SJed Brown }
2786552f7358SJed Brown 
27870ce7577fSVaclav Hapla /*@C
27880ce7577fSVaclav Hapla   DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG
27890ce7577fSVaclav Hapla 
27900ce7577fSVaclav Hapla   Not collective
27910ce7577fSVaclav Hapla 
27920ce7577fSVaclav Hapla   Input Parameters:
27930ce7577fSVaclav Hapla + dm - The DMPlex
27940ce7577fSVaclav Hapla - p - The IS of points, which must lie in the chart set with DMPlexSetChart()
27950ce7577fSVaclav Hapla 
2796d8d19677SJose E. Roman   Output Parameters:
27970ce7577fSVaclav Hapla + pConesSection - PetscSection describing the layout of pCones
27980ce7577fSVaclav Hapla - pCones - An array of points which are on the in-edges for the point set p
27990ce7577fSVaclav Hapla 
28000ce7577fSVaclav Hapla   Level: intermediate
28010ce7577fSVaclav Hapla 
2802db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeRecursive()`, `DMPlexSetChart()`
28030ce7577fSVaclav Hapla @*/
28040ce7577fSVaclav Hapla PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones)
28050ce7577fSVaclav Hapla {
28060ce7577fSVaclav Hapla   PetscSection        cs, newcs;
28070ce7577fSVaclav Hapla   PetscInt            *cones;
28080ce7577fSVaclav Hapla   PetscInt            *newarr=NULL;
28090ce7577fSVaclav Hapla   PetscInt            n;
28100ce7577fSVaclav Hapla 
28110ce7577fSVaclav Hapla   PetscFunctionBegin;
28129566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCones(dm, &cones));
28139566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSection(dm, &cs));
28149566063dSJacob Faibussowitsch   PetscCall(PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void**)&newarr) : NULL));
28150ce7577fSVaclav Hapla   if (pConesSection) *pConesSection = newcs;
28160ce7577fSVaclav Hapla   if (pCones) {
28179566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(newcs, &n));
28189566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones));
28190ce7577fSVaclav Hapla   }
28200ce7577fSVaclav Hapla   PetscFunctionReturn(0);
28210ce7577fSVaclav Hapla }
28220ce7577fSVaclav Hapla 
2823af9eab45SVaclav Hapla /*@
2824af9eab45SVaclav Hapla   DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices.
2825d4636a37SVaclav Hapla 
2826d4636a37SVaclav Hapla   Not collective
2827d4636a37SVaclav Hapla 
2828d4636a37SVaclav Hapla   Input Parameters:
2829d4636a37SVaclav Hapla + dm - The DMPlex
2830af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart()
2831d4636a37SVaclav Hapla 
2832d4636a37SVaclav Hapla   Output Parameter:
2833af9eab45SVaclav Hapla . expandedPoints - An array of vertices recursively expanded from input points
2834d4636a37SVaclav Hapla 
2835d4636a37SVaclav Hapla   Level: advanced
2836d4636a37SVaclav Hapla 
2837af9eab45SVaclav Hapla   Notes:
2838af9eab45SVaclav Hapla   Like DMPlexGetConeRecursive but returns only the 0-depth IS (i.e. vertices only) and no sections.
2839af9eab45SVaclav Hapla   There is no corresponding Restore function, just call ISDestroy() on the returned IS to deallocate.
2840af9eab45SVaclav Hapla 
2841db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetDepth()`
2842d4636a37SVaclav Hapla @*/
2843af9eab45SVaclav Hapla PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints)
2844d4636a37SVaclav Hapla {
2845af9eab45SVaclav Hapla   IS                  *expandedPointsAll;
2846af9eab45SVaclav Hapla   PetscInt            depth;
2847d4636a37SVaclav Hapla 
2848d4636a37SVaclav Hapla   PetscFunctionBegin;
2849af9eab45SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2850af9eab45SVaclav Hapla   PetscValidHeaderSpecific(points, IS_CLASSID, 2);
2851af9eab45SVaclav Hapla   PetscValidPointer(expandedPoints, 3);
28529566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL));
2853af9eab45SVaclav Hapla   *expandedPoints = expandedPointsAll[0];
28549566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)expandedPointsAll[0]));
28559566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL));
2856af9eab45SVaclav Hapla   PetscFunctionReturn(0);
2857af9eab45SVaclav Hapla }
2858af9eab45SVaclav Hapla 
2859af9eab45SVaclav Hapla /*@
2860af9eab45SVaclav 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).
2861af9eab45SVaclav Hapla 
2862af9eab45SVaclav Hapla   Not collective
2863af9eab45SVaclav Hapla 
2864af9eab45SVaclav Hapla   Input Parameters:
2865af9eab45SVaclav Hapla + dm - The DMPlex
2866af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart()
2867af9eab45SVaclav Hapla 
2868d8d19677SJose E. Roman   Output Parameters:
2869af9eab45SVaclav Hapla + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth()
2870af9eab45SVaclav Hapla . expandedPoints - (optional) An array of index sets with recursively expanded cones
2871af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points
2872af9eab45SVaclav Hapla 
2873af9eab45SVaclav Hapla   Level: advanced
2874af9eab45SVaclav Hapla 
2875af9eab45SVaclav Hapla   Notes:
2876af9eab45SVaclav Hapla   Like DMPlexGetConeTuple() but recursive.
2877af9eab45SVaclav Hapla 
2878af9eab45SVaclav 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.
2879af9eab45SVaclav Hapla   For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc.
2880af9eab45SVaclav Hapla 
2881af9eab45SVaclav 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:
2882af9eab45SVaclav Hapla   (1) DAG points in expandedPoints[d+1] with depth d+1 to their cone points in expandedPoints[d];
2883af9eab45SVaclav Hapla   (2) DAG points in expandedPoints[d+1] with depth in [0,d] to the same points in expandedPoints[d].
2884af9eab45SVaclav Hapla 
2885db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, `DMPlexGetDepth()`
2886af9eab45SVaclav Hapla @*/
2887af9eab45SVaclav Hapla PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[])
2888af9eab45SVaclav Hapla {
2889af9eab45SVaclav Hapla   const PetscInt      *arr0=NULL, *cone=NULL;
2890af9eab45SVaclav Hapla   PetscInt            *arr=NULL, *newarr=NULL;
2891af9eab45SVaclav Hapla   PetscInt            d, depth_, i, n, newn, cn, co, start, end;
2892af9eab45SVaclav Hapla   IS                  *expandedPoints_;
2893af9eab45SVaclav Hapla   PetscSection        *sections_;
2894af9eab45SVaclav Hapla 
2895af9eab45SVaclav Hapla   PetscFunctionBegin;
2896af9eab45SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2897af9eab45SVaclav Hapla   PetscValidHeaderSpecific(points, IS_CLASSID, 2);
2898af9eab45SVaclav Hapla   if (depth) PetscValidIntPointer(depth, 3);
2899af9eab45SVaclav Hapla   if (expandedPoints) PetscValidPointer(expandedPoints, 4);
2900af9eab45SVaclav Hapla   if (sections) PetscValidPointer(sections, 5);
29019566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(points, &n));
29029566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(points, &arr0));
29039566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth_));
29049566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(depth_, &expandedPoints_));
29059566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(depth_, &sections_));
2906af9eab45SVaclav Hapla   arr = (PetscInt*) arr0; /* this is ok because first generation of arr is not modified */
2907af9eab45SVaclav Hapla   for (d=depth_-1; d>=0; d--) {
29089566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &sections_[d]));
29099566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(sections_[d], 0, n));
2910af9eab45SVaclav Hapla     for (i=0; i<n; i++) {
29119566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d+1, &start, &end));
2912af9eab45SVaclav Hapla       if (arr[i] >= start && arr[i] < end) {
29139566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, arr[i], &cn));
29149566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetDof(sections_[d], i, cn));
2915af9eab45SVaclav Hapla       } else {
29169566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetDof(sections_[d], i, 1));
2917af9eab45SVaclav Hapla       }
2918af9eab45SVaclav Hapla     }
29199566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(sections_[d]));
29209566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(sections_[d], &newn));
29219566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(newn, &newarr));
2922af9eab45SVaclav Hapla     for (i=0; i<n; i++) {
29239566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sections_[d], i, &cn));
29249566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(sections_[d], i, &co));
2925af9eab45SVaclav Hapla       if (cn > 1) {
29269566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, arr[i], &cone));
29279566063dSJacob Faibussowitsch         PetscCall(PetscMemcpy(&newarr[co], cone, cn*sizeof(PetscInt)));
2928af9eab45SVaclav Hapla       } else {
2929af9eab45SVaclav Hapla         newarr[co] = arr[i];
2930af9eab45SVaclav Hapla       }
2931af9eab45SVaclav Hapla     }
29329566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d]));
2933af9eab45SVaclav Hapla     arr = newarr;
2934af9eab45SVaclav Hapla     n = newn;
2935af9eab45SVaclav Hapla   }
29369566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(points, &arr0));
2937af9eab45SVaclav Hapla   *depth = depth_;
2938af9eab45SVaclav Hapla   if (expandedPoints) *expandedPoints = expandedPoints_;
2939af9eab45SVaclav Hapla   else {
29409566063dSJacob Faibussowitsch     for (d=0; d<depth_; d++) PetscCall(ISDestroy(&expandedPoints_[d]));
29419566063dSJacob Faibussowitsch     PetscCall(PetscFree(expandedPoints_));
2942af9eab45SVaclav Hapla   }
2943af9eab45SVaclav Hapla   if (sections) *sections = sections_;
2944af9eab45SVaclav Hapla   else {
29459566063dSJacob Faibussowitsch     for (d=0; d<depth_; d++) PetscCall(PetscSectionDestroy(&sections_[d]));
29469566063dSJacob Faibussowitsch     PetscCall(PetscFree(sections_));
2947af9eab45SVaclav Hapla   }
2948af9eab45SVaclav Hapla   PetscFunctionReturn(0);
2949af9eab45SVaclav Hapla }
2950af9eab45SVaclav Hapla 
2951af9eab45SVaclav Hapla /*@
2952af9eab45SVaclav Hapla   DMPlexRestoreConeRecursive - Deallocates arrays created by DMPlexGetConeRecursive
2953af9eab45SVaclav Hapla 
2954af9eab45SVaclav Hapla   Not collective
2955af9eab45SVaclav Hapla 
2956af9eab45SVaclav Hapla   Input Parameters:
2957af9eab45SVaclav Hapla + dm - The DMPlex
2958af9eab45SVaclav Hapla - points - The IS of points, which must lie in the chart set with DMPlexSetChart()
2959af9eab45SVaclav Hapla 
2960d8d19677SJose E. Roman   Output Parameters:
2961af9eab45SVaclav Hapla + depth - (optional) Size of the output arrays, equal to DMPlex depth, returned by DMPlexGetDepth()
2962af9eab45SVaclav Hapla . expandedPoints - (optional) An array of recursively expanded cones
2963af9eab45SVaclav Hapla - sections - (optional) An array of sections which describe mappings from points to their cone points
2964af9eab45SVaclav Hapla 
2965af9eab45SVaclav Hapla   Level: advanced
2966af9eab45SVaclav Hapla 
2967af9eab45SVaclav Hapla   Notes:
2968af9eab45SVaclav Hapla   See DMPlexGetConeRecursive() for details.
2969af9eab45SVaclav Hapla 
2970db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexGetConeRecursiveVertices()`, `DMPlexGetDepth()`
2971af9eab45SVaclav Hapla @*/
2972af9eab45SVaclav Hapla PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[])
2973af9eab45SVaclav Hapla {
2974af9eab45SVaclav Hapla   PetscInt            d, depth_;
2975af9eab45SVaclav Hapla 
2976af9eab45SVaclav Hapla   PetscFunctionBegin;
29779566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth_));
29781dca8a05SBarry Smith   PetscCheck(!depth || *depth == depth_,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive");
2979af9eab45SVaclav Hapla   if (depth) *depth = 0;
2980af9eab45SVaclav Hapla   if (expandedPoints) {
29819566063dSJacob Faibussowitsch     for (d=0; d<depth_; d++) PetscCall(ISDestroy(&((*expandedPoints)[d])));
29829566063dSJacob Faibussowitsch     PetscCall(PetscFree(*expandedPoints));
2983af9eab45SVaclav Hapla   }
2984af9eab45SVaclav Hapla   if (sections)  {
29859566063dSJacob Faibussowitsch     for (d=0; d<depth_; d++) PetscCall(PetscSectionDestroy(&((*sections)[d])));
29869566063dSJacob Faibussowitsch     PetscCall(PetscFree(*sections));
2987af9eab45SVaclav Hapla   }
2988d4636a37SVaclav Hapla   PetscFunctionReturn(0);
2989d4636a37SVaclav Hapla }
2990d4636a37SVaclav Hapla 
2991552f7358SJed Brown /*@
299292371b87SBarry 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
2993552f7358SJed Brown 
2994552f7358SJed Brown   Not collective
2995552f7358SJed Brown 
2996552f7358SJed Brown   Input Parameters:
2997552f7358SJed Brown + mesh - The DMPlex
2998eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
2999552f7358SJed Brown - cone - An array of points which are on the in-edges for point p
3000552f7358SJed Brown 
3001552f7358SJed Brown   Output Parameter:
3002552f7358SJed Brown 
3003552f7358SJed Brown   Note:
3004552f7358SJed Brown   This should be called after all calls to DMPlexSetConeSize() and DMSetUp().
3005552f7358SJed Brown 
3006552f7358SJed Brown   Level: beginner
3007552f7358SJed Brown 
3008db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`, `DMPlexSetSupport()`, `DMPlexSetSupportSize()`
3009552f7358SJed Brown @*/
3010552f7358SJed Brown PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[])
3011552f7358SJed Brown {
3012552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3013552f7358SJed Brown   PetscInt       pStart, pEnd;
3014552f7358SJed Brown   PetscInt       dof, off, c;
3015552f7358SJed Brown 
3016552f7358SJed Brown   PetscFunctionBegin;
3017552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
30189566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
30199566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
3020dadcf809SJacob Faibussowitsch   if (dof) PetscValidIntPointer(cone, 3);
30219566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
302263a3b9bcSJacob 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);
3023552f7358SJed Brown   for (c = 0; c < dof; ++c) {
302463a3b9bcSJacob 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);
3025552f7358SJed Brown     mesh->cones[off+c] = cone[c];
3026552f7358SJed Brown   }
3027552f7358SJed Brown   PetscFunctionReturn(0);
3028552f7358SJed Brown }
3029552f7358SJed Brown 
3030552f7358SJed Brown /*@C
3031eaf898f9SPatrick Sanan   DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG
3032552f7358SJed Brown 
3033552f7358SJed Brown   Not collective
3034552f7358SJed Brown 
3035552f7358SJed Brown   Input Parameters:
3036552f7358SJed Brown + mesh - The DMPlex
3037eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
3038552f7358SJed Brown 
3039552f7358SJed Brown   Output Parameter:
3040552f7358SJed Brown . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an
3041b5a892a1SMatthew G. Knepley                     integer giving the prescription for cone traversal.
3042552f7358SJed Brown 
3043552f7358SJed Brown   Level: beginner
3044552f7358SJed Brown 
3045b5a892a1SMatthew G. Knepley   Notes:
3046b5a892a1SMatthew G. Knepley   The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always
3047b5a892a1SMatthew G. Knepley   the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection
3048b5a892a1SMatthew G. Knepley   of o, however it is not necessarily the inverse. To get the inverse, use DMPolytopeTypeComposeOrientationInv()
3049b5a892a1SMatthew G. Knepley   with the identity.
3050b5a892a1SMatthew G. Knepley 
30513813dfbdSMatthew G Knepley   Fortran Notes:
30523813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
30533813dfbdSMatthew G Knepley   include petsc.h90 in your code.
30543b12b3d8SVaclav Hapla   You must also call DMPlexRestoreConeOrientation() after you finish using the returned array.
3055922102d1SVaclav Hapla   DMPlexRestoreConeOrientation() is not needed/available in C.
30563813dfbdSMatthew G Knepley 
3057db781477SPatrick Sanan .seealso: `DMPolytopeTypeComposeOrientation()`, `DMPolytopeTypeComposeOrientationInv()`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetCone()`, `DMPlexSetChart()`
3058552f7358SJed Brown @*/
3059552f7358SJed Brown PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[])
3060552f7358SJed Brown {
3061552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3062552f7358SJed Brown   PetscInt       off;
3063552f7358SJed Brown 
3064552f7358SJed Brown   PetscFunctionBegin;
3065552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
306676bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
3067552f7358SJed Brown     PetscInt dof;
30689566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
3069552f7358SJed Brown     if (dof) PetscValidPointer(coneOrientation, 3);
3070552f7358SJed Brown   }
30719566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
30720d644c17SKarl Rupp 
3073552f7358SJed Brown   *coneOrientation = &mesh->coneOrientations[off];
3074552f7358SJed Brown   PetscFunctionReturn(0);
3075552f7358SJed Brown }
3076552f7358SJed Brown 
3077552f7358SJed Brown /*@
3078eaf898f9SPatrick Sanan   DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG
3079552f7358SJed Brown 
3080552f7358SJed Brown   Not collective
3081552f7358SJed Brown 
3082552f7358SJed Brown   Input Parameters:
3083552f7358SJed Brown + mesh - The DMPlex
3084eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
3085b5a892a1SMatthew G. Knepley - coneOrientation - An array of orientations
3086552f7358SJed Brown   Output Parameter:
3087552f7358SJed Brown 
3088b5a892a1SMatthew G. Knepley   Notes:
3089552f7358SJed Brown   This should be called after all calls to DMPlexSetConeSize() and DMSetUp().
3090552f7358SJed Brown 
3091b5a892a1SMatthew G. Knepley   The meaning of coneOrientation is detailed in DMPlexGetConeOrientation().
3092b5a892a1SMatthew G. Knepley 
3093552f7358SJed Brown   Level: beginner
3094552f7358SJed Brown 
3095db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetConeOrientation()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
3096552f7358SJed Brown @*/
3097552f7358SJed Brown PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[])
3098552f7358SJed Brown {
3099552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3100552f7358SJed Brown   PetscInt       pStart, pEnd;
3101552f7358SJed Brown   PetscInt       dof, off, c;
3102552f7358SJed Brown 
3103552f7358SJed Brown   PetscFunctionBegin;
3104552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
31059566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
31069566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
3107dadcf809SJacob Faibussowitsch   if (dof) PetscValidIntPointer(coneOrientation, 3);
31089566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
310963a3b9bcSJacob 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);
3110552f7358SJed Brown   for (c = 0; c < dof; ++c) {
3111552f7358SJed Brown     PetscInt cdof, o = coneOrientation[c];
3112552f7358SJed Brown 
31139566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof));
31141dca8a05SBarry 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);
3115552f7358SJed Brown     mesh->coneOrientations[off+c] = o;
3116552f7358SJed Brown   }
3117552f7358SJed Brown   PetscFunctionReturn(0);
3118552f7358SJed Brown }
3119552f7358SJed Brown 
31207cd05799SMatthew G. Knepley /*@
3121eaf898f9SPatrick Sanan   DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG
31227cd05799SMatthew G. Knepley 
31237cd05799SMatthew G. Knepley   Not collective
31247cd05799SMatthew G. Knepley 
31257cd05799SMatthew G. Knepley   Input Parameters:
31267cd05799SMatthew G. Knepley + mesh - The DMPlex
3127eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
31287cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put
31297cd05799SMatthew G. Knepley - conePoint - The mesh point to insert
31307cd05799SMatthew G. Knepley 
31317cd05799SMatthew G. Knepley   Level: beginner
31327cd05799SMatthew G. Knepley 
3133db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
31347cd05799SMatthew G. Knepley @*/
3135552f7358SJed Brown PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint)
3136552f7358SJed Brown {
3137552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3138552f7358SJed Brown   PetscInt       pStart, pEnd;
3139552f7358SJed Brown   PetscInt       dof, off;
3140552f7358SJed Brown 
3141552f7358SJed Brown   PetscFunctionBegin;
3142552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
31439566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
314463a3b9bcSJacob 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);
314563a3b9bcSJacob 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);
31469566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
31479566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
314863a3b9bcSJacob 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);
3149552f7358SJed Brown   mesh->cones[off+conePos] = conePoint;
3150552f7358SJed Brown   PetscFunctionReturn(0);
3151552f7358SJed Brown }
3152552f7358SJed Brown 
31537cd05799SMatthew G. Knepley /*@
3154eaf898f9SPatrick Sanan   DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG
31557cd05799SMatthew G. Knepley 
31567cd05799SMatthew G. Knepley   Not collective
31577cd05799SMatthew G. Knepley 
31587cd05799SMatthew G. Knepley   Input Parameters:
31597cd05799SMatthew G. Knepley + mesh - The DMPlex
3160eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
31617cd05799SMatthew G. Knepley . conePos - The local index in the cone where the point should be put
31627cd05799SMatthew G. Knepley - coneOrientation - The point orientation to insert
31637cd05799SMatthew G. Knepley 
31647cd05799SMatthew G. Knepley   Level: beginner
31657cd05799SMatthew G. Knepley 
3166b5a892a1SMatthew G. Knepley   Notes:
3167b5a892a1SMatthew G. Knepley   The meaning of coneOrientation values is detailed in DMPlexGetConeOrientation().
3168b5a892a1SMatthew G. Knepley 
3169db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
31707cd05799SMatthew G. Knepley @*/
317177c88f5bSMatthew G Knepley PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation)
317277c88f5bSMatthew G Knepley {
317377c88f5bSMatthew G Knepley   DM_Plex       *mesh = (DM_Plex*) dm->data;
317477c88f5bSMatthew G Knepley   PetscInt       pStart, pEnd;
317577c88f5bSMatthew G Knepley   PetscInt       dof, off;
317677c88f5bSMatthew G Knepley 
317777c88f5bSMatthew G Knepley   PetscFunctionBegin;
317877c88f5bSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
31799566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
318063a3b9bcSJacob 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);
31819566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
31829566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
318363a3b9bcSJacob 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);
318477c88f5bSMatthew G Knepley   mesh->coneOrientations[off+conePos] = coneOrientation;
318577c88f5bSMatthew G Knepley   PetscFunctionReturn(0);
318677c88f5bSMatthew G Knepley }
318777c88f5bSMatthew G Knepley 
3188552f7358SJed Brown /*@
3189eaf898f9SPatrick Sanan   DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG
3190552f7358SJed Brown 
3191552f7358SJed Brown   Not collective
3192552f7358SJed Brown 
3193552f7358SJed Brown   Input Parameters:
3194552f7358SJed Brown + mesh - The DMPlex
3195eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
3196552f7358SJed Brown 
3197552f7358SJed Brown   Output Parameter:
3198552f7358SJed Brown . size - The support size for point p
3199552f7358SJed Brown 
3200552f7358SJed Brown   Level: beginner
3201552f7358SJed Brown 
3202db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`, `DMPlexGetConeSize()`
3203552f7358SJed Brown @*/
3204552f7358SJed Brown PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size)
3205552f7358SJed Brown {
3206552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3207552f7358SJed Brown 
3208552f7358SJed Brown   PetscFunctionBegin;
3209552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3210dadcf809SJacob Faibussowitsch   PetscValidIntPointer(size, 3);
32119566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, size));
3212552f7358SJed Brown   PetscFunctionReturn(0);
3213552f7358SJed Brown }
3214552f7358SJed Brown 
3215552f7358SJed Brown /*@
3216eaf898f9SPatrick Sanan   DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG
3217552f7358SJed Brown 
3218552f7358SJed Brown   Not collective
3219552f7358SJed Brown 
3220552f7358SJed Brown   Input Parameters:
3221552f7358SJed Brown + mesh - The DMPlex
3222eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
3223552f7358SJed Brown - size - The support size for point p
3224552f7358SJed Brown 
3225552f7358SJed Brown   Output Parameter:
3226552f7358SJed Brown 
3227552f7358SJed Brown   Note:
3228552f7358SJed Brown   This should be called after DMPlexSetChart().
3229552f7358SJed Brown 
3230552f7358SJed Brown   Level: beginner
3231552f7358SJed Brown 
3232db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetSupportSize()`, `DMPlexSetChart()`
3233552f7358SJed Brown @*/
3234552f7358SJed Brown PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size)
3235552f7358SJed Brown {
3236552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3237552f7358SJed Brown 
3238552f7358SJed Brown   PetscFunctionBegin;
3239552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
32409566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetDof(mesh->supportSection, p, size));
3241552f7358SJed Brown   PetscFunctionReturn(0);
3242552f7358SJed Brown }
3243552f7358SJed Brown 
3244552f7358SJed Brown /*@C
3245eaf898f9SPatrick Sanan   DMPlexGetSupport - Return the points on the out-edges for this point in the DAG
3246552f7358SJed Brown 
3247552f7358SJed Brown   Not collective
3248552f7358SJed Brown 
3249552f7358SJed Brown   Input Parameters:
3250552f7358SJed Brown + mesh - The DMPlex
3251eaf898f9SPatrick Sanan - p - The point, which must lie in the chart set with DMPlexSetChart()
3252552f7358SJed Brown 
3253552f7358SJed Brown   Output Parameter:
3254552f7358SJed Brown . support - An array of points which are on the out-edges for point p
3255552f7358SJed Brown 
3256552f7358SJed Brown   Level: beginner
3257552f7358SJed Brown 
32583813dfbdSMatthew G Knepley   Fortran Notes:
32593813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
32603813dfbdSMatthew G Knepley   include petsc.h90 in your code.
32613b12b3d8SVaclav Hapla   You must also call DMPlexRestoreSupport() after you finish using the returned array.
3262922102d1SVaclav Hapla   DMPlexRestoreSupport() is not needed/available in C.
32633813dfbdSMatthew G Knepley 
3264db781477SPatrick Sanan .seealso: `DMPlexGetSupportSize()`, `DMPlexSetSupport()`, `DMPlexGetCone()`, `DMPlexSetChart()`
3265552f7358SJed Brown @*/
3266552f7358SJed Brown PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[])
3267552f7358SJed Brown {
3268552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3269552f7358SJed Brown   PetscInt       off;
3270552f7358SJed Brown 
3271552f7358SJed Brown   PetscFunctionBegin;
3272552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3273552f7358SJed Brown   PetscValidPointer(support, 3);
32749566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
3275552f7358SJed Brown   *support = &mesh->supports[off];
3276552f7358SJed Brown   PetscFunctionReturn(0);
3277552f7358SJed Brown }
3278552f7358SJed Brown 
3279552f7358SJed Brown /*@
328092371b87SBarry 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
3281552f7358SJed Brown 
3282552f7358SJed Brown   Not collective
3283552f7358SJed Brown 
3284552f7358SJed Brown   Input Parameters:
3285552f7358SJed Brown + mesh - The DMPlex
3286eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
328792371b87SBarry Smith - support - An array of points which are on the out-edges for point p
3288552f7358SJed Brown 
3289552f7358SJed Brown   Output Parameter:
3290552f7358SJed Brown 
3291552f7358SJed Brown   Note:
3292552f7358SJed Brown   This should be called after all calls to DMPlexSetSupportSize() and DMSetUp().
3293552f7358SJed Brown 
3294552f7358SJed Brown   Level: beginner
3295552f7358SJed Brown 
3296db781477SPatrick Sanan .seealso: `DMPlexSetCone()`, `DMPlexSetConeSize()`, `DMPlexCreate()`, `DMPlexGetSupport()`, `DMPlexSetChart()`, `DMPlexSetSupportSize()`, `DMSetUp()`
3297552f7358SJed Brown @*/
3298552f7358SJed Brown PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[])
3299552f7358SJed Brown {
3300552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3301552f7358SJed Brown   PetscInt       pStart, pEnd;
3302552f7358SJed Brown   PetscInt       dof, off, c;
3303552f7358SJed Brown 
3304552f7358SJed Brown   PetscFunctionBegin;
3305552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
33069566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd));
33079566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
3308dadcf809SJacob Faibussowitsch   if (dof) PetscValidIntPointer(support, 3);
33099566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
331063a3b9bcSJacob 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);
3311552f7358SJed Brown   for (c = 0; c < dof; ++c) {
331263a3b9bcSJacob 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);
3313552f7358SJed Brown     mesh->supports[off+c] = support[c];
3314552f7358SJed Brown   }
3315552f7358SJed Brown   PetscFunctionReturn(0);
3316552f7358SJed Brown }
3317552f7358SJed Brown 
33187cd05799SMatthew G. Knepley /*@
3319eaf898f9SPatrick Sanan   DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG
33207cd05799SMatthew G. Knepley 
33217cd05799SMatthew G. Knepley   Not collective
33227cd05799SMatthew G. Knepley 
33237cd05799SMatthew G. Knepley   Input Parameters:
33247cd05799SMatthew G. Knepley + mesh - The DMPlex
3325eaf898f9SPatrick Sanan . p - The point, which must lie in the chart set with DMPlexSetChart()
33267cd05799SMatthew G. Knepley . supportPos - The local index in the cone where the point should be put
33277cd05799SMatthew G. Knepley - supportPoint - The mesh point to insert
33287cd05799SMatthew G. Knepley 
33297cd05799SMatthew G. Knepley   Level: beginner
33307cd05799SMatthew G. Knepley 
3331db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
33327cd05799SMatthew G. Knepley @*/
3333552f7358SJed Brown PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint)
3334552f7358SJed Brown {
3335552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3336552f7358SJed Brown   PetscInt       pStart, pEnd;
3337552f7358SJed Brown   PetscInt       dof, off;
3338552f7358SJed Brown 
3339552f7358SJed Brown   PetscFunctionBegin;
3340552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
33419566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd));
33429566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
33439566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
334463a3b9bcSJacob 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);
334563a3b9bcSJacob 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);
334663a3b9bcSJacob 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);
3347552f7358SJed Brown   mesh->supports[off+supportPos] = supportPoint;
3348552f7358SJed Brown   PetscFunctionReturn(0);
3349552f7358SJed Brown }
3350552f7358SJed Brown 
3351b5a892a1SMatthew G. Knepley /* Converts an orientation o in the current numbering to the previous scheme used in Plex */
3352b5a892a1SMatthew G. Knepley PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o)
3353b5a892a1SMatthew G. Knepley {
3354b5a892a1SMatthew G. Knepley   switch (ct) {
3355b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:
3356b5a892a1SMatthew G. Knepley       if (o == -1) return -2;
3357b5a892a1SMatthew G. Knepley       break;
3358b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:
3359b5a892a1SMatthew G. Knepley       if (o == -3) return -1;
3360b5a892a1SMatthew G. Knepley       if (o == -2) return -3;
3361b5a892a1SMatthew G. Knepley       if (o == -1) return -2;
3362b5a892a1SMatthew G. Knepley       break;
3363b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:
3364b5a892a1SMatthew G. Knepley       if (o == -4) return -2;
3365b5a892a1SMatthew G. Knepley       if (o == -3) return -1;
3366b5a892a1SMatthew G. Knepley       if (o == -2) return -4;
3367b5a892a1SMatthew G. Knepley       if (o == -1) return -3;
3368b5a892a1SMatthew G. Knepley       break;
3369b5a892a1SMatthew G. Knepley     default: return o;
3370b5a892a1SMatthew G. Knepley   }
3371b5a892a1SMatthew G. Knepley   return o;
3372b5a892a1SMatthew G. Knepley }
3373b5a892a1SMatthew G. Knepley 
3374b5a892a1SMatthew G. Knepley /* Converts an orientation o in the previous scheme used in Plex to the current numbering */
3375b5a892a1SMatthew G. Knepley PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o)
3376b5a892a1SMatthew G. Knepley {
3377b5a892a1SMatthew G. Knepley   switch (ct) {
3378b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:
3379b5a892a1SMatthew G. Knepley       if ((o == -2) || (o == 1)) return -1;
3380b5a892a1SMatthew G. Knepley       if (o == -1) return 0;
3381b5a892a1SMatthew G. Knepley       break;
3382b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:
3383b5a892a1SMatthew G. Knepley       if (o == -3) return -2;
3384b5a892a1SMatthew G. Knepley       if (o == -2) return -1;
3385b5a892a1SMatthew G. Knepley       if (o == -1) return -3;
3386b5a892a1SMatthew G. Knepley       break;
3387b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:
3388b5a892a1SMatthew G. Knepley       if (o == -4) return -2;
3389b5a892a1SMatthew G. Knepley       if (o == -3) return -1;
3390b5a892a1SMatthew G. Knepley       if (o == -2) return -4;
3391b5a892a1SMatthew G. Knepley       if (o == -1) return -3;
3392b5a892a1SMatthew G. Knepley       break;
3393b5a892a1SMatthew G. Knepley     default: return o;
3394b5a892a1SMatthew G. Knepley   }
3395b5a892a1SMatthew G. Knepley   return o;
3396b5a892a1SMatthew G. Knepley }
3397b5a892a1SMatthew G. Knepley 
3398b5a892a1SMatthew G. Knepley /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */
3399b5a892a1SMatthew G. Knepley PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm)
3400b5a892a1SMatthew G. Knepley {
3401b5a892a1SMatthew G. Knepley   PetscInt       pStart, pEnd, p;
3402b5a892a1SMatthew G. Knepley 
3403b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
34049566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
3405b5a892a1SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
3406b5a892a1SMatthew G. Knepley     const PetscInt *cone, *ornt;
3407b5a892a1SMatthew G. Knepley     PetscInt        coneSize, c;
3408b5a892a1SMatthew G. Knepley 
34099566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
34109566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
34119566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dm, p, &ornt));
3412b5a892a1SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
3413b5a892a1SMatthew G. Knepley       DMPolytopeType ct;
3414b5a892a1SMatthew G. Knepley       const PetscInt o = ornt[c];
3415b5a892a1SMatthew G. Knepley 
34169566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, cone[c], &ct));
3417b5a892a1SMatthew G. Knepley       switch (ct) {
3418b5a892a1SMatthew G. Knepley         case DM_POLYTOPE_SEGMENT:
34199566063dSJacob Faibussowitsch           if ((o == -2) || (o == 1)) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
34209566063dSJacob Faibussowitsch           if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, 0));
3421b5a892a1SMatthew G. Knepley           break;
3422b5a892a1SMatthew G. Knepley         case DM_POLYTOPE_TRIANGLE:
34239566063dSJacob Faibussowitsch           if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2));
34249566063dSJacob Faibussowitsch           if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
34259566063dSJacob Faibussowitsch           if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3));
3426b5a892a1SMatthew G. Knepley           break;
3427b5a892a1SMatthew G. Knepley         case DM_POLYTOPE_QUADRILATERAL:
34289566063dSJacob Faibussowitsch           if (o == -4) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2));
34299566063dSJacob Faibussowitsch           if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
34309566063dSJacob Faibussowitsch           if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -4));
34319566063dSJacob Faibussowitsch           if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3));
3432b5a892a1SMatthew G. Knepley           break;
3433b5a892a1SMatthew G. Knepley         default: break;
3434b5a892a1SMatthew G. Knepley       }
3435b5a892a1SMatthew G. Knepley     }
3436b5a892a1SMatthew G. Knepley   }
3437b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
3438b5a892a1SMatthew G. Knepley }
3439b5a892a1SMatthew G. Knepley 
3440012bc364SMatthew G. Knepley static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3441b5a892a1SMatthew G. Knepley {
3442b5a892a1SMatthew G. Knepley   DMPolytopeType  ct = DM_POLYTOPE_UNKNOWN;
3443b5a892a1SMatthew G. Knepley   PetscInt       *closure;
3444b5a892a1SMatthew G. Knepley   const PetscInt *tmp = NULL, *tmpO = NULL;
3445b5a892a1SMatthew G. Knepley   PetscInt        off = 0, tmpSize, t;
3446b5a892a1SMatthew G. Knepley 
3447b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3448b5a892a1SMatthew G. Knepley   if (ornt) {
34499566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, p, &ct));
3450b5a892a1SMatthew G. Knepley     if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN;
3451b5a892a1SMatthew G. Knepley   }
3452b5a892a1SMatthew G. Knepley   if (*points) {
3453b5a892a1SMatthew G. Knepley     closure = *points;
3454b5a892a1SMatthew G. Knepley   } else {
3455b5a892a1SMatthew G. Knepley     PetscInt maxConeSize, maxSupportSize;
34569566063dSJacob Faibussowitsch     PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
34579566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, 2*(PetscMax(maxConeSize, maxSupportSize)+1), MPIU_INT, &closure));
3458b5a892a1SMatthew G. Knepley   }
3459b5a892a1SMatthew G. Knepley   if (useCone) {
34609566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &tmpSize));
34619566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &tmp));
34629566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dm, p, &tmpO));
3463b5a892a1SMatthew G. Knepley   } else {
34649566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dm, p, &tmpSize));
34659566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dm, p, &tmp));
3466b5a892a1SMatthew G. Knepley   }
3467b5a892a1SMatthew G. Knepley   if (ct == DM_POLYTOPE_UNKNOWN) {
3468b5a892a1SMatthew G. Knepley     closure[off++] = p;
3469b5a892a1SMatthew G. Knepley     closure[off++] = 0;
3470b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3471b5a892a1SMatthew G. Knepley       closure[off++] = tmp[t];
3472b5a892a1SMatthew G. Knepley       closure[off++] = tmpO ? tmpO[t] : 0;
3473b5a892a1SMatthew G. Knepley     }
3474b5a892a1SMatthew G. Knepley   } else {
34755f80ce2aSJacob Faibussowitsch     const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, ornt);
3476b5a892a1SMatthew G. Knepley 
3477b5a892a1SMatthew G. Knepley     /* We assume that cells with a valid type have faces with a valid type */
3478b5a892a1SMatthew G. Knepley     closure[off++] = p;
3479b5a892a1SMatthew G. Knepley     closure[off++] = ornt;
3480b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3481b5a892a1SMatthew G. Knepley       DMPolytopeType ft;
3482b5a892a1SMatthew G. Knepley 
34839566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, tmp[t], &ft));
3484b5a892a1SMatthew G. Knepley       closure[off++] = tmp[arr[t]];
3485b5a892a1SMatthew G. Knepley       closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0;
3486b5a892a1SMatthew G. Knepley     }
3487b5a892a1SMatthew G. Knepley   }
3488b5a892a1SMatthew G. Knepley   if (numPoints) *numPoints = tmpSize+1;
3489b5a892a1SMatthew G. Knepley   if (points)    *points    = closure;
3490b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
3491b5a892a1SMatthew G. Knepley }
3492b5a892a1SMatthew G. Knepley 
3493b5a892a1SMatthew G. Knepley /* We need a special tensor verison becasue we want to allow duplicate points in the endcaps for hybrid cells */
3494b5a892a1SMatthew G. Knepley static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points)
3495b5a892a1SMatthew G. Knepley {
3496b5a892a1SMatthew G. Knepley   const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, o);
3497b5a892a1SMatthew G. Knepley   const PetscInt *cone, *ornt;
3498b5a892a1SMatthew G. Knepley   PetscInt       *pts,  *closure = NULL;
3499b5a892a1SMatthew G. Knepley   DMPolytopeType  ft;
3500b5a892a1SMatthew G. Knepley   PetscInt        maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize;
3501b5a892a1SMatthew G. Knepley   PetscInt        dim, coneSize, c, d, clSize, cl;
3502b5a892a1SMatthew G. Knepley 
3503b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
35049566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
35059566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, point, &coneSize));
35069566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, point, &cone));
35079566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeOrientation(dm, point, &ornt));
35089566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
3509b5a892a1SMatthew G. Knepley   coneSeries    = (maxConeSize    > 1) ? ((PetscPowInt(maxConeSize,    dim+1)-1)/(maxConeSize-1))    : dim+1;
3510b5a892a1SMatthew G. Knepley   supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim+1)-1)/(maxSupportSize-1)) : dim+1;
3511b5a892a1SMatthew G. Knepley   maxSize       = PetscMax(coneSeries, supportSeries);
3512b5a892a1SMatthew G. Knepley   if (*points) {pts  = *points;}
35139566063dSJacob Faibussowitsch   else         PetscCall(DMGetWorkArray(dm, 2*maxSize, MPIU_INT, &pts));
3514b5a892a1SMatthew G. Knepley   c    = 0;
3515b5a892a1SMatthew G. Knepley   pts[c++] = point;
3516b5a892a1SMatthew G. Knepley   pts[c++] = o;
35179566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cone[arr[0*2+0]], &ft));
35189566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0*2+0]], DMPolytopeTypeComposeOrientation(ft, arr[0*2+1], ornt[0]), useCone, &clSize, &closure));
3519b5a892a1SMatthew G. Knepley   for (cl = 0; cl < clSize*2; cl += 2) {pts[c++] = closure[cl]; pts[c++] = closure[cl+1];}
35209566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1*2+0]], DMPolytopeTypeComposeOrientation(ft, arr[1*2+1], ornt[1]), useCone, &clSize, &closure));
3521b5a892a1SMatthew G. Knepley   for (cl = 0; cl < clSize*2; cl += 2) {pts[c++] = closure[cl]; pts[c++] = closure[cl+1];}
35229566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure));
3523b5a892a1SMatthew G. Knepley   for (d = 2; d < coneSize; ++d) {
35249566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, cone[arr[d*2+0]], &ft));
3525b5a892a1SMatthew G. Knepley     pts[c++] = cone[arr[d*2+0]];
3526b5a892a1SMatthew G. Knepley     pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d*2+1], ornt[d]);
3527b5a892a1SMatthew G. Knepley   }
3528b5a892a1SMatthew G. Knepley   if (dim >= 3) {
3529b5a892a1SMatthew G. Knepley     for (d = 2; d < coneSize; ++d) {
3530b5a892a1SMatthew G. Knepley       const PetscInt  fpoint = cone[arr[d*2+0]];
3531b5a892a1SMatthew G. Knepley       const PetscInt *fcone, *fornt;
3532b5a892a1SMatthew G. Knepley       PetscInt        fconeSize, fc, i;
3533b5a892a1SMatthew G. Knepley 
35349566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, fpoint, &ft));
3535b5a892a1SMatthew G. Knepley       const PetscInt *farr = DMPolytopeTypeGetArrangment(ft, DMPolytopeTypeComposeOrientation(ft, arr[d*2+1], ornt[d]));
35369566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, fpoint, &fconeSize));
35379566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, fpoint, &fcone));
35389566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeOrientation(dm, fpoint, &fornt));
3539b5a892a1SMatthew G. Knepley       for (fc = 0; fc < fconeSize; ++fc) {
3540b5a892a1SMatthew G. Knepley         const PetscInt cp = fcone[farr[fc*2+0]];
3541b5a892a1SMatthew G. Knepley         const PetscInt co = farr[fc*2+1];
3542b5a892a1SMatthew G. Knepley 
3543b5a892a1SMatthew G. Knepley         for (i = 0; i < c; i += 2) if (pts[i] == cp) break;
3544b5a892a1SMatthew G. Knepley         if (i == c) {
35459566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCellType(dm, cp, &ft));
3546b5a892a1SMatthew G. Knepley           pts[c++] = cp;
3547b5a892a1SMatthew G. Knepley           pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc*2+0]]);
3548b5a892a1SMatthew G. Knepley         }
3549b5a892a1SMatthew G. Knepley       }
3550b5a892a1SMatthew G. Knepley     }
3551b5a892a1SMatthew G. Knepley   }
3552b5a892a1SMatthew G. Knepley   *numPoints = c/2;
3553b5a892a1SMatthew G. Knepley   *points    = pts;
3554b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
3555b5a892a1SMatthew G. Knepley }
3556b5a892a1SMatthew G. Knepley 
3557b5a892a1SMatthew G. Knepley PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3558b5a892a1SMatthew G. Knepley {
3559b5a892a1SMatthew G. Knepley   DMPolytopeType ct;
3560b5a892a1SMatthew G. Knepley   PetscInt      *closure, *fifo;
3561b5a892a1SMatthew G. Knepley   PetscInt       closureSize = 0, fifoStart = 0, fifoSize = 0;
3562b5a892a1SMatthew G. Knepley   PetscInt       maxConeSize, maxSupportSize, coneSeries, supportSeries;
3563b5a892a1SMatthew G. Knepley   PetscInt       depth, maxSize;
3564b5a892a1SMatthew G. Knepley 
3565b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
35669566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
3567b5a892a1SMatthew G. Knepley   if (depth == 1) {
35689566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points));
3569b5a892a1SMatthew G. Knepley     PetscFunctionReturn(0);
3570b5a892a1SMatthew G. Knepley   }
35719566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, p, &ct));
3572b5a892a1SMatthew G. Knepley   if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN;
3573b5a892a1SMatthew G. Knepley   if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || ct == DM_POLYTOPE_TRI_PRISM_TENSOR || ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) {
35749566063dSJacob Faibussowitsch     PetscCall(DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points));
3575b5a892a1SMatthew G. Knepley     PetscFunctionReturn(0);
3576b5a892a1SMatthew G. Knepley   }
35779566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
3578b5a892a1SMatthew G. Knepley   coneSeries    = (maxConeSize    > 1) ? ((PetscPowInt(maxConeSize,    depth+1)-1)/(maxConeSize-1))    : depth+1;
3579b5a892a1SMatthew G. Knepley   supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth+1)-1)/(maxSupportSize-1)) : depth+1;
3580b5a892a1SMatthew G. Knepley   maxSize       = PetscMax(coneSeries, supportSeries);
35819566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, 3*maxSize, MPIU_INT, &fifo));
3582b5a892a1SMatthew G. Knepley   if (*points) {closure = *points;}
35839566063dSJacob Faibussowitsch   else         PetscCall(DMGetWorkArray(dm, 2*maxSize, MPIU_INT, &closure));
3584b5a892a1SMatthew G. Knepley   closure[closureSize++] = p;
3585b5a892a1SMatthew G. Knepley   closure[closureSize++] = ornt;
3586b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = p;
3587b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = ornt;
3588b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = ct;
3589b5a892a1SMatthew G. Knepley   /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */
3590b5a892a1SMatthew G. Knepley   while (fifoSize - fifoStart) {
3591b5a892a1SMatthew G. Knepley     const PetscInt       q    = fifo[fifoStart++];
3592b5a892a1SMatthew G. Knepley     const PetscInt       o    = fifo[fifoStart++];
3593b5a892a1SMatthew G. Knepley     const DMPolytopeType qt   = (DMPolytopeType) fifo[fifoStart++];
3594b5a892a1SMatthew G. Knepley     const PetscInt      *qarr = DMPolytopeTypeGetArrangment(qt, o);
3595b5a892a1SMatthew G. Knepley     const PetscInt      *tmp, *tmpO;
3596b5a892a1SMatthew G. Knepley     PetscInt             tmpSize, t;
3597b5a892a1SMatthew G. Knepley 
3598b5a892a1SMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) {
3599b5a892a1SMatthew G. Knepley       PetscInt nO = DMPolytopeTypeGetNumArrangments(qt)/2;
360063a3b9bcSJacob 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);
3601b5a892a1SMatthew G. Knepley     }
3602b5a892a1SMatthew G. Knepley     if (useCone) {
36039566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, q, &tmpSize));
36049566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, q, &tmp));
36059566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeOrientation(dm, q, &tmpO));
3606b5a892a1SMatthew G. Knepley     } else {
36079566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, q, &tmpSize));
36089566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupport(dm, q, &tmp));
3609b5a892a1SMatthew G. Knepley       tmpO = NULL;
3610b5a892a1SMatthew G. Knepley     }
3611b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3612b5a892a1SMatthew G. Knepley       const PetscInt ip = useCone && qarr ? qarr[t*2]   : t;
3613b5a892a1SMatthew G. Knepley       const PetscInt io = useCone && qarr ? qarr[t*2+1] : 0;
3614b5a892a1SMatthew G. Knepley       const PetscInt cp = tmp[ip];
36159566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, cp, &ct));
3616b5a892a1SMatthew G. Knepley       const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0;
3617b5a892a1SMatthew G. Knepley       PetscInt       c;
3618b5a892a1SMatthew G. Knepley 
3619b5a892a1SMatthew G. Knepley       /* Check for duplicate */
3620b5a892a1SMatthew G. Knepley       for (c = 0; c < closureSize; c += 2) {
3621b5a892a1SMatthew G. Knepley         if (closure[c] == cp) break;
3622b5a892a1SMatthew G. Knepley       }
3623b5a892a1SMatthew G. Knepley       if (c == closureSize) {
3624b5a892a1SMatthew G. Knepley         closure[closureSize++] = cp;
3625b5a892a1SMatthew G. Knepley         closure[closureSize++] = co;
3626b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = cp;
3627b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = co;
3628b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = ct;
3629b5a892a1SMatthew G. Knepley       }
3630b5a892a1SMatthew G. Knepley     }
3631b5a892a1SMatthew G. Knepley   }
36329566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 3*maxSize, MPIU_INT, &fifo));
3633b5a892a1SMatthew G. Knepley   if (numPoints) *numPoints = closureSize/2;
3634b5a892a1SMatthew G. Knepley   if (points)    *points    = closure;
3635b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
3636b5a892a1SMatthew G. Knepley }
3637b5a892a1SMatthew G. Knepley 
3638552f7358SJed Brown /*@C
3639eaf898f9SPatrick Sanan   DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG
3640552f7358SJed Brown 
3641552f7358SJed Brown   Not collective
3642552f7358SJed Brown 
3643552f7358SJed Brown   Input Parameters:
3644b5a892a1SMatthew G. Knepley + dm      - The DMPlex
3645b5a892a1SMatthew G. Knepley . p       - The mesh point
36466b867d5aSJose E. Roman - useCone - PETSC_TRUE for the closure, otherwise return the star
3647552f7358SJed Brown 
36486b867d5aSJose E. Roman   Input/Output Parameter:
36496b867d5aSJose E. Roman . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...];
36506b867d5aSJose E. Roman            if NULL on input, internal storage will be returned, otherwise the provided array is used
36516b867d5aSJose E. Roman 
36526b867d5aSJose E. Roman   Output Parameter:
36536b867d5aSJose E. Roman . numPoints - The number of points in the closure, so points[] is of size 2*numPoints
3654552f7358SJed Brown 
3655552f7358SJed Brown   Note:
36560298fd71SBarry Smith   If using internal storage (points is NULL on input), each call overwrites the last output.
3657552f7358SJed Brown 
36583813dfbdSMatthew G Knepley   Fortran Notes:
3659b5a892a1SMatthew G. Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must include petsc.h90 in your code.
36603813dfbdSMatthew G Knepley 
36613813dfbdSMatthew G Knepley   The numPoints argument is not present in the Fortran 90 binding since it is internal to the array.
36623813dfbdSMatthew G Knepley 
3663552f7358SJed Brown   Level: beginner
3664552f7358SJed Brown 
3665db781477SPatrick Sanan .seealso: `DMPlexRestoreTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()`
3666552f7358SJed Brown @*/
3667552f7358SJed Brown PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3668552f7358SJed Brown {
3669b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3670552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3671b5a892a1SMatthew G. Knepley   if (numPoints) PetscValidIntPointer(numPoints, 4);
3672b5a892a1SMatthew G. Knepley   if (points)    PetscValidPointer(points, 5);
36739566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points));
36749bf0dad6SMatthew G. Knepley   PetscFunctionReturn(0);
36759bf0dad6SMatthew G. Knepley }
36769bf0dad6SMatthew G. Knepley 
3677552f7358SJed Brown /*@C
3678eaf898f9SPatrick Sanan   DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG
3679552f7358SJed Brown 
3680552f7358SJed Brown   Not collective
3681552f7358SJed Brown 
3682552f7358SJed Brown   Input Parameters:
3683b5a892a1SMatthew G. Knepley + dm        - The DMPlex
3684b5a892a1SMatthew G. Knepley . p         - The mesh point
3685b5a892a1SMatthew G. Knepley . useCone   - PETSC_TRUE for the closure, otherwise return the star
3686b5a892a1SMatthew G. Knepley . numPoints - The number of points in the closure, so points[] is of size 2*numPoints
3687b5a892a1SMatthew G. Knepley - points    - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]
3688552f7358SJed Brown 
3689552f7358SJed Brown   Note:
36900298fd71SBarry Smith   If not using internal storage (points is not NULL on input), this call is unnecessary
3691552f7358SJed Brown 
36923813dfbdSMatthew G Knepley   Fortran Notes:
3693b5a892a1SMatthew G. Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must include petsc.h90 in your code.
36943813dfbdSMatthew G Knepley 
36953813dfbdSMatthew G Knepley   The numPoints argument is not present in the Fortran 90 binding since it is internal to the array.
36963813dfbdSMatthew G Knepley 
3697552f7358SJed Brown   Level: beginner
3698552f7358SJed Brown 
3699db781477SPatrick Sanan .seealso: `DMPlexGetTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()`
3700552f7358SJed Brown @*/
3701552f7358SJed Brown PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3702552f7358SJed Brown {
3703b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3704552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
37054ff43b2cSJed Brown   if (numPoints) *numPoints = 0;
37069566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, points));
3707552f7358SJed Brown   PetscFunctionReturn(0);
3708552f7358SJed Brown }
3709552f7358SJed Brown 
3710552f7358SJed Brown /*@
3711eaf898f9SPatrick Sanan   DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG
3712552f7358SJed Brown 
3713552f7358SJed Brown   Not collective
3714552f7358SJed Brown 
3715552f7358SJed Brown   Input Parameter:
3716552f7358SJed Brown . mesh - The DMPlex
3717552f7358SJed Brown 
3718552f7358SJed Brown   Output Parameters:
3719552f7358SJed Brown + maxConeSize - The maximum number of in-edges
3720552f7358SJed Brown - maxSupportSize - The maximum number of out-edges
3721552f7358SJed Brown 
3722552f7358SJed Brown   Level: beginner
3723552f7358SJed Brown 
3724db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`
3725552f7358SJed Brown @*/
3726552f7358SJed Brown PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize)
3727552f7358SJed Brown {
3728552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
3729552f7358SJed Brown 
3730552f7358SJed Brown   PetscFunctionBegin;
3731552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
37321baa6e33SBarry Smith   if (maxConeSize) PetscCall(PetscSectionGetMaxDof(mesh->coneSection, maxConeSize));
37331baa6e33SBarry Smith   if (maxSupportSize) PetscCall(PetscSectionGetMaxDof(mesh->supportSection, maxSupportSize));
3734552f7358SJed Brown   PetscFunctionReturn(0);
3735552f7358SJed Brown }
3736552f7358SJed Brown 
3737552f7358SJed Brown PetscErrorCode DMSetUp_Plex(DM dm)
3738552f7358SJed Brown {
3739552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
37406302a7fbSVaclav Hapla   PetscInt       size, maxSupportSize;
3741552f7358SJed Brown 
3742552f7358SJed Brown   PetscFunctionBegin;
3743552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
37449566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(mesh->coneSection));
37459566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(mesh->coneSection, &size));
37469566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, &mesh->cones));
37479566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(size, &mesh->coneOrientations));
37489566063dSJacob Faibussowitsch   PetscCall(PetscLogObjectMemory((PetscObject) dm, size*2*sizeof(PetscInt)));
37496302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize));
37506302a7fbSVaclav Hapla   if (maxSupportSize) {
37519566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(mesh->supportSection));
37529566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &size));
37539566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(size, &mesh->supports));
37549566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectMemory((PetscObject) dm, size*sizeof(PetscInt)));
3755552f7358SJed Brown   }
3756552f7358SJed Brown   PetscFunctionReturn(0);
3757552f7358SJed Brown }
3758552f7358SJed Brown 
3759276c5506SMatthew G. Knepley PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm)
3760552f7358SJed Brown {
3761552f7358SJed Brown   PetscFunctionBegin;
37629566063dSJacob Faibussowitsch   if (subdm) PetscCall(DMClone(dm, subdm));
37639566063dSJacob Faibussowitsch   PetscCall(DMCreateSectionSubDM(dm, numFields, fields, is, subdm));
3764c2939958SSatish Balay   if (subdm) {(*subdm)->useNatural = dm->useNatural;}
3765736995cdSBlaise Bourdin   if (dm->useNatural && dm->sfMigration) {
3766f94b4a02SBlaise Bourdin     PetscSF        sfMigrationInv,sfNatural;
3767f94b4a02SBlaise Bourdin     PetscSection   section, sectionSeq;
3768f94b4a02SBlaise Bourdin 
37693dcd263cSBlaise Bourdin     (*subdm)->sfMigration = dm->sfMigration;
37709566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject) dm->sfMigration));
37719566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection((*subdm), &section));
37729566063dSJacob Faibussowitsch     PetscCall(PetscSFCreateInverseSF((*subdm)->sfMigration, &sfMigrationInv));
37739566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject) (*subdm)), &sectionSeq));
37749566063dSJacob Faibussowitsch     PetscCall(PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq));
3775f94b4a02SBlaise Bourdin 
37769566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateGlobalToNaturalSF(*subdm, sectionSeq, (*subdm)->sfMigration, &sfNatural));
3777c40e9495SBlaise Bourdin     (*subdm)->sfNatural = sfNatural;
37789566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&sectionSeq));
37799566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sfMigrationInv));
3780f94b4a02SBlaise Bourdin   }
3781552f7358SJed Brown   PetscFunctionReturn(0);
3782552f7358SJed Brown }
3783552f7358SJed Brown 
37842adcc780SMatthew G. Knepley PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm)
37852adcc780SMatthew G. Knepley {
37863dcd263cSBlaise Bourdin   PetscInt       i = 0;
37872adcc780SMatthew G. Knepley 
37882adcc780SMatthew G. Knepley   PetscFunctionBegin;
37899566063dSJacob Faibussowitsch   PetscCall(DMClone(dms[0], superdm));
37909566063dSJacob Faibussowitsch   PetscCall(DMCreateSectionSuperDM(dms, len, is, superdm));
3791c40e9495SBlaise Bourdin   (*superdm)->useNatural = PETSC_FALSE;
37923dcd263cSBlaise Bourdin   for (i = 0; i < len; i++) {
37933dcd263cSBlaise Bourdin     if (dms[i]->useNatural && dms[i]->sfMigration) {
37943dcd263cSBlaise Bourdin       PetscSF        sfMigrationInv,sfNatural;
37953dcd263cSBlaise Bourdin       PetscSection   section, sectionSeq;
37963dcd263cSBlaise Bourdin 
37973dcd263cSBlaise Bourdin       (*superdm)->sfMigration = dms[i]->sfMigration;
37989566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject) dms[i]->sfMigration));
3799c40e9495SBlaise Bourdin       (*superdm)->useNatural = PETSC_TRUE;
38009566063dSJacob Faibussowitsch       PetscCall(DMGetLocalSection((*superdm), &section));
38019566063dSJacob Faibussowitsch       PetscCall(PetscSFCreateInverseSF((*superdm)->sfMigration, &sfMigrationInv));
38029566063dSJacob Faibussowitsch       PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject) (*superdm)), &sectionSeq));
38039566063dSJacob Faibussowitsch       PetscCall(PetscSFDistributeSection(sfMigrationInv, section, NULL, sectionSeq));
38043dcd263cSBlaise Bourdin 
38059566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateGlobalToNaturalSF(*superdm, sectionSeq, (*superdm)->sfMigration, &sfNatural));
3806c40e9495SBlaise Bourdin       (*superdm)->sfNatural = sfNatural;
38079566063dSJacob Faibussowitsch       PetscCall(PetscSectionDestroy(&sectionSeq));
38089566063dSJacob Faibussowitsch       PetscCall(PetscSFDestroy(&sfMigrationInv));
38093dcd263cSBlaise Bourdin       break;
38103dcd263cSBlaise Bourdin     }
38113dcd263cSBlaise Bourdin   }
38122adcc780SMatthew G. Knepley   PetscFunctionReturn(0);
38132adcc780SMatthew G. Knepley }
38142adcc780SMatthew G. Knepley 
3815552f7358SJed Brown /*@
3816eaf898f9SPatrick Sanan   DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information
3817552f7358SJed Brown 
3818552f7358SJed Brown   Not collective
3819552f7358SJed Brown 
3820552f7358SJed Brown   Input Parameter:
3821552f7358SJed Brown . mesh - The DMPlex
3822552f7358SJed Brown 
3823552f7358SJed Brown   Output Parameter:
3824552f7358SJed Brown 
3825552f7358SJed Brown   Note:
3826552f7358SJed Brown   This should be called after all calls to DMPlexSetCone()
3827552f7358SJed Brown 
3828552f7358SJed Brown   Level: beginner
3829552f7358SJed Brown 
3830db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMPlexSetCone()`
3831552f7358SJed Brown @*/
3832552f7358SJed Brown PetscErrorCode DMPlexSymmetrize(DM dm)
3833552f7358SJed Brown {
3834552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
3835552f7358SJed Brown   PetscInt      *offsets;
3836552f7358SJed Brown   PetscInt       supportSize;
3837552f7358SJed Brown   PetscInt       pStart, pEnd, p;
3838552f7358SJed Brown 
3839552f7358SJed Brown   PetscFunctionBegin;
3840552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
384128b400f6SJacob Faibussowitsch   PetscCheck(!mesh->supports,PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex");
38429566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_Symmetrize,dm,0,0,0));
3843552f7358SJed Brown   /* Calculate support sizes */
38449566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
3845552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
3846552f7358SJed Brown     PetscInt dof, off, c;
3847552f7358SJed Brown 
38489566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
38499566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
3850552f7358SJed Brown     for (c = off; c < off+dof; ++c) {
38519566063dSJacob Faibussowitsch       PetscCall(PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1));
3852552f7358SJed Brown     }
3853552f7358SJed Brown   }
38549566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(mesh->supportSection));
3855552f7358SJed Brown   /* Calculate supports */
38569566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &supportSize));
38579566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(supportSize, &mesh->supports));
38589566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(pEnd - pStart, &offsets));
3859552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
3860552f7358SJed Brown     PetscInt dof, off, c;
3861552f7358SJed Brown 
38629566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
38639566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
3864552f7358SJed Brown     for (c = off; c < off+dof; ++c) {
3865552f7358SJed Brown       const PetscInt q = mesh->cones[c];
3866552f7358SJed Brown       PetscInt       offS;
3867552f7358SJed Brown 
38689566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->supportSection, q, &offS));
38690d644c17SKarl Rupp 
3870552f7358SJed Brown       mesh->supports[offS+offsets[q]] = p;
3871552f7358SJed Brown       ++offsets[q];
3872552f7358SJed Brown     }
3873552f7358SJed Brown   }
38749566063dSJacob Faibussowitsch   PetscCall(PetscFree(offsets));
38759566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_Symmetrize,dm,0,0,0));
3876552f7358SJed Brown   PetscFunctionReturn(0);
3877552f7358SJed Brown }
3878552f7358SJed Brown 
3879277ea44aSLisandro Dalcin static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd)
3880277ea44aSLisandro Dalcin {
3881277ea44aSLisandro Dalcin   IS             stratumIS;
3882277ea44aSLisandro Dalcin 
3883277ea44aSLisandro Dalcin   PetscFunctionBegin;
3884277ea44aSLisandro Dalcin   if (pStart >= pEnd) PetscFunctionReturn(0);
388576bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
3886277ea44aSLisandro Dalcin     PetscInt  qStart, qEnd, numLevels, level;
3887277ea44aSLisandro Dalcin     PetscBool overlap = PETSC_FALSE;
38889566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &numLevels));
3889277ea44aSLisandro Dalcin     for (level = 0; level < numLevels; level++) {
38909566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
3891277ea44aSLisandro Dalcin       if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) {overlap = PETSC_TRUE; break;}
3892277ea44aSLisandro Dalcin     }
389363a3b9bcSJacob 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);
3894277ea44aSLisandro Dalcin   }
38959566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd-pStart, pStart, 1, &stratumIS));
38969566063dSJacob Faibussowitsch   PetscCall(DMLabelSetStratumIS(label, depth, stratumIS));
38979566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&stratumIS));
3898277ea44aSLisandro Dalcin   PetscFunctionReturn(0);
3899277ea44aSLisandro Dalcin }
3900277ea44aSLisandro Dalcin 
3901552f7358SJed Brown /*@
3902a8d69d7bSBarry Smith   DMPlexStratify - The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and
39036dd80730SBarry Smith   can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the
3904552f7358SJed Brown   same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in
3905552f7358SJed Brown   the DAG.
3906552f7358SJed Brown 
3907bf4602e4SToby Isaac   Collective on dm
3908552f7358SJed Brown 
3909552f7358SJed Brown   Input Parameter:
3910552f7358SJed Brown . mesh - The DMPlex
3911552f7358SJed Brown 
3912552f7358SJed Brown   Output Parameter:
3913552f7358SJed Brown 
3914552f7358SJed Brown   Notes:
3915b1bb481bSMatthew Knepley   Concretely, DMPlexStratify() creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex
3916b1bb481bSMatthew 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
3917b1bb481bSMatthew Knepley   until cells have depth equal to the dimension of the mesh. The depth label can be accessed through DMPlexGetDepthLabel() or DMPlexGetDepthStratum(), or
3918c58f1c22SToby Isaac   manually via DMGetLabel().  The height is defined implicitly by height = maxDimension - depth, and can be accessed
3919150b719bSJed Brown   via DMPlexGetHeightStratum().  For example, cells have height 0 and faces have height 1.
3920552f7358SJed Brown 
3921b1bb481bSMatthew Knepley   The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results
3922b1bb481bSMatthew Knepley   if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that
3923b1bb481bSMatthew 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
3924b1bb481bSMatthew Knepley   to interpolate only that one (e0), so that
3925b1bb481bSMatthew Knepley $  cone(c0) = {e0, v2}
3926b1bb481bSMatthew Knepley $  cone(e0) = {v0, v1}
3927b1bb481bSMatthew Knepley   If DMPlexStratify() is run on this mesh, it will give depths
3928b1bb481bSMatthew Knepley $  depth 0 = {v0, v1, v2}
3929b1bb481bSMatthew Knepley $  depth 1 = {e0, c0}
3930b1bb481bSMatthew Knepley   where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2.
3931b1bb481bSMatthew Knepley 
3932150b719bSJed Brown   DMPlexStratify() should be called after all calls to DMPlexSymmetrize()
3933552f7358SJed Brown 
3934552f7358SJed Brown   Level: beginner
3935552f7358SJed Brown 
3936db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexComputeCellTypes()`
3937552f7358SJed Brown @*/
3938552f7358SJed Brown PetscErrorCode DMPlexStratify(DM dm)
3939552f7358SJed Brown {
3940df0420ecSMatthew G. Knepley   DM_Plex       *mesh = (DM_Plex*) dm->data;
3941aa50250dSMatthew G. Knepley   DMLabel        label;
3942552f7358SJed Brown   PetscInt       pStart, pEnd, p;
3943552f7358SJed Brown   PetscInt       numRoots = 0, numLeaves = 0;
3944552f7358SJed Brown 
3945552f7358SJed Brown   PetscFunctionBegin;
3946552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
39479566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0));
3948277ea44aSLisandro Dalcin 
3949277ea44aSLisandro Dalcin   /* Create depth label */
39509566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
39519566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "depth"));
39529566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
3953277ea44aSLisandro Dalcin 
3954277ea44aSLisandro Dalcin   {
3955552f7358SJed Brown     /* Initialize roots and count leaves */
3956277ea44aSLisandro Dalcin     PetscInt sMin = PETSC_MAX_INT;
3957277ea44aSLisandro Dalcin     PetscInt sMax = PETSC_MIN_INT;
3958552f7358SJed Brown     PetscInt coneSize, supportSize;
3959552f7358SJed Brown 
3960277ea44aSLisandro Dalcin     for (p = pStart; p < pEnd; ++p) {
39619566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
39629566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
3963552f7358SJed Brown       if (!coneSize && supportSize) {
3964277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
3965277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
3966552f7358SJed Brown         ++numRoots;
3967552f7358SJed Brown       } else if (!supportSize && coneSize) {
3968552f7358SJed Brown         ++numLeaves;
3969552f7358SJed Brown       } else if (!supportSize && !coneSize) {
3970552f7358SJed Brown         /* Isolated points */
3971277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
3972277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
3973552f7358SJed Brown       }
3974552f7358SJed Brown     }
39759566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax+1));
3976277ea44aSLisandro Dalcin   }
3977277ea44aSLisandro Dalcin 
3978552f7358SJed Brown   if (numRoots + numLeaves == (pEnd - pStart)) {
3979277ea44aSLisandro Dalcin     PetscInt sMin = PETSC_MAX_INT;
3980277ea44aSLisandro Dalcin     PetscInt sMax = PETSC_MIN_INT;
3981552f7358SJed Brown     PetscInt coneSize, supportSize;
3982552f7358SJed Brown 
3983277ea44aSLisandro Dalcin     for (p = pStart; p < pEnd; ++p) {
39849566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
39859566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
3986552f7358SJed Brown       if (!supportSize && coneSize) {
3987277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
3988277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
3989552f7358SJed Brown       }
3990552f7358SJed Brown     }
39919566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax+1));
3992552f7358SJed Brown   } else {
3993277ea44aSLisandro Dalcin     PetscInt level = 0;
3994277ea44aSLisandro Dalcin     PetscInt qStart, qEnd, q;
3995552f7358SJed Brown 
39969566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
3997277ea44aSLisandro Dalcin     while (qEnd > qStart) {
3998277ea44aSLisandro Dalcin       PetscInt sMin = PETSC_MAX_INT;
3999277ea44aSLisandro Dalcin       PetscInt sMax = PETSC_MIN_INT;
400074ef644bSMatthew G. Knepley 
4001277ea44aSLisandro Dalcin       for (q = qStart; q < qEnd; ++q) {
400274ef644bSMatthew G. Knepley         const PetscInt *support;
400374ef644bSMatthew G. Knepley         PetscInt        supportSize, s;
400474ef644bSMatthew G. Knepley 
40059566063dSJacob Faibussowitsch         PetscCall(DMPlexGetSupportSize(dm, q, &supportSize));
40069566063dSJacob Faibussowitsch         PetscCall(DMPlexGetSupport(dm, q, &support));
400774ef644bSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
4008277ea44aSLisandro Dalcin           sMin = PetscMin(support[s], sMin);
4009277ea44aSLisandro Dalcin           sMax = PetscMax(support[s], sMax);
4010552f7358SJed Brown         }
4011552f7358SJed Brown       }
40129566063dSJacob Faibussowitsch       PetscCall(DMLabelGetNumValues(label, &level));
40139566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateDepthStratum(dm, label, level, sMin, sMax+1));
40149566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
401574ef644bSMatthew G. Knepley     }
401674ef644bSMatthew G. Knepley   }
4017bf4602e4SToby Isaac   { /* just in case there is an empty process */
4018bf4602e4SToby Isaac     PetscInt numValues, maxValues = 0, v;
4019bf4602e4SToby Isaac 
40209566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &numValues));
40219566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(&numValues,&maxValues,1,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm)));
4022bf4602e4SToby Isaac     for (v = numValues; v < maxValues; v++) {
40239566063dSJacob Faibussowitsch       PetscCall(DMLabelAddStratum(label, v));
4024bf4602e4SToby Isaac     }
4025bf4602e4SToby Isaac   }
40269566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateGet((PetscObject) label, &mesh->depthState));
40279566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0));
4028552f7358SJed Brown   PetscFunctionReturn(0);
4029552f7358SJed Brown }
4030552f7358SJed Brown 
4031412e9a14SMatthew G. Knepley PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt)
4032ba2698f1SMatthew G. Knepley {
4033412e9a14SMatthew G. Knepley   DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
4034412e9a14SMatthew G. Knepley   PetscInt       dim, depth, pheight, coneSize;
4035ba2698f1SMatthew G. Knepley 
4036412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
40379566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
40389566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
40399566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
4040ba2698f1SMatthew G. Knepley   pheight = depth - pdepth;
4041ba2698f1SMatthew G. Knepley   if (depth <= 1) {
4042ba2698f1SMatthew G. Knepley     switch (pdepth) {
4043ba2698f1SMatthew G. Knepley       case 0: ct = DM_POLYTOPE_POINT;break;
4044ba2698f1SMatthew G. Knepley       case 1:
4045ba2698f1SMatthew G. Knepley         switch (coneSize) {
4046ba2698f1SMatthew G. Knepley           case 2: ct = DM_POLYTOPE_SEGMENT;break;
4047ba2698f1SMatthew G. Knepley           case 3: ct = DM_POLYTOPE_TRIANGLE;break;
4048ba2698f1SMatthew G. Knepley           case 4:
4049ba2698f1SMatthew G. Knepley           switch (dim) {
4050ba2698f1SMatthew G. Knepley             case 2: ct = DM_POLYTOPE_QUADRILATERAL;break;
4051ba2698f1SMatthew G. Knepley             case 3: ct = DM_POLYTOPE_TETRAHEDRON;break;
4052ba2698f1SMatthew G. Knepley             default: break;
4053ba2698f1SMatthew G. Knepley           }
4054ba2698f1SMatthew G. Knepley           break;
4055da9060c4SMatthew G. Knepley         case 5: ct = DM_POLYTOPE_PYRAMID;break;
4056ba2698f1SMatthew G. Knepley         case 6: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break;
4057ba2698f1SMatthew G. Knepley         case 8: ct = DM_POLYTOPE_HEXAHEDRON;break;
4058ba2698f1SMatthew G. Knepley         default: break;
4059ba2698f1SMatthew G. Knepley       }
4060ba2698f1SMatthew G. Knepley     }
4061ba2698f1SMatthew G. Knepley   } else {
4062ba2698f1SMatthew G. Knepley     if (pdepth == 0) {
4063ba2698f1SMatthew G. Knepley       ct = DM_POLYTOPE_POINT;
4064ba2698f1SMatthew G. Knepley     } else if (pheight == 0) {
4065ba2698f1SMatthew G. Knepley       switch (dim) {
4066ba2698f1SMatthew G. Knepley         case 1:
4067ba2698f1SMatthew G. Knepley           switch (coneSize) {
4068ba2698f1SMatthew G. Knepley             case 2: ct = DM_POLYTOPE_SEGMENT;break;
4069ba2698f1SMatthew G. Knepley             default: break;
4070ba2698f1SMatthew G. Knepley           }
4071ba2698f1SMatthew G. Knepley           break;
4072ba2698f1SMatthew G. Knepley         case 2:
4073ba2698f1SMatthew G. Knepley           switch (coneSize) {
4074ba2698f1SMatthew G. Knepley             case 3: ct = DM_POLYTOPE_TRIANGLE;break;
4075ba2698f1SMatthew G. Knepley             case 4: ct = DM_POLYTOPE_QUADRILATERAL;break;
4076ba2698f1SMatthew G. Knepley             default: break;
4077ba2698f1SMatthew G. Knepley           }
4078ba2698f1SMatthew G. Knepley           break;
4079ba2698f1SMatthew G. Knepley         case 3:
4080ba2698f1SMatthew G. Knepley           switch (coneSize) {
4081ba2698f1SMatthew G. Knepley             case 4: ct = DM_POLYTOPE_TETRAHEDRON;break;
4082da9060c4SMatthew G. Knepley             case 5:
4083da9060c4SMatthew G. Knepley             {
4084da9060c4SMatthew G. Knepley               const PetscInt *cone;
4085da9060c4SMatthew G. Knepley               PetscInt        faceConeSize;
4086da9060c4SMatthew G. Knepley 
40879566063dSJacob Faibussowitsch               PetscCall(DMPlexGetCone(dm, p, &cone));
40889566063dSJacob Faibussowitsch               PetscCall(DMPlexGetConeSize(dm, cone[0], &faceConeSize));
4089da9060c4SMatthew G. Knepley               switch (faceConeSize) {
4090da9060c4SMatthew G. Knepley                 case 3: ct = DM_POLYTOPE_TRI_PRISM_TENSOR;break;
4091da9060c4SMatthew G. Knepley                 case 4: ct = DM_POLYTOPE_PYRAMID;break;
4092da9060c4SMatthew G. Knepley               }
4093da9060c4SMatthew G. Knepley             }
4094da9060c4SMatthew G. Knepley             break;
4095ba2698f1SMatthew G. Knepley             case 6: ct = DM_POLYTOPE_HEXAHEDRON;break;
4096ba2698f1SMatthew G. Knepley             default: break;
4097ba2698f1SMatthew G. Knepley           }
4098ba2698f1SMatthew G. Knepley           break;
4099ba2698f1SMatthew G. Knepley         default: break;
4100ba2698f1SMatthew G. Knepley       }
4101ba2698f1SMatthew G. Knepley     } else if (pheight > 0) {
4102ba2698f1SMatthew G. Knepley       switch (coneSize) {
4103ba2698f1SMatthew G. Knepley         case 2: ct = DM_POLYTOPE_SEGMENT;break;
4104ba2698f1SMatthew G. Knepley         case 3: ct = DM_POLYTOPE_TRIANGLE;break;
4105ba2698f1SMatthew G. Knepley         case 4: ct = DM_POLYTOPE_QUADRILATERAL;break;
4106ba2698f1SMatthew G. Knepley         default: break;
4107ba2698f1SMatthew G. Knepley       }
4108ba2698f1SMatthew G. Knepley     }
4109ba2698f1SMatthew G. Knepley   }
4110412e9a14SMatthew G. Knepley   *pt = ct;
4111412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
4112ba2698f1SMatthew G. Knepley }
4113412e9a14SMatthew G. Knepley 
4114412e9a14SMatthew G. Knepley /*@
4115412e9a14SMatthew G. Knepley   DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size.
4116412e9a14SMatthew G. Knepley 
4117412e9a14SMatthew G. Knepley   Collective on dm
4118412e9a14SMatthew G. Knepley 
4119412e9a14SMatthew G. Knepley   Input Parameter:
4120412e9a14SMatthew G. Knepley . mesh - The DMPlex
4121412e9a14SMatthew G. Knepley 
4122412e9a14SMatthew G. Knepley   DMPlexComputeCellTypes() should be called after all calls to DMPlexSymmetrize() and DMPlexStratify()
4123412e9a14SMatthew G. Knepley 
4124412e9a14SMatthew G. Knepley   Level: developer
4125412e9a14SMatthew G. Knepley 
4126412e9a14SMatthew G. Knepley   Note: This function is normally called automatically by Plex when a cell type is requested. It creates an
4127412e9a14SMatthew G. Knepley   internal DMLabel named "celltype" which can be directly accessed using DMGetLabel(). A user may disable
4128412e9a14SMatthew G. Knepley   automatic creation by creating the label manually, using DMCreateLabel(dm, "celltype").
4129412e9a14SMatthew G. Knepley 
4130db781477SPatrick Sanan .seealso: `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexStratify()`, `DMGetLabel()`, `DMCreateLabel()`
4131412e9a14SMatthew G. Knepley @*/
4132412e9a14SMatthew G. Knepley PetscErrorCode DMPlexComputeCellTypes(DM dm)
4133412e9a14SMatthew G. Knepley {
4134412e9a14SMatthew G. Knepley   DM_Plex       *mesh;
4135412e9a14SMatthew G. Knepley   DMLabel        ctLabel;
4136412e9a14SMatthew G. Knepley   PetscInt       pStart, pEnd, p;
4137412e9a14SMatthew G. Knepley 
4138412e9a14SMatthew G. Knepley   PetscFunctionBegin;
4139412e9a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4140412e9a14SMatthew G. Knepley   mesh = (DM_Plex *) dm->data;
41419566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "celltype"));
41429566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel));
41439566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
4144412e9a14SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
4145327c2912SStefano Zampini     DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
4146412e9a14SMatthew G. Knepley     PetscInt       pdepth;
4147412e9a14SMatthew G. Knepley 
41489566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPointDepth(dm, p, &pdepth));
41499566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellType_Internal(dm, p, pdepth, &ct));
415063a3b9bcSJacob Faibussowitsch     PetscCheck(ct != DM_POLYTOPE_UNKNOWN,PETSC_COMM_SELF, PETSC_ERR_SUP, "Point %" PetscInt_FMT " is screwed up", p);
41519566063dSJacob Faibussowitsch     PetscCall(DMLabelSetValue(ctLabel, p, ct));
4152412e9a14SMatthew G. Knepley   }
41539566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateGet((PetscObject) ctLabel, &mesh->celltypeState));
41549566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject) ctLabel, NULL, "-dm_plex_celltypes_view"));
4155ba2698f1SMatthew G. Knepley   PetscFunctionReturn(0);
4156ba2698f1SMatthew G. Knepley }
4157ba2698f1SMatthew G. Knepley 
4158552f7358SJed Brown /*@C
4159552f7358SJed Brown   DMPlexGetJoin - Get an array for the join of the set of points
4160552f7358SJed Brown 
4161552f7358SJed Brown   Not Collective
4162552f7358SJed Brown 
4163552f7358SJed Brown   Input Parameters:
4164552f7358SJed Brown + dm - The DMPlex object
4165552f7358SJed Brown . numPoints - The number of input points for the join
4166552f7358SJed Brown - points - The input points
4167552f7358SJed Brown 
4168552f7358SJed Brown   Output Parameters:
4169552f7358SJed Brown + numCoveredPoints - The number of points in the join
4170552f7358SJed Brown - coveredPoints - The points in the join
4171552f7358SJed Brown 
4172552f7358SJed Brown   Level: intermediate
4173552f7358SJed Brown 
4174552f7358SJed Brown   Note: Currently, this is restricted to a single level join
4175552f7358SJed Brown 
41763813dfbdSMatthew G Knepley   Fortran Notes:
41773813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
41783813dfbdSMatthew G Knepley   include petsc.h90 in your code.
41793813dfbdSMatthew G Knepley 
41803813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
41813813dfbdSMatthew G Knepley 
4182db781477SPatrick Sanan .seealso: `DMPlexRestoreJoin()`, `DMPlexGetMeet()`
4183552f7358SJed Brown @*/
4184552f7358SJed Brown PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4185552f7358SJed Brown {
4186552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
4187552f7358SJed Brown   PetscInt      *join[2];
4188552f7358SJed Brown   PetscInt       joinSize, i = 0;
4189552f7358SJed Brown   PetscInt       dof, off, p, c, m;
41906302a7fbSVaclav Hapla   PetscInt       maxSupportSize;
4191552f7358SJed Brown 
4192552f7358SJed Brown   PetscFunctionBegin;
4193552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
419448bb261cSVaclav Hapla   PetscValidIntPointer(points, 3);
419548bb261cSVaclav Hapla   PetscValidIntPointer(numCoveredPoints, 4);
419648bb261cSVaclav Hapla   PetscValidPointer(coveredPoints, 5);
41976302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize));
41986302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[0]));
41996302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[1]));
4200552f7358SJed Brown   /* Copy in support of first point */
42019566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, points[0], &dof));
42029566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, points[0], &off));
4203552f7358SJed Brown   for (joinSize = 0; joinSize < dof; ++joinSize) {
4204552f7358SJed Brown     join[i][joinSize] = mesh->supports[off+joinSize];
4205552f7358SJed Brown   }
4206552f7358SJed Brown   /* Check each successive support */
4207552f7358SJed Brown   for (p = 1; p < numPoints; ++p) {
4208552f7358SJed Brown     PetscInt newJoinSize = 0;
4209552f7358SJed Brown 
42109566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->supportSection, points[p], &dof));
42119566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->supportSection, points[p], &off));
4212552f7358SJed Brown     for (c = 0; c < dof; ++c) {
4213552f7358SJed Brown       const PetscInt point = mesh->supports[off+c];
4214552f7358SJed Brown 
4215552f7358SJed Brown       for (m = 0; m < joinSize; ++m) {
4216552f7358SJed Brown         if (point == join[i][m]) {
4217552f7358SJed Brown           join[1-i][newJoinSize++] = point;
4218552f7358SJed Brown           break;
4219552f7358SJed Brown         }
4220552f7358SJed Brown       }
4221552f7358SJed Brown     }
4222552f7358SJed Brown     joinSize = newJoinSize;
4223552f7358SJed Brown     i        = 1-i;
4224552f7358SJed Brown   }
4225552f7358SJed Brown   *numCoveredPoints = joinSize;
4226552f7358SJed Brown   *coveredPoints    = join[i];
42276302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, maxSupportSize, MPIU_INT, &join[1-i]));
4228552f7358SJed Brown   PetscFunctionReturn(0);
4229552f7358SJed Brown }
4230552f7358SJed Brown 
4231552f7358SJed Brown /*@C
4232552f7358SJed Brown   DMPlexRestoreJoin - Restore an array for the join of the set of points
4233552f7358SJed Brown 
4234552f7358SJed Brown   Not Collective
4235552f7358SJed Brown 
4236552f7358SJed Brown   Input Parameters:
4237552f7358SJed Brown + dm - The DMPlex object
4238552f7358SJed Brown . numPoints - The number of input points for the join
4239552f7358SJed Brown - points - The input points
4240552f7358SJed Brown 
4241552f7358SJed Brown   Output Parameters:
4242552f7358SJed Brown + numCoveredPoints - The number of points in the join
4243552f7358SJed Brown - coveredPoints - The points in the join
4244552f7358SJed Brown 
42453813dfbdSMatthew G Knepley   Fortran Notes:
42463813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
42473813dfbdSMatthew G Knepley   include petsc.h90 in your code.
42483813dfbdSMatthew G Knepley 
42493813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
42503813dfbdSMatthew G Knepley 
4251552f7358SJed Brown   Level: intermediate
4252552f7358SJed Brown 
4253db781477SPatrick Sanan .seealso: `DMPlexGetJoin()`, `DMPlexGetFullJoin()`, `DMPlexGetMeet()`
4254552f7358SJed Brown @*/
4255552f7358SJed Brown PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4256552f7358SJed Brown {
4257552f7358SJed Brown   PetscFunctionBegin;
4258552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4259d7902bd2SMatthew G. Knepley   if (points) PetscValidIntPointer(points,3);
4260d7902bd2SMatthew G. Knepley   if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4);
4261d7902bd2SMatthew G. Knepley   PetscValidPointer(coveredPoints, 5);
42629566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints));
4263d7902bd2SMatthew G. Knepley   if (numCoveredPoints) *numCoveredPoints = 0;
4264552f7358SJed Brown   PetscFunctionReturn(0);
4265552f7358SJed Brown }
4266552f7358SJed Brown 
4267552f7358SJed Brown /*@C
4268552f7358SJed Brown   DMPlexGetFullJoin - Get an array for the join of the set of points
4269552f7358SJed Brown 
4270552f7358SJed Brown   Not Collective
4271552f7358SJed Brown 
4272552f7358SJed Brown   Input Parameters:
4273552f7358SJed Brown + dm - The DMPlex object
4274552f7358SJed Brown . numPoints - The number of input points for the join
4275552f7358SJed Brown - points - The input points
4276552f7358SJed Brown 
4277552f7358SJed Brown   Output Parameters:
4278552f7358SJed Brown + numCoveredPoints - The number of points in the join
4279552f7358SJed Brown - coveredPoints - The points in the join
4280552f7358SJed Brown 
42813813dfbdSMatthew G Knepley   Fortran Notes:
42823813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
42833813dfbdSMatthew G Knepley   include petsc.h90 in your code.
42843813dfbdSMatthew G Knepley 
42853813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
42863813dfbdSMatthew G Knepley 
4287552f7358SJed Brown   Level: intermediate
4288552f7358SJed Brown 
4289db781477SPatrick Sanan .seealso: `DMPlexGetJoin()`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()`
4290552f7358SJed Brown @*/
4291552f7358SJed Brown PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4292552f7358SJed Brown {
4293552f7358SJed Brown   PetscInt      *offsets, **closures;
4294552f7358SJed Brown   PetscInt      *join[2];
4295552f7358SJed Brown   PetscInt       depth = 0, maxSize, joinSize = 0, i = 0;
429624c766afSToby Isaac   PetscInt       p, d, c, m, ms;
4297552f7358SJed Brown 
4298552f7358SJed Brown   PetscFunctionBegin;
4299552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
430048bb261cSVaclav Hapla   PetscValidIntPointer(points, 3);
430148bb261cSVaclav Hapla   PetscValidIntPointer(numCoveredPoints, 4);
430248bb261cSVaclav Hapla   PetscValidPointer(coveredPoints, 5);
4303552f7358SJed Brown 
43049566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
43059566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(numPoints, &closures));
43069566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets));
43076302a7fbSVaclav Hapla   PetscCall(DMPlexGetMaxSizes(dm, NULL, &ms));
430824c766afSToby Isaac   maxSize = (ms > 1) ? ((PetscPowInt(ms,depth+1)-1)/(ms-1)) : depth + 1;
43099566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0]));
43109566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1]));
4311552f7358SJed Brown 
4312552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
4313552f7358SJed Brown     PetscInt closureSize;
4314552f7358SJed Brown 
43159566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]));
43160d644c17SKarl Rupp 
4317552f7358SJed Brown     offsets[p*(depth+2)+0] = 0;
4318552f7358SJed Brown     for (d = 0; d < depth+1; ++d) {
4319552f7358SJed Brown       PetscInt pStart, pEnd, i;
4320552f7358SJed Brown 
43219566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
4322552f7358SJed Brown       for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) {
4323552f7358SJed Brown         if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) {
4324552f7358SJed Brown           offsets[p*(depth+2)+d+1] = i;
4325552f7358SJed Brown           break;
4326552f7358SJed Brown         }
4327552f7358SJed Brown       }
4328552f7358SJed Brown       if (i == closureSize) offsets[p*(depth+2)+d+1] = i;
4329552f7358SJed Brown     }
433063a3b9bcSJacob 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);
4331552f7358SJed Brown   }
4332552f7358SJed Brown   for (d = 0; d < depth+1; ++d) {
4333552f7358SJed Brown     PetscInt dof;
4334552f7358SJed Brown 
4335552f7358SJed Brown     /* Copy in support of first point */
4336552f7358SJed Brown     dof = offsets[d+1] - offsets[d];
4337552f7358SJed Brown     for (joinSize = 0; joinSize < dof; ++joinSize) {
4338552f7358SJed Brown       join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2];
4339552f7358SJed Brown     }
4340552f7358SJed Brown     /* Check each successive cone */
4341552f7358SJed Brown     for (p = 1; p < numPoints && joinSize; ++p) {
4342552f7358SJed Brown       PetscInt newJoinSize = 0;
4343552f7358SJed Brown 
4344552f7358SJed Brown       dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d];
4345552f7358SJed Brown       for (c = 0; c < dof; ++c) {
4346552f7358SJed Brown         const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2];
4347552f7358SJed Brown 
4348552f7358SJed Brown         for (m = 0; m < joinSize; ++m) {
4349552f7358SJed Brown           if (point == join[i][m]) {
4350552f7358SJed Brown             join[1-i][newJoinSize++] = point;
4351552f7358SJed Brown             break;
4352552f7358SJed Brown           }
4353552f7358SJed Brown         }
4354552f7358SJed Brown       }
4355552f7358SJed Brown       joinSize = newJoinSize;
4356552f7358SJed Brown       i        = 1-i;
4357552f7358SJed Brown     }
4358552f7358SJed Brown     if (joinSize) break;
4359552f7358SJed Brown   }
4360552f7358SJed Brown   *numCoveredPoints = joinSize;
4361552f7358SJed Brown   *coveredPoints    = join[i];
4362552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
43639566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]));
4364552f7358SJed Brown   }
43659566063dSJacob Faibussowitsch   PetscCall(PetscFree(closures));
43669566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, numPoints*(depth+2), MPIU_INT, &offsets));
43676302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, ms, MPIU_INT, &join[1-i]));
4368552f7358SJed Brown   PetscFunctionReturn(0);
4369552f7358SJed Brown }
4370552f7358SJed Brown 
4371552f7358SJed Brown /*@C
4372552f7358SJed Brown   DMPlexGetMeet - Get an array for the meet of the set of points
4373552f7358SJed Brown 
4374552f7358SJed Brown   Not Collective
4375552f7358SJed Brown 
4376552f7358SJed Brown   Input Parameters:
4377552f7358SJed Brown + dm - The DMPlex object
4378552f7358SJed Brown . numPoints - The number of input points for the meet
4379552f7358SJed Brown - points - The input points
4380552f7358SJed Brown 
4381552f7358SJed Brown   Output Parameters:
4382552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4383552f7358SJed Brown - coveredPoints - The points in the meet
4384552f7358SJed Brown 
4385552f7358SJed Brown   Level: intermediate
4386552f7358SJed Brown 
4387552f7358SJed Brown   Note: Currently, this is restricted to a single level meet
4388552f7358SJed Brown 
43893813dfbdSMatthew G Knepley   Fortran Notes:
43903813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
43913813dfbdSMatthew G Knepley   include petsc.h90 in your code.
43923813dfbdSMatthew G Knepley 
43933813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
43943813dfbdSMatthew G Knepley 
4395db781477SPatrick Sanan .seealso: `DMPlexRestoreMeet()`, `DMPlexGetJoin()`
4396552f7358SJed Brown @*/
4397552f7358SJed Brown PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints)
4398552f7358SJed Brown {
4399552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
4400552f7358SJed Brown   PetscInt      *meet[2];
4401552f7358SJed Brown   PetscInt       meetSize, i = 0;
4402552f7358SJed Brown   PetscInt       dof, off, p, c, m;
44036302a7fbSVaclav Hapla   PetscInt       maxConeSize;
4404552f7358SJed Brown 
4405552f7358SJed Brown   PetscFunctionBegin;
4406552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4407dadcf809SJacob Faibussowitsch   PetscValidIntPointer(points, 3);
4408dadcf809SJacob Faibussowitsch   PetscValidIntPointer(numCoveringPoints, 4);
4409064a246eSJacob Faibussowitsch   PetscValidPointer(coveringPoints, 5);
44106302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->coneSection, &maxConeSize));
44116302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[0]));
44126302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[1]));
4413552f7358SJed Brown   /* Copy in cone of first point */
44149566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, points[0], &dof));
44159566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, points[0], &off));
4416552f7358SJed Brown   for (meetSize = 0; meetSize < dof; ++meetSize) {
4417552f7358SJed Brown     meet[i][meetSize] = mesh->cones[off+meetSize];
4418552f7358SJed Brown   }
4419552f7358SJed Brown   /* Check each successive cone */
4420552f7358SJed Brown   for (p = 1; p < numPoints; ++p) {
4421552f7358SJed Brown     PetscInt newMeetSize = 0;
4422552f7358SJed Brown 
44239566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, points[p], &dof));
44249566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, points[p], &off));
4425552f7358SJed Brown     for (c = 0; c < dof; ++c) {
4426552f7358SJed Brown       const PetscInt point = mesh->cones[off+c];
4427552f7358SJed Brown 
4428552f7358SJed Brown       for (m = 0; m < meetSize; ++m) {
4429552f7358SJed Brown         if (point == meet[i][m]) {
4430552f7358SJed Brown           meet[1-i][newMeetSize++] = point;
4431552f7358SJed Brown           break;
4432552f7358SJed Brown         }
4433552f7358SJed Brown       }
4434552f7358SJed Brown     }
4435552f7358SJed Brown     meetSize = newMeetSize;
4436552f7358SJed Brown     i        = 1-i;
4437552f7358SJed Brown   }
4438552f7358SJed Brown   *numCoveringPoints = meetSize;
4439552f7358SJed Brown   *coveringPoints    = meet[i];
44406302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, maxConeSize, MPIU_INT, &meet[1-i]));
4441552f7358SJed Brown   PetscFunctionReturn(0);
4442552f7358SJed Brown }
4443552f7358SJed Brown 
4444552f7358SJed Brown /*@C
4445552f7358SJed Brown   DMPlexRestoreMeet - Restore an array for the meet of the set of points
4446552f7358SJed Brown 
4447552f7358SJed Brown   Not Collective
4448552f7358SJed Brown 
4449552f7358SJed Brown   Input Parameters:
4450552f7358SJed Brown + dm - The DMPlex object
4451552f7358SJed Brown . numPoints - The number of input points for the meet
4452552f7358SJed Brown - points - The input points
4453552f7358SJed Brown 
4454552f7358SJed Brown   Output Parameters:
4455552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4456552f7358SJed Brown - coveredPoints - The points in the meet
4457552f7358SJed Brown 
4458552f7358SJed Brown   Level: intermediate
4459552f7358SJed Brown 
44603813dfbdSMatthew G Knepley   Fortran Notes:
44613813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
44623813dfbdSMatthew G Knepley   include petsc.h90 in your code.
44633813dfbdSMatthew G Knepley 
44643813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
44653813dfbdSMatthew G Knepley 
4466db781477SPatrick Sanan .seealso: `DMPlexGetMeet()`, `DMPlexGetFullMeet()`, `DMPlexGetJoin()`
4467552f7358SJed Brown @*/
4468552f7358SJed Brown PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4469552f7358SJed Brown {
4470552f7358SJed Brown   PetscFunctionBegin;
4471552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4472d7902bd2SMatthew G. Knepley   if (points) PetscValidIntPointer(points,3);
4473d7902bd2SMatthew G. Knepley   if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4);
4474d7902bd2SMatthew G. Knepley   PetscValidPointer(coveredPoints,5);
44759566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void*) coveredPoints));
4476d7902bd2SMatthew G. Knepley   if (numCoveredPoints) *numCoveredPoints = 0;
4477552f7358SJed Brown   PetscFunctionReturn(0);
4478552f7358SJed Brown }
4479552f7358SJed Brown 
4480552f7358SJed Brown /*@C
4481552f7358SJed Brown   DMPlexGetFullMeet - Get an array for the meet of the set of points
4482552f7358SJed Brown 
4483552f7358SJed Brown   Not Collective
4484552f7358SJed Brown 
4485552f7358SJed Brown   Input Parameters:
4486552f7358SJed Brown + dm - The DMPlex object
4487552f7358SJed Brown . numPoints - The number of input points for the meet
4488552f7358SJed Brown - points - The input points
4489552f7358SJed Brown 
4490552f7358SJed Brown   Output Parameters:
4491552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4492552f7358SJed Brown - coveredPoints - The points in the meet
4493552f7358SJed Brown 
4494552f7358SJed Brown   Level: intermediate
4495552f7358SJed Brown 
44963813dfbdSMatthew G Knepley   Fortran Notes:
44973813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
44983813dfbdSMatthew G Knepley   include petsc.h90 in your code.
44993813dfbdSMatthew G Knepley 
45003813dfbdSMatthew G Knepley   The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array.
45013813dfbdSMatthew G Knepley 
4502db781477SPatrick Sanan .seealso: `DMPlexGetMeet()`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()`
4503552f7358SJed Brown @*/
4504552f7358SJed Brown PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4505552f7358SJed Brown {
4506552f7358SJed Brown   PetscInt      *offsets, **closures;
4507552f7358SJed Brown   PetscInt      *meet[2];
4508552f7358SJed Brown   PetscInt       height = 0, maxSize, meetSize = 0, i = 0;
450924c766afSToby Isaac   PetscInt       p, h, c, m, mc;
4510552f7358SJed Brown 
4511552f7358SJed Brown   PetscFunctionBegin;
4512552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4513dadcf809SJacob Faibussowitsch   PetscValidIntPointer(points, 3);
4514dadcf809SJacob Faibussowitsch   PetscValidIntPointer(numCoveredPoints, 4);
4515064a246eSJacob Faibussowitsch   PetscValidPointer(coveredPoints, 5);
4516552f7358SJed Brown 
45179566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &height));
45189566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(numPoints, &closures));
45199566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets));
45206302a7fbSVaclav Hapla   PetscCall(DMPlexGetMaxSizes(dm, &mc, NULL));
452124c766afSToby Isaac   maxSize = (mc > 1) ? ((PetscPowInt(mc,height+1)-1)/(mc-1)) : height + 1;
45229566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0]));
45239566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1]));
4524552f7358SJed Brown 
4525552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
4526552f7358SJed Brown     PetscInt closureSize;
4527552f7358SJed Brown 
45289566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]));
45290d644c17SKarl Rupp 
4530552f7358SJed Brown     offsets[p*(height+2)+0] = 0;
4531552f7358SJed Brown     for (h = 0; h < height+1; ++h) {
4532552f7358SJed Brown       PetscInt pStart, pEnd, i;
4533552f7358SJed Brown 
45349566063dSJacob Faibussowitsch       PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd));
4535552f7358SJed Brown       for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) {
4536552f7358SJed Brown         if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) {
4537552f7358SJed Brown           offsets[p*(height+2)+h+1] = i;
4538552f7358SJed Brown           break;
4539552f7358SJed Brown         }
4540552f7358SJed Brown       }
4541552f7358SJed Brown       if (i == closureSize) offsets[p*(height+2)+h+1] = i;
4542552f7358SJed Brown     }
454363a3b9bcSJacob 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);
4544552f7358SJed Brown   }
4545552f7358SJed Brown   for (h = 0; h < height+1; ++h) {
4546552f7358SJed Brown     PetscInt dof;
4547552f7358SJed Brown 
4548552f7358SJed Brown     /* Copy in cone of first point */
4549552f7358SJed Brown     dof = offsets[h+1] - offsets[h];
4550552f7358SJed Brown     for (meetSize = 0; meetSize < dof; ++meetSize) {
4551552f7358SJed Brown       meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2];
4552552f7358SJed Brown     }
4553552f7358SJed Brown     /* Check each successive cone */
4554552f7358SJed Brown     for (p = 1; p < numPoints && meetSize; ++p) {
4555552f7358SJed Brown       PetscInt newMeetSize = 0;
4556552f7358SJed Brown 
4557552f7358SJed Brown       dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h];
4558552f7358SJed Brown       for (c = 0; c < dof; ++c) {
4559552f7358SJed Brown         const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2];
4560552f7358SJed Brown 
4561552f7358SJed Brown         for (m = 0; m < meetSize; ++m) {
4562552f7358SJed Brown           if (point == meet[i][m]) {
4563552f7358SJed Brown             meet[1-i][newMeetSize++] = point;
4564552f7358SJed Brown             break;
4565552f7358SJed Brown           }
4566552f7358SJed Brown         }
4567552f7358SJed Brown       }
4568552f7358SJed Brown       meetSize = newMeetSize;
4569552f7358SJed Brown       i        = 1-i;
4570552f7358SJed Brown     }
4571552f7358SJed Brown     if (meetSize) break;
4572552f7358SJed Brown   }
4573552f7358SJed Brown   *numCoveredPoints = meetSize;
4574552f7358SJed Brown   *coveredPoints    = meet[i];
4575552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
45769566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]));
4577552f7358SJed Brown   }
45789566063dSJacob Faibussowitsch   PetscCall(PetscFree(closures));
45799566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, numPoints*(height+2), MPIU_INT, &offsets));
45806302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, mc, MPIU_INT, &meet[1-i]));
4581552f7358SJed Brown   PetscFunctionReturn(0);
4582552f7358SJed Brown }
4583552f7358SJed Brown 
45844e3744c5SMatthew G. Knepley /*@C
45854e3744c5SMatthew G. Knepley   DMPlexEqual - Determine if two DMs have the same topology
45864e3744c5SMatthew G. Knepley 
45874e3744c5SMatthew G. Knepley   Not Collective
45884e3744c5SMatthew G. Knepley 
45894e3744c5SMatthew G. Knepley   Input Parameters:
45904e3744c5SMatthew G. Knepley + dmA - A DMPlex object
45914e3744c5SMatthew G. Knepley - dmB - A DMPlex object
45924e3744c5SMatthew G. Knepley 
45934e3744c5SMatthew G. Knepley   Output Parameters:
45944e3744c5SMatthew G. Knepley . equal - PETSC_TRUE if the topologies are identical
45954e3744c5SMatthew G. Knepley 
45964e3744c5SMatthew G. Knepley   Level: intermediate
45974e3744c5SMatthew G. Knepley 
45984e3744c5SMatthew G. Knepley   Notes:
45994e3744c5SMatthew G. Knepley   We are not solving graph isomorphism, so we do not permutation.
46004e3744c5SMatthew G. Knepley 
4601db781477SPatrick Sanan .seealso: `DMPlexGetCone()`
46024e3744c5SMatthew G. Knepley @*/
46034e3744c5SMatthew G. Knepley PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal)
46044e3744c5SMatthew G. Knepley {
46054e3744c5SMatthew G. Knepley   PetscInt       depth, depthB, pStart, pEnd, pStartB, pEndB, p;
46064e3744c5SMatthew G. Knepley 
46074e3744c5SMatthew G. Knepley   PetscFunctionBegin;
46084e3744c5SMatthew G. Knepley   PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
46094e3744c5SMatthew G. Knepley   PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
4610dadcf809SJacob Faibussowitsch   PetscValidBoolPointer(equal, 3);
46114e3744c5SMatthew G. Knepley 
46124e3744c5SMatthew G. Knepley   *equal = PETSC_FALSE;
46139566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmA, &depth));
46149566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmB, &depthB));
46154e3744c5SMatthew G. Knepley   if (depth != depthB) PetscFunctionReturn(0);
46169566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dmA, &pStart,  &pEnd));
46179566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dmB, &pStartB, &pEndB));
46184e3744c5SMatthew G. Knepley   if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(0);
46194e3744c5SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
46204e3744c5SMatthew G. Knepley     const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB;
46214e3744c5SMatthew G. Knepley     PetscInt        coneSize, coneSizeB, c, supportSize, supportSizeB, s;
46224e3744c5SMatthew G. Knepley 
46239566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dmA, p, &coneSize));
46249566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dmA, p, &cone));
46259566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dmA, p, &ornt));
46269566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dmB, p, &coneSizeB));
46279566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dmB, p, &coneB));
46289566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dmB, p, &orntB));
46294e3744c5SMatthew G. Knepley     if (coneSize != coneSizeB) PetscFunctionReturn(0);
46304e3744c5SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
46314e3744c5SMatthew G. Knepley       if (cone[c] != coneB[c]) PetscFunctionReturn(0);
46324e3744c5SMatthew G. Knepley       if (ornt[c] != orntB[c]) PetscFunctionReturn(0);
46334e3744c5SMatthew G. Knepley     }
46349566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dmA, p, &supportSize));
46359566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dmA, p, &support));
46369566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dmB, p, &supportSizeB));
46379566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dmB, p, &supportB));
46384e3744c5SMatthew G. Knepley     if (supportSize != supportSizeB) PetscFunctionReturn(0);
46394e3744c5SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
46404e3744c5SMatthew G. Knepley       if (support[s] != supportB[s]) PetscFunctionReturn(0);
46414e3744c5SMatthew G. Knepley     }
46424e3744c5SMatthew G. Knepley   }
46434e3744c5SMatthew G. Knepley   *equal = PETSC_TRUE;
46444e3744c5SMatthew G. Knepley   PetscFunctionReturn(0);
46454e3744c5SMatthew G. Knepley }
46464e3744c5SMatthew G. Knepley 
46477cd05799SMatthew G. Knepley /*@C
46487cd05799SMatthew G. Knepley   DMPlexGetNumFaceVertices - Returns the number of vertices on a face
46497cd05799SMatthew G. Knepley 
46507cd05799SMatthew G. Knepley   Not Collective
46517cd05799SMatthew G. Knepley 
46527cd05799SMatthew G. Knepley   Input Parameters:
46537cd05799SMatthew G. Knepley + dm         - The DMPlex
46547cd05799SMatthew G. Knepley . cellDim    - The cell dimension
46557cd05799SMatthew G. Knepley - numCorners - The number of vertices on a cell
46567cd05799SMatthew G. Knepley 
46577cd05799SMatthew G. Knepley   Output Parameters:
46587cd05799SMatthew G. Knepley . numFaceVertices - The number of vertices on a face
46597cd05799SMatthew G. Knepley 
46607cd05799SMatthew G. Knepley   Level: developer
46617cd05799SMatthew G. Knepley 
46627cd05799SMatthew G. Knepley   Notes:
46637cd05799SMatthew G. Knepley   Of course this can only work for a restricted set of symmetric shapes
46647cd05799SMatthew G. Knepley 
4665db781477SPatrick Sanan .seealso: `DMPlexGetCone()`
46667cd05799SMatthew G. Knepley @*/
466718ad9376SMatthew G. Knepley PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices)
4668a6dfd86eSKarl Rupp {
466982f516ccSBarry Smith   MPI_Comm       comm;
4670552f7358SJed Brown 
4671552f7358SJed Brown   PetscFunctionBegin;
46729566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm,&comm));
4673dadcf809SJacob Faibussowitsch   PetscValidIntPointer(numFaceVertices,4);
4674552f7358SJed Brown   switch (cellDim) {
4675552f7358SJed Brown   case 0:
4676552f7358SJed Brown     *numFaceVertices = 0;
4677552f7358SJed Brown     break;
4678552f7358SJed Brown   case 1:
4679552f7358SJed Brown     *numFaceVertices = 1;
4680552f7358SJed Brown     break;
4681552f7358SJed Brown   case 2:
4682552f7358SJed Brown     switch (numCorners) {
468319436ca2SJed Brown     case 3: /* triangle */
468419436ca2SJed Brown       *numFaceVertices = 2; /* Edge has 2 vertices */
4685552f7358SJed Brown       break;
468619436ca2SJed Brown     case 4: /* quadrilateral */
468719436ca2SJed Brown       *numFaceVertices = 2; /* Edge has 2 vertices */
4688552f7358SJed Brown       break;
468919436ca2SJed Brown     case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */
469019436ca2SJed Brown       *numFaceVertices = 3; /* Edge has 3 vertices */
4691552f7358SJed Brown       break;
469219436ca2SJed Brown     case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */
469319436ca2SJed Brown       *numFaceVertices = 3; /* Edge has 3 vertices */
4694552f7358SJed Brown       break;
4695552f7358SJed Brown     default:
469663a3b9bcSJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim);
4697552f7358SJed Brown     }
4698552f7358SJed Brown     break;
4699552f7358SJed Brown   case 3:
4700552f7358SJed Brown     switch (numCorners) {
470119436ca2SJed Brown     case 4: /* tetradehdron */
470219436ca2SJed Brown       *numFaceVertices = 3; /* Face has 3 vertices */
4703552f7358SJed Brown       break;
470419436ca2SJed Brown     case 6: /* tet cohesive cells */
470519436ca2SJed Brown       *numFaceVertices = 4; /* Face has 4 vertices */
4706552f7358SJed Brown       break;
470719436ca2SJed Brown     case 8: /* hexahedron */
470819436ca2SJed Brown       *numFaceVertices = 4; /* Face has 4 vertices */
4709552f7358SJed Brown       break;
471019436ca2SJed Brown     case 9: /* tet cohesive Lagrange cells */
471119436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4712552f7358SJed Brown       break;
471319436ca2SJed Brown     case 10: /* quadratic tetrahedron */
471419436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4715552f7358SJed Brown       break;
471619436ca2SJed Brown     case 12: /* hex cohesive Lagrange cells */
471719436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4718552f7358SJed Brown       break;
471919436ca2SJed Brown     case 18: /* quadratic tet cohesive Lagrange cells */
472019436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4721552f7358SJed Brown       break;
472219436ca2SJed Brown     case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */
472319436ca2SJed Brown       *numFaceVertices = 9; /* Face has 9 vertices */
4724552f7358SJed Brown       break;
4725552f7358SJed Brown     default:
472663a3b9bcSJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim);
4727552f7358SJed Brown     }
4728552f7358SJed Brown     break;
4729552f7358SJed Brown   default:
473063a3b9bcSJacob Faibussowitsch     SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %" PetscInt_FMT, cellDim);
4731552f7358SJed Brown   }
4732552f7358SJed Brown   PetscFunctionReturn(0);
4733552f7358SJed Brown }
4734552f7358SJed Brown 
4735552f7358SJed Brown /*@
4736aa50250dSMatthew G. Knepley   DMPlexGetDepthLabel - Get the DMLabel recording the depth of each point
4737552f7358SJed Brown 
4738552f7358SJed Brown   Not Collective
4739552f7358SJed Brown 
4740aa50250dSMatthew G. Knepley   Input Parameter:
4741552f7358SJed Brown . dm    - The DMPlex object
4742552f7358SJed Brown 
4743aa50250dSMatthew G. Knepley   Output Parameter:
4744aa50250dSMatthew G. Knepley . depthLabel - The DMLabel recording point depth
4745552f7358SJed Brown 
4746552f7358SJed Brown   Level: developer
4747552f7358SJed Brown 
4748db781477SPatrick Sanan .seealso: `DMPlexGetDepth()`, `DMPlexGetHeightStratum()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`,
4749aa50250dSMatthew G. Knepley @*/
4750aa50250dSMatthew G. Knepley PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel)
4751aa50250dSMatthew G. Knepley {
4752aa50250dSMatthew G. Knepley   PetscFunctionBegin;
4753aa50250dSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4754aa50250dSMatthew G. Knepley   PetscValidPointer(depthLabel, 2);
4755c58f1c22SToby Isaac   *depthLabel = dm->depthLabel;
4756aa50250dSMatthew G. Knepley   PetscFunctionReturn(0);
4757aa50250dSMatthew G. Knepley }
4758aa50250dSMatthew G. Knepley 
4759aa50250dSMatthew G. Knepley /*@
4760aa50250dSMatthew G. Knepley   DMPlexGetDepth - Get the depth of the DAG representing this mesh
4761aa50250dSMatthew G. Knepley 
4762aa50250dSMatthew G. Knepley   Not Collective
4763aa50250dSMatthew G. Knepley 
4764aa50250dSMatthew G. Knepley   Input Parameter:
4765aa50250dSMatthew G. Knepley . dm    - The DMPlex object
4766aa50250dSMatthew G. Knepley 
4767aa50250dSMatthew G. Knepley   Output Parameter:
4768aa50250dSMatthew G. Knepley . depth - The number of strata (breadth first levels) in the DAG
4769aa50250dSMatthew G. Knepley 
4770aa50250dSMatthew G. Knepley   Level: developer
4771552f7358SJed Brown 
4772b1bb481bSMatthew Knepley   Notes:
4773b1bb481bSMatthew Knepley   This returns maximum of point depths over all points, i.e. maximum value of the label returned by DMPlexGetDepthLabel().
4774dc287ab2SVaclav Hapla   The point depth is described more in detail in DMPlexGetDepthStratum().
4775dc287ab2SVaclav Hapla   An empty mesh gives -1.
4776b1bb481bSMatthew Knepley 
4777db781477SPatrick Sanan .seealso: `DMPlexGetDepthLabel()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`
4778552f7358SJed Brown @*/
4779552f7358SJed Brown PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth)
4780552f7358SJed Brown {
4781aa50250dSMatthew G. Knepley   DMLabel        label;
4782aa50250dSMatthew G. Knepley   PetscInt       d = 0;
4783552f7358SJed Brown 
4784552f7358SJed Brown   PetscFunctionBegin;
4785552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4786dadcf809SJacob Faibussowitsch   PetscValidIntPointer(depth, 2);
47879566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
47889566063dSJacob Faibussowitsch   if (label) PetscCall(DMLabelGetNumValues(label, &d));
4789552f7358SJed Brown   *depth = d-1;
4790552f7358SJed Brown   PetscFunctionReturn(0);
4791552f7358SJed Brown }
4792552f7358SJed Brown 
4793552f7358SJed Brown /*@
4794552f7358SJed Brown   DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth.
4795552f7358SJed Brown 
4796552f7358SJed Brown   Not Collective
4797552f7358SJed Brown 
4798552f7358SJed Brown   Input Parameters:
4799552f7358SJed Brown + dm    - The DMPlex object
4800570fa34dSVaclav Hapla - depth - The requested depth
4801552f7358SJed Brown 
4802552f7358SJed Brown   Output Parameters:
4803552f7358SJed Brown + start - The first point at this depth
4804552f7358SJed Brown - end   - One beyond the last point at this depth
4805552f7358SJed Brown 
4806647867b2SJed Brown   Notes:
4807647867b2SJed Brown   Depth indexing is related to topological dimension.  Depth stratum 0 contains the lowest topological dimension points,
4808647867b2SJed Brown   often "vertices".  If the mesh is "interpolated" (see DMPlexInterpolate()), then depth stratum 1 contains the next
4809647867b2SJed Brown   higher dimension, e.g., "edges".
4810647867b2SJed Brown 
4811552f7358SJed Brown   Level: developer
4812552f7358SJed Brown 
4813db781477SPatrick Sanan .seealso: `DMPlexGetHeightStratum()`, `DMPlexGetDepth()`, `DMPlexGetDepthLabel()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`, `DMPlexInterpolate()`
4814552f7358SJed Brown @*/
4815570fa34dSVaclav Hapla PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt depth, PetscInt *start, PetscInt *end)
48160adebc6cSBarry Smith {
4817aa50250dSMatthew G. Knepley   DMLabel        label;
481863d1a920SMatthew G. Knepley   PetscInt       pStart, pEnd;
4819552f7358SJed Brown 
4820552f7358SJed Brown   PetscFunctionBegin;
4821552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4822dadcf809SJacob Faibussowitsch   if (start) {PetscValidIntPointer(start, 3); *start = 0;}
4823dadcf809SJacob Faibussowitsch   if (end)   {PetscValidIntPointer(end,   4); *end   = 0;}
48249566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
48250d644c17SKarl Rupp   if (pStart == pEnd) PetscFunctionReturn(0);
4826570fa34dSVaclav Hapla   if (depth < 0) {
482763d1a920SMatthew G. Knepley     if (start) *start = pStart;
482863d1a920SMatthew G. Knepley     if (end)   *end   = pEnd;
482963d1a920SMatthew G. Knepley     PetscFunctionReturn(0);
4830552f7358SJed Brown   }
48319566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
483228b400f6SJacob Faibussowitsch   PetscCheck(label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");
4833570fa34dSVaclav Hapla   PetscCall(DMLabelGetStratumBounds(label, depth, start, end));
4834552f7358SJed Brown   PetscFunctionReturn(0);
4835552f7358SJed Brown }
4836552f7358SJed Brown 
4837552f7358SJed Brown /*@
4838552f7358SJed Brown   DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height.
4839552f7358SJed Brown 
4840552f7358SJed Brown   Not Collective
4841552f7358SJed Brown 
4842552f7358SJed Brown   Input Parameters:
4843552f7358SJed Brown + dm     - The DMPlex object
4844570fa34dSVaclav Hapla - height - The requested height
4845552f7358SJed Brown 
4846552f7358SJed Brown   Output Parameters:
4847552f7358SJed Brown + start - The first point at this height
4848552f7358SJed Brown - end   - One beyond the last point at this height
4849552f7358SJed Brown 
4850647867b2SJed Brown   Notes:
4851647867b2SJed Brown   Height indexing is related to topological codimension.  Height stratum 0 contains the highest topological dimension
4852647867b2SJed Brown   points, often called "cells" or "elements".  If the mesh is "interpolated" (see DMPlexInterpolate()), then height
4853647867b2SJed Brown   stratum 1 contains the boundary of these "cells", often called "faces" or "facets".
4854647867b2SJed Brown 
4855552f7358SJed Brown   Level: developer
4856552f7358SJed Brown 
4857db781477SPatrick Sanan .seealso: `DMPlexGetDepthStratum()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()`
4858552f7358SJed Brown @*/
4859570fa34dSVaclav Hapla PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt height, PetscInt *start, PetscInt *end)
48600adebc6cSBarry Smith {
4861aa50250dSMatthew G. Knepley   DMLabel        label;
486263d1a920SMatthew G. Knepley   PetscInt       depth, pStart, pEnd;
4863552f7358SJed Brown 
4864552f7358SJed Brown   PetscFunctionBegin;
4865552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4866dadcf809SJacob Faibussowitsch   if (start) {PetscValidIntPointer(start, 3); *start = 0;}
4867dadcf809SJacob Faibussowitsch   if (end)   {PetscValidIntPointer(end,   4); *end   = 0;}
48689566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
48690d644c17SKarl Rupp   if (pStart == pEnd) PetscFunctionReturn(0);
4870570fa34dSVaclav Hapla   if (height < 0) {
487163d1a920SMatthew G. Knepley     if (start) *start = pStart;
487263d1a920SMatthew G. Knepley     if (end)   *end   = pEnd;
487363d1a920SMatthew G. Knepley     PetscFunctionReturn(0);
4874552f7358SJed Brown   }
48759566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
487628b400f6SJacob Faibussowitsch   PetscCheck(label,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");
48779566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(label, &depth));
4878570fa34dSVaclav Hapla   PetscCall(DMLabelGetStratumBounds(label, depth-1-height, start, end));
4879552f7358SJed Brown   PetscFunctionReturn(0);
4880552f7358SJed Brown }
4881552f7358SJed Brown 
4882ba2698f1SMatthew G. Knepley /*@
4883ba2698f1SMatthew G. Knepley   DMPlexGetPointDepth - Get the depth of a given point
4884ba2698f1SMatthew G. Knepley 
4885ba2698f1SMatthew G. Knepley   Not Collective
4886ba2698f1SMatthew G. Knepley 
4887d8d19677SJose E. Roman   Input Parameters:
4888ba2698f1SMatthew G. Knepley + dm    - The DMPlex object
4889ba2698f1SMatthew G. Knepley - point - The point
4890ba2698f1SMatthew G. Knepley 
4891ba2698f1SMatthew G. Knepley   Output Parameter:
4892ba2698f1SMatthew G. Knepley . depth - The depth of the point
4893ba2698f1SMatthew G. Knepley 
4894ba2698f1SMatthew G. Knepley   Level: intermediate
4895ba2698f1SMatthew G. Knepley 
4896db781477SPatrick Sanan .seealso: `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()`
4897ba2698f1SMatthew G. Knepley @*/
4898ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth)
4899ba2698f1SMatthew G. Knepley {
4900ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
4901ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
490240a2aa30SMatthew G. Knepley   PetscValidIntPointer(depth, 3);
49039566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(dm->depthLabel, point, depth));
4904ba2698f1SMatthew G. Knepley   PetscFunctionReturn(0);
4905ba2698f1SMatthew G. Knepley }
4906ba2698f1SMatthew G. Knepley 
4907ba2698f1SMatthew G. Knepley /*@
49080c0a32dcSVaclav Hapla   DMPlexGetPointHeight - Get the height of a given point
49090c0a32dcSVaclav Hapla 
49100c0a32dcSVaclav Hapla   Not Collective
49110c0a32dcSVaclav Hapla 
4912d8d19677SJose E. Roman   Input Parameters:
49130c0a32dcSVaclav Hapla + dm    - The DMPlex object
49140c0a32dcSVaclav Hapla - point - The point
49150c0a32dcSVaclav Hapla 
49160c0a32dcSVaclav Hapla   Output Parameter:
49170c0a32dcSVaclav Hapla . height - The height of the point
49180c0a32dcSVaclav Hapla 
49190c0a32dcSVaclav Hapla   Level: intermediate
49200c0a32dcSVaclav Hapla 
4921db781477SPatrick Sanan .seealso: `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointDepth()`
49220c0a32dcSVaclav Hapla @*/
49230c0a32dcSVaclav Hapla PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height)
49240c0a32dcSVaclav Hapla {
49250c0a32dcSVaclav Hapla   PetscInt       n, pDepth;
49260c0a32dcSVaclav Hapla 
49270c0a32dcSVaclav Hapla   PetscFunctionBegin;
49280c0a32dcSVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
49290c0a32dcSVaclav Hapla   PetscValidIntPointer(height, 3);
49309566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(dm->depthLabel, &n));
49319566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(dm->depthLabel, point, &pDepth));
49320c0a32dcSVaclav Hapla   *height = n - 1 - pDepth;  /* DAG depth is n-1 */
49330c0a32dcSVaclav Hapla   PetscFunctionReturn(0);
49340c0a32dcSVaclav Hapla }
49350c0a32dcSVaclav Hapla 
49360c0a32dcSVaclav Hapla /*@
4937ba2698f1SMatthew G. Knepley   DMPlexGetCellTypeLabel - Get the DMLabel recording the polytope type of each cell
4938ba2698f1SMatthew G. Knepley 
4939ba2698f1SMatthew G. Knepley   Not Collective
4940ba2698f1SMatthew G. Knepley 
4941ba2698f1SMatthew G. Knepley   Input Parameter:
4942ba2698f1SMatthew G. Knepley . dm - The DMPlex object
4943ba2698f1SMatthew G. Knepley 
4944ba2698f1SMatthew G. Knepley   Output Parameter:
4945ba2698f1SMatthew G. Knepley . celltypeLabel - The DMLabel recording cell polytope type
4946ba2698f1SMatthew G. Knepley 
4947412e9a14SMatthew G. Knepley   Note: This function will trigger automatica computation of cell types. This can be disabled by calling
4948412e9a14SMatthew G. Knepley   DMCreateLabel(dm, "celltype") beforehand.
4949412e9a14SMatthew G. Knepley 
4950ba2698f1SMatthew G. Knepley   Level: developer
4951ba2698f1SMatthew G. Knepley 
4952db781477SPatrick Sanan .seealso: `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMCreateLabel()`
4953ba2698f1SMatthew G. Knepley @*/
4954ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel)
4955ba2698f1SMatthew G. Knepley {
4956ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
4957ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4958ba2698f1SMatthew G. Knepley   PetscValidPointer(celltypeLabel, 2);
49599566063dSJacob Faibussowitsch   if (!dm->celltypeLabel) PetscCall(DMPlexComputeCellTypes(dm));
4960ba2698f1SMatthew G. Knepley   *celltypeLabel = dm->celltypeLabel;
4961ba2698f1SMatthew G. Knepley   PetscFunctionReturn(0);
4962ba2698f1SMatthew G. Knepley }
4963ba2698f1SMatthew G. Knepley 
4964ba2698f1SMatthew G. Knepley /*@
4965ba2698f1SMatthew G. Knepley   DMPlexGetCellType - Get the polytope type of a given cell
4966ba2698f1SMatthew G. Knepley 
4967ba2698f1SMatthew G. Knepley   Not Collective
4968ba2698f1SMatthew G. Knepley 
4969d8d19677SJose E. Roman   Input Parameters:
4970ba2698f1SMatthew G. Knepley + dm   - The DMPlex object
4971ba2698f1SMatthew G. Knepley - cell - The cell
4972ba2698f1SMatthew G. Knepley 
4973ba2698f1SMatthew G. Knepley   Output Parameter:
4974ba2698f1SMatthew G. Knepley . celltype - The polytope type of the cell
4975ba2698f1SMatthew G. Knepley 
4976ba2698f1SMatthew G. Knepley   Level: intermediate
4977ba2698f1SMatthew G. Knepley 
4978db781477SPatrick Sanan .seealso: `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`
4979ba2698f1SMatthew G. Knepley @*/
4980ba2698f1SMatthew G. Knepley PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype)
4981ba2698f1SMatthew G. Knepley {
4982ba2698f1SMatthew G. Knepley   DMLabel        label;
4983ba2698f1SMatthew G. Knepley   PetscInt       ct;
4984ba2698f1SMatthew G. Knepley 
4985ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
4986ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4987ba2698f1SMatthew G. Knepley   PetscValidPointer(celltype, 3);
49889566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &label));
49899566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(label, cell, &ct));
499063a3b9bcSJacob Faibussowitsch   PetscCheck(ct >= 0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %" PetscInt_FMT " has not been assigned a cell type", cell);
4991ba2698f1SMatthew G. Knepley   *celltype = (DMPolytopeType) ct;
4992ba2698f1SMatthew G. Knepley   PetscFunctionReturn(0);
4993ba2698f1SMatthew G. Knepley }
4994ba2698f1SMatthew G. Knepley 
4995412e9a14SMatthew G. Knepley /*@
4996412e9a14SMatthew G. Knepley   DMPlexSetCellType - Set the polytope type of a given cell
4997412e9a14SMatthew G. Knepley 
4998412e9a14SMatthew G. Knepley   Not Collective
4999412e9a14SMatthew G. Knepley 
5000412e9a14SMatthew G. Knepley   Input Parameters:
5001412e9a14SMatthew G. Knepley + dm   - The DMPlex object
5002412e9a14SMatthew G. Knepley . cell - The cell
5003412e9a14SMatthew G. Knepley - celltype - The polytope type of the cell
5004412e9a14SMatthew G. Knepley 
5005412e9a14SMatthew G. Knepley   Note: By default, cell types will be automatically computed using DMPlexComputeCellTypes() before this function
5006412e9a14SMatthew G. Knepley   is executed. This function will override the computed type. However, if automatic classification will not succeed
5007412e9a14SMatthew G. Knepley   and a user wants to manually specify all types, the classification must be disabled by calling
5008412e9a14SMatthew G. Knepley   DMCreaateLabel(dm, "celltype") before getting or setting any cell types.
5009412e9a14SMatthew G. Knepley 
5010412e9a14SMatthew G. Knepley   Level: advanced
5011412e9a14SMatthew G. Knepley 
5012db781477SPatrick Sanan .seealso: `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexComputeCellTypes()`, `DMCreateLabel()`
5013412e9a14SMatthew G. Knepley @*/
5014412e9a14SMatthew G. Knepley PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype)
5015412e9a14SMatthew G. Knepley {
5016412e9a14SMatthew G. Knepley   DMLabel        label;
5017412e9a14SMatthew G. Knepley 
5018412e9a14SMatthew G. Knepley   PetscFunctionBegin;
5019412e9a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
50209566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &label));
50219566063dSJacob Faibussowitsch   PetscCall(DMLabelSetValue(label, cell, celltype));
5022412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
5023412e9a14SMatthew G. Knepley }
5024412e9a14SMatthew G. Knepley 
50250adebc6cSBarry Smith PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm)
50260adebc6cSBarry Smith {
5027efe440bfSMatthew G. Knepley   PetscSection   section, s;
5028efe440bfSMatthew G. Knepley   Mat            m;
50293e922f36SToby Isaac   PetscInt       maxHeight;
5030552f7358SJed Brown 
5031552f7358SJed Brown   PetscFunctionBegin;
50329566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, cdm));
50339566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxProjectionHeight(dm, &maxHeight));
50349566063dSJacob Faibussowitsch   PetscCall(DMPlexSetMaxProjectionHeight(*cdm, maxHeight));
50359566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section));
50369566063dSJacob Faibussowitsch   PetscCall(DMSetLocalSection(*cdm, section));
50379566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&section));
50389566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &s));
50399566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_SELF, &m));
50409566063dSJacob Faibussowitsch   PetscCall(DMSetDefaultConstraints(*cdm, s, m, NULL));
50419566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&s));
50429566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&m));
50438f4c458bSMatthew G. Knepley 
50449566063dSJacob Faibussowitsch   PetscCall(DMSetNumFields(*cdm, 1));
50459566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(*cdm));
5046552f7358SJed Brown   PetscFunctionReturn(0);
5047552f7358SJed Brown }
5048552f7358SJed Brown 
5049f19dbd58SToby Isaac PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field)
5050f19dbd58SToby Isaac {
50516858538eSMatthew G. Knepley   Vec coordsLocal, cellCoordsLocal;
50526858538eSMatthew G. Knepley   DM  coordsDM,    cellCoordsDM;
5053f19dbd58SToby Isaac 
5054f19dbd58SToby Isaac   PetscFunctionBegin;
5055f19dbd58SToby Isaac   *field = NULL;
50569566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal));
50579566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &coordsDM));
50586858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dm, &cellCoordsLocal));
50596858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dm, &cellCoordsDM));
5060f19dbd58SToby Isaac   if (coordsLocal && coordsDM) {
50616858538eSMatthew G. Knepley     if (cellCoordsLocal && cellCoordsDM) PetscCall(DMFieldCreateDSWithDG(coordsDM, cellCoordsDM, 0, coordsLocal, cellCoordsLocal, field));
50626858538eSMatthew G. Knepley     else                                 PetscCall(DMFieldCreateDS(coordsDM, 0, coordsLocal, field));
5063f19dbd58SToby Isaac   }
5064f19dbd58SToby Isaac   PetscFunctionReturn(0);
5065f19dbd58SToby Isaac }
5066f19dbd58SToby Isaac 
50677cd05799SMatthew G. Knepley /*@C
50687cd05799SMatthew G. Knepley   DMPlexGetConeSection - Return a section which describes the layout of cone data
50697cd05799SMatthew G. Knepley 
50707cd05799SMatthew G. Knepley   Not Collective
50717cd05799SMatthew G. Knepley 
50727cd05799SMatthew G. Knepley   Input Parameters:
50737cd05799SMatthew G. Knepley . dm        - The DMPlex object
50747cd05799SMatthew G. Knepley 
50757cd05799SMatthew G. Knepley   Output Parameter:
50767cd05799SMatthew G. Knepley . section - The PetscSection object
50777cd05799SMatthew G. Knepley 
50787cd05799SMatthew G. Knepley   Level: developer
50797cd05799SMatthew G. Knepley 
5080db781477SPatrick Sanan .seealso: `DMPlexGetSupportSection()`, `DMPlexGetCones()`, `DMPlexGetConeOrientations()`
50817cd05799SMatthew G. Knepley @*/
50820adebc6cSBarry Smith PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section)
50830adebc6cSBarry Smith {
5084552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
5085552f7358SJed Brown 
5086552f7358SJed Brown   PetscFunctionBegin;
5087552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5088552f7358SJed Brown   if (section) *section = mesh->coneSection;
5089552f7358SJed Brown   PetscFunctionReturn(0);
5090552f7358SJed Brown }
5091552f7358SJed Brown 
50927cd05799SMatthew G. Knepley /*@C
50937cd05799SMatthew G. Knepley   DMPlexGetSupportSection - Return a section which describes the layout of support data
50947cd05799SMatthew G. Knepley 
50957cd05799SMatthew G. Knepley   Not Collective
50967cd05799SMatthew G. Knepley 
50977cd05799SMatthew G. Knepley   Input Parameters:
50987cd05799SMatthew G. Knepley . dm        - The DMPlex object
50997cd05799SMatthew G. Knepley 
51007cd05799SMatthew G. Knepley   Output Parameter:
51017cd05799SMatthew G. Knepley . section - The PetscSection object
51027cd05799SMatthew G. Knepley 
51037cd05799SMatthew G. Knepley   Level: developer
51047cd05799SMatthew G. Knepley 
5105db781477SPatrick Sanan .seealso: `DMPlexGetConeSection()`
51067cd05799SMatthew G. Knepley @*/
51078cb4d582SMatthew G. Knepley PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section)
51088cb4d582SMatthew G. Knepley {
51098cb4d582SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex*) dm->data;
51108cb4d582SMatthew G. Knepley 
51118cb4d582SMatthew G. Knepley   PetscFunctionBegin;
51128cb4d582SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
51138cb4d582SMatthew G. Knepley   if (section) *section = mesh->supportSection;
51148cb4d582SMatthew G. Knepley   PetscFunctionReturn(0);
51158cb4d582SMatthew G. Knepley }
51168cb4d582SMatthew G. Knepley 
51177cd05799SMatthew G. Knepley /*@C
51187cd05799SMatthew G. Knepley   DMPlexGetCones - Return cone data
51197cd05799SMatthew G. Knepley 
51207cd05799SMatthew G. Knepley   Not Collective
51217cd05799SMatthew G. Knepley 
51227cd05799SMatthew G. Knepley   Input Parameters:
51237cd05799SMatthew G. Knepley . dm        - The DMPlex object
51247cd05799SMatthew G. Knepley 
51257cd05799SMatthew G. Knepley   Output Parameter:
51267cd05799SMatthew G. Knepley . cones - The cone for each point
51277cd05799SMatthew G. Knepley 
51287cd05799SMatthew G. Knepley   Level: developer
51297cd05799SMatthew G. Knepley 
5130db781477SPatrick Sanan .seealso: `DMPlexGetConeSection()`
51317cd05799SMatthew G. Knepley @*/
5132a6dfd86eSKarl Rupp PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[])
5133a6dfd86eSKarl Rupp {
5134552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
5135552f7358SJed Brown 
5136552f7358SJed Brown   PetscFunctionBegin;
5137552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5138552f7358SJed Brown   if (cones) *cones = mesh->cones;
5139552f7358SJed Brown   PetscFunctionReturn(0);
5140552f7358SJed Brown }
5141552f7358SJed Brown 
51427cd05799SMatthew G. Knepley /*@C
51437cd05799SMatthew G. Knepley   DMPlexGetConeOrientations - Return cone orientation data
51447cd05799SMatthew G. Knepley 
51457cd05799SMatthew G. Knepley   Not Collective
51467cd05799SMatthew G. Knepley 
51477cd05799SMatthew G. Knepley   Input Parameters:
51487cd05799SMatthew G. Knepley . dm        - The DMPlex object
51497cd05799SMatthew G. Knepley 
51507cd05799SMatthew G. Knepley   Output Parameter:
5151b5a892a1SMatthew G. Knepley . coneOrientations - The array of cone orientations for all points
51527cd05799SMatthew G. Knepley 
51537cd05799SMatthew G. Knepley   Level: developer
51547cd05799SMatthew G. Knepley 
5155b5a892a1SMatthew G. Knepley   Notes:
5156b5a892a1SMatthew G. Knepley   The PetscSection returned by DMPlexGetConeSection() partitions coneOrientations into cone orientations of particular points as returned by DMPlexGetConeOrientation().
5157b5a892a1SMatthew G. Knepley 
5158b5a892a1SMatthew G. Knepley   The meaning of coneOrientations values is detailed in DMPlexGetConeOrientation().
5159b5a892a1SMatthew G. Knepley 
5160db781477SPatrick Sanan .seealso: `DMPlexGetConeSection()`, `DMPlexGetConeOrientation()`
51617cd05799SMatthew G. Knepley @*/
5162a6dfd86eSKarl Rupp PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[])
5163a6dfd86eSKarl Rupp {
5164552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
5165552f7358SJed Brown 
5166552f7358SJed Brown   PetscFunctionBegin;
5167552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5168552f7358SJed Brown   if (coneOrientations) *coneOrientations = mesh->coneOrientations;
5169552f7358SJed Brown   PetscFunctionReturn(0);
5170552f7358SJed Brown }
5171552f7358SJed Brown 
5172552f7358SJed Brown /******************************** FEM Support **********************************/
5173552f7358SJed Brown 
51749e8305c2SJed Brown /*
51759e8305c2SJed Brown  Returns number of components and tensor degree for the field.  For interpolated meshes, line should be a point
51769e8305c2SJed Brown  representing a line in the section.
51779e8305c2SJed Brown */
51789e8305c2SJed Brown static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(PetscSection section,PetscInt field,PetscInt line,PetscBool vertexchart,PetscInt *Nc,PetscInt *k)
51799e8305c2SJed Brown {
51809e8305c2SJed Brown   PetscFunctionBeginHot;
51819566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldComponents(section, field, Nc));
5182a433471fSStefano Zampini   if (line < 0) {
5183a433471fSStefano Zampini     *k = 0;
5184a433471fSStefano Zampini     *Nc = 0;
5185a433471fSStefano Zampini   } else if (vertexchart) {            /* If we only have a vertex chart, we must have degree k=1 */
51869e8305c2SJed Brown     *k = 1;
51879e8305c2SJed Brown   } else {                      /* Assume the full interpolated mesh is in the chart; lines in particular */
51889e8305c2SJed Brown     /* An order k SEM disc has k-1 dofs on an edge */
51899566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, line, field, k));
51909e8305c2SJed Brown     *k = *k / *Nc + 1;
51919e8305c2SJed Brown   }
51929e8305c2SJed Brown   PetscFunctionReturn(0);
51939e8305c2SJed Brown }
51949e8305c2SJed Brown 
5195a4355906SMatthew Knepley /*@
5196bc1eb3faSJed Brown 
5197bc1eb3faSJed Brown   DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a
5198bc1eb3faSJed Brown   lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the
51991bb6d2a8SBarry Smith   section provided (or the section of the DM).
5200a4355906SMatthew Knepley 
5201a4355906SMatthew Knepley   Input Parameters:
5202a4355906SMatthew Knepley + dm      - The DM
5203a4355906SMatthew Knepley . point   - Either a cell (highest dim point) or an edge (dim 1 point), or PETSC_DETERMINE
5204a4355906SMatthew Knepley - section - The PetscSection to reorder, or NULL for the default section
5205a4355906SMatthew Knepley 
5206a4355906SMatthew Knepley   Note: The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial
5207a4355906SMatthew Knepley   degree of the basis.
5208a4355906SMatthew Knepley 
5209bc1eb3faSJed Brown   Example:
5210bc1eb3faSJed Brown   A typical interpolated single-quad mesh might order points as
5211bc1eb3faSJed Brown .vb
5212bc1eb3faSJed Brown   [c0, v1, v2, v3, v4, e5, e6, e7, e8]
5213bc1eb3faSJed Brown 
5214bc1eb3faSJed Brown   v4 -- e6 -- v3
5215bc1eb3faSJed Brown   |           |
5216bc1eb3faSJed Brown   e7    c0    e8
5217bc1eb3faSJed Brown   |           |
5218bc1eb3faSJed Brown   v1 -- e5 -- v2
5219bc1eb3faSJed Brown .ve
5220bc1eb3faSJed Brown 
5221bc1eb3faSJed Brown   (There is no significance to the ordering described here.)  The default section for a Q3 quad might typically assign
5222bc1eb3faSJed Brown   dofs in the order of points, e.g.,
5223bc1eb3faSJed Brown .vb
5224bc1eb3faSJed Brown     c0 -> [0,1,2,3]
5225bc1eb3faSJed Brown     v1 -> [4]
5226bc1eb3faSJed Brown     ...
5227bc1eb3faSJed Brown     e5 -> [8, 9]
5228bc1eb3faSJed Brown .ve
5229bc1eb3faSJed Brown 
5230bc1eb3faSJed Brown   which corresponds to the dofs
5231bc1eb3faSJed Brown .vb
5232bc1eb3faSJed Brown     6   10  11  7
5233bc1eb3faSJed Brown     13  2   3   15
5234bc1eb3faSJed Brown     12  0   1   14
5235bc1eb3faSJed Brown     4   8   9   5
5236bc1eb3faSJed Brown .ve
5237bc1eb3faSJed Brown 
5238bc1eb3faSJed Brown   The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering
5239bc1eb3faSJed Brown .vb
5240bc1eb3faSJed Brown   0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6
5241bc1eb3faSJed Brown .ve
5242bc1eb3faSJed Brown 
5243bc1eb3faSJed Brown   After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically,
5244bc1eb3faSJed Brown .vb
5245bc1eb3faSJed Brown    4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7
5246bc1eb3faSJed Brown .ve
5247bc1eb3faSJed Brown 
5248a4355906SMatthew Knepley   Level: developer
5249a4355906SMatthew Knepley 
5250db781477SPatrick Sanan .seealso: `DMGetLocalSection()`, `PetscSectionSetClosurePermutation()`, `DMSetGlobalSection()`
5251a4355906SMatthew Knepley @*/
5252bc1eb3faSJed Brown PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section)
52533194fc30SMatthew G. Knepley {
52547391a63aSMatthew G. Knepley   DMLabel        label;
5255bb197d40SJed Brown   PetscInt       dim, depth = -1, eStart = -1, Nf;
52569e8305c2SJed Brown   PetscBool      vertexchart;
52573194fc30SMatthew G. Knepley 
52583194fc30SMatthew G. Knepley   PetscFunctionBegin;
52599566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
5260a433471fSStefano Zampini   if (dim < 1) PetscFunctionReturn(0);
5261a433471fSStefano Zampini   if (point < 0) {
5262a433471fSStefano Zampini     PetscInt sStart,sEnd;
5263a433471fSStefano Zampini 
52649566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd));
5265a433471fSStefano Zampini     point = sEnd-sStart ? sStart : point;
5266a433471fSStefano Zampini   }
52679566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
52689566063dSJacob Faibussowitsch   if (point >= 0) PetscCall(DMLabelGetValue(label, point, &depth));
52699566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
52707391a63aSMatthew G. Knepley   if (depth == 1) {eStart = point;}
52717391a63aSMatthew G. Knepley   else if  (depth == dim) {
52727391a63aSMatthew G. Knepley     const PetscInt *cone;
52737391a63aSMatthew G. Knepley 
52749566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, point, &cone));
5275d4e6627bSStefano Zampini     if (dim == 2) eStart = cone[0];
5276d4e6627bSStefano Zampini     else if (dim == 3) {
5277d4e6627bSStefano Zampini       const PetscInt *cone2;
52789566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, cone[0], &cone2));
5279d4e6627bSStefano Zampini       eStart = cone2[0];
528063a3b9bcSJacob 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);
528163a3b9bcSJacob 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);
52829e8305c2SJed Brown   {                             /* Determine whether the chart covers all points or just vertices. */
52839e8305c2SJed Brown     PetscInt pStart,pEnd,cStart,cEnd;
52849566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm,0,&pStart,&pEnd));
52859566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(section,&cStart,&cEnd));
5286796d0a68SJed Brown     if (pStart == cStart && pEnd == cEnd) vertexchart = PETSC_TRUE;      /* Only vertices are in the chart */
5287796d0a68SJed Brown     else if (cStart <= point && point < cEnd) vertexchart = PETSC_FALSE; /* Some interpolated points exist in the chart */
5288796d0a68SJed Brown     else vertexchart = PETSC_TRUE;                                       /* Some interpolated points are not in chart; assume dofs only at cells and vertices */
52899e8305c2SJed Brown   }
52909566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &Nf));
5291bb197d40SJed Brown   for (PetscInt d=1; d<=dim; d++) {
5292bb197d40SJed Brown     PetscInt k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0;
5293bb197d40SJed Brown     PetscInt *perm;
5294bb197d40SJed Brown 
52953194fc30SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
52969566063dSJacob Faibussowitsch       PetscCall(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k));
5297bb197d40SJed Brown       size += PetscPowInt(k+1, d)*Nc;
52983194fc30SMatthew G. Knepley     }
52999566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(size, &perm));
53003194fc30SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
5301bb197d40SJed Brown       switch (d) {
5302babf31e0SJed Brown       case 1:
53039566063dSJacob Faibussowitsch         PetscCall(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k));
5304babf31e0SJed Brown         /*
5305babf31e0SJed Brown          Original ordering is [ edge of length k-1; vtx0; vtx1 ]
5306babf31e0SJed Brown          We want              [ vtx0; edge of length k-1; vtx1 ]
5307babf31e0SJed Brown          */
5308babf31e0SJed Brown         for (c=0; c<Nc; c++,offset++) perm[offset] = (k-1)*Nc + c + foffset;
5309babf31e0SJed Brown         for (i=0; i<k-1; i++) for (c=0; c<Nc; c++,offset++) perm[offset] = i*Nc + c + foffset;
5310babf31e0SJed Brown         for (c=0; c<Nc; c++,offset++) perm[offset] = k*Nc + c + foffset;
5311babf31e0SJed Brown         foffset = offset;
5312babf31e0SJed Brown         break;
531389eabcffSMatthew G. Knepley       case 2:
53143194fc30SMatthew 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} */
53159566063dSJacob Faibussowitsch         PetscCall(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k));
53163194fc30SMatthew G. Knepley         /* The SEM order is
53173194fc30SMatthew G. Knepley 
53183194fc30SMatthew G. Knepley          v_lb, {e_b}, v_rb,
531989eabcffSMatthew G. Knepley          e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r,
53203194fc30SMatthew G. Knepley          v_lt, reverse {e_t}, v_rt
53213194fc30SMatthew G. Knepley          */
53223194fc30SMatthew G. Knepley         {
53233194fc30SMatthew G. Knepley           const PetscInt of   = 0;
53243194fc30SMatthew G. Knepley           const PetscInt oeb  = of   + PetscSqr(k-1);
53253194fc30SMatthew G. Knepley           const PetscInt oer  = oeb  + (k-1);
53263194fc30SMatthew G. Knepley           const PetscInt oet  = oer  + (k-1);
53273194fc30SMatthew G. Knepley           const PetscInt oel  = oet  + (k-1);
53283194fc30SMatthew G. Knepley           const PetscInt ovlb = oel  + (k-1);
53293194fc30SMatthew G. Knepley           const PetscInt ovrb = ovlb + 1;
53303194fc30SMatthew G. Knepley           const PetscInt ovrt = ovrb + 1;
53313194fc30SMatthew G. Knepley           const PetscInt ovlt = ovrt + 1;
53323194fc30SMatthew G. Knepley           PetscInt       o;
53333194fc30SMatthew G. Knepley 
53343194fc30SMatthew G. Knepley           /* bottom */
53353194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb*Nc + c + foffset;
53363194fc30SMatthew G. Knepley           for (o = oeb; o < oer; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
53373194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb*Nc + c + foffset;
53383194fc30SMatthew G. Knepley           /* middle */
53393194fc30SMatthew G. Knepley           for (i = 0; i < k-1; ++i) {
53403194fc30SMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel+(k-2)-i)*Nc + c + foffset;
53413194fc30SMatthew G. Knepley             for (o = of+(k-1)*i; o < of+(k-1)*(i+1); ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
53423194fc30SMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer+i)*Nc + c + foffset;
53433194fc30SMatthew G. Knepley           }
53443194fc30SMatthew G. Knepley           /* top */
53453194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt*Nc + c + foffset;
53463194fc30SMatthew G. Knepley           for (o = oel-1; o >= oet; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
53473194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt*Nc + c + foffset;
53483194fc30SMatthew G. Knepley           foffset = offset;
53493194fc30SMatthew G. Knepley         }
535089eabcffSMatthew G. Knepley         break;
535189eabcffSMatthew G. Knepley       case 3:
535289eabcffSMatthew G. Knepley         /* The original hex closure is
535389eabcffSMatthew G. Knepley 
535489eabcffSMatthew G. Knepley          {c,
535589eabcffSMatthew G. Knepley          f_b, f_t, f_f, f_b, f_r, f_l,
535689eabcffSMatthew 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,
535789eabcffSMatthew G. Knepley          v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb}
535889eabcffSMatthew G. Knepley          */
53599566063dSJacob Faibussowitsch         PetscCall(PetscSectionFieldGetTensorDegree_Private(section,f,eStart,vertexchart,&Nc,&k));
536089eabcffSMatthew G. Knepley         /* The SEM order is
536189eabcffSMatthew G. Knepley          Bottom Slice
536289eabcffSMatthew G. Knepley          v_blf, {e^{(k-1)-n}_bf}, v_brf,
536389eabcffSMatthew G. Knepley          e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br,
536489eabcffSMatthew G. Knepley          v_blb, {e_bb}, v_brb,
536589eabcffSMatthew G. Knepley 
536689eabcffSMatthew G. Knepley          Middle Slice (j)
536789eabcffSMatthew G. Knepley          {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf,
536889eabcffSMatthew G. Knepley          f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r,
536989eabcffSMatthew G. Knepley          e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb,
537089eabcffSMatthew G. Knepley 
537189eabcffSMatthew G. Knepley          Top Slice
537289eabcffSMatthew G. Knepley          v_tlf, {e_tf}, v_trf,
537389eabcffSMatthew G. Knepley          e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr,
537489eabcffSMatthew G. Knepley          v_tlb, {e^{(k-1)-n}_tb}, v_trb,
537589eabcffSMatthew G. Knepley          */
537689eabcffSMatthew G. Knepley         {
537789eabcffSMatthew G. Knepley           const PetscInt oc    = 0;
537889eabcffSMatthew G. Knepley           const PetscInt ofb   = oc    + PetscSqr(k-1)*(k-1);
537989eabcffSMatthew G. Knepley           const PetscInt oft   = ofb   + PetscSqr(k-1);
538089eabcffSMatthew G. Knepley           const PetscInt off   = oft   + PetscSqr(k-1);
538189eabcffSMatthew G. Knepley           const PetscInt ofk   = off   + PetscSqr(k-1);
538289eabcffSMatthew G. Knepley           const PetscInt ofr   = ofk   + PetscSqr(k-1);
538389eabcffSMatthew G. Knepley           const PetscInt ofl   = ofr   + PetscSqr(k-1);
538489eabcffSMatthew G. Knepley           const PetscInt oebl  = ofl   + PetscSqr(k-1);
538589eabcffSMatthew G. Knepley           const PetscInt oebb  = oebl  + (k-1);
538689eabcffSMatthew G. Knepley           const PetscInt oebr  = oebb  + (k-1);
538789eabcffSMatthew G. Knepley           const PetscInt oebf  = oebr  + (k-1);
538889eabcffSMatthew G. Knepley           const PetscInt oetf  = oebf  + (k-1);
538989eabcffSMatthew G. Knepley           const PetscInt oetr  = oetf  + (k-1);
539089eabcffSMatthew G. Knepley           const PetscInt oetb  = oetr  + (k-1);
539189eabcffSMatthew G. Knepley           const PetscInt oetl  = oetb  + (k-1);
539289eabcffSMatthew G. Knepley           const PetscInt oerf  = oetl  + (k-1);
539389eabcffSMatthew G. Knepley           const PetscInt oelf  = oerf  + (k-1);
539489eabcffSMatthew G. Knepley           const PetscInt oelb  = oelf  + (k-1);
539589eabcffSMatthew G. Knepley           const PetscInt oerb  = oelb  + (k-1);
539689eabcffSMatthew G. Knepley           const PetscInt ovblf = oerb  + (k-1);
539789eabcffSMatthew G. Knepley           const PetscInt ovblb = ovblf + 1;
539889eabcffSMatthew G. Knepley           const PetscInt ovbrb = ovblb + 1;
539989eabcffSMatthew G. Knepley           const PetscInt ovbrf = ovbrb + 1;
540089eabcffSMatthew G. Knepley           const PetscInt ovtlf = ovbrf + 1;
540189eabcffSMatthew G. Knepley           const PetscInt ovtrf = ovtlf + 1;
540289eabcffSMatthew G. Knepley           const PetscInt ovtrb = ovtrf + 1;
540389eabcffSMatthew G. Knepley           const PetscInt ovtlb = ovtrb + 1;
540489eabcffSMatthew G. Knepley           PetscInt       o, n;
540589eabcffSMatthew G. Knepley 
540689eabcffSMatthew G. Knepley           /* Bottom Slice */
540789eabcffSMatthew G. Knepley           /*   bottom */
540889eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf*Nc + c + foffset;
540989eabcffSMatthew G. Knepley           for (o = oetf-1; o >= oebf; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
541089eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf*Nc + c + foffset;
541189eabcffSMatthew G. Knepley           /*   middle */
541289eabcffSMatthew G. Knepley           for (i = 0; i < k-1; ++i) {
541389eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl+i)*Nc + c + foffset;
5414316b7f87SMax Rietmann             for (n = 0; n < k-1; ++n) {o = ofb+n*(k-1)+i; for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;}
541589eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr+(k-2)-i)*Nc + c + foffset;
54163194fc30SMatthew G. Knepley           }
541789eabcffSMatthew G. Knepley           /*   top */
541889eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb*Nc + c + foffset;
541989eabcffSMatthew G. Knepley           for (o = oebb; o < oebr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
542089eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb*Nc + c + foffset;
542189eabcffSMatthew G. Knepley 
542289eabcffSMatthew G. Knepley           /* Middle Slice */
542389eabcffSMatthew G. Knepley           for (j = 0; j < k-1; ++j) {
542489eabcffSMatthew G. Knepley             /*   bottom */
542589eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf+(k-2)-j)*Nc + c + foffset;
542689eabcffSMatthew G. Knepley             for (o = off+j*(k-1); o < off+(j+1)*(k-1); ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
542789eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf+j)*Nc + c + foffset;
542889eabcffSMatthew G. Knepley             /*   middle */
542989eabcffSMatthew G. Knepley             for (i = 0; i < k-1; ++i) {
543089eabcffSMatthew G. Knepley               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl+i*(k-1)+j)*Nc + c + foffset;
543189eabcffSMatthew G. Knepley               for (n = 0; n < k-1; ++n) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oc+(j*(k-1)+i)*(k-1)+n)*Nc + c + foffset;
543289eabcffSMatthew G. Knepley               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr+j*(k-1)+i)*Nc + c + foffset;
543389eabcffSMatthew G. Knepley             }
543489eabcffSMatthew G. Knepley             /*   top */
543589eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb+j)*Nc + c + foffset;
543689eabcffSMatthew G. Knepley             for (o = ofk+j*(k-1)+(k-2); o >= ofk+j*(k-1); --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
543789eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb+(k-2)-j)*Nc + c + foffset;
543889eabcffSMatthew G. Knepley           }
543989eabcffSMatthew G. Knepley 
544089eabcffSMatthew G. Knepley           /* Top Slice */
544189eabcffSMatthew G. Knepley           /*   bottom */
544289eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf*Nc + c + foffset;
544389eabcffSMatthew G. Knepley           for (o = oetf; o < oetr; ++o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
544489eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf*Nc + c + foffset;
544589eabcffSMatthew G. Knepley           /*   middle */
544689eabcffSMatthew G. Knepley           for (i = 0; i < k-1; ++i) {
544789eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl+(k-2)-i)*Nc + c + foffset;
544889eabcffSMatthew G. Knepley             for (n = 0; n < k-1; ++n) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft+i*(k-1)+n)*Nc + c + foffset;
544989eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr+i)*Nc + c + foffset;
545089eabcffSMatthew G. Knepley           }
545189eabcffSMatthew G. Knepley           /*   top */
545289eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb*Nc + c + foffset;
545389eabcffSMatthew G. Knepley           for (o = oetl-1; o >= oetb; --o) for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o*Nc + c + foffset;
545489eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb*Nc + c + foffset;
545589eabcffSMatthew G. Knepley 
545689eabcffSMatthew G. Knepley           foffset = offset;
545789eabcffSMatthew G. Knepley         }
545889eabcffSMatthew G. Knepley         break;
545963a3b9bcSJacob Faibussowitsch       default: SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %" PetscInt_FMT, d);
546089eabcffSMatthew G. Knepley       }
546189eabcffSMatthew G. Knepley     }
546263a3b9bcSJacob Faibussowitsch     PetscCheck(offset == size,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Number of permutation entries %" PetscInt_FMT " != %" PetscInt_FMT, offset, size);
54633194fc30SMatthew G. Knepley     /* Check permutation */
54643194fc30SMatthew G. Knepley     {
54653194fc30SMatthew G. Knepley       PetscInt *check;
54663194fc30SMatthew G. Knepley 
54679566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(size, &check));
54681dca8a05SBarry Smith       for (i = 0; i < size; ++i) {
54691dca8a05SBarry Smith         check[i] = -1;
54701dca8a05SBarry 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]);
54711dca8a05SBarry Smith       }
54723194fc30SMatthew G. Knepley       for (i = 0; i < size; ++i) check[perm[i]] = i;
54731dca8a05SBarry Smith       for (i = 0; i < size; ++i) PetscCheck(check[i] >= 0,PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Missing permutation index %" PetscInt_FMT, i);
54749566063dSJacob Faibussowitsch       PetscCall(PetscFree(check));
54753194fc30SMatthew G. Knepley     }
54769566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size, PETSC_OWN_POINTER, perm));
5477a05c9aa3SJed Brown     if (d == dim) { // Add permutation for localized (in case this is a coordinate DM)
5478a05c9aa3SJed Brown       PetscInt *loc_perm;
54799566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(size*2, &loc_perm));
5480a05c9aa3SJed Brown       for (PetscInt i=0; i<size; i++) {
5481a05c9aa3SJed Brown         loc_perm[i] = perm[i];
5482a05c9aa3SJed Brown         loc_perm[size+i] = size + perm[i];
5483a05c9aa3SJed Brown       }
54849566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject) dm, d, size*2, PETSC_OWN_POINTER, loc_perm));
5485a05c9aa3SJed Brown     }
5486bb197d40SJed Brown   }
54873194fc30SMatthew G. Knepley   PetscFunctionReturn(0);
54883194fc30SMatthew G. Knepley }
54893194fc30SMatthew G. Knepley 
5490e071409bSToby Isaac PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace)
5491e071409bSToby Isaac {
5492e071409bSToby Isaac   PetscDS        prob;
5493e071409bSToby Isaac   PetscInt       depth, Nf, h;
5494e071409bSToby Isaac   DMLabel        label;
5495e071409bSToby Isaac 
5496e071409bSToby Isaac   PetscFunctionBeginHot;
54979566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &prob));
5498e071409bSToby Isaac   Nf      = prob->Nf;
5499e071409bSToby Isaac   label   = dm->depthLabel;
5500e071409bSToby Isaac   *dspace = NULL;
5501e071409bSToby Isaac   if (field < Nf) {
5502e071409bSToby Isaac     PetscObject disc = prob->disc[field];
5503e071409bSToby Isaac 
5504e071409bSToby Isaac     if (disc->classid == PETSCFE_CLASSID) {
5505e071409bSToby Isaac       PetscDualSpace dsp;
5506e071409bSToby Isaac 
55079566063dSJacob Faibussowitsch       PetscCall(PetscFEGetDualSpace((PetscFE)disc,&dsp));
55089566063dSJacob Faibussowitsch       PetscCall(DMLabelGetNumValues(label,&depth));
55099566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(label,point,&h));
5510e071409bSToby Isaac       h    = depth - 1 - h;
5511e071409bSToby Isaac       if (h) {
55129566063dSJacob Faibussowitsch         PetscCall(PetscDualSpaceGetHeightSubspace(dsp,h,dspace));
5513e071409bSToby Isaac       } else {
5514e071409bSToby Isaac         *dspace = dsp;
5515e071409bSToby Isaac       }
5516e071409bSToby Isaac     }
5517e071409bSToby Isaac   }
5518e071409bSToby Isaac   PetscFunctionReturn(0);
5519e071409bSToby Isaac }
5520e071409bSToby Isaac 
55219fbee547SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
5522a6dfd86eSKarl Rupp {
5523552f7358SJed Brown   PetscScalar    *array, *vArray;
5524d9917b9dSMatthew G. Knepley   const PetscInt *cone, *coneO;
55251a271a75SMatthew G. Knepley   PetscInt        pStart, pEnd, p, numPoints, size = 0, offset = 0;
5526552f7358SJed Brown 
55271b406b76SMatthew G. Knepley   PetscFunctionBeginHot;
55289566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
55299566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, point, &numPoints));
55309566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, point, &cone));
55319566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeOrientation(dm, point, &coneO));
55323f7cbbe7SMatthew G. Knepley   if (!values || !*values) {
55339df71ca4SMatthew G. Knepley     if ((point >= pStart) && (point < pEnd)) {
55349df71ca4SMatthew G. Knepley       PetscInt dof;
5535d9917b9dSMatthew G. Knepley 
55369566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, point, &dof));
55379df71ca4SMatthew G. Knepley       size += dof;
55389df71ca4SMatthew G. Knepley     }
55399df71ca4SMatthew G. Knepley     for (p = 0; p < numPoints; ++p) {
55409df71ca4SMatthew G. Knepley       const PetscInt cp = cone[p];
55412a3aaacfSMatthew G. Knepley       PetscInt       dof;
55425a1bb5cfSMatthew G. Knepley 
55435a1bb5cfSMatthew G. Knepley       if ((cp < pStart) || (cp >= pEnd)) continue;
55449566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, cp, &dof));
55455a1bb5cfSMatthew G. Knepley       size += dof;
55465a1bb5cfSMatthew G. Knepley     }
55473f7cbbe7SMatthew G. Knepley     if (!values) {
55483f7cbbe7SMatthew G. Knepley       if (csize) *csize = size;
55493f7cbbe7SMatthew G. Knepley       PetscFunctionReturn(0);
55503f7cbbe7SMatthew G. Knepley     }
55519566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, size, MPIU_SCALAR, &array));
5552982e9ed1SMatthew G. Knepley   } else {
5553982e9ed1SMatthew G. Knepley     array = *values;
5554982e9ed1SMatthew G. Knepley   }
55559df71ca4SMatthew G. Knepley   size = 0;
55569566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &vArray));
55579df71ca4SMatthew G. Knepley   if ((point >= pStart) && (point < pEnd)) {
55589df71ca4SMatthew G. Knepley     PetscInt     dof, off, d;
55599df71ca4SMatthew G. Knepley     PetscScalar *varr;
5560d9917b9dSMatthew G. Knepley 
55619566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, point, &dof));
55629566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, point, &off));
55639df71ca4SMatthew G. Knepley     varr = &vArray[off];
55641a271a75SMatthew G. Knepley     for (d = 0; d < dof; ++d, ++offset) {
55651a271a75SMatthew G. Knepley       array[offset] = varr[d];
55669df71ca4SMatthew G. Knepley     }
55679df71ca4SMatthew G. Knepley     size += dof;
55689df71ca4SMatthew G. Knepley   }
55699df71ca4SMatthew G. Knepley   for (p = 0; p < numPoints; ++p) {
55709df71ca4SMatthew G. Knepley     const PetscInt cp = cone[p];
55719df71ca4SMatthew G. Knepley     PetscInt       o  = coneO[p];
55725a1bb5cfSMatthew G. Knepley     PetscInt       dof, off, d;
55735a1bb5cfSMatthew G. Knepley     PetscScalar   *varr;
55745a1bb5cfSMatthew G. Knepley 
557552ed52e8SMatthew G. Knepley     if ((cp < pStart) || (cp >= pEnd)) continue;
55769566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, cp, &dof));
55779566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, cp, &off));
55785a1bb5cfSMatthew G. Knepley     varr = &vArray[off];
55795a1bb5cfSMatthew G. Knepley     if (o >= 0) {
55801a271a75SMatthew G. Knepley       for (d = 0; d < dof; ++d, ++offset) {
55811a271a75SMatthew G. Knepley         array[offset] = varr[d];
55825a1bb5cfSMatthew G. Knepley       }
55835a1bb5cfSMatthew G. Knepley     } else {
55841a271a75SMatthew G. Knepley       for (d = dof-1; d >= 0; --d, ++offset) {
55851a271a75SMatthew G. Knepley         array[offset] = varr[d];
55865a1bb5cfSMatthew G. Knepley       }
55875a1bb5cfSMatthew G. Knepley     }
55889df71ca4SMatthew G. Knepley     size += dof;
55895a1bb5cfSMatthew G. Knepley   }
55909566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &vArray));
55919df71ca4SMatthew G. Knepley   if (!*values) {
55925a1bb5cfSMatthew G. Knepley     if (csize) *csize = size;
55935a1bb5cfSMatthew G. Knepley     *values = array;
55949df71ca4SMatthew G. Knepley   } else {
559563a3b9bcSJacob Faibussowitsch     PetscCheck(size <= *csize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size);
55968c312ff3SMatthew G. Knepley     *csize = size;
55979df71ca4SMatthew G. Knepley   }
55985a1bb5cfSMatthew G. Knepley   PetscFunctionReturn(0);
55995a1bb5cfSMatthew G. Knepley }
5600d9917b9dSMatthew G. Knepley 
560127f02ce8SMatthew G. Knepley /* Compress out points not in the section */
56029fbee547SJacob Faibussowitsch static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[])
560327f02ce8SMatthew G. Knepley {
560427f02ce8SMatthew G. Knepley   const PetscInt np = *numPoints;
560527f02ce8SMatthew G. Knepley   PetscInt       pStart, pEnd, p, q;
560627f02ce8SMatthew G. Knepley 
56079566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
560827f02ce8SMatthew G. Knepley   for (p = 0, q = 0; p < np; ++p) {
560927f02ce8SMatthew G. Knepley     const PetscInt r = points[p*2];
561027f02ce8SMatthew G. Knepley     if ((r >= pStart) && (r < pEnd)) {
561127f02ce8SMatthew G. Knepley       points[q*2]   = r;
561227f02ce8SMatthew G. Knepley       points[q*2+1] = points[p*2+1];
561327f02ce8SMatthew G. Knepley       ++q;
561427f02ce8SMatthew G. Knepley     }
561527f02ce8SMatthew G. Knepley   }
561627f02ce8SMatthew G. Knepley   *numPoints = q;
561727f02ce8SMatthew G. Knepley   return 0;
561827f02ce8SMatthew G. Knepley }
561927f02ce8SMatthew G. Knepley 
562097529cf3SJed Brown /* Compressed closure does not apply closure permutation */
56211dc59d61SMatthew G. Knepley PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp)
5622923c78e0SToby Isaac {
562327f02ce8SMatthew G. Knepley   const PetscInt *cla = NULL;
5624923c78e0SToby Isaac   PetscInt       np, *pts = NULL;
5625923c78e0SToby Isaac 
5626923c78e0SToby Isaac   PetscFunctionBeginHot;
56279566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureIndex(section, (PetscObject) dm, clSec, clPoints));
562827f02ce8SMatthew G. Knepley   if (*clPoints) {
5629923c78e0SToby Isaac     PetscInt dof, off;
5630923c78e0SToby Isaac 
56319566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(*clSec, point, &dof));
56329566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(*clSec, point, &off));
56339566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(*clPoints, &cla));
5634923c78e0SToby Isaac     np   = dof/2;
5635923c78e0SToby Isaac     pts  = (PetscInt *) &cla[off];
563627f02ce8SMatthew G. Knepley   } else {
56379566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &np, &pts));
56389566063dSJacob Faibussowitsch     PetscCall(CompressPoints_Private(section, &np, pts));
5639923c78e0SToby Isaac   }
5640923c78e0SToby Isaac   *numPoints = np;
5641923c78e0SToby Isaac   *points    = pts;
5642923c78e0SToby Isaac   *clp       = cla;
5643923c78e0SToby Isaac   PetscFunctionReturn(0);
5644923c78e0SToby Isaac }
5645923c78e0SToby Isaac 
56461dc59d61SMatthew G. Knepley PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp)
5647923c78e0SToby Isaac {
5648923c78e0SToby Isaac   PetscFunctionBeginHot;
5649923c78e0SToby Isaac   if (!*clPoints) {
56509566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points));
5651923c78e0SToby Isaac   } else {
56529566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(*clPoints, clp));
5653923c78e0SToby Isaac   }
5654923c78e0SToby Isaac   *numPoints = 0;
5655923c78e0SToby Isaac   *points    = NULL;
5656923c78e0SToby Isaac   *clSec     = NULL;
5657923c78e0SToby Isaac   *clPoints  = NULL;
5658923c78e0SToby Isaac   *clp       = NULL;
5659923c78e0SToby Isaac   PetscFunctionReturn(0);
5660923c78e0SToby Isaac }
5661923c78e0SToby Isaac 
56629fbee547SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Static(DM dm, PetscSection section, PetscInt numPoints, const PetscInt points[], const PetscInt clperm[], const PetscScalar vArray[], PetscInt *size, PetscScalar array[])
56631a271a75SMatthew G. Knepley {
56641a271a75SMatthew G. Knepley   PetscInt          offset = 0, p;
566597e99dd9SToby Isaac   const PetscInt    **perms = NULL;
566697e99dd9SToby Isaac   const PetscScalar **flips = NULL;
56671a271a75SMatthew G. Knepley 
56681a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
5669fe02ba77SJed Brown   *size = 0;
56709566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips));
567197e99dd9SToby Isaac   for (p = 0; p < numPoints; p++) {
567297e99dd9SToby Isaac     const PetscInt    point = points[2*p];
567397e99dd9SToby Isaac     const PetscInt    *perm = perms ? perms[p] : NULL;
567497e99dd9SToby Isaac     const PetscScalar *flip = flips ? flips[p] : NULL;
56751a271a75SMatthew G. Knepley     PetscInt          dof, off, d;
56761a271a75SMatthew G. Knepley     const PetscScalar *varr;
56771a271a75SMatthew G. Knepley 
56789566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, point, &dof));
56799566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, point, &off));
56801a271a75SMatthew G. Knepley     varr = &vArray[off];
568197e99dd9SToby Isaac     if (clperm) {
568297e99dd9SToby Isaac       if (perm) {
568397e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]]  = varr[d];
56841a271a75SMatthew G. Knepley       } else {
568597e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset +      d ]]  = varr[d];
568697e99dd9SToby Isaac       }
568797e99dd9SToby Isaac       if (flip) {
568897e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset +      d ]] *= flip[d];
568997e99dd9SToby Isaac       }
569097e99dd9SToby Isaac     } else {
569197e99dd9SToby Isaac       if (perm) {
569297e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset + perm[d]]  = varr[d];
569397e99dd9SToby Isaac       } else {
569497e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset +      d ]  = varr[d];
569597e99dd9SToby Isaac       }
569697e99dd9SToby Isaac       if (flip) {
569797e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset +      d ] *= flip[d];
56981a271a75SMatthew G. Knepley       }
56991a271a75SMatthew G. Knepley     }
570097e99dd9SToby Isaac     offset += dof;
570197e99dd9SToby Isaac   }
57029566063dSJacob Faibussowitsch   PetscCall(PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips));
57031a271a75SMatthew G. Knepley   *size = offset;
57041a271a75SMatthew G. Knepley   PetscFunctionReturn(0);
57051a271a75SMatthew G. Knepley }
57061a271a75SMatthew G. Knepley 
57079fbee547SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Fields_Static(DM dm, PetscSection section, PetscInt numPoints, const PetscInt points[], PetscInt numFields, const PetscInt clperm[], const PetscScalar vArray[], PetscInt *size, PetscScalar array[])
57081a271a75SMatthew G. Knepley {
57091a271a75SMatthew G. Knepley   PetscInt          offset = 0, f;
57101a271a75SMatthew G. Knepley 
57111a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
5712fe02ba77SJed Brown   *size = 0;
57131a271a75SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
571497e99dd9SToby Isaac     PetscInt          p;
571597e99dd9SToby Isaac     const PetscInt    **perms = NULL;
571697e99dd9SToby Isaac     const PetscScalar **flips = NULL;
57171a271a75SMatthew G. Knepley 
57189566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips));
571997e99dd9SToby Isaac     for (p = 0; p < numPoints; p++) {
572097e99dd9SToby Isaac       const PetscInt    point = points[2*p];
572197e99dd9SToby Isaac       PetscInt          fdof, foff, b;
57221a271a75SMatthew G. Knepley       const PetscScalar *varr;
572397e99dd9SToby Isaac       const PetscInt    *perm = perms ? perms[p] : NULL;
572497e99dd9SToby Isaac       const PetscScalar *flip = flips ? flips[p] : NULL;
57251a271a75SMatthew G. Knepley 
57269566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
57279566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
57281a271a75SMatthew G. Knepley       varr = &vArray[foff];
572997e99dd9SToby Isaac       if (clperm) {
573097e99dd9SToby Isaac         if (perm) {for (b = 0; b < fdof; b++) {array[clperm[offset + perm[b]]]  = varr[b];}}
573197e99dd9SToby Isaac         else      {for (b = 0; b < fdof; b++) {array[clperm[offset +      b ]]  = varr[b];}}
573297e99dd9SToby Isaac         if (flip) {for (b = 0; b < fdof; b++) {array[clperm[offset +      b ]] *= flip[b];}}
57331a271a75SMatthew G. Knepley       } else {
573497e99dd9SToby Isaac         if (perm) {for (b = 0; b < fdof; b++) {array[offset + perm[b]]  = varr[b];}}
573597e99dd9SToby Isaac         else      {for (b = 0; b < fdof; b++) {array[offset +      b ]  = varr[b];}}
573697e99dd9SToby Isaac         if (flip) {for (b = 0; b < fdof; b++) {array[offset +      b ] *= flip[b];}}
57371a271a75SMatthew G. Knepley       }
573897e99dd9SToby Isaac       offset += fdof;
57391a271a75SMatthew G. Knepley     }
57409566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips));
57411a271a75SMatthew G. Knepley   }
57421a271a75SMatthew G. Knepley   *size = offset;
57431a271a75SMatthew G. Knepley   PetscFunctionReturn(0);
57441a271a75SMatthew G. Knepley }
57451a271a75SMatthew G. Knepley 
5746552f7358SJed Brown /*@C
5747552f7358SJed Brown   DMPlexVecGetClosure - Get an array of the values on the closure of 'point'
5748552f7358SJed Brown 
5749552f7358SJed Brown   Not collective
5750552f7358SJed Brown 
5751552f7358SJed Brown   Input Parameters:
5752552f7358SJed Brown + dm - The DM
5753552f7358SJed Brown . section - The section describing the layout in v, or NULL to use the default section
5754552f7358SJed Brown . v - The local vector
57556b867d5aSJose E. Roman - point - The point in the DM
5756552f7358SJed Brown 
57576b867d5aSJose E. Roman   Input/Output Parameters:
57586b867d5aSJose E. Roman + csize  - The size of the input values array, or NULL; on output the number of values in the closure
57596b867d5aSJose E. Roman - values - An array to use for the values, or NULL to have it allocated automatically;
57606b867d5aSJose E. Roman            if the user provided NULL, it is a borrowed array and should not be freed
576122c1ee49SMatthew G. Knepley 
576222c1ee49SMatthew G. Knepley $ Note that DMPlexVecGetClosure/DMPlexVecRestoreClosure only allocates the values array if it set to NULL in the
576322c1ee49SMatthew G. Knepley $ calling function. This is because DMPlexVecGetClosure() is typically called in the inner loop of a Vec or Mat
576422c1ee49SMatthew G. Knepley $ assembly function, and a user may already have allocated storage for this operation.
576522c1ee49SMatthew G. Knepley $
576622c1ee49SMatthew G. Knepley $ A typical use could be
576722c1ee49SMatthew G. Knepley $
576822c1ee49SMatthew G. Knepley $  values = NULL;
57699566063dSJacob Faibussowitsch $  PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values));
577022c1ee49SMatthew G. Knepley $  for (cl = 0; cl < clSize; ++cl) {
577122c1ee49SMatthew G. Knepley $    <Compute on closure>
577222c1ee49SMatthew G. Knepley $  }
57739566063dSJacob Faibussowitsch $  PetscCall(DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values));
577422c1ee49SMatthew G. Knepley $
577522c1ee49SMatthew G. Knepley $ or
577622c1ee49SMatthew G. Knepley $
577722c1ee49SMatthew G. Knepley $  PetscMalloc1(clMaxSize, &values);
577822c1ee49SMatthew G. Knepley $  for (p = pStart; p < pEnd; ++p) {
577922c1ee49SMatthew G. Knepley $    clSize = clMaxSize;
57809566063dSJacob Faibussowitsch $    PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values));
578122c1ee49SMatthew G. Knepley $    for (cl = 0; cl < clSize; ++cl) {
578222c1ee49SMatthew G. Knepley $      <Compute on closure>
578322c1ee49SMatthew G. Knepley $    }
578422c1ee49SMatthew G. Knepley $  }
578522c1ee49SMatthew G. Knepley $  PetscFree(values);
5786552f7358SJed Brown 
5787552f7358SJed Brown   Fortran Notes:
5788552f7358SJed Brown   Since it returns an array, this routine is only available in Fortran 90, and you must
5789552f7358SJed Brown   include petsc.h90 in your code.
5790552f7358SJed Brown 
5791552f7358SJed Brown   The csize argument is not present in the Fortran 90 binding since it is internal to the array.
5792552f7358SJed Brown 
5793552f7358SJed Brown   Level: intermediate
5794552f7358SJed Brown 
5795db781477SPatrick Sanan .seealso `DMPlexVecRestoreClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()`
5796552f7358SJed Brown @*/
5797552f7358SJed Brown PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
5798552f7358SJed Brown {
5799552f7358SJed Brown   PetscSection       clSection;
5800d9917b9dSMatthew G. Knepley   IS                 clPoints;
5801552f7358SJed Brown   PetscInt          *points = NULL;
5802c459fbc1SJed Brown   const PetscInt    *clp, *perm;
5803c459fbc1SJed Brown   PetscInt           depth, numFields, numPoints, asize;
5804552f7358SJed Brown 
5805d9917b9dSMatthew G. Knepley   PetscFunctionBeginHot;
5806552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
58079566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
58081a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
58091a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
58109566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
58119566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
5812552f7358SJed Brown   if (depth == 1 && numFields < 2) {
58139566063dSJacob Faibussowitsch     PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values));
5814552f7358SJed Brown     PetscFunctionReturn(0);
5815552f7358SJed Brown   }
58161a271a75SMatthew G. Knepley   /* Get points */
58179566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
5818c459fbc1SJed Brown   /* Get sizes */
5819c459fbc1SJed Brown   asize = 0;
5820c459fbc1SJed Brown   for (PetscInt p = 0; p < numPoints*2; p += 2) {
5821c459fbc1SJed Brown     PetscInt dof;
58229566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[p], &dof));
58231a271a75SMatthew G. Knepley     asize += dof;
5824552f7358SJed Brown   }
5825c459fbc1SJed Brown   if (values) {
5826c459fbc1SJed Brown     const PetscScalar *vArray;
5827c459fbc1SJed Brown     PetscInt          size;
5828c459fbc1SJed Brown 
5829c459fbc1SJed Brown     if (*values) {
583063a3b9bcSJacob 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);
58319566063dSJacob Faibussowitsch     } else PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, values));
58329566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, asize, &perm));
58339566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(v, &vArray));
58341a271a75SMatthew G. Knepley     /* Get values */
58359566063dSJacob Faibussowitsch     if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values));
58369566063dSJacob Faibussowitsch     else               PetscCall(DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values));
583763a3b9bcSJacob Faibussowitsch     PetscCheck(asize == size,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Section size %" PetscInt_FMT " does not match Vec closure size %" PetscInt_FMT, asize, size);
58381a271a75SMatthew G. Knepley     /* Cleanup array */
58399566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(v, &vArray));
5840d0f6b257SMatthew G. Knepley   }
5841c459fbc1SJed Brown   if (csize) *csize = asize;
5842c459fbc1SJed Brown   /* Cleanup points */
58439566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
5844552f7358SJed Brown   PetscFunctionReturn(0);
5845552f7358SJed Brown }
5846552f7358SJed Brown 
5847e5c487bfSMatthew G. Knepley PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[])
5848e5c487bfSMatthew G. Knepley {
5849e5c487bfSMatthew G. Knepley   DMLabel            depthLabel;
5850e5c487bfSMatthew G. Knepley   PetscSection       clSection;
5851e5c487bfSMatthew G. Knepley   IS                 clPoints;
5852e5c487bfSMatthew G. Knepley   PetscScalar       *array;
5853e5c487bfSMatthew G. Knepley   const PetscScalar *vArray;
5854e5c487bfSMatthew G. Knepley   PetscInt          *points = NULL;
5855c459fbc1SJed Brown   const PetscInt    *clp, *perm = NULL;
5856c459fbc1SJed Brown   PetscInt           mdepth, numFields, numPoints, Np = 0, p, clsize, size;
5857e5c487bfSMatthew G. Knepley 
5858e5c487bfSMatthew G. Knepley   PetscFunctionBeginHot;
5859e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
58609566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
5861e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
5862e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
58639566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &mdepth));
58649566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
58659566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
5866e5c487bfSMatthew G. Knepley   if (mdepth == 1 && numFields < 2) {
58679566063dSJacob Faibussowitsch     PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values));
5868e5c487bfSMatthew G. Knepley     PetscFunctionReturn(0);
5869e5c487bfSMatthew G. Knepley   }
5870e5c487bfSMatthew G. Knepley   /* Get points */
58719566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
5872c459fbc1SJed Brown   for (clsize=0,p=0; p<Np; p++) {
5873c459fbc1SJed Brown     PetscInt dof;
58749566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[2*p], &dof));
5875c459fbc1SJed Brown     clsize += dof;
5876c459fbc1SJed Brown   }
58779566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &perm));
5878e5c487bfSMatthew G. Knepley   /* Filter points */
5879e5c487bfSMatthew G. Knepley   for (p = 0; p < numPoints*2; p += 2) {
5880e5c487bfSMatthew G. Knepley     PetscInt dep;
5881e5c487bfSMatthew G. Knepley 
58829566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(depthLabel, points[p], &dep));
5883e5c487bfSMatthew G. Knepley     if (dep != depth) continue;
5884e5c487bfSMatthew G. Knepley     points[Np*2+0] = points[p];
5885e5c487bfSMatthew G. Knepley     points[Np*2+1] = points[p+1];
5886e5c487bfSMatthew G. Knepley     ++Np;
5887e5c487bfSMatthew G. Knepley   }
5888e5c487bfSMatthew G. Knepley   /* Get array */
5889e5c487bfSMatthew G. Knepley   if (!values || !*values) {
5890e5c487bfSMatthew G. Knepley     PetscInt asize = 0, dof;
5891e5c487bfSMatthew G. Knepley 
5892e5c487bfSMatthew G. Knepley     for (p = 0; p < Np*2; p += 2) {
58939566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, points[p], &dof));
5894e5c487bfSMatthew G. Knepley       asize += dof;
5895e5c487bfSMatthew G. Knepley     }
5896e5c487bfSMatthew G. Knepley     if (!values) {
58979566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
5898e5c487bfSMatthew G. Knepley       if (csize) *csize = asize;
5899e5c487bfSMatthew G. Knepley       PetscFunctionReturn(0);
5900e5c487bfSMatthew G. Knepley     }
59019566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, &array));
5902e5c487bfSMatthew G. Knepley   } else {
5903e5c487bfSMatthew G. Knepley     array = *values;
5904e5c487bfSMatthew G. Knepley   }
59059566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(v, &vArray));
5906e5c487bfSMatthew G. Knepley   /* Get values */
59079566063dSJacob Faibussowitsch   if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array));
59089566063dSJacob Faibussowitsch   else               PetscCall(DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array));
5909e5c487bfSMatthew G. Knepley   /* Cleanup points */
59109566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
5911e5c487bfSMatthew G. Knepley   /* Cleanup array */
59129566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(v, &vArray));
5913e5c487bfSMatthew G. Knepley   if (!*values) {
5914e5c487bfSMatthew G. Knepley     if (csize) *csize = size;
5915e5c487bfSMatthew G. Knepley     *values = array;
5916e5c487bfSMatthew G. Knepley   } else {
591763a3b9bcSJacob Faibussowitsch     PetscCheck(size <= *csize,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size);
5918e5c487bfSMatthew G. Knepley     *csize = size;
5919e5c487bfSMatthew G. Knepley   }
5920e5c487bfSMatthew G. Knepley   PetscFunctionReturn(0);
5921e5c487bfSMatthew G. Knepley }
5922e5c487bfSMatthew G. Knepley 
5923552f7358SJed Brown /*@C
5924552f7358SJed Brown   DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point'
5925552f7358SJed Brown 
5926552f7358SJed Brown   Not collective
5927552f7358SJed Brown 
5928552f7358SJed Brown   Input Parameters:
5929552f7358SJed Brown + dm - The DM
59300298fd71SBarry Smith . section - The section describing the layout in v, or NULL to use the default section
5931552f7358SJed Brown . v - The local vector
5932eaf898f9SPatrick Sanan . point - The point in the DM
59330298fd71SBarry Smith . csize - The number of values in the closure, or NULL
5934552f7358SJed Brown - values - The array of values, which is a borrowed array and should not be freed
5935552f7358SJed Brown 
593622c1ee49SMatthew 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()
593722c1ee49SMatthew G. Knepley 
59383813dfbdSMatthew G Knepley   Fortran Notes:
59393813dfbdSMatthew G Knepley   Since it returns an array, this routine is only available in Fortran 90, and you must
59403813dfbdSMatthew G Knepley   include petsc.h90 in your code.
59413813dfbdSMatthew G Knepley 
59423813dfbdSMatthew G Knepley   The csize argument is not present in the Fortran 90 binding since it is internal to the array.
59433813dfbdSMatthew G Knepley 
5944552f7358SJed Brown   Level: intermediate
5945552f7358SJed Brown 
5946db781477SPatrick Sanan .seealso `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()`
5947552f7358SJed Brown @*/
59487c1f9639SMatthew G Knepley PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
5949a6dfd86eSKarl Rupp {
5950552f7358SJed Brown   PetscInt       size = 0;
5951552f7358SJed Brown 
5952552f7358SJed Brown   PetscFunctionBegin;
5953552f7358SJed Brown   /* Should work without recalculating size */
59549566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void*) values));
5955c9fdaa05SMatthew G. Knepley   *values = NULL;
5956552f7358SJed Brown   PetscFunctionReturn(0);
5957552f7358SJed Brown }
5958552f7358SJed Brown 
59599fbee547SJacob Faibussowitsch static inline void add   (PetscScalar *x, PetscScalar y) {*x += y;}
59609fbee547SJacob Faibussowitsch static inline void insert(PetscScalar *x, PetscScalar y) {*x  = y;}
5961552f7358SJed Brown 
59629fbee547SJacob Faibussowitsch static inline PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, const PetscInt perm[], const PetscScalar flip[], const PetscInt clperm[], const PetscScalar values[], PetscInt offset, PetscScalar array[])
5963552f7358SJed Brown {
5964552f7358SJed Brown   PetscInt        cdof;   /* The number of constraints on this point */
5965552f7358SJed Brown   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
5966552f7358SJed Brown   PetscScalar    *a;
5967552f7358SJed Brown   PetscInt        off, cind = 0, k;
5968552f7358SJed Brown 
5969552f7358SJed Brown   PetscFunctionBegin;
59709566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
59719566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(section, point, &off));
5972552f7358SJed Brown   a    = &array[off];
5973552f7358SJed Brown   if (!cdof || setBC) {
597497e99dd9SToby Isaac     if (clperm) {
597597e99dd9SToby Isaac       if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));}}
597697e99dd9SToby Isaac       else      {for (k = 0; k < dof; ++k) {fuse(&a[k], values[clperm[offset+     k ]] * (flip ? flip[     k ] : 1.));}}
5977552f7358SJed Brown     } else {
597897e99dd9SToby Isaac       if (perm) {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));}}
597997e99dd9SToby Isaac       else      {for (k = 0; k < dof; ++k) {fuse(&a[k], values[offset+     k ] * (flip ? flip[     k ] : 1.));}}
5980552f7358SJed Brown     }
5981552f7358SJed Brown   } else {
59829566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
598397e99dd9SToby Isaac     if (clperm) {
598497e99dd9SToby Isaac       if (perm) {for (k = 0; k < dof; ++k) {
5985552f7358SJed Brown           if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
598697e99dd9SToby Isaac           fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));
5987552f7358SJed Brown         }
5988552f7358SJed Brown       } else {
5989552f7358SJed Brown         for (k = 0; k < dof; ++k) {
5990552f7358SJed Brown           if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
599197e99dd9SToby Isaac           fuse(&a[k], values[clperm[offset+     k ]] * (flip ? flip[     k ] : 1.));
599297e99dd9SToby Isaac         }
599397e99dd9SToby Isaac       }
599497e99dd9SToby Isaac     } else {
599597e99dd9SToby Isaac       if (perm) {
599697e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
599797e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
599897e99dd9SToby Isaac           fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));
599997e99dd9SToby Isaac         }
600097e99dd9SToby Isaac       } else {
600197e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
600297e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
600397e99dd9SToby Isaac           fuse(&a[k], values[offset+     k ] * (flip ? flip[     k ] : 1.));
600497e99dd9SToby Isaac         }
6005552f7358SJed Brown       }
6006552f7358SJed Brown     }
6007552f7358SJed Brown   }
6008552f7358SJed Brown   PetscFunctionReturn(0);
6009552f7358SJed Brown }
6010552f7358SJed Brown 
60119fbee547SJacob Faibussowitsch static inline PetscErrorCode updatePointBC_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), const PetscInt perm[], const PetscScalar flip[], const PetscInt clperm[], const PetscScalar values[], PetscInt offset, PetscScalar array[])
6012a5e93ea8SMatthew G. Knepley {
6013a5e93ea8SMatthew G. Knepley   PetscInt        cdof;   /* The number of constraints on this point */
6014a5e93ea8SMatthew G. Knepley   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6015a5e93ea8SMatthew G. Knepley   PetscScalar    *a;
6016a5e93ea8SMatthew G. Knepley   PetscInt        off, cind = 0, k;
6017a5e93ea8SMatthew G. Knepley 
6018a5e93ea8SMatthew G. Knepley   PetscFunctionBegin;
60199566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
60209566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(section, point, &off));
6021a5e93ea8SMatthew G. Knepley   a    = &array[off];
6022a5e93ea8SMatthew G. Knepley   if (cdof) {
60239566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
602497e99dd9SToby Isaac     if (clperm) {
602597e99dd9SToby Isaac       if (perm) {
6026a5e93ea8SMatthew G. Knepley         for (k = 0; k < dof; ++k) {
6027a5e93ea8SMatthew G. Knepley           if ((cind < cdof) && (k == cdofs[cind])) {
602897e99dd9SToby Isaac             fuse(&a[k], values[clperm[offset+perm[k]]] * (flip ? flip[perm[k]] : 1.));
602997e99dd9SToby Isaac             cind++;
6030a5e93ea8SMatthew G. Knepley           }
6031a5e93ea8SMatthew G. Knepley         }
6032a5e93ea8SMatthew G. Knepley       } else {
6033a5e93ea8SMatthew G. Knepley         for (k = 0; k < dof; ++k) {
6034a5e93ea8SMatthew G. Knepley           if ((cind < cdof) && (k == cdofs[cind])) {
603597e99dd9SToby Isaac             fuse(&a[k], values[clperm[offset+     k ]] * (flip ? flip[     k ] : 1.));
603697e99dd9SToby Isaac             cind++;
603797e99dd9SToby Isaac           }
603897e99dd9SToby Isaac         }
603997e99dd9SToby Isaac       }
604097e99dd9SToby Isaac     } else {
604197e99dd9SToby Isaac       if (perm) {
604297e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
604397e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {
604497e99dd9SToby Isaac             fuse(&a[k], values[offset+perm[k]] * (flip ? flip[perm[k]] : 1.));
604597e99dd9SToby Isaac             cind++;
604697e99dd9SToby Isaac           }
604797e99dd9SToby Isaac         }
604897e99dd9SToby Isaac       } else {
604997e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
605097e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {
605197e99dd9SToby Isaac             fuse(&a[k], values[offset+     k ] * (flip ? flip[     k ] : 1.));
605297e99dd9SToby Isaac             cind++;
605397e99dd9SToby Isaac           }
6054a5e93ea8SMatthew G. Knepley         }
6055a5e93ea8SMatthew G. Knepley       }
6056a5e93ea8SMatthew G. Knepley     }
6057a5e93ea8SMatthew G. Knepley   }
6058a5e93ea8SMatthew G. Knepley   PetscFunctionReturn(0);
6059a5e93ea8SMatthew G. Knepley }
6060a5e93ea8SMatthew G. Knepley 
60619fbee547SJacob Faibussowitsch static inline PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, const PetscInt *perm, const PetscScalar *flip, PetscInt f, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, const PetscInt clperm[], const PetscScalar values[], PetscInt *offset, PetscScalar array[])
6062a6dfd86eSKarl Rupp {
6063552f7358SJed Brown   PetscScalar    *a;
60641a271a75SMatthew G. Knepley   PetscInt        fdof, foff, fcdof, foffset = *offset;
60651a271a75SMatthew G. Knepley   const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
606697e99dd9SToby Isaac   PetscInt        cind = 0, b;
6067552f7358SJed Brown 
6068552f7358SJed Brown   PetscFunctionBegin;
60699566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
60709566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof));
60719566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
60721a271a75SMatthew G. Knepley   a    = &array[foff];
6073552f7358SJed Brown   if (!fcdof || setBC) {
607497e99dd9SToby Isaac     if (clperm) {
607597e99dd9SToby Isaac       if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));}}
607697e99dd9SToby Isaac       else      {for (b = 0; b < fdof; b++) {fuse(&a[b], values[clperm[foffset+     b ]] * (flip ? flip[     b ] : 1.));}}
6077552f7358SJed Brown     } else {
607897e99dd9SToby Isaac       if (perm) {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));}}
607997e99dd9SToby Isaac       else      {for (b = 0; b < fdof; b++) {fuse(&a[b], values[foffset+     b ] * (flip ? flip[     b ] : 1.));}}
6080552f7358SJed Brown     }
6081552f7358SJed Brown   } else {
60829566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
608397e99dd9SToby Isaac     if (clperm) {
608497e99dd9SToby Isaac       if (perm) {
608597e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
608697e99dd9SToby Isaac           if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;}
608797e99dd9SToby Isaac           fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));
6088552f7358SJed Brown         }
6089552f7358SJed Brown       } else {
609097e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
609197e99dd9SToby Isaac           if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;}
609297e99dd9SToby Isaac           fuse(&a[b], values[clperm[foffset+     b ]] * (flip ? flip[     b ] : 1.));
609397e99dd9SToby Isaac         }
609497e99dd9SToby Isaac       }
609597e99dd9SToby Isaac     } else {
609697e99dd9SToby Isaac       if (perm) {
609797e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
609897e99dd9SToby Isaac           if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;}
609997e99dd9SToby Isaac           fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));
610097e99dd9SToby Isaac         }
610197e99dd9SToby Isaac       } else {
610297e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
610397e99dd9SToby Isaac           if ((cind < fcdof) && (b == fcdofs[cind])) {++cind; continue;}
610497e99dd9SToby Isaac           fuse(&a[b], values[foffset+     b ] * (flip ? flip[     b ] : 1.));
6105552f7358SJed Brown         }
6106552f7358SJed Brown       }
6107552f7358SJed Brown     }
6108552f7358SJed Brown   }
61091a271a75SMatthew G. Knepley   *offset += fdof;
6110552f7358SJed Brown   PetscFunctionReturn(0);
6111552f7358SJed Brown }
6112552f7358SJed Brown 
61139fbee547SJacob Faibussowitsch static inline PetscErrorCode updatePointFieldsBC_private(PetscSection section, PetscInt point, const PetscInt perm[], const PetscScalar flip[], PetscInt f, PetscInt Ncc, const PetscInt comps[], void (*fuse)(PetscScalar*, PetscScalar), const PetscInt clperm[], const PetscScalar values[], PetscInt *offset, PetscScalar array[])
6114a5e93ea8SMatthew G. Knepley {
6115a5e93ea8SMatthew G. Knepley   PetscScalar    *a;
61161a271a75SMatthew G. Knepley   PetscInt        fdof, foff, fcdof, foffset = *offset;
61171a271a75SMatthew G. Knepley   const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
61185da9d227SMatthew G. Knepley   PetscInt        Nc, cind = 0, ncind = 0, b;
6119ba322698SMatthew G. Knepley   PetscBool       ncSet, fcSet;
6120a5e93ea8SMatthew G. Knepley 
6121a5e93ea8SMatthew G. Knepley   PetscFunctionBegin;
61229566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldComponents(section, f, &Nc));
61239566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
61249566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof));
61259566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
61261a271a75SMatthew G. Knepley   a    = &array[foff];
6127a5e93ea8SMatthew G. Knepley   if (fcdof) {
6128ba322698SMatthew G. Knepley     /* We just override fcdof and fcdofs with Ncc and comps */
61299566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
613097e99dd9SToby Isaac     if (clperm) {
613197e99dd9SToby Isaac       if (perm) {
6132ba322698SMatthew G. Knepley         if (comps) {
6133ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6134ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
61355da9d227SMatthew G. Knepley             if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;}
6136ba322698SMatthew G. Knepley             if ((cind < fcdof) && (b == fcdofs[cind])) {++cind;  fcSet = PETSC_TRUE;}
6137ba322698SMatthew G. Knepley             if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));}
6138ba322698SMatthew G. Knepley           }
6139ba322698SMatthew G. Knepley         } else {
614097e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
614197e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
614297e99dd9SToby Isaac               fuse(&a[b], values[clperm[foffset+perm[b]]] * (flip ? flip[perm[b]] : 1.));
6143a5e93ea8SMatthew G. Knepley               ++cind;
6144a5e93ea8SMatthew G. Knepley             }
6145a5e93ea8SMatthew G. Knepley           }
6146ba322698SMatthew G. Knepley         }
6147ba322698SMatthew G. Knepley       } else {
6148ba322698SMatthew G. Knepley         if (comps) {
6149ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6150ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
61515da9d227SMatthew G. Knepley             if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;}
6152ba322698SMatthew G. Knepley             if ((cind < fcdof) && (b == fcdofs[cind])) {++cind;  fcSet = PETSC_TRUE;}
6153ba322698SMatthew G. Knepley             if (ncSet && fcSet) {fuse(&a[b], values[clperm[foffset+     b ]] * (flip ? flip[     b ] : 1.));}
6154ba322698SMatthew G. Knepley           }
6155a5e93ea8SMatthew G. Knepley         } else {
615697e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
615797e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
615897e99dd9SToby Isaac               fuse(&a[b], values[clperm[foffset+     b ]] * (flip ? flip[     b ] : 1.));
615997e99dd9SToby Isaac               ++cind;
616097e99dd9SToby Isaac             }
616197e99dd9SToby Isaac           }
616297e99dd9SToby Isaac         }
6163ba322698SMatthew G. Knepley       }
616497e99dd9SToby Isaac     } else {
616597e99dd9SToby Isaac       if (perm) {
6166ba322698SMatthew G. Knepley         if (comps) {
6167ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6168ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
61695da9d227SMatthew G. Knepley             if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;}
6170ba322698SMatthew G. Knepley             if ((cind < fcdof) && (b == fcdofs[cind])) {++cind;  fcSet = PETSC_TRUE;}
6171ba322698SMatthew G. Knepley             if (ncSet && fcSet) {fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));}
6172ba322698SMatthew G. Knepley           }
6173ba322698SMatthew G. Knepley         } else {
617497e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
617597e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
617697e99dd9SToby Isaac               fuse(&a[b], values[foffset+perm[b]] * (flip ? flip[perm[b]] : 1.));
617797e99dd9SToby Isaac               ++cind;
617897e99dd9SToby Isaac             }
617997e99dd9SToby Isaac           }
6180ba322698SMatthew G. Knepley         }
6181ba322698SMatthew G. Knepley       } else {
6182ba322698SMatthew G. Knepley         if (comps) {
6183ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6184ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
61855da9d227SMatthew G. Knepley             if (b%Nc == comps[ncind]) {ncind = (ncind+1)%Ncc; ncSet = PETSC_TRUE;}
6186ba322698SMatthew G. Knepley             if ((cind < fcdof) && (b == fcdofs[cind])) {++cind;  fcSet = PETSC_TRUE;}
6187ba322698SMatthew G. Knepley             if (ncSet && fcSet) {fuse(&a[b], values[foffset+     b ] * (flip ? flip[     b ] : 1.));}
6188ba322698SMatthew G. Knepley           }
618997e99dd9SToby Isaac         } else {
619097e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
619197e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
619297e99dd9SToby Isaac               fuse(&a[b], values[foffset+     b ] * (flip ? flip[     b ] : 1.));
6193a5e93ea8SMatthew G. Knepley               ++cind;
6194a5e93ea8SMatthew G. Knepley             }
6195a5e93ea8SMatthew G. Knepley           }
6196a5e93ea8SMatthew G. Knepley         }
6197a5e93ea8SMatthew G. Knepley       }
6198a5e93ea8SMatthew G. Knepley     }
6199ba322698SMatthew G. Knepley   }
62001a271a75SMatthew G. Knepley   *offset += fdof;
6201a5e93ea8SMatthew G. Knepley   PetscFunctionReturn(0);
6202a5e93ea8SMatthew G. Knepley }
6203a5e93ea8SMatthew G. Knepley 
62049fbee547SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode)
6205a6dfd86eSKarl Rupp {
6206552f7358SJed Brown   PetscScalar    *array;
62071b406b76SMatthew G. Knepley   const PetscInt *cone, *coneO;
62081b406b76SMatthew G. Knepley   PetscInt        pStart, pEnd, p, numPoints, off, dof;
6209552f7358SJed Brown 
62101b406b76SMatthew G. Knepley   PetscFunctionBeginHot;
62119566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
62129566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, point, &numPoints));
62139566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, point, &cone));
62149566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeOrientation(dm, point, &coneO));
62159566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
6216b6ebb6e6SMatthew G. Knepley   for (p = 0, off = 0; p <= numPoints; ++p, off += dof) {
6217b6ebb6e6SMatthew G. Knepley     const PetscInt cp = !p ? point : cone[p-1];
6218b6ebb6e6SMatthew G. Knepley     const PetscInt o  = !p ? 0     : coneO[p-1];
6219b6ebb6e6SMatthew G. Knepley 
6220b6ebb6e6SMatthew G. Knepley     if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;}
62219566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, cp, &dof));
6222b6ebb6e6SMatthew G. Knepley     /* ADD_VALUES */
6223b6ebb6e6SMatthew G. Knepley     {
6224b6ebb6e6SMatthew G. Knepley       const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6225b6ebb6e6SMatthew G. Knepley       PetscScalar    *a;
6226b6ebb6e6SMatthew G. Knepley       PetscInt        cdof, coff, cind = 0, k;
6227b6ebb6e6SMatthew G. Knepley 
62289566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetConstraintDof(section, cp, &cdof));
62299566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(section, cp, &coff));
6230b6ebb6e6SMatthew G. Knepley       a    = &array[coff];
6231b6ebb6e6SMatthew G. Knepley       if (!cdof) {
6232b6ebb6e6SMatthew G. Knepley         if (o >= 0) {
6233b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
6234b6ebb6e6SMatthew G. Knepley             a[k] += values[off+k];
6235b6ebb6e6SMatthew G. Knepley           }
6236b6ebb6e6SMatthew G. Knepley         } else {
6237b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
6238b6ebb6e6SMatthew G. Knepley             a[k] += values[off+dof-k-1];
6239b6ebb6e6SMatthew G. Knepley           }
6240b6ebb6e6SMatthew G. Knepley         }
6241b6ebb6e6SMatthew G. Knepley       } else {
62429566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintIndices(section, cp, &cdofs));
6243b6ebb6e6SMatthew G. Knepley         if (o >= 0) {
6244b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
6245b6ebb6e6SMatthew G. Knepley             if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
6246b6ebb6e6SMatthew G. Knepley             a[k] += values[off+k];
6247b6ebb6e6SMatthew G. Knepley           }
6248b6ebb6e6SMatthew G. Knepley         } else {
6249b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
6250b6ebb6e6SMatthew G. Knepley             if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;}
6251b6ebb6e6SMatthew G. Knepley             a[k] += values[off+dof-k-1];
6252b6ebb6e6SMatthew G. Knepley           }
6253b6ebb6e6SMatthew G. Knepley         }
6254b6ebb6e6SMatthew G. Knepley       }
6255b6ebb6e6SMatthew G. Knepley     }
6256b6ebb6e6SMatthew G. Knepley   }
62579566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
6258b6ebb6e6SMatthew G. Knepley   PetscFunctionReturn(0);
6259b6ebb6e6SMatthew G. Knepley }
62601b406b76SMatthew G. Knepley 
62611b406b76SMatthew G. Knepley /*@C
62621b406b76SMatthew G. Knepley   DMPlexVecSetClosure - Set an array of the values on the closure of 'point'
62631b406b76SMatthew G. Knepley 
62641b406b76SMatthew G. Knepley   Not collective
62651b406b76SMatthew G. Knepley 
62661b406b76SMatthew G. Knepley   Input Parameters:
62671b406b76SMatthew G. Knepley + dm - The DM
62681b406b76SMatthew G. Knepley . section - The section describing the layout in v, or NULL to use the default section
62691b406b76SMatthew G. Knepley . v - The local vector
6270eaf898f9SPatrick Sanan . point - The point in the DM
62711b406b76SMatthew G. Knepley . values - The array of values
627222c1ee49SMatthew 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,
627322c1ee49SMatthew G. Knepley          where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions.
62741b406b76SMatthew G. Knepley 
62751b406b76SMatthew G. Knepley   Fortran Notes:
62761b406b76SMatthew G. Knepley   This routine is only available in Fortran 90, and you must include petsc.h90 in your code.
62771b406b76SMatthew G. Knepley 
62781b406b76SMatthew G. Knepley   Level: intermediate
62791b406b76SMatthew G. Knepley 
6280db781477SPatrick Sanan .seealso `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`
62811b406b76SMatthew G. Knepley @*/
62821b406b76SMatthew G. Knepley PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode)
62831b406b76SMatthew G. Knepley {
62841b406b76SMatthew G. Knepley   PetscSection    clSection;
62851b406b76SMatthew G. Knepley   IS              clPoints;
62861b406b76SMatthew G. Knepley   PetscScalar    *array;
62871b406b76SMatthew G. Knepley   PetscInt       *points = NULL;
628827f02ce8SMatthew G. Knepley   const PetscInt *clp, *clperm = NULL;
6289c459fbc1SJed Brown   PetscInt        depth, numFields, numPoints, p, clsize;
62901b406b76SMatthew G. Knepley 
62911a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
62921b406b76SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
62939566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
62941a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
62951a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
62969566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
62979566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
62981b406b76SMatthew G. Knepley   if (depth == 1 && numFields < 2 && mode == ADD_VALUES) {
62999566063dSJacob Faibussowitsch     PetscCall(DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode));
63001b406b76SMatthew G. Knepley     PetscFunctionReturn(0);
63011b406b76SMatthew G. Knepley   }
63021a271a75SMatthew G. Knepley   /* Get points */
63039566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
6304c459fbc1SJed Brown   for (clsize=0,p=0; p<numPoints; p++) {
6305c459fbc1SJed Brown     PetscInt dof;
63069566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[2*p], &dof));
6307c459fbc1SJed Brown     clsize += dof;
6308c459fbc1SJed Brown   }
63099566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm));
63101a271a75SMatthew G. Knepley   /* Get array */
63119566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
63121a271a75SMatthew G. Knepley   /* Get values */
6313ef90cfe2SMatthew G. Knepley   if (numFields > 0) {
631497e99dd9SToby Isaac     PetscInt offset = 0, f;
6315552f7358SJed Brown     for (f = 0; f < numFields; ++f) {
631697e99dd9SToby Isaac       const PetscInt    **perms = NULL;
631797e99dd9SToby Isaac       const PetscScalar **flips = NULL;
631897e99dd9SToby Isaac 
63199566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips));
6320552f7358SJed Brown       switch (mode) {
6321552f7358SJed Brown       case INSERT_VALUES:
632297e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
632397e99dd9SToby Isaac           const PetscInt    point = points[2*p];
632497e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
632597e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
632697e99dd9SToby Isaac           updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array);
6327552f7358SJed Brown         } break;
6328552f7358SJed Brown       case INSERT_ALL_VALUES:
632997e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
633097e99dd9SToby Isaac           const PetscInt    point = points[2*p];
633197e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
633297e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
633397e99dd9SToby Isaac           updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array);
6334552f7358SJed Brown         } break;
6335a5e93ea8SMatthew G. Knepley       case INSERT_BC_VALUES:
633697e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
633797e99dd9SToby Isaac           const PetscInt    point = points[2*p];
633897e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
633997e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
6340ba322698SMatthew G. Knepley           updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array);
6341a5e93ea8SMatthew G. Knepley         } break;
6342552f7358SJed Brown       case ADD_VALUES:
634397e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
634497e99dd9SToby Isaac           const PetscInt    point = points[2*p];
634597e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
634697e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
634797e99dd9SToby Isaac           updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array);
6348552f7358SJed Brown         } break;
6349552f7358SJed Brown       case ADD_ALL_VALUES:
635097e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
635197e99dd9SToby Isaac           const PetscInt    point = points[2*p];
635297e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
635397e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
635497e99dd9SToby Isaac           updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array);
6355552f7358SJed Brown         } break;
6356304ab55fSMatthew G. Knepley       case ADD_BC_VALUES:
635797e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
635897e99dd9SToby Isaac           const PetscInt    point = points[2*p];
635997e99dd9SToby Isaac           const PetscInt    *perm = perms ? perms[p] : NULL;
636097e99dd9SToby Isaac           const PetscScalar *flip = flips ? flips[p] : NULL;
6361ba322698SMatthew G. Knepley           updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array);
6362304ab55fSMatthew G. Knepley         } break;
6363552f7358SJed Brown       default:
636498921bdaSJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
6365552f7358SJed Brown       }
63669566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips));
63671a271a75SMatthew G. Knepley     }
6368552f7358SJed Brown   } else {
63691a271a75SMatthew G. Knepley     PetscInt dof, off;
637097e99dd9SToby Isaac     const PetscInt    **perms = NULL;
637197e99dd9SToby Isaac     const PetscScalar **flips = NULL;
63721a271a75SMatthew G. Knepley 
63739566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(section,numPoints,points,&perms,&flips));
6374552f7358SJed Brown     switch (mode) {
6375552f7358SJed Brown     case INSERT_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_FALSE, perm, flip, clperm, values, off, array);
6382552f7358SJed Brown       } break;
6383552f7358SJed Brown     case INSERT_ALL_VALUES:
638497e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
638597e99dd9SToby Isaac         const PetscInt    point = points[2*p];
638697e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
638797e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
63889566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
638997e99dd9SToby Isaac         updatePoint_private(section, point, dof, insert, PETSC_TRUE,  perm, flip, clperm, values, off, array);
6390552f7358SJed Brown       } break;
6391a5e93ea8SMatthew G. Knepley     case INSERT_BC_VALUES:
639297e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
639397e99dd9SToby Isaac         const PetscInt    point = points[2*p];
639497e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
639597e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
63969566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
639797e99dd9SToby Isaac         updatePointBC_private(section, point, dof, insert,  perm, flip, clperm, values, off, array);
6398a5e93ea8SMatthew G. Knepley       } break;
6399552f7358SJed Brown     case ADD_VALUES:
640097e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
640197e99dd9SToby Isaac         const PetscInt    point = points[2*p];
640297e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
640397e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
64049566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
640597e99dd9SToby Isaac         updatePoint_private(section, point, dof, add,    PETSC_FALSE, perm, flip, clperm, values, off, array);
6406552f7358SJed Brown       } break;
6407552f7358SJed Brown     case ADD_ALL_VALUES:
640897e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
640997e99dd9SToby Isaac         const PetscInt    point = points[2*p];
641097e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
641197e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
64129566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
641397e99dd9SToby Isaac         updatePoint_private(section, point, dof, add,    PETSC_TRUE,  perm, flip, clperm, values, off, array);
6414552f7358SJed Brown       } break;
6415304ab55fSMatthew G. Knepley     case ADD_BC_VALUES:
641697e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
641797e99dd9SToby Isaac         const PetscInt    point = points[2*p];
641897e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
641997e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
64209566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
642197e99dd9SToby Isaac         updatePointBC_private(section, point, dof, add,  perm, flip, clperm, values, off, array);
6422304ab55fSMatthew G. Knepley       } break;
6423552f7358SJed Brown     default:
642498921bdaSJacob Faibussowitsch       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
6425552f7358SJed Brown     }
64269566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(section,numPoints,points,&perms,&flips));
6427552f7358SJed Brown   }
64281a271a75SMatthew G. Knepley   /* Cleanup points */
64299566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
64301a271a75SMatthew G. Knepley   /* Cleanup array */
64319566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
6432552f7358SJed Brown   PetscFunctionReturn(0);
6433552f7358SJed Brown }
6434552f7358SJed Brown 
64355f790a90SMatthew G. Knepley /* Check whether the given point is in the label. If not, update the offset to skip this point */
64369fbee547SJacob Faibussowitsch static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset)
64375f790a90SMatthew G. Knepley {
64385f790a90SMatthew G. Knepley   PetscFunctionBegin;
64395f790a90SMatthew G. Knepley   if (label) {
6440d6177c40SToby Isaac     PetscBool contains;
6441d6177c40SToby Isaac     PetscInt  fdof;
64425f790a90SMatthew G. Knepley 
6443d6177c40SToby Isaac     PetscCall(DMLabelStratumHasPoint(label, labelId, point, &contains));
6444d6177c40SToby Isaac     if (!contains) {
64459566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
64465f790a90SMatthew G. Knepley       *offset += fdof;
64475f790a90SMatthew G. Knepley       PetscFunctionReturn(1);
64485f790a90SMatthew G. Knepley     }
64495f790a90SMatthew G. Knepley   }
64505f790a90SMatthew G. Knepley   PetscFunctionReturn(0);
64515f790a90SMatthew G. Knepley }
64525f790a90SMatthew G. Knepley 
645397529cf3SJed Brown /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */
64545f790a90SMatthew G. Knepley PetscErrorCode DMPlexVecSetFieldClosure_Internal(DM dm, PetscSection section, Vec v, PetscBool fieldActive[], PetscInt point, PetscInt Ncc, const PetscInt comps[], DMLabel label, PetscInt labelId, const PetscScalar values[], InsertMode mode)
6455e07394fbSMatthew G. Knepley {
6456e07394fbSMatthew G. Knepley   PetscSection    clSection;
6457e07394fbSMatthew G. Knepley   IS              clPoints;
6458e07394fbSMatthew G. Knepley   PetscScalar    *array;
6459e07394fbSMatthew G. Knepley   PetscInt       *points = NULL;
646097529cf3SJed Brown   const PetscInt *clp;
6461e07394fbSMatthew G. Knepley   PetscInt        numFields, numPoints, p;
646297e99dd9SToby Isaac   PetscInt        offset = 0, f;
6463e07394fbSMatthew G. Knepley 
6464e07394fbSMatthew G. Knepley   PetscFunctionBeginHot;
6465e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
64669566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
6467e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
6468e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
64699566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
6470e07394fbSMatthew G. Knepley   /* Get points */
64719566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
6472e07394fbSMatthew G. Knepley   /* Get array */
64739566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
6474e07394fbSMatthew G. Knepley   /* Get values */
6475e07394fbSMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
647697e99dd9SToby Isaac     const PetscInt    **perms = NULL;
647797e99dd9SToby Isaac     const PetscScalar **flips = NULL;
647897e99dd9SToby Isaac 
6479e07394fbSMatthew G. Knepley     if (!fieldActive[f]) {
6480e07394fbSMatthew G. Knepley       for (p = 0; p < numPoints*2; p += 2) {
6481e07394fbSMatthew G. Knepley         PetscInt fdof;
64829566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof));
6483e07394fbSMatthew G. Knepley         offset += fdof;
6484e07394fbSMatthew G. Knepley       }
6485e07394fbSMatthew G. Knepley       continue;
6486e07394fbSMatthew G. Knepley     }
64879566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldPointSyms(section,f,numPoints,points,&perms,&flips));
6488e07394fbSMatthew G. Knepley     switch (mode) {
6489e07394fbSMatthew G. Knepley     case INSERT_VALUES:
649097e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
649197e99dd9SToby Isaac         const PetscInt    point = points[2*p];
649297e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
649397e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
64945f80ce2aSJacob Faibussowitsch         if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue;
64959566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array));
6496e07394fbSMatthew G. Knepley       } break;
6497e07394fbSMatthew G. Knepley     case INSERT_ALL_VALUES:
649897e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
649997e99dd9SToby Isaac         const PetscInt    point = points[2*p];
650097e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
650197e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
65025f80ce2aSJacob Faibussowitsch         if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue;
65039566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array));
6504e07394fbSMatthew G. Knepley       } break;
6505e07394fbSMatthew G. Knepley     case INSERT_BC_VALUES:
650697e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
650797e99dd9SToby Isaac         const PetscInt    point = points[2*p];
650897e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
650997e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
65105f80ce2aSJacob Faibussowitsch         if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue;
65119566063dSJacob Faibussowitsch         PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array));
6512e07394fbSMatthew G. Knepley       } break;
6513e07394fbSMatthew G. Knepley     case ADD_VALUES:
651497e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
651597e99dd9SToby Isaac         const PetscInt    point = points[2*p];
651697e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
651797e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
65185f80ce2aSJacob Faibussowitsch         if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue;
65199566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array));
6520e07394fbSMatthew G. Knepley       } break;
6521e07394fbSMatthew G. Knepley     case ADD_ALL_VALUES:
652297e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
652397e99dd9SToby Isaac         const PetscInt    point = points[2*p];
652497e99dd9SToby Isaac         const PetscInt    *perm = perms ? perms[p] : NULL;
652597e99dd9SToby Isaac         const PetscScalar *flip = flips ? flips[p] : NULL;
65265f80ce2aSJacob Faibussowitsch         if (CheckPoint_Private(label, labelId, section, point, f, &offset)) continue;
65279566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array));
6528e07394fbSMatthew G. Knepley       } break;
6529e07394fbSMatthew G. Knepley     default:
653098921bdaSJacob Faibussowitsch       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
6531e07394fbSMatthew G. Knepley     }
65329566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestoreFieldPointSyms(section,f,numPoints,points,&perms,&flips));
6533e07394fbSMatthew G. Knepley   }
6534e07394fbSMatthew G. Knepley   /* Cleanup points */
65359566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm,section,point,&numPoints,&points,&clSection,&clPoints,&clp));
6536e07394fbSMatthew G. Knepley   /* Cleanup array */
65379566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
6538e07394fbSMatthew G. Knepley   PetscFunctionReturn(0);
6539e07394fbSMatthew G. Knepley }
6540e07394fbSMatthew G. Knepley 
65417cd05799SMatthew G. Knepley static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[])
6542552f7358SJed Brown {
6543552f7358SJed Brown   PetscMPIInt    rank;
6544552f7358SJed Brown   PetscInt       i, j;
6545552f7358SJed Brown 
6546552f7358SJed Brown   PetscFunctionBegin;
65479566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
654863a3b9bcSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat for point %" PetscInt_FMT "\n", rank, point));
654963a3b9bcSJacob Faibussowitsch   for (i = 0; i < numRIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, rindices[i]));
655063a3b9bcSJacob Faibussowitsch   for (i = 0; i < numCIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, cindices[i]));
6551b0ecff45SMatthew G. Knepley   numCIndices = numCIndices ? numCIndices : numRIndices;
6552557cf195SMatthew G. Knepley   if (!values) PetscFunctionReturn(0);
6553b0ecff45SMatthew G. Knepley   for (i = 0; i < numRIndices; i++) {
65549566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]", rank));
6555b0ecff45SMatthew G. Knepley     for (j = 0; j < numCIndices; j++) {
6556519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX)
65579566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j])));
6558552f7358SJed Brown #else
65599566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j]));
6560552f7358SJed Brown #endif
6561552f7358SJed Brown     }
65629566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
6563552f7358SJed Brown   }
6564552f7358SJed Brown   PetscFunctionReturn(0);
6565552f7358SJed Brown }
6566552f7358SJed Brown 
656705586334SMatthew G. Knepley /*
656805586334SMatthew G. Knepley   DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array
656905586334SMatthew G. Knepley 
657005586334SMatthew G. Knepley   Input Parameters:
657105586334SMatthew G. Knepley + section - The section for this data layout
657236fa2b79SJed Brown . islocal - Is the section (and thus indices being requested) local or global?
657305586334SMatthew G. Knepley . point   - The point contributing dofs with these indices
657405586334SMatthew G. Knepley . off     - The global offset of this point
657505586334SMatthew G. Knepley . loff    - The local offset of each field
6576a5b23f4aSJose E. Roman . setBC   - The flag determining whether to include indices of boundary values
657705586334SMatthew G. Knepley . perm    - A permutation of the dofs on this point, or NULL
657805586334SMatthew G. Knepley - indperm - A permutation of the entire indices array, or NULL
657905586334SMatthew G. Knepley 
658005586334SMatthew G. Knepley   Output Parameter:
658105586334SMatthew G. Knepley . indices - Indices for dofs on this point
658205586334SMatthew G. Knepley 
658305586334SMatthew G. Knepley   Level: developer
658405586334SMatthew G. Knepley 
658505586334SMatthew G. Knepley   Note: The indices could be local or global, depending on the value of 'off'.
658605586334SMatthew G. Knepley */
658736fa2b79SJed Brown PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal,PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[])
6588a6dfd86eSKarl Rupp {
6589e6ccafaeSMatthew G Knepley   PetscInt        dof;   /* The number of unknowns on this point */
6590552f7358SJed Brown   PetscInt        cdof;  /* The number of constraints on this point */
6591552f7358SJed Brown   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6592552f7358SJed Brown   PetscInt        cind = 0, k;
6593552f7358SJed Brown 
6594552f7358SJed Brown   PetscFunctionBegin;
659508401ef6SPierre Jolivet   PetscCheck(islocal || !setBC,PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC");
65969566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(section, point, &dof));
65979566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
6598552f7358SJed Brown   if (!cdof || setBC) {
659905586334SMatthew G. Knepley     for (k = 0; k < dof; ++k) {
660005586334SMatthew G. Knepley       const PetscInt preind = perm ? *loff+perm[k] : *loff+k;
660105586334SMatthew G. Knepley       const PetscInt ind    = indperm ? indperm[preind] : preind;
660205586334SMatthew G. Knepley 
660305586334SMatthew G. Knepley       indices[ind] = off + k;
6604552f7358SJed Brown     }
6605552f7358SJed Brown   } else {
66069566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
66074acb8e1eSToby Isaac     for (k = 0; k < dof; ++k) {
660805586334SMatthew G. Knepley       const PetscInt preind = perm ? *loff+perm[k] : *loff+k;
660905586334SMatthew G. Knepley       const PetscInt ind    = indperm ? indperm[preind] : preind;
661005586334SMatthew G. Knepley 
66114acb8e1eSToby Isaac       if ((cind < cdof) && (k == cdofs[cind])) {
66124acb8e1eSToby Isaac         /* Insert check for returning constrained indices */
661305586334SMatthew G. Knepley         indices[ind] = -(off+k+1);
66144acb8e1eSToby Isaac         ++cind;
66154acb8e1eSToby Isaac       } else {
661636fa2b79SJed Brown         indices[ind] = off + k - (islocal ? 0 : cind);
6617552f7358SJed Brown       }
6618552f7358SJed Brown     }
6619552f7358SJed Brown   }
6620e6ccafaeSMatthew G Knepley   *loff += dof;
6621552f7358SJed Brown   PetscFunctionReturn(0);
6622552f7358SJed Brown }
6623552f7358SJed Brown 
66247e29afd2SMatthew G. Knepley /*
662536fa2b79SJed Brown  DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering.
66267e29afd2SMatthew G. Knepley 
662736fa2b79SJed Brown  Input Parameters:
662836fa2b79SJed Brown + section - a section (global or local)
662936fa2b79SJed Brown - islocal - PETSC_TRUE if requesting local indices (i.e., section is local); PETSC_FALSE for global
663036fa2b79SJed Brown . point - point within section
663136fa2b79SJed Brown . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section
663236fa2b79SJed Brown . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field
663336fa2b79SJed Brown . setBC - identify constrained (boundary condition) points via involution.
663436fa2b79SJed Brown . perms - perms[f][permsoff][:] is a permutation of dofs within each field
663536fa2b79SJed Brown . permsoff - offset
663636fa2b79SJed Brown - indperm - index permutation
663736fa2b79SJed Brown 
663836fa2b79SJed Brown  Output Parameter:
663936fa2b79SJed Brown . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field
664036fa2b79SJed Brown . indices - array to hold indices (as defined by section) of each dof associated with point
664136fa2b79SJed Brown 
664236fa2b79SJed Brown  Notes:
664336fa2b79SJed Brown  If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs.
664436fa2b79SJed Brown  If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position
664536fa2b79SJed Brown  in the local vector.
664636fa2b79SJed Brown 
664736fa2b79SJed Brown  If section is global and setBC=false, the indices for constrained points are negative (and their value is not
664836fa2b79SJed Brown  significant).  It is invalid to call with a global section and setBC=true.
664936fa2b79SJed Brown 
665036fa2b79SJed Brown  Developer Note:
665136fa2b79SJed Brown  The section is only used for field layout, so islocal is technically a statement about the offset (off).  At some point
665236fa2b79SJed Brown  in the future, global sections may have fields set, in which case we could pass the global section and obtain the
665336fa2b79SJed Brown  offset could be obtained from the section instead of passing it explicitly as we do now.
665436fa2b79SJed Brown 
665536fa2b79SJed Brown  Example:
665636fa2b79SJed Brown  Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}.
665736fa2b79SJed Brown  When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE).
665836fa2b79SJed Brown  Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices.
665936fa2b79SJed 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.
666036fa2b79SJed Brown 
666136fa2b79SJed Brown  Level: developer
66627e29afd2SMatthew G. Knepley */
666336fa2b79SJed Brown PetscErrorCode DMPlexGetIndicesPointFields_Internal(PetscSection section, PetscBool islocal, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[])
6664a6dfd86eSKarl Rupp {
6665552f7358SJed Brown   PetscInt       numFields, foff, f;
6666552f7358SJed Brown 
6667552f7358SJed Brown   PetscFunctionBegin;
666808401ef6SPierre Jolivet   PetscCheck(islocal || !setBC,PetscObjectComm((PetscObject)section),PETSC_ERR_ARG_INCOMP,"setBC incompatible with global indices; use a local section or disable setBC");
66699566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
6670552f7358SJed Brown   for (f = 0, foff = 0; f < numFields; ++f) {
66714acb8e1eSToby Isaac     PetscInt        fdof, cfdof;
6672552f7358SJed Brown     const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
66734acb8e1eSToby Isaac     PetscInt        cind = 0, b;
66744acb8e1eSToby Isaac     const PetscInt  *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL;
6675552f7358SJed Brown 
66769566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
66779566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof));
6678552f7358SJed Brown     if (!cfdof || setBC) {
667905586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
668005586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b;
668105586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
668205586334SMatthew G. Knepley 
668305586334SMatthew G. Knepley         indices[ind] = off+foff+b;
668405586334SMatthew G. Knepley       }
6685552f7358SJed Brown     } else {
66869566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
668705586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
668805586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f]+perm[b] : foffs[f]+b;
668905586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
669005586334SMatthew G. Knepley 
66914acb8e1eSToby Isaac         if ((cind < cfdof) && (b == fcdofs[cind])) {
669205586334SMatthew G. Knepley           indices[ind] = -(off+foff+b+1);
6693552f7358SJed Brown           ++cind;
6694552f7358SJed Brown         } else {
669536fa2b79SJed Brown           indices[ind] = off + foff + b - (islocal ? 0 : cind);
6696552f7358SJed Brown         }
6697552f7358SJed Brown       }
6698552f7358SJed Brown     }
669936fa2b79SJed Brown     foff     += (setBC || islocal ? fdof : (fdof - cfdof));
6700552f7358SJed Brown     foffs[f] += fdof;
6701552f7358SJed Brown   }
6702552f7358SJed Brown   PetscFunctionReturn(0);
6703552f7358SJed Brown }
6704552f7358SJed Brown 
67057e29afd2SMatthew G. Knepley /*
67067e29afd2SMatthew G. Knepley   This version believes the globalSection offsets for each field, rather than just the point offset
67077e29afd2SMatthew G. Knepley 
67087e29afd2SMatthew G. Knepley  . foffs - The offset into 'indices' for each field, since it is segregated by field
6709645102dcSJed Brown 
6710645102dcSJed Brown  Notes:
6711645102dcSJed Brown  The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal.
6712645102dcSJed Brown  Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists.
67137e29afd2SMatthew G. Knepley */
6714645102dcSJed Brown static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[])
67157e29afd2SMatthew G. Knepley {
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 
67554acb8e1eSToby Isaac PetscErrorCode DMPlexAnchorsModifyMat(DM dm, PetscSection section, PetscInt numPoints, PetscInt numIndices, const PetscInt points[], const PetscInt ***perms, const PetscScalar values[], PetscInt *outNumPoints, PetscInt *outNumIndices, PetscInt *outPoints[], PetscScalar *outValues[], PetscInt offsets[], PetscBool multiplyLeft)
6756d3d1a6afSToby Isaac {
6757d3d1a6afSToby Isaac   Mat             cMat;
6758d3d1a6afSToby Isaac   PetscSection    aSec, cSec;
6759d3d1a6afSToby Isaac   IS              aIS;
6760d3d1a6afSToby Isaac   PetscInt        aStart = -1, aEnd = -1;
6761d3d1a6afSToby Isaac   const PetscInt  *anchors;
6762e17c06e0SMatthew G. Knepley   PetscInt        numFields, f, p, q, newP = 0;
6763d3d1a6afSToby Isaac   PetscInt        newNumPoints = 0, newNumIndices = 0;
6764d3d1a6afSToby Isaac   PetscInt        *newPoints, *indices, *newIndices;
6765d3d1a6afSToby Isaac   PetscInt        maxAnchor, maxDof;
6766d3d1a6afSToby Isaac   PetscInt        newOffsets[32];
6767d3d1a6afSToby Isaac   PetscInt        *pointMatOffsets[32];
6768d3d1a6afSToby Isaac   PetscInt        *newPointOffsets[32];
6769d3d1a6afSToby Isaac   PetscScalar     *pointMat[32];
67706ecaa68aSToby Isaac   PetscScalar     *newValues=NULL,*tmpValues;
6771d3d1a6afSToby Isaac   PetscBool       anyConstrained = PETSC_FALSE;
6772d3d1a6afSToby Isaac 
6773d3d1a6afSToby Isaac   PetscFunctionBegin;
6774d3d1a6afSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
6775d3d1a6afSToby Isaac   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
67769566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
6777d3d1a6afSToby Isaac 
67789566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm,&aSec,&aIS));
6779d3d1a6afSToby Isaac   /* if there are point-to-point constraints */
6780d3d1a6afSToby Isaac   if (aSec) {
67819566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(newOffsets, 32));
67829566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(aIS,&anchors));
67839566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(aSec,&aStart,&aEnd));
6784d3d1a6afSToby Isaac     /* figure out how many points are going to be in the new element matrix
6785d3d1a6afSToby Isaac      * (we allow double counting, because it's all just going to be summed
6786d3d1a6afSToby Isaac      * into the global matrix anyway) */
6787d3d1a6afSToby Isaac     for (p = 0; p < 2*numPoints; p+=2) {
6788d3d1a6afSToby Isaac       PetscInt b    = points[p];
67894b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
6790d3d1a6afSToby Isaac 
67919566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section,b,&bSecDof));
67924b2f2278SToby Isaac       if (!bSecDof) {
67934b2f2278SToby Isaac         continue;
67944b2f2278SToby Isaac       }
6795d3d1a6afSToby Isaac       if (b >= aStart && b < aEnd) {
67969566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(aSec,b,&bDof));
6797d3d1a6afSToby Isaac       }
6798d3d1a6afSToby Isaac       if (bDof) {
6799d3d1a6afSToby Isaac         /* this point is constrained */
6800d3d1a6afSToby Isaac         /* it is going to be replaced by its anchors */
6801d3d1a6afSToby Isaac         PetscInt bOff, q;
6802d3d1a6afSToby Isaac 
6803d3d1a6afSToby Isaac         anyConstrained = PETSC_TRUE;
6804d3d1a6afSToby Isaac         newNumPoints  += bDof;
68059566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec,b,&bOff));
6806d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
6807d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q];
6808d3d1a6afSToby Isaac           PetscInt aDof;
6809d3d1a6afSToby Isaac 
68109566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section,a,&aDof));
6811d3d1a6afSToby Isaac           newNumIndices += aDof;
6812d3d1a6afSToby Isaac           for (f = 0; f < numFields; ++f) {
6813d3d1a6afSToby Isaac             PetscInt fDof;
6814d3d1a6afSToby Isaac 
68159566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, a, f, &fDof));
6816d3d1a6afSToby Isaac             newOffsets[f+1] += fDof;
6817d3d1a6afSToby Isaac           }
6818d3d1a6afSToby Isaac         }
6819d3d1a6afSToby Isaac       }
6820d3d1a6afSToby Isaac       else {
6821d3d1a6afSToby Isaac         /* this point is not constrained */
6822d3d1a6afSToby Isaac         newNumPoints++;
68234b2f2278SToby Isaac         newNumIndices += bSecDof;
6824d3d1a6afSToby Isaac         for (f = 0; f < numFields; ++f) {
6825d3d1a6afSToby Isaac           PetscInt fDof;
6826d3d1a6afSToby Isaac 
68279566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
6828d3d1a6afSToby Isaac           newOffsets[f+1] += fDof;
6829d3d1a6afSToby Isaac         }
6830d3d1a6afSToby Isaac       }
6831d3d1a6afSToby Isaac     }
6832d3d1a6afSToby Isaac   }
6833d3d1a6afSToby Isaac   if (!anyConstrained) {
683472b80496SMatthew G. Knepley     if (outNumPoints)  *outNumPoints  = 0;
683572b80496SMatthew G. Knepley     if (outNumIndices) *outNumIndices = 0;
683672b80496SMatthew G. Knepley     if (outPoints)     *outPoints     = NULL;
683772b80496SMatthew G. Knepley     if (outValues)     *outValues     = NULL;
68389566063dSJacob Faibussowitsch     if (aSec) PetscCall(ISRestoreIndices(aIS,&anchors));
6839d3d1a6afSToby Isaac     PetscFunctionReturn(0);
6840d3d1a6afSToby Isaac   }
6841d3d1a6afSToby Isaac 
68426ecaa68aSToby Isaac   if (outNumPoints)  *outNumPoints  = newNumPoints;
68436ecaa68aSToby Isaac   if (outNumIndices) *outNumIndices = newNumIndices;
68446ecaa68aSToby Isaac 
6845f13f9184SToby Isaac   for (f = 0; f < numFields; ++f) newOffsets[f+1] += newOffsets[f];
6846d3d1a6afSToby Isaac 
68476ecaa68aSToby Isaac   if (!outPoints && !outValues) {
68486ecaa68aSToby Isaac     if (offsets) {
68496ecaa68aSToby Isaac       for (f = 0; f <= numFields; f++) {
68506ecaa68aSToby Isaac         offsets[f] = newOffsets[f];
68516ecaa68aSToby Isaac       }
68526ecaa68aSToby Isaac     }
68539566063dSJacob Faibussowitsch     if (aSec) PetscCall(ISRestoreIndices(aIS,&anchors));
68546ecaa68aSToby Isaac     PetscFunctionReturn(0);
68556ecaa68aSToby Isaac   }
68566ecaa68aSToby Isaac 
68571dca8a05SBarry 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);
6858d3d1a6afSToby Isaac 
68599566063dSJacob Faibussowitsch   PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, NULL));
6860d3d1a6afSToby Isaac 
6861d3d1a6afSToby Isaac   /* workspaces */
6862d3d1a6afSToby Isaac   if (numFields) {
6863d3d1a6afSToby Isaac     for (f = 0; f < numFields; f++) {
68649566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]));
68659566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]));
6866d3d1a6afSToby Isaac     }
6867d3d1a6afSToby Isaac   }
6868d3d1a6afSToby Isaac   else {
68699566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]));
68709566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm,numPoints,MPIU_INT,&newPointOffsets[0]));
6871d3d1a6afSToby Isaac   }
6872d3d1a6afSToby Isaac 
6873d3d1a6afSToby Isaac   /* get workspaces for the point-to-point matrices */
6874d3d1a6afSToby Isaac   if (numFields) {
68754b2f2278SToby Isaac     PetscInt totalOffset, totalMatOffset;
68764b2f2278SToby Isaac 
6877d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
6878d3d1a6afSToby Isaac       PetscInt b    = points[2*p];
68794b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
6880d3d1a6afSToby Isaac 
68819566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section,b,&bSecDof));
68824b2f2278SToby Isaac       if (!bSecDof) {
68834b2f2278SToby Isaac         for (f = 0; f < numFields; f++) {
68844b2f2278SToby Isaac           newPointOffsets[f][p + 1] = 0;
68854b2f2278SToby Isaac           pointMatOffsets[f][p + 1] = 0;
68864b2f2278SToby Isaac         }
68874b2f2278SToby Isaac         continue;
68884b2f2278SToby Isaac       }
6889d3d1a6afSToby Isaac       if (b >= aStart && b < aEnd) {
68909566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(aSec, b, &bDof));
6891d3d1a6afSToby Isaac       }
6892d3d1a6afSToby Isaac       if (bDof) {
6893d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
6894d3d1a6afSToby Isaac           PetscInt fDof, q, bOff, allFDof = 0;
6895d3d1a6afSToby Isaac 
68969566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
68979566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
6898d3d1a6afSToby Isaac           for (q = 0; q < bDof; q++) {
6899d3d1a6afSToby Isaac             PetscInt a = anchors[bOff + q];
6900d3d1a6afSToby Isaac             PetscInt aFDof;
6901d3d1a6afSToby Isaac 
69029566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, a, f, &aFDof));
6903d3d1a6afSToby Isaac             allFDof += aFDof;
6904d3d1a6afSToby Isaac           }
6905d3d1a6afSToby Isaac           newPointOffsets[f][p+1] = allFDof;
6906d3d1a6afSToby Isaac           pointMatOffsets[f][p+1] = fDof * allFDof;
6907d3d1a6afSToby Isaac         }
6908d3d1a6afSToby Isaac       }
6909d3d1a6afSToby Isaac       else {
6910d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
6911d3d1a6afSToby Isaac           PetscInt fDof;
6912d3d1a6afSToby Isaac 
69139566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
6914d3d1a6afSToby Isaac           newPointOffsets[f][p+1] = fDof;
6915d3d1a6afSToby Isaac           pointMatOffsets[f][p+1] = 0;
6916d3d1a6afSToby Isaac         }
6917d3d1a6afSToby Isaac       }
6918d3d1a6afSToby Isaac     }
69194b2f2278SToby Isaac     for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) {
69204b2f2278SToby Isaac       newPointOffsets[f][0] = totalOffset;
69214b2f2278SToby Isaac       pointMatOffsets[f][0] = totalMatOffset;
6922d3d1a6afSToby Isaac       for (p = 0; p < numPoints; p++) {
6923d3d1a6afSToby Isaac         newPointOffsets[f][p+1] += newPointOffsets[f][p];
6924d3d1a6afSToby Isaac         pointMatOffsets[f][p+1] += pointMatOffsets[f][p];
6925d3d1a6afSToby Isaac       }
692619f70fd5SToby Isaac       totalOffset    = newPointOffsets[f][numPoints];
692719f70fd5SToby Isaac       totalMatOffset = pointMatOffsets[f][numPoints];
69289566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]));
6929d3d1a6afSToby Isaac     }
6930d3d1a6afSToby Isaac   }
6931d3d1a6afSToby Isaac   else {
6932d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
6933d3d1a6afSToby Isaac       PetscInt b    = points[2*p];
69344b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
6935d3d1a6afSToby Isaac 
69369566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section,b,&bSecDof));
69374b2f2278SToby Isaac       if (!bSecDof) {
69384b2f2278SToby Isaac         newPointOffsets[0][p + 1] = 0;
69394b2f2278SToby Isaac         pointMatOffsets[0][p + 1] = 0;
69404b2f2278SToby Isaac         continue;
69414b2f2278SToby Isaac       }
6942d3d1a6afSToby Isaac       if (b >= aStart && b < aEnd) {
69439566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(aSec, b, &bDof));
6944d3d1a6afSToby Isaac       }
6945d3d1a6afSToby Isaac       if (bDof) {
69464b2f2278SToby Isaac         PetscInt bOff, q, allDof = 0;
6947d3d1a6afSToby Isaac 
69489566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
6949d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
6950d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aDof;
6951d3d1a6afSToby Isaac 
69529566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section, a, &aDof));
6953d3d1a6afSToby Isaac           allDof += aDof;
6954d3d1a6afSToby Isaac         }
6955d3d1a6afSToby Isaac         newPointOffsets[0][p+1] = allDof;
69564b2f2278SToby Isaac         pointMatOffsets[0][p+1] = bSecDof * allDof;
6957d3d1a6afSToby Isaac       }
6958d3d1a6afSToby Isaac       else {
69594b2f2278SToby Isaac         newPointOffsets[0][p+1] = bSecDof;
6960d3d1a6afSToby Isaac         pointMatOffsets[0][p+1] = 0;
6961d3d1a6afSToby Isaac       }
6962d3d1a6afSToby Isaac     }
6963d3d1a6afSToby Isaac     newPointOffsets[0][0] = 0;
6964d3d1a6afSToby Isaac     pointMatOffsets[0][0] = 0;
6965d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
6966d3d1a6afSToby Isaac       newPointOffsets[0][p+1] += newPointOffsets[0][p];
6967d3d1a6afSToby Isaac       pointMatOffsets[0][p+1] += pointMatOffsets[0][p];
6968d3d1a6afSToby Isaac     }
69699566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]));
6970d3d1a6afSToby Isaac   }
6971d3d1a6afSToby Isaac 
69726ecaa68aSToby Isaac   /* output arrays */
69739566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints));
69746ecaa68aSToby Isaac 
6975d3d1a6afSToby Isaac   /* get the point-to-point matrices; construct newPoints */
69769566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetMaxDof(aSec, &maxAnchor));
69779566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetMaxDof(section, &maxDof));
69789566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm,maxDof,MPIU_INT,&indices));
69799566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices));
6980d3d1a6afSToby Isaac   if (numFields) {
6981d3d1a6afSToby Isaac     for (p = 0, newP = 0; p < numPoints; p++) {
6982d3d1a6afSToby Isaac       PetscInt b    = points[2*p];
6983d3d1a6afSToby Isaac       PetscInt o    = points[2*p+1];
69844b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
6985d3d1a6afSToby Isaac 
69869566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
69874b2f2278SToby Isaac       if (!bSecDof) {
69884b2f2278SToby Isaac         continue;
69894b2f2278SToby Isaac       }
6990d3d1a6afSToby Isaac       if (b >= aStart && b < aEnd) {
69919566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(aSec, b, &bDof));
6992d3d1a6afSToby Isaac       }
6993d3d1a6afSToby Isaac       if (bDof) {
6994d3d1a6afSToby Isaac         PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q;
6995d3d1a6afSToby Isaac 
6996d3d1a6afSToby Isaac         fStart[0] = 0;
6997d3d1a6afSToby Isaac         fEnd[0]   = 0;
6998d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
6999d3d1a6afSToby Isaac           PetscInt fDof;
7000d3d1a6afSToby Isaac 
70019566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(cSec, b, f, &fDof));
7002d3d1a6afSToby Isaac           fStart[f+1] = fStart[f] + fDof;
7003d3d1a6afSToby Isaac           fEnd[f+1]   = fStart[f+1];
7004d3d1a6afSToby Isaac         }
70059566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(cSec, b, &bOff));
70069566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices));
7007d3d1a6afSToby Isaac 
7008d3d1a6afSToby Isaac         fAnchorStart[0] = 0;
7009d3d1a6afSToby Isaac         fAnchorEnd[0]   = 0;
7010d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7011d3d1a6afSToby Isaac           PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p];
7012d3d1a6afSToby Isaac 
7013d3d1a6afSToby Isaac           fAnchorStart[f+1] = fAnchorStart[f] + fDof;
7014d3d1a6afSToby Isaac           fAnchorEnd[f+1]   = fAnchorStart[f + 1];
7015d3d1a6afSToby Isaac         }
70169566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7017d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7018d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aOff;
7019d3d1a6afSToby Isaac 
7020d3d1a6afSToby 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 */
7021d3d1a6afSToby Isaac           newPoints[2*(newP + q)]     = a;
7022d3d1a6afSToby Isaac           newPoints[2*(newP + q) + 1] = 0;
70239566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(section, a, &aOff));
70249566063dSJacob Faibussowitsch           PetscCall(DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices));
7025d3d1a6afSToby Isaac         }
7026d3d1a6afSToby Isaac         newP += bDof;
7027d3d1a6afSToby Isaac 
70286ecaa68aSToby Isaac         if (outValues) {
7029d3d1a6afSToby Isaac           /* get the point-to-point submatrix */
7030d3d1a6afSToby Isaac           for (f = 0; f < numFields; f++) {
70319566063dSJacob Faibussowitsch             PetscCall(MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p]));
7032d3d1a6afSToby Isaac           }
7033d3d1a6afSToby Isaac         }
70346ecaa68aSToby Isaac       }
7035d3d1a6afSToby Isaac       else {
7036d3d1a6afSToby Isaac         newPoints[2 * newP]     = b;
7037d3d1a6afSToby Isaac         newPoints[2 * newP + 1] = o;
7038d3d1a6afSToby Isaac         newP++;
7039d3d1a6afSToby Isaac       }
7040d3d1a6afSToby Isaac     }
7041d3d1a6afSToby Isaac   } else {
7042d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
7043d3d1a6afSToby Isaac       PetscInt b    = points[2*p];
7044d3d1a6afSToby Isaac       PetscInt o    = points[2*p+1];
70454b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7046d3d1a6afSToby Isaac 
70479566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
70484b2f2278SToby Isaac       if (!bSecDof) {
70494b2f2278SToby Isaac         continue;
70504b2f2278SToby Isaac       }
7051d3d1a6afSToby Isaac       if (b >= aStart && b < aEnd) {
70529566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7053d3d1a6afSToby Isaac       }
7054d3d1a6afSToby Isaac       if (bDof) {
7055d3d1a6afSToby Isaac         PetscInt bEnd = 0, bAnchorEnd = 0, bOff;
7056d3d1a6afSToby Isaac 
70579566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(cSec, b, &bOff));
70589566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices));
7059d3d1a6afSToby Isaac 
70609566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset (aSec, b, &bOff));
7061d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7062d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aOff;
7063d3d1a6afSToby Isaac 
7064d3d1a6afSToby 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 */
7065d3d1a6afSToby Isaac 
7066d3d1a6afSToby Isaac           newPoints[2*(newP + q)]     = a;
7067d3d1a6afSToby Isaac           newPoints[2*(newP + q) + 1] = 0;
70689566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(section, a, &aOff));
70699566063dSJacob Faibussowitsch           PetscCall(DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices));
7070d3d1a6afSToby Isaac         }
7071d3d1a6afSToby Isaac         newP += bDof;
7072d3d1a6afSToby Isaac 
7073d3d1a6afSToby Isaac         /* get the point-to-point submatrix */
70746ecaa68aSToby Isaac         if (outValues) {
70759566063dSJacob Faibussowitsch           PetscCall(MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p]));
7076d3d1a6afSToby Isaac         }
70776ecaa68aSToby Isaac       }
7078d3d1a6afSToby Isaac       else {
7079d3d1a6afSToby Isaac         newPoints[2 * newP]     = b;
7080d3d1a6afSToby Isaac         newPoints[2 * newP + 1] = o;
7081d3d1a6afSToby Isaac         newP++;
7082d3d1a6afSToby Isaac       }
7083d3d1a6afSToby Isaac     }
7084d3d1a6afSToby Isaac   }
7085d3d1a6afSToby Isaac 
70866ecaa68aSToby Isaac   if (outValues) {
70879566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues));
70889566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(tmpValues,newNumIndices*numIndices));
7089d3d1a6afSToby Isaac     /* multiply constraints on the right */
7090d3d1a6afSToby Isaac     if (numFields) {
7091d3d1a6afSToby Isaac       for (f = 0; f < numFields; f++) {
7092d3d1a6afSToby Isaac         PetscInt oldOff = offsets[f];
7093d3d1a6afSToby Isaac 
7094d3d1a6afSToby Isaac         for (p = 0; p < numPoints; p++) {
7095d3d1a6afSToby Isaac           PetscInt cStart = newPointOffsets[f][p];
7096d3d1a6afSToby Isaac           PetscInt b      = points[2 * p];
7097d3d1a6afSToby Isaac           PetscInt c, r, k;
7098d3d1a6afSToby Isaac           PetscInt dof;
7099d3d1a6afSToby Isaac 
71009566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section,b,f,&dof));
71014b2f2278SToby Isaac           if (!dof) {
71024b2f2278SToby Isaac             continue;
71034b2f2278SToby Isaac           }
7104d3d1a6afSToby Isaac           if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) {
7105d3d1a6afSToby Isaac             PetscInt nCols         = newPointOffsets[f][p+1]-cStart;
7106d3d1a6afSToby Isaac             const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p];
7107d3d1a6afSToby Isaac 
7108d3d1a6afSToby Isaac             for (r = 0; r < numIndices; r++) {
7109d3d1a6afSToby Isaac               for (c = 0; c < nCols; c++) {
7110d3d1a6afSToby Isaac                 for (k = 0; k < dof; k++) {
71114acb8e1eSToby Isaac                   tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c];
7112d3d1a6afSToby Isaac                 }
7113d3d1a6afSToby Isaac               }
7114d3d1a6afSToby Isaac             }
7115d3d1a6afSToby Isaac           }
7116d3d1a6afSToby Isaac           else {
7117d3d1a6afSToby Isaac             /* copy this column as is */
7118d3d1a6afSToby Isaac             for (r = 0; r < numIndices; r++) {
7119d3d1a6afSToby Isaac               for (c = 0; c < dof; c++) {
7120d3d1a6afSToby Isaac                 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c];
7121d3d1a6afSToby Isaac               }
7122d3d1a6afSToby Isaac             }
7123d3d1a6afSToby Isaac           }
7124d3d1a6afSToby Isaac           oldOff += dof;
7125d3d1a6afSToby Isaac         }
7126d3d1a6afSToby Isaac       }
7127d3d1a6afSToby Isaac     }
7128d3d1a6afSToby Isaac     else {
7129d3d1a6afSToby Isaac       PetscInt oldOff = 0;
7130d3d1a6afSToby Isaac       for (p = 0; p < numPoints; p++) {
7131d3d1a6afSToby Isaac         PetscInt cStart = newPointOffsets[0][p];
7132d3d1a6afSToby Isaac         PetscInt b      = points[2 * p];
7133d3d1a6afSToby Isaac         PetscInt c, r, k;
7134d3d1a6afSToby Isaac         PetscInt dof;
7135d3d1a6afSToby Isaac 
71369566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section,b,&dof));
71374b2f2278SToby Isaac         if (!dof) {
71384b2f2278SToby Isaac           continue;
71394b2f2278SToby Isaac         }
7140d3d1a6afSToby Isaac         if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) {
7141d3d1a6afSToby Isaac           PetscInt nCols         = newPointOffsets[0][p+1]-cStart;
7142d3d1a6afSToby Isaac           const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p];
7143d3d1a6afSToby Isaac 
7144d3d1a6afSToby Isaac           for (r = 0; r < numIndices; r++) {
7145d3d1a6afSToby Isaac             for (c = 0; c < nCols; c++) {
7146d3d1a6afSToby Isaac               for (k = 0; k < dof; k++) {
7147d3d1a6afSToby Isaac                 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k];
7148d3d1a6afSToby Isaac               }
7149d3d1a6afSToby Isaac             }
7150d3d1a6afSToby Isaac           }
7151d3d1a6afSToby Isaac         }
7152d3d1a6afSToby Isaac         else {
7153d3d1a6afSToby Isaac           /* copy this column as is */
7154d3d1a6afSToby Isaac           for (r = 0; r < numIndices; r++) {
7155d3d1a6afSToby Isaac             for (c = 0; c < dof; c++) {
7156d3d1a6afSToby Isaac               tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c];
7157d3d1a6afSToby Isaac             }
7158d3d1a6afSToby Isaac           }
7159d3d1a6afSToby Isaac         }
7160d3d1a6afSToby Isaac         oldOff += dof;
7161d3d1a6afSToby Isaac       }
7162d3d1a6afSToby Isaac     }
7163d3d1a6afSToby Isaac 
71646ecaa68aSToby Isaac     if (multiplyLeft) {
71659566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm,newNumIndices*newNumIndices,MPIU_SCALAR,&newValues));
71669566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(newValues,newNumIndices*newNumIndices));
7167d3d1a6afSToby Isaac       /* multiply constraints transpose on the left */
7168d3d1a6afSToby Isaac       if (numFields) {
7169d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7170d3d1a6afSToby Isaac           PetscInt oldOff = offsets[f];
7171d3d1a6afSToby Isaac 
7172d3d1a6afSToby Isaac           for (p = 0; p < numPoints; p++) {
7173d3d1a6afSToby Isaac             PetscInt rStart = newPointOffsets[f][p];
7174d3d1a6afSToby Isaac             PetscInt b      = points[2 * p];
7175d3d1a6afSToby Isaac             PetscInt c, r, k;
7176d3d1a6afSToby Isaac             PetscInt dof;
7177d3d1a6afSToby Isaac 
71789566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section,b,f,&dof));
7179d3d1a6afSToby Isaac             if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) {
7180d3d1a6afSToby Isaac               PetscInt nRows                        = newPointOffsets[f][p+1]-rStart;
7181d3d1a6afSToby Isaac               const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p];
7182d3d1a6afSToby Isaac 
7183d3d1a6afSToby Isaac               for (r = 0; r < nRows; r++) {
7184d3d1a6afSToby Isaac                 for (c = 0; c < newNumIndices; c++) {
7185d3d1a6afSToby Isaac                   for (k = 0; k < dof; k++) {
7186d3d1a6afSToby Isaac                     newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c];
7187d3d1a6afSToby Isaac                   }
7188d3d1a6afSToby Isaac                 }
7189d3d1a6afSToby Isaac               }
7190d3d1a6afSToby Isaac             }
7191d3d1a6afSToby Isaac             else {
7192d3d1a6afSToby Isaac               /* copy this row as is */
7193d3d1a6afSToby Isaac               for (r = 0; r < dof; r++) {
7194d3d1a6afSToby Isaac                 for (c = 0; c < newNumIndices; c++) {
7195d3d1a6afSToby Isaac                   newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c];
7196d3d1a6afSToby Isaac                 }
7197d3d1a6afSToby Isaac               }
7198d3d1a6afSToby Isaac             }
7199d3d1a6afSToby Isaac             oldOff += dof;
7200d3d1a6afSToby Isaac           }
7201d3d1a6afSToby Isaac         }
7202d3d1a6afSToby Isaac       }
7203d3d1a6afSToby Isaac       else {
7204d3d1a6afSToby Isaac         PetscInt oldOff = 0;
7205d3d1a6afSToby Isaac 
7206d3d1a6afSToby Isaac         for (p = 0; p < numPoints; p++) {
7207d3d1a6afSToby Isaac           PetscInt rStart = newPointOffsets[0][p];
7208d3d1a6afSToby Isaac           PetscInt b      = points[2 * p];
7209d3d1a6afSToby Isaac           PetscInt c, r, k;
7210d3d1a6afSToby Isaac           PetscInt dof;
7211d3d1a6afSToby Isaac 
72129566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section,b,&dof));
7213d3d1a6afSToby Isaac           if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) {
7214d3d1a6afSToby Isaac             PetscInt nRows                        = newPointOffsets[0][p+1]-rStart;
7215d3d1a6afSToby Isaac             const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p];
7216d3d1a6afSToby Isaac 
7217d3d1a6afSToby Isaac             for (r = 0; r < nRows; r++) {
7218d3d1a6afSToby Isaac               for (c = 0; c < newNumIndices; c++) {
7219d3d1a6afSToby Isaac                 for (k = 0; k < dof; k++) {
7220d3d1a6afSToby Isaac                   newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c];
7221d3d1a6afSToby Isaac                 }
7222d3d1a6afSToby Isaac               }
7223d3d1a6afSToby Isaac             }
7224d3d1a6afSToby Isaac           }
7225d3d1a6afSToby Isaac           else {
7226d3d1a6afSToby Isaac             /* copy this row as is */
72279fc93327SToby Isaac             for (r = 0; r < dof; r++) {
7228d3d1a6afSToby Isaac               for (c = 0; c < newNumIndices; c++) {
7229d3d1a6afSToby Isaac                 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c];
7230d3d1a6afSToby Isaac               }
7231d3d1a6afSToby Isaac             }
7232d3d1a6afSToby Isaac           }
7233d3d1a6afSToby Isaac           oldOff += dof;
7234d3d1a6afSToby Isaac         }
7235d3d1a6afSToby Isaac       }
7236d3d1a6afSToby Isaac 
72379566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm,newNumIndices*numIndices,MPIU_SCALAR,&tmpValues));
72386ecaa68aSToby Isaac     }
72396ecaa68aSToby Isaac     else {
72406ecaa68aSToby Isaac       newValues = tmpValues;
72416ecaa68aSToby Isaac     }
72426ecaa68aSToby Isaac   }
72436ecaa68aSToby Isaac 
7244d3d1a6afSToby Isaac   /* clean up */
72459566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm,maxDof,MPIU_INT,&indices));
72469566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm,maxAnchor*maxDof,MPIU_INT,&newIndices));
72476ecaa68aSToby Isaac 
7248d3d1a6afSToby Isaac   if (numFields) {
7249d3d1a6afSToby Isaac     for (f = 0; f < numFields; f++) {
72509566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],MPIU_SCALAR,&pointMat[f]));
72519566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[f]));
72529566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[f]));
7253d3d1a6afSToby Isaac     }
7254d3d1a6afSToby Isaac   }
7255d3d1a6afSToby Isaac   else {
72569566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],MPIU_SCALAR,&pointMat[0]));
72579566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&pointMatOffsets[0]));
72589566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm,numPoints+1,MPIU_INT,&newPointOffsets[0]));
7259d3d1a6afSToby Isaac   }
72609566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(aIS,&anchors));
7261d3d1a6afSToby Isaac 
7262d3d1a6afSToby Isaac   /* output */
72636ecaa68aSToby Isaac   if (outPoints) {
7264d3d1a6afSToby Isaac     *outPoints = newPoints;
72656ecaa68aSToby Isaac   }
72666ecaa68aSToby Isaac   else {
72679566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm,2*newNumPoints,MPIU_INT,&newPoints));
72686ecaa68aSToby Isaac   }
726931620726SToby Isaac   if (outValues) {
7270d3d1a6afSToby Isaac     *outValues = newValues;
72716ecaa68aSToby Isaac   }
72726ecaa68aSToby Isaac   for (f = 0; f <= numFields; f++) {
7273d3d1a6afSToby Isaac     offsets[f] = newOffsets[f];
7274d3d1a6afSToby Isaac   }
7275d3d1a6afSToby Isaac   PetscFunctionReturn(0);
7276d3d1a6afSToby Isaac }
7277d3d1a6afSToby Isaac 
72784a1e0b3eSMatthew G. Knepley /*@C
727971f0bbf9SMatthew G. Knepley   DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections.
72807cd05799SMatthew G. Knepley 
72817cd05799SMatthew G. Knepley   Not collective
72827cd05799SMatthew G. Knepley 
72837cd05799SMatthew G. Knepley   Input Parameters:
72847cd05799SMatthew G. Knepley + dm         - The DM
728571f0bbf9SMatthew G. Knepley . section    - The PetscSection describing the points (a local section)
728671f0bbf9SMatthew G. Knepley . idxSection - The PetscSection from which to obtain indices (may be local or global)
728771f0bbf9SMatthew G. Knepley . point      - The point defining the closure
728871f0bbf9SMatthew G. Knepley - useClPerm  - Use the closure point permutation if available
72897cd05799SMatthew G. Knepley 
729071f0bbf9SMatthew G. Knepley   Output Parameters:
729171f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections
729271f0bbf9SMatthew G. Knepley . indices    - The dof indices
729371f0bbf9SMatthew G. Knepley . outOffsets - Array to write the field offsets into, or NULL
729471f0bbf9SMatthew G. Knepley - values     - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL
72957cd05799SMatthew G. Knepley 
729636fa2b79SJed Brown   Notes:
729736fa2b79SJed Brown   Must call DMPlexRestoreClosureIndices() to free allocated memory
729836fa2b79SJed Brown 
729936fa2b79SJed Brown   If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices.  The value
730036fa2b79SJed Brown   of those indices is not significant.  If idxSection is local, the constrained dofs will yield the involution -(idx+1)
730136fa2b79SJed Brown   of their index in a local vector.  A caller who does not wish to distinguish those points may recover the nonnegative
730236fa2b79SJed Brown   indices via involution, -(-(idx+1)+1)==idx.  Local indices are provided when idxSection == section, otherwise global
730336fa2b79SJed Brown   indices (with the above semantics) are implied.
73047cd05799SMatthew G. Knepley 
73057cd05799SMatthew G. Knepley   Level: advanced
73067cd05799SMatthew G. Knepley 
7307db781477SPatrick Sanan .seealso `DMPlexRestoreClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()`
73084a1e0b3eSMatthew G. Knepley @*/
730971f0bbf9SMatthew G. Knepley PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm,
731071f0bbf9SMatthew G. Knepley                                        PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[])
73117773e69fSMatthew G. Knepley {
731271f0bbf9SMatthew G. Knepley   /* Closure ordering */
73137773e69fSMatthew G. Knepley   PetscSection        clSection;
73147773e69fSMatthew G. Knepley   IS                  clPoints;
731571f0bbf9SMatthew G. Knepley   const PetscInt     *clp;
731671f0bbf9SMatthew G. Knepley   PetscInt           *points;
731771f0bbf9SMatthew G. Knepley   const PetscInt     *clperm = NULL;
731871f0bbf9SMatthew G. Knepley   /* Dof permutation and sign flips */
73194acb8e1eSToby Isaac   const PetscInt    **perms[32] = {NULL};
732071f0bbf9SMatthew G. Knepley   const PetscScalar **flips[32] = {NULL};
732171f0bbf9SMatthew G. Knepley   PetscScalar        *valCopy   = NULL;
732271f0bbf9SMatthew G. Knepley   /* Hanging node constraints */
732371f0bbf9SMatthew G. Knepley   PetscInt           *pointsC = NULL;
732471f0bbf9SMatthew G. Knepley   PetscScalar        *valuesC = NULL;
732571f0bbf9SMatthew G. Knepley   PetscInt            NclC, NiC;
732671f0bbf9SMatthew G. Knepley 
732771f0bbf9SMatthew G. Knepley   PetscInt           *idx;
732871f0bbf9SMatthew G. Knepley   PetscInt            Nf, Ncl, Ni = 0, offsets[32], p, f;
732971f0bbf9SMatthew G. Knepley   PetscBool           isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE;
73307773e69fSMatthew G. Knepley 
733171f0bbf9SMatthew G. Knepley   PetscFunctionBeginHot;
73327773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
73337773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
733436fa2b79SJed Brown   PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3);
7335dadcf809SJacob Faibussowitsch   if (numIndices) PetscValidIntPointer(numIndices, 6);
733671f0bbf9SMatthew G. Knepley   if (indices)    PetscValidPointer(indices, 7);
7337dadcf809SJacob Faibussowitsch   if (outOffsets) PetscValidIntPointer(outOffsets, 8);
733871f0bbf9SMatthew G. Knepley   if (values)     PetscValidPointer(values, 9);
73399566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &Nf));
734063a3b9bcSJacob Faibussowitsch   PetscCheck(Nf <= 31,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", Nf);
73419566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(offsets, 32));
734271f0bbf9SMatthew G. Knepley   /* 1) Get points in closure */
73439566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
7344c459fbc1SJed Brown   if (useClPerm) {
7345c459fbc1SJed Brown     PetscInt depth, clsize;
73469566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPointDepth(dm, point, &depth));
7347c459fbc1SJed Brown     for (clsize=0,p=0; p<Ncl; p++) {
7348c459fbc1SJed Brown       PetscInt dof;
73499566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, points[2*p], &dof));
7350c459fbc1SJed Brown       clsize += dof;
7351c459fbc1SJed Brown     }
73529566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject) dm, depth, clsize, &clperm));
7353c459fbc1SJed Brown   }
735471f0bbf9SMatthew G. Knepley   /* 2) Get number of indices on these points and field offsets from section */
735571f0bbf9SMatthew G. Knepley   for (p = 0; p < Ncl*2; p += 2) {
73567773e69fSMatthew G. Knepley     PetscInt dof, fdof;
73577773e69fSMatthew G. Knepley 
73589566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[p], &dof));
73597773e69fSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
73609566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof));
73617773e69fSMatthew G. Knepley       offsets[f+1] += fdof;
73627773e69fSMatthew G. Knepley     }
736371f0bbf9SMatthew G. Knepley     Ni += dof;
73647773e69fSMatthew G. Knepley   }
73657773e69fSMatthew G. Knepley   for (f = 1; f < Nf; ++f) offsets[f+1] += offsets[f];
73661dca8a05SBarry 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);
736771f0bbf9SMatthew G. Knepley   /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */
736871f0bbf9SMatthew G. Knepley   for (f = 0; f < PetscMax(1, Nf); ++f) {
73699566063dSJacob Faibussowitsch     if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
73709566063dSJacob Faibussowitsch     else    PetscCall(PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f]));
737171f0bbf9SMatthew G. Knepley     /* may need to apply sign changes to the element matrix */
737271f0bbf9SMatthew G. Knepley     if (values && flips[f]) {
737371f0bbf9SMatthew G. Knepley       PetscInt foffset = offsets[f];
73746ecaa68aSToby Isaac 
737571f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
737671f0bbf9SMatthew G. Knepley         PetscInt           pnt  = points[2*p], fdof;
737771f0bbf9SMatthew G. Knepley         const PetscScalar *flip = flips[f] ? flips[f][p] : NULL;
737871f0bbf9SMatthew G. Knepley 
73799566063dSJacob Faibussowitsch         if (!Nf) PetscCall(PetscSectionGetDof(section, pnt, &fdof));
73809566063dSJacob Faibussowitsch         else     PetscCall(PetscSectionGetFieldDof(section, pnt, f, &fdof));
738171f0bbf9SMatthew G. Knepley         if (flip) {
738271f0bbf9SMatthew G. Knepley           PetscInt i, j, k;
738371f0bbf9SMatthew G. Knepley 
738471f0bbf9SMatthew G. Knepley           if (!valCopy) {
73859566063dSJacob Faibussowitsch             PetscCall(DMGetWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy));
738671f0bbf9SMatthew G. Knepley             for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j];
738771f0bbf9SMatthew G. Knepley             *values = valCopy;
738871f0bbf9SMatthew G. Knepley           }
738971f0bbf9SMatthew G. Knepley           for (i = 0; i < fdof; ++i) {
739071f0bbf9SMatthew G. Knepley             PetscScalar fval = flip[i];
739171f0bbf9SMatthew G. Knepley 
739271f0bbf9SMatthew G. Knepley             for (k = 0; k < Ni; ++k) {
739371f0bbf9SMatthew G. Knepley               valCopy[Ni * (foffset + i) + k] *= fval;
739471f0bbf9SMatthew G. Knepley               valCopy[Ni * k + (foffset + i)] *= fval;
73956ecaa68aSToby Isaac             }
73966ecaa68aSToby Isaac           }
739771f0bbf9SMatthew G. Knepley         }
739871f0bbf9SMatthew G. Knepley         foffset += fdof;
739971f0bbf9SMatthew G. Knepley       }
740071f0bbf9SMatthew G. Knepley     }
740171f0bbf9SMatthew G. Knepley   }
740271f0bbf9SMatthew G. Knepley   /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */
74039566063dSJacob Faibussowitsch   PetscCall(DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE));
740471f0bbf9SMatthew G. Knepley   if (NclC) {
74059566063dSJacob Faibussowitsch     if (valCopy) PetscCall(DMRestoreWorkArray(dm, Ni*Ni, MPIU_SCALAR, &valCopy));
740671f0bbf9SMatthew G. Knepley     for (f = 0; f < PetscMax(1, Nf); ++f) {
74079566063dSJacob Faibussowitsch       if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
74089566063dSJacob Faibussowitsch       else    PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]));
740971f0bbf9SMatthew G. Knepley     }
741071f0bbf9SMatthew G. Knepley     for (f = 0; f < PetscMax(1, Nf); ++f) {
74119566063dSJacob Faibussowitsch       if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f]));
74129566063dSJacob Faibussowitsch       else    PetscCall(PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f]));
741371f0bbf9SMatthew G. Knepley     }
74149566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
741571f0bbf9SMatthew G. Knepley     Ncl     = NclC;
741671f0bbf9SMatthew G. Knepley     Ni      = NiC;
741771f0bbf9SMatthew G. Knepley     points  = pointsC;
741871f0bbf9SMatthew G. Knepley     if (values) *values = valuesC;
741971f0bbf9SMatthew G. Knepley   }
742071f0bbf9SMatthew G. Knepley   /* 5) Calculate indices */
74219566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, Ni, MPIU_INT, &idx));
742271f0bbf9SMatthew G. Knepley   if (Nf) {
742371f0bbf9SMatthew G. Knepley     PetscInt  idxOff;
742471f0bbf9SMatthew G. Knepley     PetscBool useFieldOffsets;
742571f0bbf9SMatthew G. Knepley 
742671f0bbf9SMatthew G. Knepley     if (outOffsets) {for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f];}
74279566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets));
742871f0bbf9SMatthew G. Knepley     if (useFieldOffsets) {
742971f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
743071f0bbf9SMatthew G. Knepley         const PetscInt pnt = points[p*2];
743171f0bbf9SMatthew G. Knepley 
74329566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx));
74337773e69fSMatthew G. Knepley       }
74347773e69fSMatthew G. Knepley     } else {
743571f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
743671f0bbf9SMatthew G. Knepley         const PetscInt pnt = points[p*2];
743771f0bbf9SMatthew G. Knepley 
74389566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff));
743971f0bbf9SMatthew G. Knepley         /* Note that we pass a local section even though we're using global offsets.  This is because global sections do
744071f0bbf9SMatthew G. Knepley          * not (at the time of this writing) have fields set. They probably should, in which case we would pass the
744171f0bbf9SMatthew G. Knepley          * global section. */
74429566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx));
744371f0bbf9SMatthew G. Knepley       }
744471f0bbf9SMatthew G. Knepley     }
744571f0bbf9SMatthew G. Knepley   } else {
744671f0bbf9SMatthew G. Knepley     PetscInt off = 0, idxOff;
744771f0bbf9SMatthew G. Knepley 
744871f0bbf9SMatthew G. Knepley     for (p = 0; p < Ncl; ++p) {
744971f0bbf9SMatthew G. Knepley       const PetscInt  pnt  = points[p*2];
74504acb8e1eSToby Isaac       const PetscInt *perm = perms[0] ? perms[0][p] : NULL;
74514acb8e1eSToby Isaac 
74529566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff));
745371f0bbf9SMatthew G. Knepley       /* Note that we pass a local section even though we're using global offsets.  This is because global sections do
745471f0bbf9SMatthew G. Knepley        * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */
74559566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff+1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx));
74567773e69fSMatthew G. Knepley     }
74577773e69fSMatthew G. Knepley   }
745871f0bbf9SMatthew G. Knepley   /* 6) Cleanup */
745971f0bbf9SMatthew G. Knepley   for (f = 0; f < PetscMax(1, Nf); ++f) {
74609566063dSJacob Faibussowitsch     if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
74619566063dSJacob Faibussowitsch     else    PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]));
74624acb8e1eSToby Isaac   }
746371f0bbf9SMatthew G. Knepley   if (NclC) {
74649566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, NclC*2, MPIU_INT, &pointsC));
74657773e69fSMatthew G. Knepley   } else {
74669566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
74677773e69fSMatthew G. Knepley   }
746871f0bbf9SMatthew G. Knepley 
746971f0bbf9SMatthew G. Knepley   if (numIndices) *numIndices = Ni;
747071f0bbf9SMatthew G. Knepley   if (indices)    *indices    = idx;
74717773e69fSMatthew G. Knepley   PetscFunctionReturn(0);
74727773e69fSMatthew G. Knepley }
74737773e69fSMatthew G. Knepley 
74747cd05799SMatthew G. Knepley /*@C
747571f0bbf9SMatthew G. Knepley   DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections.
74767cd05799SMatthew G. Knepley 
74777cd05799SMatthew G. Knepley   Not collective
74787cd05799SMatthew G. Knepley 
74797cd05799SMatthew G. Knepley   Input Parameters:
74807cd05799SMatthew G. Knepley + dm         - The DM
748171f0bbf9SMatthew G. Knepley . section    - The PetscSection describing the points (a local section)
748271f0bbf9SMatthew G. Knepley . idxSection - The PetscSection from which to obtain indices (may be local or global)
748371f0bbf9SMatthew G. Knepley . point      - The point defining the closure
748471f0bbf9SMatthew G. Knepley - useClPerm  - Use the closure point permutation if available
748571f0bbf9SMatthew G. Knepley 
748671f0bbf9SMatthew G. Knepley   Output Parameters:
748771f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections
748871f0bbf9SMatthew G. Knepley . indices    - The dof indices
748971f0bbf9SMatthew G. Knepley . outOffsets - Array to write the field offsets into, or NULL
749071f0bbf9SMatthew G. Knepley - values     - The input values, which may be modified if sign flips are induced by the point symmetries, or NULL
749171f0bbf9SMatthew G. Knepley 
749271f0bbf9SMatthew G. Knepley   Notes:
749371f0bbf9SMatthew G. Knepley   If values were modified, the user is responsible for calling DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values).
749471f0bbf9SMatthew G. Knepley 
749571f0bbf9SMatthew G. Knepley   If idxSection is global, any constrained dofs (see DMAddBoundary(), for example) will get negative indices.  The value
749671f0bbf9SMatthew G. Knepley   of those indices is not significant.  If idxSection is local, the constrained dofs will yield the involution -(idx+1)
749771f0bbf9SMatthew G. Knepley   of their index in a local vector.  A caller who does not wish to distinguish those points may recover the nonnegative
749871f0bbf9SMatthew G. Knepley   indices via involution, -(-(idx+1)+1)==idx.  Local indices are provided when idxSection == section, otherwise global
749971f0bbf9SMatthew G. Knepley   indices (with the above semantics) are implied.
75007cd05799SMatthew G. Knepley 
75017cd05799SMatthew G. Knepley   Level: advanced
75027cd05799SMatthew G. Knepley 
7503db781477SPatrick Sanan .seealso `DMPlexGetClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()`
75047cd05799SMatthew G. Knepley @*/
750571f0bbf9SMatthew G. Knepley PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm,
750671f0bbf9SMatthew G. Knepley                                            PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[])
75077773e69fSMatthew G. Knepley {
75087773e69fSMatthew G. Knepley   PetscFunctionBegin;
75097773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7510064a246eSJacob Faibussowitsch   PetscValidPointer(indices, 7);
75119566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, indices));
75127773e69fSMatthew G. Knepley   PetscFunctionReturn(0);
75137773e69fSMatthew G. Knepley }
75147773e69fSMatthew G. Knepley 
75157f5d1fdeSMatthew G. Knepley /*@C
75167f5d1fdeSMatthew G. Knepley   DMPlexMatSetClosure - Set an array of the values on the closure of 'point'
75177f5d1fdeSMatthew G. Knepley 
75187f5d1fdeSMatthew G. Knepley   Not collective
75197f5d1fdeSMatthew G. Knepley 
75207f5d1fdeSMatthew G. Knepley   Input Parameters:
75217f5d1fdeSMatthew G. Knepley + dm - The DM
7522ebd6d717SJed Brown . section - The section describing the layout in v, or NULL to use the default section
7523ebd6d717SJed Brown . globalSection - The section describing the layout in v, or NULL to use the default global section
75247f5d1fdeSMatthew G. Knepley . A - The matrix
7525eaf898f9SPatrick Sanan . point - The point in the DM
75267f5d1fdeSMatthew G. Knepley . values - The array of values
75277f5d1fdeSMatthew G. Knepley - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions
75287f5d1fdeSMatthew G. Knepley 
75297f5d1fdeSMatthew G. Knepley   Fortran Notes:
75307f5d1fdeSMatthew G. Knepley   This routine is only available in Fortran 90, and you must include petsc.h90 in your code.
75317f5d1fdeSMatthew G. Knepley 
75327f5d1fdeSMatthew G. Knepley   Level: intermediate
75337f5d1fdeSMatthew G. Knepley 
7534db781477SPatrick Sanan .seealso `DMPlexMatSetClosureGeneral()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`
75357f5d1fdeSMatthew G. Knepley @*/
75367c1f9639SMatthew G Knepley PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
7537552f7358SJed Brown {
7538552f7358SJed Brown   DM_Plex           *mesh = (DM_Plex*) dm->data;
7539552f7358SJed Brown   PetscInt          *indices;
754071f0bbf9SMatthew G. Knepley   PetscInt           numIndices;
754171f0bbf9SMatthew G. Knepley   const PetscScalar *valuesOrig = values;
7542552f7358SJed Brown   PetscErrorCode     ierr;
7543552f7358SJed Brown 
7544552f7358SJed Brown   PetscFunctionBegin;
7545552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
75469566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
75473dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
75489566063dSJacob Faibussowitsch   if (!globalSection) PetscCall(DMGetGlobalSection(dm, &globalSection));
75493dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3);
75503dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 4);
7551552f7358SJed Brown 
75529566063dSJacob Faibussowitsch   PetscCall(DMPlexGetClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values));
75530d644c17SKarl Rupp 
75549566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values));
7555d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
75564a1e0b3eSMatthew G. Knepley   ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode);
7557552f7358SJed Brown   if (ierr) {
7558552f7358SJed Brown     PetscMPIInt    rank;
7559552f7358SJed Brown 
75609566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
75619566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
75629566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values));
75639566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values));
75649566063dSJacob Faibussowitsch     if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values));
7565c3e24edfSBarry Smith     SETERRQ(PetscObjectComm((PetscObject)dm),ierr,"Not possible to set matrix values");
7566552f7358SJed Brown   }
75674a1e0b3eSMatthew G. Knepley   if (mesh->printFEM > 1) {
75684a1e0b3eSMatthew G. Knepley     PetscInt i;
75699566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "  Indices:"));
757063a3b9bcSJacob Faibussowitsch     for (i = 0; i < numIndices; ++i) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, indices[i]));
75719566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
75724a1e0b3eSMatthew G. Knepley   }
757371f0bbf9SMatthew G. Knepley 
75749566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **) &values));
75759566063dSJacob Faibussowitsch   if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values));
757671f0bbf9SMatthew G. Knepley   PetscFunctionReturn(0);
75774acb8e1eSToby Isaac }
757871f0bbf9SMatthew G. Knepley 
75794a1e0b3eSMatthew G. Knepley /*@C
75804a1e0b3eSMatthew G. Knepley   DMPlexMatSetClosure - Set an array of the values on the closure of 'point' using a different row and column section
75814a1e0b3eSMatthew G. Knepley 
75824a1e0b3eSMatthew G. Knepley   Not collective
75834a1e0b3eSMatthew G. Knepley 
75844a1e0b3eSMatthew G. Knepley   Input Parameters:
75854a1e0b3eSMatthew G. Knepley + dmRow - The DM for the row fields
75864a1e0b3eSMatthew G. Knepley . sectionRow - The section describing the layout, or NULL to use the default section in dmRow
75874a1e0b3eSMatthew G. Knepley . globalSectionRow - The section describing the layout, or NULL to use the default global section in dmRow
75884a1e0b3eSMatthew G. Knepley . dmCol - The DM for the column fields
75894a1e0b3eSMatthew G. Knepley . sectionCol - The section describing the layout, or NULL to use the default section in dmCol
75904a1e0b3eSMatthew G. Knepley . globalSectionCol - The section describing the layout, or NULL to use the default global section in dmCol
75914a1e0b3eSMatthew G. Knepley . A - The matrix
75924a1e0b3eSMatthew G. Knepley . point - The point in the DMs
75934a1e0b3eSMatthew G. Knepley . values - The array of values
75944a1e0b3eSMatthew G. Knepley - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions
75954a1e0b3eSMatthew G. Knepley 
75964a1e0b3eSMatthew G. Knepley   Level: intermediate
75974a1e0b3eSMatthew G. Knepley 
7598db781477SPatrick Sanan .seealso `DMPlexMatSetClosure()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`
75994a1e0b3eSMatthew G. Knepley @*/
760071f0bbf9SMatthew G. Knepley PetscErrorCode DMPlexMatSetClosureGeneral(DM dmRow, PetscSection sectionRow, PetscSection globalSectionRow, DM dmCol, PetscSection sectionCol, PetscSection globalSectionCol, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
760171f0bbf9SMatthew G. Knepley {
760271f0bbf9SMatthew G. Knepley   DM_Plex           *mesh = (DM_Plex*) dmRow->data;
760371f0bbf9SMatthew G. Knepley   PetscInt          *indicesRow, *indicesCol;
760471f0bbf9SMatthew G. Knepley   PetscInt           numIndicesRow, numIndicesCol;
760571f0bbf9SMatthew G. Knepley   const PetscScalar *valuesOrig = values;
760671f0bbf9SMatthew G. Knepley   PetscErrorCode     ierr;
760771f0bbf9SMatthew G. Knepley 
760871f0bbf9SMatthew G. Knepley   PetscFunctionBegin;
760971f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1);
76109566063dSJacob Faibussowitsch   if (!sectionRow) PetscCall(DMGetLocalSection(dmRow, &sectionRow));
761171f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2);
76129566063dSJacob Faibussowitsch   if (!globalSectionRow) PetscCall(DMGetGlobalSection(dmRow, &globalSectionRow));
761371f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3);
761471f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(dmCol, DM_CLASSID, 4);
76159566063dSJacob Faibussowitsch   if (!sectionCol) PetscCall(DMGetLocalSection(dmCol, &sectionCol));
761671f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 5);
76179566063dSJacob Faibussowitsch   if (!globalSectionCol) PetscCall(DMGetGlobalSection(dmCol, &globalSectionCol));
761871f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 6);
761971f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 7);
762071f0bbf9SMatthew G. Knepley 
76219566063dSJacob Faibussowitsch   PetscCall(DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values));
76229566063dSJacob Faibussowitsch   PetscCall(DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values));
762371f0bbf9SMatthew G. Knepley 
76249566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values));
7625d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
76264a1e0b3eSMatthew G. Knepley   ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode);
762771f0bbf9SMatthew G. Knepley   if (ierr) {
762871f0bbf9SMatthew G. Knepley     PetscMPIInt    rank;
762971f0bbf9SMatthew G. Knepley 
76309566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
76319566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
76329566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values));
76339566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values));
76349566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **) &values));
76359566063dSJacob Faibussowitsch     if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values));
7636d3d1a6afSToby Isaac   }
763771f0bbf9SMatthew G. Knepley 
76389566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **) &values));
76399566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **) &values));
76409566063dSJacob Faibussowitsch   if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values));
7641552f7358SJed Brown   PetscFunctionReturn(0);
7642552f7358SJed Brown }
7643552f7358SJed Brown 
7644de41b84cSMatthew G. Knepley PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
7645de41b84cSMatthew G. Knepley {
7646de41b84cSMatthew G. Knepley   DM_Plex        *mesh   = (DM_Plex*) dmf->data;
7647de41b84cSMatthew G. Knepley   PetscInt       *fpoints = NULL, *ftotpoints = NULL;
7648de41b84cSMatthew G. Knepley   PetscInt       *cpoints = NULL;
7649de41b84cSMatthew G. Knepley   PetscInt       *findices, *cindices;
765017c0192bSMatthew G. Knepley   const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */
7651de41b84cSMatthew G. Knepley   PetscInt        foffsets[32], coffsets[32];
7652412e9a14SMatthew G. Knepley   DMPolytopeType  ct;
76534ca5e9f5SMatthew G. Knepley   PetscInt        numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f;
7654de41b84cSMatthew G. Knepley   PetscErrorCode  ierr;
7655de41b84cSMatthew G. Knepley 
7656de41b84cSMatthew G. Knepley   PetscFunctionBegin;
7657de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 1);
7658de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 4);
76599566063dSJacob Faibussowitsch   if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection));
7660de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2);
76619566063dSJacob Faibussowitsch   if (!csection) PetscCall(DMGetLocalSection(dmc, &csection));
7662de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5);
76639566063dSJacob Faibussowitsch   if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection));
7664de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3);
76659566063dSJacob Faibussowitsch   if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection));
7666de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6);
7667de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 7);
76689566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(fsection, &numFields));
766963a3b9bcSJacob Faibussowitsch   PetscCheck(numFields <= 31,PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields);
76709566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(foffsets, 32));
76719566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(coffsets, 32));
7672de41b84cSMatthew G. Knepley   /* Column indices */
76739566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
76744ca5e9f5SMatthew G. Knepley   maxFPoints = numCPoints;
7675de41b84cSMatthew G. Knepley   /* Compress out points not in the section */
7676de41b84cSMatthew G. Knepley   /*   TODO: Squeeze out points with 0 dof as well */
76779566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd));
7678de41b84cSMatthew G. Knepley   for (p = 0, q = 0; p < numCPoints*2; p += 2) {
7679de41b84cSMatthew G. Knepley     if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) {
7680de41b84cSMatthew G. Knepley       cpoints[q*2]   = cpoints[p];
7681de41b84cSMatthew G. Knepley       cpoints[q*2+1] = cpoints[p+1];
7682de41b84cSMatthew G. Knepley       ++q;
7683de41b84cSMatthew G. Knepley     }
7684de41b84cSMatthew G. Knepley   }
7685de41b84cSMatthew G. Knepley   numCPoints = q;
7686de41b84cSMatthew G. Knepley   for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) {
7687de41b84cSMatthew G. Knepley     PetscInt fdof;
7688de41b84cSMatthew G. Knepley 
76899566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof));
76904ca5e9f5SMatthew G. Knepley     if (!dof) continue;
7691de41b84cSMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
76929566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof));
7693de41b84cSMatthew G. Knepley       coffsets[f+1] += fdof;
7694de41b84cSMatthew G. Knepley     }
7695de41b84cSMatthew G. Knepley     numCIndices += dof;
7696de41b84cSMatthew G. Knepley   }
7697de41b84cSMatthew G. Knepley   for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f];
7698de41b84cSMatthew G. Knepley   /* Row indices */
76999566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dmc, point, &ct));
7700412e9a14SMatthew G. Knepley   {
7701012bc364SMatthew G. Knepley     DMPlexTransform tr;
7702012bc364SMatthew G. Knepley     DMPolytopeType *rct;
7703012bc364SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt, Nt;
7704012bc364SMatthew G. Knepley 
77059566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr));
77069566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR));
77079566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt));
7708012bc364SMatthew G. Knepley     numSubcells = rsize[Nt-1];
77099566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformDestroy(&tr));
7710412e9a14SMatthew G. Knepley   }
77119566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints));
7712de41b84cSMatthew G. Knepley   for (r = 0, q = 0; r < numSubcells; ++r) {
7713de41b84cSMatthew G. Knepley     /* TODO Map from coarse to fine cells */
77149566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints));
7715de41b84cSMatthew G. Knepley     /* Compress out points not in the section */
77169566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd));
7717de41b84cSMatthew G. Knepley     for (p = 0; p < numFPoints*2; p += 2) {
7718de41b84cSMatthew G. Knepley       if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) {
77199566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof));
77204ca5e9f5SMatthew G. Knepley         if (!dof) continue;
77214ca5e9f5SMatthew G. Knepley         for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break;
77224ca5e9f5SMatthew G. Knepley         if (s < q) continue;
7723de41b84cSMatthew G. Knepley         ftotpoints[q*2]   = fpoints[p];
7724de41b84cSMatthew G. Knepley         ftotpoints[q*2+1] = fpoints[p+1];
7725de41b84cSMatthew G. Knepley         ++q;
7726de41b84cSMatthew G. Knepley       }
7727de41b84cSMatthew G. Knepley     }
77289566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints));
7729de41b84cSMatthew G. Knepley   }
7730de41b84cSMatthew G. Knepley   numFPoints = q;
7731de41b84cSMatthew G. Knepley   for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) {
7732de41b84cSMatthew G. Knepley     PetscInt fdof;
7733de41b84cSMatthew G. Knepley 
77349566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof));
77354ca5e9f5SMatthew G. Knepley     if (!dof) continue;
7736de41b84cSMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
77379566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof));
7738de41b84cSMatthew G. Knepley       foffsets[f+1] += fdof;
7739de41b84cSMatthew G. Knepley     }
7740de41b84cSMatthew G. Knepley     numFIndices += dof;
7741de41b84cSMatthew G. Knepley   }
7742de41b84cSMatthew G. Knepley   for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f];
7743de41b84cSMatthew G. Knepley 
77441dca8a05SBarry 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);
77451dca8a05SBarry 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);
77469566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices));
77479566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
7748de41b84cSMatthew G. Knepley   if (numFields) {
77494acb8e1eSToby Isaac     const PetscInt **permsF[32] = {NULL};
77504acb8e1eSToby Isaac     const PetscInt **permsC[32] = {NULL};
77514acb8e1eSToby Isaac 
77524acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
77539566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL));
77549566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL));
7755de41b84cSMatthew G. Knepley     }
77564acb8e1eSToby Isaac     for (p = 0; p < numFPoints; p++) {
77579566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff));
77589566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices));
77594acb8e1eSToby Isaac     }
77604acb8e1eSToby Isaac     for (p = 0; p < numCPoints; p++) {
77619566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff));
77629566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices));
77634acb8e1eSToby Isaac     }
77644acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
77659566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL));
77669566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL));
7767de41b84cSMatthew G. Knepley     }
7768de41b84cSMatthew G. Knepley   } else {
77694acb8e1eSToby Isaac     const PetscInt **permsF = NULL;
77704acb8e1eSToby Isaac     const PetscInt **permsC = NULL;
77714acb8e1eSToby Isaac 
77729566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL));
77739566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL));
77744acb8e1eSToby Isaac     for (p = 0, off = 0; p < numFPoints; p++) {
77754acb8e1eSToby Isaac       const PetscInt *perm = permsF ? permsF[p] : NULL;
77764acb8e1eSToby Isaac 
77779566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff));
77789566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices));
7779de41b84cSMatthew G. Knepley     }
77804acb8e1eSToby Isaac     for (p = 0, off = 0; p < numCPoints; p++) {
77814acb8e1eSToby Isaac       const PetscInt *perm = permsC ? permsC[p] : NULL;
77824acb8e1eSToby Isaac 
77839566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff));
77849566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices));
7785de41b84cSMatthew G. Knepley     }
77869566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL));
77879566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL));
7788de41b84cSMatthew G. Knepley   }
77899566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values));
77904acb8e1eSToby Isaac   /* TODO: flips */
7791d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
7792de41b84cSMatthew G. Knepley   ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode);
7793de41b84cSMatthew G. Knepley   if (ierr) {
7794de41b84cSMatthew G. Knepley     PetscMPIInt    rank;
7795de41b84cSMatthew G. Knepley 
77969566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
77979566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
77989566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values));
77999566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices));
78009566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
7801de41b84cSMatthew G. Knepley   }
78029566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints));
78039566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
78049566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices));
78059566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
7806de41b84cSMatthew G. Knepley   PetscFunctionReturn(0);
7807de41b84cSMatthew G. Knepley }
7808de41b84cSMatthew G. Knepley 
78097c927364SMatthew G. Knepley PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[])
78107c927364SMatthew G. Knepley {
78117c927364SMatthew G. Knepley   PetscInt      *fpoints = NULL, *ftotpoints = NULL;
78127c927364SMatthew G. Knepley   PetscInt      *cpoints = NULL;
78137c927364SMatthew G. Knepley   PetscInt       foffsets[32], coffsets[32];
781417c0192bSMatthew G. Knepley   const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */
7815412e9a14SMatthew G. Knepley   DMPolytopeType ct;
78167c927364SMatthew G. Knepley   PetscInt       numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f;
78177c927364SMatthew G. Knepley 
78187c927364SMatthew G. Knepley   PetscFunctionBegin;
78197c927364SMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 1);
78207c927364SMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 4);
78219566063dSJacob Faibussowitsch   if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection));
78227c927364SMatthew G. Knepley   PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2);
78239566063dSJacob Faibussowitsch   if (!csection) PetscCall(DMGetLocalSection(dmc, &csection));
78247c927364SMatthew G. Knepley   PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5);
78259566063dSJacob Faibussowitsch   if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection));
78267c927364SMatthew G. Knepley   PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3);
78279566063dSJacob Faibussowitsch   if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection));
78287c927364SMatthew G. Knepley   PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6);
78299566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(fsection, &numFields));
783063a3b9bcSJacob Faibussowitsch   PetscCheck(numFields <= 31,PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields);
78319566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(foffsets, 32));
78329566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(coffsets, 32));
78337c927364SMatthew G. Knepley   /* Column indices */
78349566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
78357c927364SMatthew G. Knepley   maxFPoints = numCPoints;
78367c927364SMatthew G. Knepley   /* Compress out points not in the section */
78377c927364SMatthew G. Knepley   /*   TODO: Squeeze out points with 0 dof as well */
78389566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd));
78397c927364SMatthew G. Knepley   for (p = 0, q = 0; p < numCPoints*2; p += 2) {
78407c927364SMatthew G. Knepley     if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) {
78417c927364SMatthew G. Knepley       cpoints[q*2]   = cpoints[p];
78427c927364SMatthew G. Knepley       cpoints[q*2+1] = cpoints[p+1];
78437c927364SMatthew G. Knepley       ++q;
78447c927364SMatthew G. Knepley     }
78457c927364SMatthew G. Knepley   }
78467c927364SMatthew G. Knepley   numCPoints = q;
78477c927364SMatthew G. Knepley   for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) {
78487c927364SMatthew G. Knepley     PetscInt fdof;
78497c927364SMatthew G. Knepley 
78509566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof));
78517c927364SMatthew G. Knepley     if (!dof) continue;
78527c927364SMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
78539566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof));
78547c927364SMatthew G. Knepley       coffsets[f+1] += fdof;
78557c927364SMatthew G. Knepley     }
78567c927364SMatthew G. Knepley     numCIndices += dof;
78577c927364SMatthew G. Knepley   }
78587c927364SMatthew G. Knepley   for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f];
78597c927364SMatthew G. Knepley   /* Row indices */
78609566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dmc, point, &ct));
7861412e9a14SMatthew G. Knepley   {
7862012bc364SMatthew G. Knepley     DMPlexTransform tr;
7863012bc364SMatthew G. Knepley     DMPolytopeType *rct;
7864012bc364SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt, Nt;
7865012bc364SMatthew G. Knepley 
78669566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr));
78679566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR));
78689566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt));
7869012bc364SMatthew G. Knepley     numSubcells = rsize[Nt-1];
78709566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformDestroy(&tr));
7871412e9a14SMatthew G. Knepley   }
78729566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, maxFPoints*2*numSubcells, MPIU_INT, &ftotpoints));
78737c927364SMatthew G. Knepley   for (r = 0, q = 0; r < numSubcells; ++r) {
78747c927364SMatthew G. Knepley     /* TODO Map from coarse to fine cells */
78759566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints));
78767c927364SMatthew G. Knepley     /* Compress out points not in the section */
78779566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd));
78787c927364SMatthew G. Knepley     for (p = 0; p < numFPoints*2; p += 2) {
78797c927364SMatthew G. Knepley       if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) {
78809566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof));
78817c927364SMatthew G. Knepley         if (!dof) continue;
78827c927364SMatthew G. Knepley         for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break;
78837c927364SMatthew G. Knepley         if (s < q) continue;
78847c927364SMatthew G. Knepley         ftotpoints[q*2]   = fpoints[p];
78857c927364SMatthew G. Knepley         ftotpoints[q*2+1] = fpoints[p+1];
78867c927364SMatthew G. Knepley         ++q;
78877c927364SMatthew G. Knepley       }
78887c927364SMatthew G. Knepley     }
78899566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints));
78907c927364SMatthew G. Knepley   }
78917c927364SMatthew G. Knepley   numFPoints = q;
78927c927364SMatthew G. Knepley   for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) {
78937c927364SMatthew G. Knepley     PetscInt fdof;
78947c927364SMatthew G. Knepley 
78959566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof));
78967c927364SMatthew G. Knepley     if (!dof) continue;
78977c927364SMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
78989566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof));
78997c927364SMatthew G. Knepley       foffsets[f+1] += fdof;
79007c927364SMatthew G. Knepley     }
79017c927364SMatthew G. Knepley     numFIndices += dof;
79027c927364SMatthew G. Knepley   }
79037c927364SMatthew G. Knepley   for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f];
79047c927364SMatthew G. Knepley 
79051dca8a05SBarry 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);
79061dca8a05SBarry 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);
79077c927364SMatthew G. Knepley   if (numFields) {
79084acb8e1eSToby Isaac     const PetscInt **permsF[32] = {NULL};
79094acb8e1eSToby Isaac     const PetscInt **permsC[32] = {NULL};
79104acb8e1eSToby Isaac 
79114acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
79129566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL));
79139566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL));
79147c927364SMatthew G. Knepley     }
79154acb8e1eSToby Isaac     for (p = 0; p < numFPoints; p++) {
79169566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff));
79179566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices));
79184acb8e1eSToby Isaac     }
79194acb8e1eSToby Isaac     for (p = 0; p < numCPoints; p++) {
79209566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff));
79219566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices));
79224acb8e1eSToby Isaac     }
79234acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
79249566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(fsection,f,numFPoints,ftotpoints,&permsF[f],NULL));
79259566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(csection,f,numCPoints,cpoints,&permsC[f],NULL));
79267c927364SMatthew G. Knepley     }
79277c927364SMatthew G. Knepley   } else {
79284acb8e1eSToby Isaac     const PetscInt **permsF = NULL;
79294acb8e1eSToby Isaac     const PetscInt **permsC = NULL;
79304acb8e1eSToby Isaac 
79319566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL));
79329566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(csection,numCPoints,cpoints,&permsC,NULL));
79334acb8e1eSToby Isaac     for (p = 0, off = 0; p < numFPoints; p++) {
79344acb8e1eSToby Isaac       const PetscInt *perm = permsF ? permsF[p] : NULL;
79354acb8e1eSToby Isaac 
79369566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2*p], &globalOff));
79379566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices));
79387c927364SMatthew G. Knepley     }
79394acb8e1eSToby Isaac     for (p = 0, off = 0; p < numCPoints; p++) {
79404acb8e1eSToby Isaac       const PetscInt *perm = permsC ? permsC[p] : NULL;
79414acb8e1eSToby Isaac 
79429566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2*p], &globalOff));
79439566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2*p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices));
79447c927364SMatthew G. Knepley     }
79459566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(fsection,numFPoints,ftotpoints,&permsF,NULL));
79469566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(csection,numCPoints,cpoints,&permsC,NULL));
79477c927364SMatthew G. Knepley   }
79489566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numCPoints*2*4, MPIU_INT, &ftotpoints));
79499566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
79507c927364SMatthew G. Knepley   PetscFunctionReturn(0);
79517c927364SMatthew G. Knepley }
79527c927364SMatthew G. Knepley 
79537cd05799SMatthew G. Knepley /*@C
79547cd05799SMatthew G. Knepley   DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0)
79557cd05799SMatthew G. Knepley 
79567cd05799SMatthew G. Knepley   Input Parameter:
79577cd05799SMatthew G. Knepley . dm   - The DMPlex object
79587cd05799SMatthew G. Knepley 
79597cd05799SMatthew G. Knepley   Output Parameter:
79607cd05799SMatthew G. Knepley . cellHeight - The height of a cell
79617cd05799SMatthew G. Knepley 
79627cd05799SMatthew G. Knepley   Level: developer
79637cd05799SMatthew G. Knepley 
7964db781477SPatrick Sanan .seealso `DMPlexSetVTKCellHeight()`
79657cd05799SMatthew G. Knepley @*/
7966552f7358SJed Brown PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight)
7967552f7358SJed Brown {
7968552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
7969552f7358SJed Brown 
7970552f7358SJed Brown   PetscFunctionBegin;
7971552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7972dadcf809SJacob Faibussowitsch   PetscValidIntPointer(cellHeight, 2);
7973552f7358SJed Brown   *cellHeight = mesh->vtkCellHeight;
7974552f7358SJed Brown   PetscFunctionReturn(0);
7975552f7358SJed Brown }
7976552f7358SJed Brown 
79777cd05799SMatthew G. Knepley /*@C
79787cd05799SMatthew G. Knepley   DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0)
79797cd05799SMatthew G. Knepley 
79807cd05799SMatthew G. Knepley   Input Parameters:
79817cd05799SMatthew G. Knepley + dm   - The DMPlex object
79827cd05799SMatthew G. Knepley - cellHeight - The height of a cell
79837cd05799SMatthew G. Knepley 
79847cd05799SMatthew G. Knepley   Level: developer
79857cd05799SMatthew G. Knepley 
7986db781477SPatrick Sanan .seealso `DMPlexGetVTKCellHeight()`
79877cd05799SMatthew G. Knepley @*/
7988552f7358SJed Brown PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight)
7989552f7358SJed Brown {
7990552f7358SJed Brown   DM_Plex *mesh = (DM_Plex*) dm->data;
7991552f7358SJed Brown 
7992552f7358SJed Brown   PetscFunctionBegin;
7993552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7994552f7358SJed Brown   mesh->vtkCellHeight = cellHeight;
7995552f7358SJed Brown   PetscFunctionReturn(0);
7996552f7358SJed Brown }
7997552f7358SJed Brown 
7998e6139122SMatthew G. Knepley /*@
7999e6139122SMatthew G. Knepley   DMPlexGetGhostCellStratum - Get the range of cells which are used to enforce FV boundary conditions
8000e6139122SMatthew G. Knepley 
8001e6139122SMatthew G. Knepley   Input Parameter:
8002e6139122SMatthew G. Knepley . dm - The DMPlex object
8003e6139122SMatthew G. Knepley 
8004e6139122SMatthew G. Knepley   Output Parameters:
80052a9f31c0SMatthew G. Knepley + gcStart - The first ghost cell, or NULL
80062a9f31c0SMatthew G. Knepley - gcEnd   - The upper bound on ghost cells, or NULL
8007e6139122SMatthew G. Knepley 
80082a9f31c0SMatthew G. Knepley   Level: advanced
8009e6139122SMatthew G. Knepley 
8010db781477SPatrick Sanan .seealso `DMPlexConstructGhostCells()`, `DMPlexGetGhostCellStratum()`
8011e6139122SMatthew G. Knepley @*/
8012e6139122SMatthew G. Knepley PetscErrorCode DMPlexGetGhostCellStratum(DM dm, PetscInt *gcStart, PetscInt *gcEnd)
8013e6139122SMatthew G. Knepley {
8014412e9a14SMatthew G. Knepley   DMLabel        ctLabel;
8015e6139122SMatthew G. Knepley 
8016e6139122SMatthew G. Knepley   PetscFunctionBegin;
8017e6139122SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
80189566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel));
80199566063dSJacob Faibussowitsch   PetscCall(DMLabelGetStratumBounds(ctLabel, DM_POLYTOPE_FV_GHOST, gcStart, gcEnd));
8020e6139122SMatthew G. Knepley   PetscFunctionReturn(0);
8021e6139122SMatthew G. Knepley }
8022e6139122SMatthew G. Knepley 
80239886b8cfSStefano Zampini PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering)
8024552f7358SJed Brown {
8025552f7358SJed Brown   PetscSection   section, globalSection;
8026552f7358SJed Brown   PetscInt      *numbers, p;
8027552f7358SJed Brown 
8028552f7358SJed Brown   PetscFunctionBegin;
80296c1ef331SVaclav Hapla   if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf));
80309566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section));
80319566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(section, pStart, pEnd));
8032552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
80339566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(section, p, 1));
8034552f7358SJed Brown   }
80359566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(section));
80369566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection));
80379566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(pEnd - pStart, &numbers));
8038552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
80399566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]));
8040ef48cebcSMatthew G. Knepley     if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift;
8041ef48cebcSMatthew G. Knepley     else                       numbers[p-pStart] += shift;
8042552f7358SJed Brown   }
80439566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering));
8044ef48cebcSMatthew G. Knepley   if (globalSize) {
8045ef48cebcSMatthew G. Knepley     PetscLayout layout;
80469566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout));
80479566063dSJacob Faibussowitsch     PetscCall(PetscLayoutGetSize(layout, globalSize));
80489566063dSJacob Faibussowitsch     PetscCall(PetscLayoutDestroy(&layout));
8049ef48cebcSMatthew G. Knepley   }
80509566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&section));
80519566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&globalSection));
8052552f7358SJed Brown   PetscFunctionReturn(0);
8053552f7358SJed Brown }
8054552f7358SJed Brown 
805581ed3555SMatthew G. Knepley PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers)
8056552f7358SJed Brown {
8057412e9a14SMatthew G. Knepley   PetscInt       cellHeight, cStart, cEnd;
8058552f7358SJed Brown 
8059552f7358SJed Brown   PetscFunctionBegin;
80609566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
80619566063dSJacob Faibussowitsch   if (includeHybrid) PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
80629566063dSJacob Faibussowitsch   else               PetscCall(DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd));
80639566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers));
806481ed3555SMatthew G. Knepley   PetscFunctionReturn(0);
8065552f7358SJed Brown }
806681ed3555SMatthew G. Knepley 
80678dab3259SMatthew G. Knepley /*@
80687cd05799SMatthew G. Knepley   DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process
80697cd05799SMatthew G. Knepley 
80707cd05799SMatthew G. Knepley   Input Parameter:
80717cd05799SMatthew G. Knepley . dm   - The DMPlex object
80727cd05799SMatthew G. Knepley 
80737cd05799SMatthew G. Knepley   Output Parameter:
80747cd05799SMatthew G. Knepley . globalCellNumbers - Global cell numbers for all cells on this process
80757cd05799SMatthew G. Knepley 
80767cd05799SMatthew G. Knepley   Level: developer
80777cd05799SMatthew G. Knepley 
8078db781477SPatrick Sanan .seealso `DMPlexGetVertexNumbering()`
80797cd05799SMatthew G. Knepley @*/
808081ed3555SMatthew G. Knepley PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers)
808181ed3555SMatthew G. Knepley {
808281ed3555SMatthew G. Knepley   DM_Plex       *mesh = (DM_Plex*) dm->data;
808381ed3555SMatthew G. Knepley 
808481ed3555SMatthew G. Knepley   PetscFunctionBegin;
808581ed3555SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
80869566063dSJacob Faibussowitsch   if (!mesh->globalCellNumbers) PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers));
8087552f7358SJed Brown   *globalCellNumbers = mesh->globalCellNumbers;
8088552f7358SJed Brown   PetscFunctionReturn(0);
8089552f7358SJed Brown }
8090552f7358SJed Brown 
809181ed3555SMatthew G. Knepley PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers)
809281ed3555SMatthew G. Knepley {
8093412e9a14SMatthew G. Knepley   PetscInt       vStart, vEnd;
809481ed3555SMatthew G. Knepley 
809581ed3555SMatthew G. Knepley   PetscFunctionBegin;
809681ed3555SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
80979566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
80989566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers));
809981ed3555SMatthew G. Knepley   PetscFunctionReturn(0);
810081ed3555SMatthew G. Knepley }
810181ed3555SMatthew G. Knepley 
81028dab3259SMatthew G. Knepley /*@
81036aa51ba9SJacob Faibussowitsch   DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process
81047cd05799SMatthew G. Knepley 
81057cd05799SMatthew G. Knepley   Input Parameter:
81067cd05799SMatthew G. Knepley . dm   - The DMPlex object
81077cd05799SMatthew G. Knepley 
81087cd05799SMatthew G. Knepley   Output Parameter:
81097cd05799SMatthew G. Knepley . globalVertexNumbers - Global vertex numbers for all vertices on this process
81107cd05799SMatthew G. Knepley 
81117cd05799SMatthew G. Knepley   Level: developer
81127cd05799SMatthew G. Knepley 
8113db781477SPatrick Sanan .seealso `DMPlexGetCellNumbering()`
81147cd05799SMatthew G. Knepley @*/
8115552f7358SJed Brown PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers)
8116552f7358SJed Brown {
8117552f7358SJed Brown   DM_Plex       *mesh = (DM_Plex*) dm->data;
8118552f7358SJed Brown 
8119552f7358SJed Brown   PetscFunctionBegin;
8120552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
81219566063dSJacob Faibussowitsch   if (!mesh->globalVertexNumbers) PetscCall(DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers));
8122552f7358SJed Brown   *globalVertexNumbers = mesh->globalVertexNumbers;
8123552f7358SJed Brown   PetscFunctionReturn(0);
8124552f7358SJed Brown }
8125552f7358SJed Brown 
81268dab3259SMatthew G. Knepley /*@
81277cd05799SMatthew G. Knepley   DMPlexCreatePointNumbering - Create a global numbering for all points on this process
81287cd05799SMatthew G. Knepley 
81297cd05799SMatthew G. Knepley   Input Parameter:
81307cd05799SMatthew G. Knepley . dm   - The DMPlex object
81317cd05799SMatthew G. Knepley 
81327cd05799SMatthew G. Knepley   Output Parameter:
81337cd05799SMatthew G. Knepley . globalPointNumbers - Global numbers for all points on this process
81347cd05799SMatthew G. Knepley 
81357cd05799SMatthew G. Knepley   Level: developer
81367cd05799SMatthew G. Knepley 
8137db781477SPatrick Sanan .seealso `DMPlexGetCellNumbering()`
81387cd05799SMatthew G. Knepley @*/
8139ef48cebcSMatthew G. Knepley PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers)
8140ef48cebcSMatthew G. Knepley {
8141ef48cebcSMatthew G. Knepley   IS             nums[4];
8142862913ffSStefano Zampini   PetscInt       depths[4], gdepths[4], starts[4];
8143ef48cebcSMatthew G. Knepley   PetscInt       depth, d, shift = 0;
8144ef48cebcSMatthew G. Knepley 
8145ef48cebcSMatthew G. Knepley   PetscFunctionBegin;
8146ef48cebcSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
81479566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
81488abc87a0SMichael Lange   /* For unstratified meshes use dim instead of depth */
81499566063dSJacob Faibussowitsch   if (depth < 0) PetscCall(DMGetDimension(dm, &depth));
8150862913ffSStefano Zampini   for (d = 0; d <= depth; ++d) {
8151862913ffSStefano Zampini     PetscInt end;
8152862913ffSStefano Zampini 
8153862913ffSStefano Zampini     depths[d] = depth-d;
81549566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end));
8155862913ffSStefano Zampini     if (!(starts[d]-end)) { starts[d] = depths[d] = -1; }
8156862913ffSStefano Zampini   }
81579566063dSJacob Faibussowitsch   PetscCall(PetscSortIntWithArray(depth+1, starts, depths));
81581c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(depths, gdepths, depth+1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject) dm)));
8159862913ffSStefano Zampini   for (d = 0; d <= depth; ++d) {
81601dca8a05SBarry Smith     PetscCheck(starts[d] < 0 || depths[d] == gdepths[d],PETSC_COMM_SELF,PETSC_ERR_PLIB,"Expected depth %" PetscInt_FMT ", found %" PetscInt_FMT,depths[d],gdepths[d]);
8161862913ffSStefano Zampini   }
8162ef48cebcSMatthew G. Knepley   for (d = 0; d <= depth; ++d) {
8163ef48cebcSMatthew G. Knepley     PetscInt pStart, pEnd, gsize;
8164ef48cebcSMatthew G. Knepley 
81659566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd));
81669566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]));
8167ef48cebcSMatthew G. Knepley     shift += gsize;
8168ef48cebcSMatthew G. Knepley   }
81699566063dSJacob Faibussowitsch   PetscCall(ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers));
81709566063dSJacob Faibussowitsch   for (d = 0; d <= depth; ++d) PetscCall(ISDestroy(&nums[d]));
8171ef48cebcSMatthew G. Knepley   PetscFunctionReturn(0);
8172ef48cebcSMatthew G. Knepley }
8173ef48cebcSMatthew G. Knepley 
817408a22f4bSMatthew G. Knepley /*@
817508a22f4bSMatthew G. Knepley   DMPlexCreateRankField - Create a cell field whose value is the rank of the owner
817608a22f4bSMatthew G. Knepley 
817708a22f4bSMatthew G. Knepley   Input Parameter:
817808a22f4bSMatthew G. Knepley . dm - The DMPlex object
817908a22f4bSMatthew G. Knepley 
818008a22f4bSMatthew G. Knepley   Output Parameter:
818108a22f4bSMatthew G. Knepley . ranks - The rank field
818208a22f4bSMatthew G. Knepley 
818308a22f4bSMatthew G. Knepley   Options Database Keys:
818408a22f4bSMatthew G. Knepley . -dm_partition_view - Adds the rank field into the DM output from -dm_view using the same viewer
818508a22f4bSMatthew G. Knepley 
818608a22f4bSMatthew G. Knepley   Level: intermediate
818708a22f4bSMatthew G. Knepley 
8188db781477SPatrick Sanan .seealso: `DMView()`
818908a22f4bSMatthew G. Knepley @*/
819008a22f4bSMatthew G. Knepley PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks)
819108a22f4bSMatthew G. Knepley {
819208a22f4bSMatthew G. Knepley   DM             rdm;
819308a22f4bSMatthew G. Knepley   PetscFE        fe;
819408a22f4bSMatthew G. Knepley   PetscScalar   *r;
819508a22f4bSMatthew G. Knepley   PetscMPIInt    rank;
8196a55f9a55SMatthew G. Knepley   DMPolytopeType ct;
819708a22f4bSMatthew G. Knepley   PetscInt       dim, cStart, cEnd, c;
8198a55f9a55SMatthew G. Knepley   PetscBool      simplex;
819908a22f4bSMatthew G. Knepley 
820008a22f4bSMatthew G. Knepley   PetscFunctionBeginUser;
8201f95ace6aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8202f95ace6aSMatthew G. Knepley   PetscValidPointer(ranks, 2);
82039566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank));
82049566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &rdm));
82059566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(rdm, &dim));
82069566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd));
82079566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cStart, &ct));
8208a55f9a55SMatthew G. Knepley   simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE;
82099566063dSJacob Faibussowitsch   PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe));
82109566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject) fe, "rank"));
82119566063dSJacob Faibussowitsch   PetscCall(DMSetField(rdm, 0, NULL, (PetscObject) fe));
82129566063dSJacob Faibussowitsch   PetscCall(PetscFEDestroy(&fe));
82139566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(rdm));
82149566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(rdm, ranks));
82159566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject) *ranks, "partition"));
82169566063dSJacob Faibussowitsch   PetscCall(VecGetArray(*ranks, &r));
821708a22f4bSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
821808a22f4bSMatthew G. Knepley     PetscScalar *lr;
821908a22f4bSMatthew G. Knepley 
82209566063dSJacob Faibussowitsch     PetscCall(DMPlexPointGlobalRef(rdm, c, r, &lr));
822171f09efeSPierre Jolivet     if (lr) *lr = rank;
822208a22f4bSMatthew G. Knepley   }
82239566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(*ranks, &r));
82249566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&rdm));
822508a22f4bSMatthew G. Knepley   PetscFunctionReturn(0);
822608a22f4bSMatthew G. Knepley }
822708a22f4bSMatthew G. Knepley 
8228ca8062c8SMatthew G. Knepley /*@
822918e14f0cSMatthew G. Knepley   DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell
823018e14f0cSMatthew G. Knepley 
823118e14f0cSMatthew G. Knepley   Input Parameters:
823218e14f0cSMatthew G. Knepley + dm    - The DMPlex
823318e14f0cSMatthew G. Knepley - label - The DMLabel
823418e14f0cSMatthew G. Knepley 
823518e14f0cSMatthew G. Knepley   Output Parameter:
823618e14f0cSMatthew G. Knepley . val - The label value field
823718e14f0cSMatthew G. Knepley 
823818e14f0cSMatthew G. Knepley   Options Database Keys:
823918e14f0cSMatthew G. Knepley . -dm_label_view - Adds the label value field into the DM output from -dm_view using the same viewer
824018e14f0cSMatthew G. Knepley 
824118e14f0cSMatthew G. Knepley   Level: intermediate
824218e14f0cSMatthew G. Knepley 
8243db781477SPatrick Sanan .seealso: `DMView()`
824418e14f0cSMatthew G. Knepley @*/
824518e14f0cSMatthew G. Knepley PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val)
824618e14f0cSMatthew G. Knepley {
824718e14f0cSMatthew G. Knepley   DM             rdm;
824818e14f0cSMatthew G. Knepley   PetscFE        fe;
824918e14f0cSMatthew G. Knepley   PetscScalar   *v;
825018e14f0cSMatthew G. Knepley   PetscInt       dim, cStart, cEnd, c;
825118e14f0cSMatthew G. Knepley 
825218e14f0cSMatthew G. Knepley   PetscFunctionBeginUser;
825318e14f0cSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
825418e14f0cSMatthew G. Knepley   PetscValidPointer(label, 2);
825518e14f0cSMatthew G. Knepley   PetscValidPointer(val, 3);
82569566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &rdm));
82579566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(rdm, &dim));
82589566063dSJacob Faibussowitsch   PetscCall(PetscFECreateDefault(PetscObjectComm((PetscObject) rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe));
82599566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject) fe, "label_value"));
82609566063dSJacob Faibussowitsch   PetscCall(DMSetField(rdm, 0, NULL, (PetscObject) fe));
82619566063dSJacob Faibussowitsch   PetscCall(PetscFEDestroy(&fe));
82629566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(rdm));
82639566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd));
82649566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(rdm, val));
82659566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject) *val, "label_value"));
82669566063dSJacob Faibussowitsch   PetscCall(VecGetArray(*val, &v));
826718e14f0cSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
826818e14f0cSMatthew G. Knepley     PetscScalar *lv;
826918e14f0cSMatthew G. Knepley     PetscInt     cval;
827018e14f0cSMatthew G. Knepley 
82719566063dSJacob Faibussowitsch     PetscCall(DMPlexPointGlobalRef(rdm, c, v, &lv));
82729566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(label, c, &cval));
827318e14f0cSMatthew G. Knepley     *lv = cval;
827418e14f0cSMatthew G. Knepley   }
82759566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(*val, &v));
82769566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&rdm));
827718e14f0cSMatthew G. Knepley   PetscFunctionReturn(0);
827818e14f0cSMatthew G. Knepley }
827918e14f0cSMatthew G. Knepley 
828018e14f0cSMatthew G. Knepley /*@
8281ca8062c8SMatthew G. Knepley   DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric.
8282ca8062c8SMatthew G. Knepley 
828369916449SMatthew G. Knepley   Input Parameter:
828469916449SMatthew G. Knepley . dm - The DMPlex object
8285ca8062c8SMatthew G. Knepley 
828695eb5ee5SVaclav Hapla   Notes:
828795eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
828895eb5ee5SVaclav Hapla 
828995eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
8290ca8062c8SMatthew G. Knepley 
8291ca8062c8SMatthew G. Knepley   Level: developer
8292ca8062c8SMatthew G. Knepley 
8293db781477SPatrick Sanan .seealso: `DMCreate()`, `DMSetFromOptions()`
8294ca8062c8SMatthew G. Knepley @*/
8295ca8062c8SMatthew G. Knepley PetscErrorCode DMPlexCheckSymmetry(DM dm)
8296ca8062c8SMatthew G. Knepley {
8297ca8062c8SMatthew G. Knepley   PetscSection    coneSection, supportSection;
8298ca8062c8SMatthew G. Knepley   const PetscInt *cone, *support;
8299ca8062c8SMatthew G. Knepley   PetscInt        coneSize, c, supportSize, s;
830057beb4faSStefano Zampini   PetscInt        pStart, pEnd, p, pp, csize, ssize;
830157beb4faSStefano Zampini   PetscBool       storagecheck = PETSC_TRUE;
8302ca8062c8SMatthew G. Knepley 
8303ca8062c8SMatthew G. Knepley   PetscFunctionBegin;
8304ca8062c8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
83059566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(dm, NULL, "-sym_dm_view"));
83069566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSection(dm, &coneSection));
83079566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSupportSection(dm, &supportSection));
8308ca8062c8SMatthew G. Knepley   /* Check that point p is found in the support of its cone points, and vice versa */
83099566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
8310ca8062c8SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
83119566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
83129566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
8313ca8062c8SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
831442e66dfaSMatthew G. Knepley       PetscBool dup = PETSC_FALSE;
831542e66dfaSMatthew G. Knepley       PetscInt  d;
831642e66dfaSMatthew G. Knepley       for (d = c-1; d >= 0; --d) {
831742e66dfaSMatthew G. Knepley         if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;}
831842e66dfaSMatthew G. Knepley       }
83199566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, cone[c], &supportSize));
83209566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupport(dm, cone[c], &support));
8321ca8062c8SMatthew G. Knepley       for (s = 0; s < supportSize; ++s) {
8322ca8062c8SMatthew G. Knepley         if (support[s] == p) break;
8323ca8062c8SMatthew G. Knepley       }
832442e66dfaSMatthew G. Knepley       if ((s >= supportSize) || (dup && (support[s+1] != p))) {
832563a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", p));
8326ca8062c8SMatthew G. Knepley         for (s = 0; s < coneSize; ++s) {
832763a3b9bcSJacob Faibussowitsch           PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[s]));
8328ca8062c8SMatthew G. Knepley         }
83299566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
833063a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", cone[c]));
8331ca8062c8SMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
833263a3b9bcSJacob Faibussowitsch           PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[s]));
8333ca8062c8SMatthew G. Knepley         }
83349566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
833563a3b9bcSJacob 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]);
8336f7d195e4SLawrence Mitchell         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in support of cone point %" PetscInt_FMT, p, cone[c]);
8337ca8062c8SMatthew G. Knepley       }
833842e66dfaSMatthew G. Knepley     }
83399566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTreeParent(dm, p, &pp, NULL));
834057beb4faSStefano Zampini     if (p != pp) { storagecheck = PETSC_FALSE; continue; }
83419566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
83429566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dm, p, &support));
8343ca8062c8SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
83449566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, support[s], &coneSize));
83459566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, support[s], &cone));
8346ca8062c8SMatthew G. Knepley       for (c = 0; c < coneSize; ++c) {
83479566063dSJacob Faibussowitsch         PetscCall(DMPlexGetTreeParent(dm, cone[c], &pp, NULL));
834857beb4faSStefano Zampini         if (cone[c] != pp) { c = 0; break; }
8349ca8062c8SMatthew G. Knepley         if (cone[c] == p) break;
8350ca8062c8SMatthew G. Knepley       }
8351ca8062c8SMatthew G. Knepley       if (c >= coneSize) {
835263a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", p));
8353ca8062c8SMatthew G. Knepley         for (c = 0; c < supportSize; ++c) {
835463a3b9bcSJacob Faibussowitsch           PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[c]));
8355ca8062c8SMatthew G. Knepley         }
83569566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
835763a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", support[s]));
8358ca8062c8SMatthew G. Knepley         for (c = 0; c < coneSize; ++c) {
835963a3b9bcSJacob Faibussowitsch           PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[c]));
8360ca8062c8SMatthew G. Knepley         }
83619566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
836263a3b9bcSJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in cone of support point %" PetscInt_FMT, p, support[s]);
8363ca8062c8SMatthew G. Knepley       }
8364ca8062c8SMatthew G. Knepley     }
8365ca8062c8SMatthew G. Knepley   }
836657beb4faSStefano Zampini   if (storagecheck) {
83679566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coneSection, &csize));
83689566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(supportSection, &ssize));
836963a3b9bcSJacob Faibussowitsch     PetscCheck(csize == ssize,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %" PetscInt_FMT " != Total support size %" PetscInt_FMT, csize, ssize);
837057beb4faSStefano Zampini   }
8371ca8062c8SMatthew G. Knepley   PetscFunctionReturn(0);
8372ca8062c8SMatthew G. Knepley }
8373ca8062c8SMatthew G. Knepley 
8374412e9a14SMatthew G. Knepley /*
8375412e9a14SMatthew 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.
8376412e9a14SMatthew G. Knepley */
8377412e9a14SMatthew G. Knepley static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit)
8378412e9a14SMatthew G. Knepley {
8379412e9a14SMatthew G. Knepley   DMPolytopeType  cct;
8380412e9a14SMatthew G. Knepley   PetscInt        ptpoints[4];
8381412e9a14SMatthew G. Knepley   const PetscInt *cone, *ccone, *ptcone;
8382412e9a14SMatthew G. Knepley   PetscInt        coneSize, cp, cconeSize, ccp, npt = 0, pt;
8383412e9a14SMatthew G. Knepley 
8384412e9a14SMatthew G. Knepley   PetscFunctionBegin;
8385412e9a14SMatthew G. Knepley   *unsplit = 0;
8386412e9a14SMatthew G. Knepley   switch (ct) {
8387b5a892a1SMatthew G. Knepley     case DM_POLYTOPE_POINT_PRISM_TENSOR:
8388b5a892a1SMatthew G. Knepley       ptpoints[npt++] = c;
8389b5a892a1SMatthew G. Knepley       break;
8390412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEG_PRISM_TENSOR:
83919566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, c, &cone));
83929566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
8393412e9a14SMatthew G. Knepley       for (cp = 0; cp < coneSize; ++cp) {
83949566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, cone[cp], &cct));
8395412e9a14SMatthew G. Knepley         if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp];
8396412e9a14SMatthew G. Knepley       }
8397412e9a14SMatthew G. Knepley       break;
8398412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:
8399412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
84009566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, c, &cone));
84019566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
8402412e9a14SMatthew G. Knepley       for (cp = 0; cp < coneSize; ++cp) {
84039566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, cone[cp], &ccone));
84049566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, cone[cp], &cconeSize));
8405412e9a14SMatthew G. Knepley         for (ccp = 0; ccp < cconeSize; ++ccp) {
84069566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCellType(dm, ccone[ccp], &cct));
8407412e9a14SMatthew G. Knepley           if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) {
8408412e9a14SMatthew G. Knepley             PetscInt p;
8409412e9a14SMatthew G. Knepley             for (p = 0; p < npt; ++p) if (ptpoints[p] == ccone[ccp]) break;
8410412e9a14SMatthew G. Knepley             if (p == npt) ptpoints[npt++] = ccone[ccp];
8411412e9a14SMatthew G. Knepley           }
8412412e9a14SMatthew G. Knepley         }
8413412e9a14SMatthew G. Knepley       }
8414412e9a14SMatthew G. Knepley       break;
8415412e9a14SMatthew G. Knepley     default: break;
8416412e9a14SMatthew G. Knepley   }
8417412e9a14SMatthew G. Knepley   for (pt = 0; pt < npt; ++pt) {
84189566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, ptpoints[pt], &ptcone));
8419412e9a14SMatthew G. Knepley     if (ptcone[0] == ptcone[1]) ++(*unsplit);
8420412e9a14SMatthew G. Knepley   }
8421412e9a14SMatthew G. Knepley   PetscFunctionReturn(0);
8422412e9a14SMatthew G. Knepley }
8423412e9a14SMatthew G. Knepley 
8424ca8062c8SMatthew G. Knepley /*@
8425ca8062c8SMatthew G. Knepley   DMPlexCheckSkeleton - Check that each cell has the correct number of vertices
8426ca8062c8SMatthew G. Knepley 
8427ca8062c8SMatthew G. Knepley   Input Parameters:
8428ca8062c8SMatthew G. Knepley + dm - The DMPlex object
842958723a97SMatthew G. Knepley - cellHeight - Normally 0
8430ca8062c8SMatthew G. Knepley 
843195eb5ee5SVaclav Hapla   Notes:
843295eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
843325c50c26SVaclav Hapla   Currently applicable only to homogeneous simplex or tensor meshes.
8434ca8062c8SMatthew G. Knepley 
843595eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
843695eb5ee5SVaclav Hapla 
8437ca8062c8SMatthew G. Knepley   Level: developer
8438ca8062c8SMatthew G. Knepley 
8439db781477SPatrick Sanan .seealso: `DMCreate()`, `DMSetFromOptions()`
8440ca8062c8SMatthew G. Knepley @*/
844125c50c26SVaclav Hapla PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight)
8442ca8062c8SMatthew G. Knepley {
8443412e9a14SMatthew G. Knepley   DMPlexInterpolatedFlag interp;
8444412e9a14SMatthew G. Knepley   DMPolytopeType         ct;
8445412e9a14SMatthew G. Knepley   PetscInt               vStart, vEnd, cStart, cEnd, c;
8446ca8062c8SMatthew G. Knepley 
8447ca8062c8SMatthew G. Knepley   PetscFunctionBegin;
8448ca8062c8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
84499566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolated(dm, &interp));
84509566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
84519566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
8452412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
8453412e9a14SMatthew G. Knepley     PetscInt *closure = NULL;
8454412e9a14SMatthew G. Knepley     PetscInt  coneSize, closureSize, cl, Nv = 0;
845558723a97SMatthew G. Knepley 
84569566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
845763a3b9bcSJacob Faibussowitsch     PetscCheck((PetscInt) ct >= 0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " has no cell type", c);
8458412e9a14SMatthew G. Knepley     if (ct == DM_POLYTOPE_UNKNOWN) continue;
8459412e9a14SMatthew G. Knepley     if (interp == DMPLEX_INTERPOLATED_FULL) {
84609566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
846163a3b9bcSJacob 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));
8462412e9a14SMatthew G. Knepley     }
84639566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
846458723a97SMatthew G. Knepley     for (cl = 0; cl < closureSize*2; cl += 2) {
846558723a97SMatthew G. Knepley       const PetscInt p = closure[cl];
8466412e9a14SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) ++Nv;
846758723a97SMatthew G. Knepley     }
84689566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
8469412e9a14SMatthew G. Knepley     /* Special Case: Tensor faces with identified vertices */
8470412e9a14SMatthew G. Knepley     if (Nv < DMPolytopeTypeGetNumVertices(ct)) {
8471412e9a14SMatthew G. Knepley       PetscInt unsplit;
847242363296SMatthew G. Knepley 
84739566063dSJacob Faibussowitsch       PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
8474412e9a14SMatthew G. Knepley       if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue;
847542363296SMatthew G. Knepley     }
847663a3b9bcSJacob 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));
847742363296SMatthew G. Knepley   }
8478ca8062c8SMatthew G. Knepley   PetscFunctionReturn(0);
8479ca8062c8SMatthew G. Knepley }
84809bf0dad6SMatthew G. Knepley 
84819bf0dad6SMatthew G. Knepley /*@
84829bf0dad6SMatthew 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
84839bf0dad6SMatthew G. Knepley 
84848f6815adSVaclav Hapla   Collective
8485899ea2b8SJacob Faibussowitsch 
84869bf0dad6SMatthew G. Knepley   Input Parameters:
84879bf0dad6SMatthew G. Knepley + dm - The DMPlex object
84889bf0dad6SMatthew G. Knepley - cellHeight - Normally 0
84899bf0dad6SMatthew G. Knepley 
849045da879fSVaclav Hapla   Notes:
849145da879fSVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
849245da879fSVaclav Hapla   This routine is only relevant for meshes that are fully interpolated across all ranks.
849345da879fSVaclav Hapla   It will error out if a partially interpolated mesh is given on some rank.
849445da879fSVaclav Hapla   It will do nothing for locally uninterpolated mesh (as there is nothing to check).
84959bf0dad6SMatthew G. Knepley 
849695eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
849795eb5ee5SVaclav Hapla 
84989bf0dad6SMatthew G. Knepley   Level: developer
84999bf0dad6SMatthew G. Knepley 
8500db781477SPatrick Sanan .seealso: `DMCreate()`, `DMPlexGetVTKCellHeight()`, `DMSetFromOptions()`
85019bf0dad6SMatthew G. Knepley @*/
850225c50c26SVaclav Hapla PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight)
85039bf0dad6SMatthew G. Knepley {
8504ab91121cSMatthew G. Knepley   PetscInt       dim, depth, vStart, vEnd, cStart, cEnd, c, h;
8505899ea2b8SJacob Faibussowitsch   DMPlexInterpolatedFlag interpEnum;
85069bf0dad6SMatthew G. Knepley 
85079bf0dad6SMatthew G. Knepley   PetscFunctionBegin;
85089bf0dad6SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
85098f6815adSVaclav Hapla   PetscCall(DMPlexIsInterpolatedCollective(dm, &interpEnum));
851045da879fSVaclav Hapla   if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(0);
85118f6815adSVaclav Hapla   if (interpEnum != DMPLEX_INTERPOLATED_FULL) {
85128f6815adSVaclav Hapla     PetscPrintf(PetscObjectComm((PetscObject)dm), "DMPlexCheckFaces() warning: Mesh is only partially interpolated, this is currently not supported");
85138f6815adSVaclav Hapla     PetscFunctionReturn(0);
8514899ea2b8SJacob Faibussowitsch   }
8515899ea2b8SJacob Faibussowitsch 
85169566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
85179566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
85189566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
8519ab91121cSMatthew G. Knepley   for (h = cellHeight; h < PetscMin(depth, dim); ++h) {
85209566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, h, &cStart, &cEnd));
85213554e41dSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
8522412e9a14SMatthew G. Knepley       const PetscInt      *cone, *ornt, *faceSizes, *faces;
8523412e9a14SMatthew G. Knepley       const DMPolytopeType *faceTypes;
8524ba2698f1SMatthew G. Knepley       DMPolytopeType        ct;
8525412e9a14SMatthew G. Knepley       PetscInt              numFaces, coneSize, f;
8526412e9a14SMatthew G. Knepley       PetscInt             *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit;
85279bf0dad6SMatthew G. Knepley 
85289566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, c, &ct));
85299566063dSJacob Faibussowitsch       PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
8530412e9a14SMatthew G. Knepley       if (unsplit) continue;
85319566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
85329566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, c, &cone));
85339566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeOrientation(dm, c, &ornt));
85349566063dSJacob Faibussowitsch       PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
85359bf0dad6SMatthew G. Knepley       for (cl = 0; cl < closureSize*2; cl += 2) {
85369bf0dad6SMatthew G. Knepley         const PetscInt p = closure[cl];
85379bf0dad6SMatthew G. Knepley         if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p;
85389bf0dad6SMatthew G. Knepley       }
85399566063dSJacob Faibussowitsch       PetscCall(DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces));
854063a3b9bcSJacob 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);
85419bf0dad6SMatthew G. Knepley       for (f = 0; f < numFaces; ++f) {
8542d4961f80SStefano Zampini         DMPolytopeType fct;
85439bf0dad6SMatthew G. Knepley         PetscInt       *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v;
85449bf0dad6SMatthew G. Knepley 
85459566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, cone[f], &fct));
85469566063dSJacob Faibussowitsch         PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure));
85479bf0dad6SMatthew G. Knepley         for (cl = 0; cl < fclosureSize*2; cl += 2) {
85489bf0dad6SMatthew G. Knepley           const PetscInt p = fclosure[cl];
85499bf0dad6SMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p;
85509bf0dad6SMatthew G. Knepley         }
855163a3b9bcSJacob 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]);
85529bf0dad6SMatthew G. Knepley         for (v = 0; v < fnumCorners; ++v) {
8553b5a892a1SMatthew G. Knepley           if (fclosure[v] != faces[fOff+v]) {
8554b5a892a1SMatthew G. Knepley             PetscInt v1;
8555b5a892a1SMatthew G. Knepley 
85569566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "face closure:"));
855763a3b9bcSJacob Faibussowitsch             for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, fclosure[v1]));
85589566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "\ncell face:"));
855963a3b9bcSJacob Faibussowitsch             for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, faces[fOff+v1]));
85609566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
856163a3b9bcSJacob 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]);
8562b5a892a1SMatthew G. Knepley           }
85639bf0dad6SMatthew G. Knepley         }
85649566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure));
8565412e9a14SMatthew G. Knepley         fOff += faceSizes[f];
85669bf0dad6SMatthew G. Knepley       }
85679566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces));
85689566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
85699bf0dad6SMatthew G. Knepley     }
85703554e41dSMatthew G. Knepley   }
8571552f7358SJed Brown   PetscFunctionReturn(0);
8572552f7358SJed Brown }
85733913d7c8SMatthew G. Knepley 
8574bb6a34a8SMatthew G. Knepley /*@
8575bb6a34a8SMatthew G. Knepley   DMPlexCheckGeometry - Check the geometry of mesh cells
8576bb6a34a8SMatthew G. Knepley 
8577bb6a34a8SMatthew G. Knepley   Input Parameter:
8578bb6a34a8SMatthew G. Knepley . dm - The DMPlex object
8579bb6a34a8SMatthew G. Knepley 
858095eb5ee5SVaclav Hapla   Notes:
858195eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
858295eb5ee5SVaclav Hapla 
858395eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
8584bb6a34a8SMatthew G. Knepley 
8585bb6a34a8SMatthew G. Knepley   Level: developer
8586bb6a34a8SMatthew G. Knepley 
8587db781477SPatrick Sanan .seealso: `DMCreate()`, `DMSetFromOptions()`
8588bb6a34a8SMatthew G. Knepley @*/
8589bb6a34a8SMatthew G. Knepley PetscErrorCode DMPlexCheckGeometry(DM dm)
8590bb6a34a8SMatthew G. Knepley {
8591a2a9e04cSMatthew G. Knepley   Vec       coordinates;
8592bb6a34a8SMatthew G. Knepley   PetscReal detJ, J[9], refVol = 1.0;
8593bb6a34a8SMatthew G. Knepley   PetscReal vol;
859451a74b61SMatthew G. Knepley   PetscInt  dim, depth, dE, d, cStart, cEnd, c;
8595bb6a34a8SMatthew G. Knepley 
8596bb6a34a8SMatthew G. Knepley   PetscFunctionBegin;
85979566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
85989566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dE));
859951a74b61SMatthew G. Knepley   if (dim != dE) PetscFunctionReturn(0);
86009566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
8601bb6a34a8SMatthew G. Knepley   for (d = 0; d < dim; ++d) refVol *= 2.0;
86029566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
8603a2a9e04cSMatthew G. Knepley   /* Make sure local coordinates are created, because that step is collective */
86049566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
8605412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
8606412e9a14SMatthew G. Knepley     DMPolytopeType ct;
8607412e9a14SMatthew G. Knepley     PetscInt       unsplit;
8608412e9a14SMatthew G. Knepley     PetscBool      ignoreZeroVol = PETSC_FALSE;
8609412e9a14SMatthew G. Knepley 
86109566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
8611412e9a14SMatthew G. Knepley     switch (ct) {
8612412e9a14SMatthew G. Knepley       case DM_POLYTOPE_SEG_PRISM_TENSOR:
8613412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM_TENSOR:
8614412e9a14SMatthew G. Knepley       case DM_POLYTOPE_QUAD_PRISM_TENSOR:
8615412e9a14SMatthew G. Knepley         ignoreZeroVol = PETSC_TRUE; break;
8616412e9a14SMatthew G. Knepley       default: break;
8617412e9a14SMatthew G. Knepley     }
8618412e9a14SMatthew G. Knepley     switch (ct) {
8619412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM:
8620412e9a14SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM_TENSOR:
8621412e9a14SMatthew G. Knepley       case DM_POLYTOPE_QUAD_PRISM_TENSOR:
8622a2a9e04cSMatthew G. Knepley       case DM_POLYTOPE_PYRAMID:
8623412e9a14SMatthew G. Knepley         continue;
8624412e9a14SMatthew G. Knepley       default: break;
8625412e9a14SMatthew G. Knepley     }
86269566063dSJacob Faibussowitsch     PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
8627412e9a14SMatthew G. Knepley     if (unsplit) continue;
86289566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ));
86291dca8a05SBarry 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);
863063a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FEM Volume %g\n", c, (double)(detJ*refVol)));
86316858538eSMatthew G. Knepley     /* This should work with periodicity since DG coordinates should be used */
86326858538eSMatthew G. Knepley     if (depth > 1) {
86339566063dSJacob Faibussowitsch       PetscCall(DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL));
86341dca8a05SBarry 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);
863563a3b9bcSJacob Faibussowitsch       PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FVM Volume %g\n", c, (double) vol));
8636bb6a34a8SMatthew G. Knepley     }
8637bb6a34a8SMatthew G. Knepley   }
8638bb6a34a8SMatthew G. Knepley   PetscFunctionReturn(0);
8639bb6a34a8SMatthew G. Knepley }
8640bb6a34a8SMatthew G. Knepley 
864103da9461SVaclav Hapla /*@
86427726db96SVaclav Hapla   DMPlexCheckPointSF - Check that several necessary conditions are met for the Point SF of this plex.
86437726db96SVaclav Hapla 
86447726db96SVaclav Hapla   Collective
864503da9461SVaclav Hapla 
864603da9461SVaclav Hapla   Input Parameters:
86477726db96SVaclav Hapla + dm - The DMPlex object
86487726db96SVaclav Hapla - pointSF - The Point SF, or NULL for Point SF attached to DM
864903da9461SVaclav Hapla 
8650e83a0d2dSVaclav Hapla   Notes:
8651e83a0d2dSVaclav Hapla   This is mainly intended for debugging/testing purposes.
865203da9461SVaclav Hapla 
865395eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
865495eb5ee5SVaclav Hapla 
865503da9461SVaclav Hapla   Level: developer
865603da9461SVaclav Hapla 
8657db781477SPatrick Sanan .seealso: `DMGetPointSF()`, `DMSetFromOptions()`
865803da9461SVaclav Hapla @*/
86597726db96SVaclav Hapla PetscErrorCode DMPlexCheckPointSF(DM dm, PetscSF pointSF)
866003da9461SVaclav Hapla {
86617726db96SVaclav Hapla   PetscInt        l, nleaves, nroots, overlap;
86627726db96SVaclav Hapla   const PetscInt *locals;
86637726db96SVaclav Hapla   const PetscSFNode *remotes;
8664f0cfc026SVaclav Hapla   PetscBool       distributed;
86657726db96SVaclav Hapla   MPI_Comm        comm;
86667726db96SVaclav Hapla   PetscMPIInt     rank;
866703da9461SVaclav Hapla 
866803da9461SVaclav Hapla   PetscFunctionBegin;
866903da9461SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
86707726db96SVaclav Hapla   if (pointSF) PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2);
86717726db96SVaclav Hapla   else         pointSF = dm->sf;
86727726db96SVaclav Hapla   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
86737726db96SVaclav Hapla   PetscCheck(pointSF, comm, PETSC_ERR_ARG_WRONGSTATE, "DMPlex must have Point SF attached");
86747726db96SVaclav Hapla   PetscCallMPI(MPI_Comm_rank(comm, &rank));
86757726db96SVaclav Hapla   {
86767726db96SVaclav Hapla     PetscMPIInt    mpiFlag;
86777726db96SVaclav Hapla 
86787726db96SVaclav Hapla     PetscCallMPI(MPI_Comm_compare(comm, PetscObjectComm((PetscObject)pointSF),&mpiFlag));
86797726db96SVaclav 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);
86807726db96SVaclav Hapla   }
86817726db96SVaclav Hapla   PetscCall(PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, &remotes));
86829566063dSJacob Faibussowitsch   PetscCall(DMPlexIsDistributed(dm, &distributed));
86837726db96SVaclav Hapla   if (!distributed) {
86847726db96SVaclav 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);
86858918e3e2SVaclav Hapla     PetscFunctionReturn(0);
86868918e3e2SVaclav Hapla   }
86877726db96SVaclav 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);
86887726db96SVaclav Hapla   PetscCall(DMPlexGetOverlap(dm, &overlap));
868903da9461SVaclav Hapla 
86907726db96SVaclav Hapla   /* Check SF graph is compatible with DMPlex chart */
86917726db96SVaclav Hapla   {
86927726db96SVaclav Hapla     PetscInt pStart, pEnd, maxLeaf;
86937726db96SVaclav Hapla 
86947726db96SVaclav Hapla     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
86957726db96SVaclav Hapla     PetscCall(PetscSFGetLeafRange(pointSF, NULL, &maxLeaf));
86967726db96SVaclav Hapla     PetscCheck(pEnd - pStart == nroots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "pEnd - pStart = %" PetscInt_FMT " != nroots = %" PetscInt_FMT, pEnd-pStart, nroots);
86977726db96SVaclav Hapla     PetscCheck(maxLeaf < pEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "maxLeaf = %" PetscInt_FMT " >= pEnd = %" PetscInt_FMT, maxLeaf, pEnd);
86987726db96SVaclav Hapla   }
86997726db96SVaclav Hapla 
87007726db96SVaclav Hapla   /* Check Point SF has no local points referenced */
87017726db96SVaclav Hapla   for (l = 0; l < nleaves; l++) {
87027726db96SVaclav 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);
87037726db96SVaclav Hapla   }
87047726db96SVaclav Hapla 
87057726db96SVaclav Hapla   /* Check there are no cells in interface */
87067726db96SVaclav Hapla   if (!overlap) {
87077726db96SVaclav Hapla     PetscInt cellHeight, cStart, cEnd;
87087726db96SVaclav Hapla 
87099566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
87109566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
8711f5869d18SMatthew G. Knepley     for (l = 0; l < nleaves; ++l) {
87127726db96SVaclav Hapla       const PetscInt point = locals ? locals[l] : l;
8713f5869d18SMatthew G. Knepley 
87147726db96SVaclav Hapla       PetscCheck(point < cStart || point >= cEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %" PetscInt_FMT " which is a cell", point);
87157726db96SVaclav Hapla     }
871603da9461SVaclav Hapla   }
8717ece87651SVaclav Hapla 
87187726db96SVaclav Hapla   /* If some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */
87197726db96SVaclav Hapla   {
87207726db96SVaclav Hapla     const PetscInt *rootdegree;
87217726db96SVaclav Hapla 
87227726db96SVaclav Hapla     PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree));
87237726db96SVaclav Hapla     PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree));
8724f5869d18SMatthew G. Knepley     for (l = 0; l < nleaves; ++l) {
87257726db96SVaclav Hapla       const PetscInt  point = locals ? locals[l] : l;
8726f5869d18SMatthew G. Knepley       const PetscInt *cone;
8727f5869d18SMatthew G. Knepley       PetscInt        coneSize, c, idx;
8728f5869d18SMatthew G. Knepley 
87299566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, point, &coneSize));
87309566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, point, &cone));
8731f5869d18SMatthew G. Knepley       for (c = 0; c < coneSize; ++c) {
8732f5869d18SMatthew G. Knepley         if (!rootdegree[cone[c]]) {
87337726db96SVaclav Hapla           if (locals) {
87349566063dSJacob Faibussowitsch             PetscCall(PetscFindInt(cone[c], nleaves, locals, &idx));
87357726db96SVaclav Hapla           } else {
87367726db96SVaclav Hapla             idx = (cone[c] < nleaves) ? cone[c] : -1;
87377726db96SVaclav Hapla           }
873863a3b9bcSJacob 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]);
8739f5869d18SMatthew G. Knepley         }
8740f5869d18SMatthew G. Knepley       }
8741ece87651SVaclav Hapla     }
87427726db96SVaclav Hapla   }
874303da9461SVaclav Hapla   PetscFunctionReturn(0);
874403da9461SVaclav Hapla }
874503da9461SVaclav Hapla 
87467f9d8d6cSVaclav Hapla /*@
87477f9d8d6cSVaclav Hapla   DMPlexCheck - Perform various checks of Plex sanity
87487f9d8d6cSVaclav Hapla 
87497f9d8d6cSVaclav Hapla   Input Parameter:
87507f9d8d6cSVaclav Hapla . dm - The DMPlex object
87517f9d8d6cSVaclav Hapla 
87527f9d8d6cSVaclav Hapla   Notes:
87537f9d8d6cSVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
87547f9d8d6cSVaclav Hapla 
87557f9d8d6cSVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
87567f9d8d6cSVaclav Hapla 
87577f9d8d6cSVaclav Hapla   Currently does not include DMPlexCheckCellShape().
87587f9d8d6cSVaclav Hapla 
87597f9d8d6cSVaclav Hapla   Level: developer
87607f9d8d6cSVaclav Hapla 
87617f9d8d6cSVaclav Hapla .seealso: DMCreate(), DMSetFromOptions()
87627f9d8d6cSVaclav Hapla @*/
87637f9d8d6cSVaclav Hapla PetscErrorCode DMPlexCheck(DM dm)
8764b5a892a1SMatthew G. Knepley {
87657f9d8d6cSVaclav Hapla   PetscInt cellHeight;
87667f9d8d6cSVaclav Hapla 
8767b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
87687f9d8d6cSVaclav Hapla   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
87699566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckSymmetry(dm));
87709566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckSkeleton(dm, cellHeight));
87719566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckFaces(dm, cellHeight));
87729566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckGeometry(dm));
87737726db96SVaclav Hapla   PetscCall(DMPlexCheckPointSF(dm, NULL));
87749566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckInterfaceCones(dm));
8775b5a892a1SMatthew G. Knepley   PetscFunctionReturn(0);
8776b5a892a1SMatthew G. Knepley }
8777b5a892a1SMatthew G. Knepley 
8778068a5610SStefano Zampini typedef struct cell_stats
8779068a5610SStefano Zampini {
8780068a5610SStefano Zampini   PetscReal min, max, sum, squaresum;
8781068a5610SStefano Zampini   PetscInt  count;
8782068a5610SStefano Zampini } cell_stats_t;
8783068a5610SStefano Zampini 
878425befc3bSSatish Balay static void MPIAPI cell_stats_reduce(void *a, void *b, int * len, MPI_Datatype *datatype)
8785068a5610SStefano Zampini {
8786068a5610SStefano Zampini   PetscInt i, N = *len;
8787068a5610SStefano Zampini 
8788068a5610SStefano Zampini   for (i = 0; i < N; i++) {
8789068a5610SStefano Zampini     cell_stats_t *A = (cell_stats_t *) a;
8790068a5610SStefano Zampini     cell_stats_t *B = (cell_stats_t *) b;
8791068a5610SStefano Zampini 
8792068a5610SStefano Zampini     B->min = PetscMin(A->min,B->min);
8793068a5610SStefano Zampini     B->max = PetscMax(A->max,B->max);
8794068a5610SStefano Zampini     B->sum += A->sum;
8795068a5610SStefano Zampini     B->squaresum += A->squaresum;
8796068a5610SStefano Zampini     B->count += A->count;
8797068a5610SStefano Zampini   }
8798068a5610SStefano Zampini }
8799068a5610SStefano Zampini 
8800068a5610SStefano Zampini /*@
880143fa8764SMatthew G. Knepley   DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics.
8802068a5610SStefano Zampini 
88038261a58bSMatthew G. Knepley   Collective on dm
88048261a58bSMatthew G. Knepley 
8805068a5610SStefano Zampini   Input Parameters:
8806068a5610SStefano Zampini + dm        - The DMPlex object
880743fa8764SMatthew G. Knepley . output    - If true, statistics will be displayed on stdout
880843fa8764SMatthew G. Knepley - condLimit - Display all cells above this condition number, or PETSC_DETERMINE for no cell output
8809068a5610SStefano Zampini 
881095eb5ee5SVaclav Hapla   Notes:
881195eb5ee5SVaclav Hapla   This is mainly intended for debugging/testing purposes.
881295eb5ee5SVaclav Hapla 
881395eb5ee5SVaclav Hapla   For the complete list of DMPlexCheck* functions, see DMSetFromOptions().
8814068a5610SStefano Zampini 
8815068a5610SStefano Zampini   Level: developer
8816068a5610SStefano Zampini 
8817db781477SPatrick Sanan .seealso: `DMSetFromOptions()`, `DMPlexComputeOrthogonalQuality()`
8818068a5610SStefano Zampini @*/
881943fa8764SMatthew G. Knepley PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit)
8820068a5610SStefano Zampini {
8821068a5610SStefano Zampini   DM             dmCoarse;
882243fa8764SMatthew G. Knepley   cell_stats_t   stats, globalStats;
882343fa8764SMatthew G. Knepley   MPI_Comm       comm = PetscObjectComm((PetscObject)dm);
882443fa8764SMatthew G. Knepley   PetscReal      *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0;
882543fa8764SMatthew G. Knepley   PetscReal      limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL;
8826412e9a14SMatthew G. Knepley   PetscInt       cdim, cStart, cEnd, c, eStart, eEnd, count = 0;
882743fa8764SMatthew G. Knepley   PetscMPIInt    rank,size;
8828068a5610SStefano Zampini 
8829068a5610SStefano Zampini   PetscFunctionBegin;
8830068a5610SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8831068a5610SStefano Zampini   stats.min   = PETSC_MAX_REAL;
8832068a5610SStefano Zampini   stats.max   = PETSC_MIN_REAL;
8833068a5610SStefano Zampini   stats.sum   = stats.squaresum = 0.;
8834068a5610SStefano Zampini   stats.count = 0;
8835068a5610SStefano Zampini 
88369566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
88379566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
88389566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm,&cdim));
88399566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ));
88409566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSimplexOrBoxCells(dm,0,&cStart,&cEnd));
88419566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm,1,&eStart,&eEnd));
8842412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; c++) {
8843068a5610SStefano Zampini     PetscInt  i;
8844068a5610SStefano Zampini     PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ;
8845068a5610SStefano Zampini 
88469566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellGeometryAffineFEM(dm,c,NULL,J,invJ,&detJ));
884763a3b9bcSJacob Faibussowitsch     PetscCheck(detJ >= 0.0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " is inverted", c);
884843fa8764SMatthew G. Knepley     for (i = 0; i < PetscSqr(cdim); ++i) {
8849068a5610SStefano Zampini       frobJ    += J[i] * J[i];
8850068a5610SStefano Zampini       frobInvJ += invJ[i] * invJ[i];
8851068a5610SStefano Zampini     }
8852068a5610SStefano Zampini     cond2 = frobJ * frobInvJ;
8853068a5610SStefano Zampini     cond  = PetscSqrtReal(cond2);
8854068a5610SStefano Zampini 
8855068a5610SStefano Zampini     stats.min        = PetscMin(stats.min,cond);
8856068a5610SStefano Zampini     stats.max        = PetscMax(stats.max,cond);
8857068a5610SStefano Zampini     stats.sum       += cond;
8858068a5610SStefano Zampini     stats.squaresum += cond2;
8859068a5610SStefano Zampini     stats.count++;
88608261a58bSMatthew G. Knepley     if (output && cond > limit) {
886143fa8764SMatthew G. Knepley       PetscSection coordSection;
886243fa8764SMatthew G. Knepley       Vec          coordsLocal;
886343fa8764SMatthew G. Knepley       PetscScalar *coords = NULL;
886443fa8764SMatthew G. Knepley       PetscInt     Nv, d, clSize, cl, *closure = NULL;
886543fa8764SMatthew G. Knepley 
88669566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal));
88679566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinateSection(dm, &coordSection));
88689566063dSJacob Faibussowitsch       PetscCall(DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords));
886963a3b9bcSJacob Faibussowitsch       PetscCall(PetscSynchronizedPrintf(comm, "[%d] Cell %" PetscInt_FMT " cond %g\n", rank, c, (double) cond));
887043fa8764SMatthew G. Knepley       for (i = 0; i < Nv/cdim; ++i) {
887163a3b9bcSJacob Faibussowitsch         PetscCall(PetscSynchronizedPrintf(comm, "  Vertex %" PetscInt_FMT ": (", i));
887243fa8764SMatthew G. Knepley         for (d = 0; d < cdim; ++d) {
88739566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscSynchronizedPrintf(comm, ", "));
88749566063dSJacob Faibussowitsch           PetscCall(PetscSynchronizedPrintf(comm, "%g", (double) PetscRealPart(coords[i*cdim+d])));
887543fa8764SMatthew G. Knepley         }
88769566063dSJacob Faibussowitsch         PetscCall(PetscSynchronizedPrintf(comm, ")\n"));
887743fa8764SMatthew G. Knepley       }
88789566063dSJacob Faibussowitsch       PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure));
887943fa8764SMatthew G. Knepley       for (cl = 0; cl < clSize*2; cl += 2) {
888043fa8764SMatthew G. Knepley         const PetscInt edge = closure[cl];
888143fa8764SMatthew G. Knepley 
888243fa8764SMatthew G. Knepley         if ((edge >= eStart) && (edge < eEnd)) {
888343fa8764SMatthew G. Knepley           PetscReal len;
888443fa8764SMatthew G. Knepley 
88859566063dSJacob Faibussowitsch           PetscCall(DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL));
888663a3b9bcSJacob Faibussowitsch           PetscCall(PetscSynchronizedPrintf(comm, "  Edge %" PetscInt_FMT ": length %g\n", edge, (double) len));
888743fa8764SMatthew G. Knepley         }
888843fa8764SMatthew G. Knepley       }
88899566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure));
88909566063dSJacob Faibussowitsch       PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords));
889143fa8764SMatthew G. Knepley     }
8892068a5610SStefano Zampini   }
88939566063dSJacob Faibussowitsch   if (output) PetscCall(PetscSynchronizedFlush(comm, NULL));
8894068a5610SStefano Zampini 
8895068a5610SStefano Zampini   if (size > 1) {
8896068a5610SStefano Zampini     PetscMPIInt   blockLengths[2] = {4,1};
8897068a5610SStefano Zampini     MPI_Aint      blockOffsets[2] = {offsetof(cell_stats_t,min),offsetof(cell_stats_t,count)};
8898068a5610SStefano Zampini     MPI_Datatype  blockTypes[2]   = {MPIU_REAL,MPIU_INT}, statType;
8899068a5610SStefano Zampini     MPI_Op        statReduce;
8900068a5610SStefano Zampini 
89019566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_create_struct(2,blockLengths,blockOffsets,blockTypes,&statType));
89029566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_commit(&statType));
89039566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce));
89049566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&stats,&globalStats,1,statType,statReduce,0,comm));
89059566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Op_free(&statReduce));
89069566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_free(&statType));
8907068a5610SStefano Zampini   } else {
89089566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(&globalStats,&stats,1));
8909068a5610SStefano Zampini   }
8910dd400576SPatrick Sanan   if (rank == 0) {
8911068a5610SStefano Zampini     count = globalStats.count;
8912068a5610SStefano Zampini     min   = globalStats.min;
8913068a5610SStefano Zampini     max   = globalStats.max;
8914068a5610SStefano Zampini     mean  = globalStats.sum / globalStats.count;
8915068a5610SStefano Zampini     stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1),0)) : 0.0;
8916068a5610SStefano Zampini   }
8917068a5610SStefano Zampini 
8918068a5610SStefano Zampini   if (output) {
891963a3b9bcSJacob Faibussowitsch     PetscCall(PetscPrintf(comm,"Mesh with %" PetscInt_FMT " cells, shape condition numbers: min = %g, max = %g, mean = %g, stddev = %g\n", count, (double) min, (double) max, (double) mean, (double) stdev));
8920068a5610SStefano Zampini   }
89219566063dSJacob Faibussowitsch   PetscCall(PetscFree2(J,invJ));
8922068a5610SStefano Zampini 
89239566063dSJacob Faibussowitsch   PetscCall(DMGetCoarseDM(dm,&dmCoarse));
8924068a5610SStefano Zampini   if (dmCoarse) {
8925068a5610SStefano Zampini     PetscBool isplex;
8926068a5610SStefano Zampini 
89279566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)dmCoarse,DMPLEX,&isplex));
89281baa6e33SBarry Smith     if (isplex) PetscCall(DMPlexCheckCellShape(dmCoarse,output,condLimit));
8929068a5610SStefano Zampini   }
8930068a5610SStefano Zampini   PetscFunctionReturn(0);
8931068a5610SStefano Zampini }
8932068a5610SStefano Zampini 
8933f108dbd7SJacob Faibussowitsch /*@
8934f108dbd7SJacob Faibussowitsch   DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with
8935f108dbd7SJacob Faibussowitsch   orthogonal quality below given tolerance.
8936f108dbd7SJacob Faibussowitsch 
89376ed19f2fSJacob Faibussowitsch   Collective on dm
8938f108dbd7SJacob Faibussowitsch 
8939f108dbd7SJacob Faibussowitsch   Input Parameters:
8940f108dbd7SJacob Faibussowitsch + dm   - The DMPlex object
8941f108dbd7SJacob Faibussowitsch . fv   - Optional PetscFV object for pre-computed cell/face centroid information
8942f108dbd7SJacob Faibussowitsch - atol - [0, 1] Absolute tolerance for tagging cells.
8943f108dbd7SJacob Faibussowitsch 
8944f108dbd7SJacob Faibussowitsch   Output Parameters:
8945f108dbd7SJacob Faibussowitsch + OrthQual      - Vec containing orthogonal quality per cell
8946f108dbd7SJacob Faibussowitsch - OrthQualLabel - DMLabel tagging cells below atol with DM_ADAPT_REFINE
8947f108dbd7SJacob Faibussowitsch 
8948f108dbd7SJacob Faibussowitsch   Options Database Keys:
8949f108dbd7SJacob Faibussowitsch + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only PETSCVIEWERASCII is
8950f108dbd7SJacob Faibussowitsch supported.
8951f108dbd7SJacob Faibussowitsch - -dm_plex_orthogonal_quality_vec_view - view OrthQual vector.
8952f108dbd7SJacob Faibussowitsch 
8953f108dbd7SJacob Faibussowitsch   Notes:
8954f108dbd7SJacob Faibussowitsch   Orthogonal quality is given by the following formula:
8955f108dbd7SJacob Faibussowitsch 
8956f108dbd7SJacob Faibussowitsch   \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right]
8957f108dbd7SJacob Faibussowitsch 
8958f108dbd7SJacob 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
8959f108dbd7SJacob Faibussowitsch   is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the
8960f108dbd7SJacob Faibussowitsch   current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by
8961f108dbd7SJacob Faibussowitsch   calculating the cosine of the angle between these vectors.
8962f108dbd7SJacob Faibussowitsch 
8963f108dbd7SJacob Faibussowitsch   Orthogonal quality ranges from 1 (best) to 0 (worst).
8964f108dbd7SJacob Faibussowitsch 
8965f108dbd7SJacob Faibussowitsch   This routine is mainly useful for FVM, however is not restricted to only FVM. The PetscFV object is optionally used to check for
8966f108dbd7SJacob Faibussowitsch   pre-computed FVM cell data, but if it is not passed in then this data will be computed.
8967f108dbd7SJacob Faibussowitsch 
8968f108dbd7SJacob Faibussowitsch   Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance.
8969f108dbd7SJacob Faibussowitsch 
8970f108dbd7SJacob Faibussowitsch   Level: intermediate
8971f108dbd7SJacob Faibussowitsch 
8972db781477SPatrick Sanan .seealso: `DMPlexCheckCellShape()`, `DMCreateLabel()`
8973f108dbd7SJacob Faibussowitsch @*/
8974f108dbd7SJacob Faibussowitsch PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel)
8975f108dbd7SJacob Faibussowitsch {
89766ed19f2fSJacob Faibussowitsch   PetscInt                nc, cellHeight, cStart, cEnd, cell, cellIter = 0;
89776ed19f2fSJacob Faibussowitsch   PetscInt                *idx;
89786ed19f2fSJacob Faibussowitsch   PetscScalar             *oqVals;
8979f108dbd7SJacob Faibussowitsch   const PetscScalar       *cellGeomArr, *faceGeomArr;
89806ed19f2fSJacob Faibussowitsch   PetscReal               *ci, *fi, *Ai;
8981f108dbd7SJacob Faibussowitsch   MPI_Comm                comm;
8982f108dbd7SJacob Faibussowitsch   Vec                     cellgeom, facegeom;
8983f108dbd7SJacob Faibussowitsch   DM                      dmFace, dmCell;
8984f108dbd7SJacob Faibussowitsch   IS                      glob;
8985f108dbd7SJacob Faibussowitsch   ISLocalToGlobalMapping  ltog;
8986f108dbd7SJacob Faibussowitsch   PetscViewer             vwr;
8987f108dbd7SJacob Faibussowitsch 
8988f108dbd7SJacob Faibussowitsch   PetscFunctionBegin;
8989f108dbd7SJacob Faibussowitsch   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
89906ed19f2fSJacob Faibussowitsch   if (fv) {PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2);}
8991f108dbd7SJacob Faibussowitsch   PetscValidPointer(OrthQual, 4);
89926bdcaf15SBarry Smith   PetscCheck(atol >= 0.0 && atol <= 1.0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Absolute tolerance %g not in [0,1]",(double)atol);
89939566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject) dm, &comm));
89949566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &nc));
899563a3b9bcSJacob Faibussowitsch   PetscCheck(nc >= 2,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %" PetscInt_FMT ")", nc);
89966ed19f2fSJacob Faibussowitsch   {
89976ed19f2fSJacob Faibussowitsch     DMPlexInterpolatedFlag interpFlag;
89986ed19f2fSJacob Faibussowitsch 
89999566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated(dm, &interpFlag));
9000f108dbd7SJacob Faibussowitsch     if (interpFlag != DMPLEX_INTERPOLATED_FULL) {
9001f108dbd7SJacob Faibussowitsch       PetscMPIInt rank;
9002f108dbd7SJacob Faibussowitsch 
90039566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(comm, &rank));
900498921bdaSJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank);
9005f108dbd7SJacob Faibussowitsch     }
90066ed19f2fSJacob Faibussowitsch   }
9007f108dbd7SJacob Faibussowitsch   if (OrthQualLabel) {
9008f108dbd7SJacob Faibussowitsch     PetscValidPointer(OrthQualLabel, 5);
90099566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(dm, "Orthogonal_Quality"));
90109566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel));
90116ed19f2fSJacob Faibussowitsch   } else {*OrthQualLabel = NULL;}
90129566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
90139566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
90149566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob));
90159566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreateIS(glob, &ltog));
90169566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH));
90179566063dSJacob Faibussowitsch   PetscCall(VecCreate(comm, OrthQual));
90189566063dSJacob Faibussowitsch   PetscCall(VecSetType(*OrthQual, VECSTANDARD));
90199566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(*OrthQual, cEnd-cStart, PETSC_DETERMINE));
90209566063dSJacob Faibussowitsch   PetscCall(VecSetLocalToGlobalMapping(*OrthQual, ltog));
90219566063dSJacob Faibussowitsch   PetscCall(VecSetUp(*OrthQual));
90229566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&glob));
90239566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&ltog));
90249566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL));
90259566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(cellgeom, &cellGeomArr));
90269566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(facegeom, &faceGeomArr));
90279566063dSJacob Faibussowitsch   PetscCall(VecGetDM(cellgeom, &dmCell));
90289566063dSJacob Faibussowitsch   PetscCall(VecGetDM(facegeom, &dmFace));
90299566063dSJacob Faibussowitsch   PetscCall(PetscMalloc5(cEnd-cStart, &idx, cEnd-cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai));
90306ed19f2fSJacob Faibussowitsch   for (cell = cStart; cell < cEnd; cellIter++,cell++) {
90316ed19f2fSJacob Faibussowitsch     PetscInt           cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE;
9032f108dbd7SJacob Faibussowitsch     PetscInt           cellarr[2], *adj = NULL;
9033f108dbd7SJacob Faibussowitsch     PetscScalar        *cArr, *fArr;
9034898cd552SSatish Balay     PetscReal          minvalc = 1.0, minvalf = 1.0;
9035f108dbd7SJacob Faibussowitsch     PetscFVCellGeom    *cg;
9036f108dbd7SJacob Faibussowitsch 
90376ed19f2fSJacob Faibussowitsch     idx[cellIter] = cell-cStart;
9038f108dbd7SJacob Faibussowitsch     cellarr[0] = cell;
9039f108dbd7SJacob Faibussowitsch     /* Make indexing into cellGeom easier */
90409566063dSJacob Faibussowitsch     PetscCall(DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg));
90419566063dSJacob Faibussowitsch     PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj));
9042f108dbd7SJacob Faibussowitsch     /* Technically 1 too big, but easier than fiddling with empty adjacency array */
90439566063dSJacob Faibussowitsch     PetscCall(PetscCalloc2(adjSize, &cArr, adjSize, &fArr));
90446ed19f2fSJacob Faibussowitsch     for (cellneigh = 0; cellneigh < adjSize; cellneighiter++,cellneigh++) {
90456ed19f2fSJacob Faibussowitsch       PetscInt         i;
90466ed19f2fSJacob Faibussowitsch       const PetscInt   neigh = adj[cellneigh];
9047f108dbd7SJacob Faibussowitsch       PetscReal        normci = 0, normfi = 0, normai = 0;
9048f108dbd7SJacob Faibussowitsch       PetscFVCellGeom  *cgneigh;
9049f108dbd7SJacob Faibussowitsch       PetscFVFaceGeom  *fg;
9050f108dbd7SJacob Faibussowitsch 
9051f108dbd7SJacob Faibussowitsch       /* Don't count ourselves in the neighbor list */
9052f108dbd7SJacob Faibussowitsch       if (neigh == cell) continue;
90539566063dSJacob Faibussowitsch       PetscCall(DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh));
9054f108dbd7SJacob Faibussowitsch       cellarr[1] = neigh;
90556ed19f2fSJacob Faibussowitsch       {
90566ed19f2fSJacob Faibussowitsch         PetscInt       numcovpts;
90576ed19f2fSJacob Faibussowitsch         const PetscInt *covpts;
90586ed19f2fSJacob Faibussowitsch 
90599566063dSJacob Faibussowitsch         PetscCall(DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts));
90609566063dSJacob Faibussowitsch         PetscCall(DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg));
90619566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts));
90626ed19f2fSJacob Faibussowitsch       }
9063f108dbd7SJacob Faibussowitsch 
9064f108dbd7SJacob Faibussowitsch       /* Compute c_i, f_i and their norms */
9065f108dbd7SJacob Faibussowitsch       for (i = 0; i < nc; i++) {
9066f108dbd7SJacob Faibussowitsch         ci[i] = cgneigh->centroid[i] - cg->centroid[i];
9067f108dbd7SJacob Faibussowitsch         fi[i] = fg->centroid[i] - cg->centroid[i];
9068f108dbd7SJacob Faibussowitsch         Ai[i] = fg->normal[i];
9069addd1e01SJunchao Zhang         normci += PetscPowReal(ci[i], 2);
9070addd1e01SJunchao Zhang         normfi += PetscPowReal(fi[i], 2);
9071addd1e01SJunchao Zhang         normai += PetscPowReal(Ai[i], 2);
9072f108dbd7SJacob Faibussowitsch       }
9073addd1e01SJunchao Zhang       normci = PetscSqrtReal(normci);
9074addd1e01SJunchao Zhang       normfi = PetscSqrtReal(normfi);
9075addd1e01SJunchao Zhang       normai = PetscSqrtReal(normai);
9076f108dbd7SJacob Faibussowitsch 
9077f108dbd7SJacob Faibussowitsch       /* Normalize and compute for each face-cell-normal pair */
9078f108dbd7SJacob Faibussowitsch       for (i = 0; i < nc; i++) {
9079f108dbd7SJacob Faibussowitsch         ci[i] = ci[i]/normci;
9080f108dbd7SJacob Faibussowitsch         fi[i] = fi[i]/normfi;
9081f108dbd7SJacob Faibussowitsch         Ai[i] = Ai[i]/normai;
9082f108dbd7SJacob Faibussowitsch         /* PetscAbs because I don't know if normals are guaranteed to point out */
9083f108dbd7SJacob Faibussowitsch         cArr[cellneighiter] += PetscAbs(Ai[i]*ci[i]);
9084f108dbd7SJacob Faibussowitsch         fArr[cellneighiter] += PetscAbs(Ai[i]*fi[i]);
9085f108dbd7SJacob Faibussowitsch       }
9086f108dbd7SJacob Faibussowitsch       if (PetscRealPart(cArr[cellneighiter]) < minvalc) {
9087f108dbd7SJacob Faibussowitsch         minvalc = PetscRealPart(cArr[cellneighiter]);
9088f108dbd7SJacob Faibussowitsch       }
9089f108dbd7SJacob Faibussowitsch       if (PetscRealPart(fArr[cellneighiter]) < minvalf) {
9090f108dbd7SJacob Faibussowitsch         minvalf = PetscRealPart(fArr[cellneighiter]);
9091f108dbd7SJacob Faibussowitsch       }
9092f108dbd7SJacob Faibussowitsch     }
90939566063dSJacob Faibussowitsch     PetscCall(PetscFree(adj));
90949566063dSJacob Faibussowitsch     PetscCall(PetscFree2(cArr, fArr));
9095f108dbd7SJacob Faibussowitsch     /* Defer to cell if they're equal */
90966ed19f2fSJacob Faibussowitsch     oqVals[cellIter] = PetscMin(minvalf, minvalc);
9097f108dbd7SJacob Faibussowitsch     if (OrthQualLabel) {
90989566063dSJacob Faibussowitsch       if (PetscRealPart(oqVals[cellIter]) <= atol) PetscCall(DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE));
9099f108dbd7SJacob Faibussowitsch     }
9100f108dbd7SJacob Faibussowitsch   }
91019566063dSJacob Faibussowitsch   PetscCall(VecSetValuesLocal(*OrthQual, cEnd-cStart, idx, oqVals, INSERT_VALUES));
91029566063dSJacob Faibussowitsch   PetscCall(VecAssemblyBegin(*OrthQual));
91039566063dSJacob Faibussowitsch   PetscCall(VecAssemblyEnd(*OrthQual));
91049566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(cellgeom, &cellGeomArr));
91059566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(facegeom, &faceGeomArr));
91069566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL));
9107f108dbd7SJacob Faibussowitsch   if (OrthQualLabel) {
91089566063dSJacob Faibussowitsch     if (vwr) PetscCall(DMLabelView(*OrthQualLabel, vwr));
9109f108dbd7SJacob Faibussowitsch   }
91109566063dSJacob Faibussowitsch   PetscCall(PetscFree5(idx, oqVals, ci, fi, Ai));
91119566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(&vwr));
91129566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view"));
9113f108dbd7SJacob Faibussowitsch   PetscFunctionReturn(0);
9114f108dbd7SJacob Faibussowitsch }
9115f108dbd7SJacob Faibussowitsch 
91161eb70e55SToby Isaac /* this is here insead of DMGetOutputDM because output DM still has constraints in the local indices that affect
91171eb70e55SToby Isaac  * interpolator construction */
91181eb70e55SToby Isaac static PetscErrorCode DMGetFullDM(DM dm, DM *odm)
91191eb70e55SToby Isaac {
91201eb70e55SToby Isaac   PetscSection   section, newSection, gsection;
91211eb70e55SToby Isaac   PetscSF        sf;
91221eb70e55SToby Isaac   PetscBool      hasConstraints, ghasConstraints;
91231eb70e55SToby Isaac 
91241eb70e55SToby Isaac   PetscFunctionBegin;
91251eb70e55SToby Isaac   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
91261eb70e55SToby Isaac   PetscValidPointer(odm,2);
91279566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
91289566063dSJacob Faibussowitsch   PetscCall(PetscSectionHasConstraints(section, &hasConstraints));
91299566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject) dm)));
91301eb70e55SToby Isaac   if (!ghasConstraints) {
91319566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm));
91321eb70e55SToby Isaac     *odm = dm;
91331eb70e55SToby Isaac     PetscFunctionReturn(0);
91341eb70e55SToby Isaac   }
91359566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, odm));
91369566063dSJacob Faibussowitsch   PetscCall(DMCopyFields(dm, *odm));
91379566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(*odm, &newSection));
91389566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(*odm, &sf));
91399566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_FALSE, &gsection));
91409566063dSJacob Faibussowitsch   PetscCall(DMSetGlobalSection(*odm, gsection));
91419566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&gsection));
91421eb70e55SToby Isaac   PetscFunctionReturn(0);
91431eb70e55SToby Isaac }
91441eb70e55SToby Isaac 
91451eb70e55SToby Isaac static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift)
91461eb70e55SToby Isaac {
91471eb70e55SToby Isaac   DM             dmco, dmfo;
91481eb70e55SToby Isaac   Mat            interpo;
91491eb70e55SToby Isaac   Vec            rscale;
91501eb70e55SToby Isaac   Vec            cglobalo, clocal;
91511eb70e55SToby Isaac   Vec            fglobal, fglobalo, flocal;
91521eb70e55SToby Isaac   PetscBool      regular;
91531eb70e55SToby Isaac 
91541eb70e55SToby Isaac   PetscFunctionBegin;
91559566063dSJacob Faibussowitsch   PetscCall(DMGetFullDM(dmc, &dmco));
91569566063dSJacob Faibussowitsch   PetscCall(DMGetFullDM(dmf, &dmfo));
91579566063dSJacob Faibussowitsch   PetscCall(DMSetCoarseDM(dmfo, dmco));
91589566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRegularRefinement(dmf, &regular));
91599566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRegularRefinement(dmfo, regular));
91609566063dSJacob Faibussowitsch   PetscCall(DMCreateInterpolation(dmco, dmfo, &interpo, &rscale));
91619566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmco, &cglobalo));
91629566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dmc, &clocal));
91639566063dSJacob Faibussowitsch   PetscCall(VecSet(cglobalo, 0.));
91649566063dSJacob Faibussowitsch   PetscCall(VecSet(clocal, 0.));
91659566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmf, &fglobal));
91669566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmfo, &fglobalo));
91679566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dmf, &flocal));
91689566063dSJacob Faibussowitsch   PetscCall(VecSet(fglobal, 0.));
91699566063dSJacob Faibussowitsch   PetscCall(VecSet(fglobalo, 0.));
91709566063dSJacob Faibussowitsch   PetscCall(VecSet(flocal, 0.));
91719566063dSJacob Faibussowitsch   PetscCall(DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL));
91729566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo));
91739566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo));
91749566063dSJacob Faibussowitsch   PetscCall(MatMult(interpo, cglobalo, fglobalo));
91759566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal));
91769566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal));
91779566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal));
91789566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal));
91791eb70e55SToby Isaac   *shift = fglobal;
91809566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&flocal));
91819566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&fglobalo));
91829566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&clocal));
91839566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&cglobalo));
91849566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&rscale));
91859566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&interpo));
91869566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmfo));
91879566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmco));
91881eb70e55SToby Isaac   PetscFunctionReturn(0);
91891eb70e55SToby Isaac }
91901eb70e55SToby Isaac 
91911eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol)
91921eb70e55SToby Isaac {
91931eb70e55SToby Isaac   PetscObject    shifto;
91941eb70e55SToby Isaac   Vec            shift;
91951eb70e55SToby Isaac 
91961eb70e55SToby Isaac   PetscFunctionBegin;
91971eb70e55SToby Isaac   if (!interp) {
91981eb70e55SToby Isaac     Vec rscale;
91991eb70e55SToby Isaac 
92009566063dSJacob Faibussowitsch     PetscCall(DMCreateInterpolation(coarse, fine, &interp, &rscale));
92019566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&rscale));
92021eb70e55SToby Isaac   } else {
92039566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)interp));
92041eb70e55SToby Isaac   }
92059566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto));
92061eb70e55SToby Isaac   if (!shifto) {
92079566063dSJacob Faibussowitsch     PetscCall(DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift));
92089566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject) shift));
92091eb70e55SToby Isaac     shifto = (PetscObject) shift;
92109566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&shift));
92111eb70e55SToby Isaac   }
92121eb70e55SToby Isaac   shift = (Vec) shifto;
92139566063dSJacob Faibussowitsch   PetscCall(MatInterpolate(interp, coarseSol, fineSol));
92149566063dSJacob Faibussowitsch   PetscCall(VecAXPY(fineSol, 1.0, shift));
92159566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&interp));
92161eb70e55SToby Isaac   PetscFunctionReturn(0);
92171eb70e55SToby Isaac }
92181eb70e55SToby Isaac 
9219bceba477SMatthew G. Knepley /* Pointwise interpolation
9220bceba477SMatthew G. Knepley      Just code FEM for now
9221bceba477SMatthew G. Knepley      u^f = I u^c
92224ca5e9f5SMatthew G. Knepley      sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j
92234ca5e9f5SMatthew G. Knepley      u^f_i = sum_j psi^f_i I phi^c_j u^c_j
92244ca5e9f5SMatthew G. Knepley      I_{ij} = psi^f_i phi^c_j
9225bceba477SMatthew G. Knepley */
9226bceba477SMatthew G. Knepley PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling)
9227bceba477SMatthew G. Knepley {
9228bceba477SMatthew G. Knepley   PetscSection   gsc, gsf;
9229bceba477SMatthew G. Knepley   PetscInt       m, n;
9230a063dac3SMatthew G. Knepley   void          *ctx;
923168132eb9SMatthew G. Knepley   DM             cdm;
9232cf51de39SMatthew G. Knepley   PetscBool      regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE;
9233bceba477SMatthew G. Knepley 
9234bceba477SMatthew G. Knepley   PetscFunctionBegin;
92359566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmFine, &gsf));
92369566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m));
92379566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmCoarse, &gsc));
92389566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n));
923968132eb9SMatthew G. Knepley 
92409566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis));
92419566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation));
92429566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE));
92439566063dSJacob Faibussowitsch   PetscCall(MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype));
92449566063dSJacob Faibussowitsch   PetscCall(DMGetApplicationContext(dmFine, &ctx));
924568132eb9SMatthew G. Knepley 
92469566063dSJacob Faibussowitsch   PetscCall(DMGetCoarseDM(dmFine, &cdm));
92479566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRegularRefinement(dmFine, &regular));
92489566063dSJacob Faibussowitsch   if (!isRefined || (regular && cdm == dmCoarse)) PetscCall(DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx));
92499566063dSJacob Faibussowitsch   else                                            PetscCall(DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx));
92509566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view"));
92514db47ee9SStefano Zampini   if (scaling) {
92525d1c2e58SMatthew G. Knepley     /* Use naive scaling */
92539566063dSJacob Faibussowitsch     PetscCall(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling));
92544db47ee9SStefano Zampini   }
9255a063dac3SMatthew G. Knepley   PetscFunctionReturn(0);
9256a063dac3SMatthew G. Knepley }
9257bceba477SMatthew G. Knepley 
92586dbf9973SLawrence Mitchell PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat)
9259a063dac3SMatthew G. Knepley {
92606dbf9973SLawrence Mitchell   VecScatter     ctx;
926190748bafSMatthew G. Knepley 
9262a063dac3SMatthew G. Knepley   PetscFunctionBegin;
92639566063dSJacob Faibussowitsch   PetscCall(DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL));
92649566063dSJacob Faibussowitsch   PetscCall(MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat));
92659566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&ctx));
9266bceba477SMatthew G. Knepley   PetscFunctionReturn(0);
9267bceba477SMatthew G. Knepley }
9268bceba477SMatthew G. Knepley 
92693e9753d6SMatthew G. Knepley static void g0_identity_private(PetscInt dim, PetscInt Nf, PetscInt NfAux,
92703e9753d6SMatthew G. Knepley                                 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[],
92713e9753d6SMatthew G. Knepley                                 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[],
92723e9753d6SMatthew G. Knepley                                 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[])
92733e9753d6SMatthew G. Knepley {
927400635df3SMatthew G. Knepley   const PetscInt Nc = uOff[1] - uOff[0];
927500635df3SMatthew G. Knepley   PetscInt       c;
927600635df3SMatthew G. Knepley   for (c = 0; c < Nc; ++c) g0[c*Nc+c] = 1.0;
92773e9753d6SMatthew G. Knepley }
92783e9753d6SMatthew G. Knepley 
9279b4937a87SMatthew G. Knepley PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *mass)
9280b4937a87SMatthew G. Knepley {
9281b4937a87SMatthew G. Knepley   DM             dmc;
9282b4937a87SMatthew G. Knepley   PetscDS        ds;
9283b4937a87SMatthew G. Knepley   Vec            ones, locmass;
9284b4937a87SMatthew G. Knepley   IS             cellIS;
9285b4937a87SMatthew G. Knepley   PetscFormKey   key;
9286b4937a87SMatthew G. Knepley   PetscInt       depth;
9287b4937a87SMatthew G. Knepley 
9288b4937a87SMatthew G. Knepley   PetscFunctionBegin;
92899566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &dmc));
92909566063dSJacob Faibussowitsch   PetscCall(DMCopyDisc(dm, dmc));
92919566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dmc, &ds));
92929566063dSJacob Faibussowitsch   PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL));
92939566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmc, mass));
92949566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dmc, &ones));
92959566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dmc, &locmass));
92969566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmc, &depth));
92979566063dSJacob Faibussowitsch   PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS));
92989566063dSJacob Faibussowitsch   PetscCall(VecSet(locmass, 0.0));
92999566063dSJacob Faibussowitsch   PetscCall(VecSet(ones, 1.0));
9300b4937a87SMatthew G. Knepley   key.label = NULL;
9301b4937a87SMatthew G. Knepley   key.value = 0;
9302b4937a87SMatthew G. Knepley   key.field = 0;
9303b4937a87SMatthew G. Knepley   key.part  = 0;
93049566063dSJacob Faibussowitsch   PetscCall(DMPlexComputeJacobian_Action_Internal(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL));
93059566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&cellIS));
93069566063dSJacob Faibussowitsch   PetscCall(VecSet(*mass, 0.0));
93079566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmc, locmass, ADD_VALUES, *mass));
93089566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmc, locmass, ADD_VALUES, *mass));
93099566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dmc, &ones));
93109566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dmc, &locmass));
93119566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmc));
9312b4937a87SMatthew G. Knepley   PetscFunctionReturn(0);
9313b4937a87SMatthew G. Knepley }
9314b4937a87SMatthew G. Knepley 
9315bd041c0cSMatthew G. Knepley PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass)
9316bd041c0cSMatthew G. Knepley {
9317bd041c0cSMatthew G. Knepley   PetscSection   gsc, gsf;
9318bd041c0cSMatthew G. Knepley   PetscInt       m, n;
9319bd041c0cSMatthew G. Knepley   void          *ctx;
9320bd041c0cSMatthew G. Knepley   DM             cdm;
9321bd041c0cSMatthew G. Knepley   PetscBool      regular;
9322bd041c0cSMatthew G. Knepley 
9323bd041c0cSMatthew G. Knepley   PetscFunctionBegin;
93243e9753d6SMatthew G. Knepley   if (dmFine == dmCoarse) {
93253e9753d6SMatthew G. Knepley     DM            dmc;
93263e9753d6SMatthew G. Knepley     PetscDS       ds;
9327b4937a87SMatthew G. Knepley     PetscWeakForm wf;
93283e9753d6SMatthew G. Knepley     Vec           u;
93293e9753d6SMatthew G. Knepley     IS            cellIS;
933006ad1575SMatthew G. Knepley     PetscFormKey  key;
93313e9753d6SMatthew G. Knepley     PetscInt      depth;
93323e9753d6SMatthew G. Knepley 
93339566063dSJacob Faibussowitsch     PetscCall(DMClone(dmFine, &dmc));
93349566063dSJacob Faibussowitsch     PetscCall(DMCopyDisc(dmFine, dmc));
93359566063dSJacob Faibussowitsch     PetscCall(DMGetDS(dmc, &ds));
93369566063dSJacob Faibussowitsch     PetscCall(PetscDSGetWeakForm(ds, &wf));
93379566063dSJacob Faibussowitsch     PetscCall(PetscWeakFormClear(wf));
93389566063dSJacob Faibussowitsch     PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL));
93399566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(dmc, mass));
93409566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalVector(dmc, &u));
93419566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dmc, &depth));
93429566063dSJacob Faibussowitsch     PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS));
93439566063dSJacob Faibussowitsch     PetscCall(MatZeroEntries(*mass));
93446528b96dSMatthew G. Knepley     key.label = NULL;
93456528b96dSMatthew G. Knepley     key.value = 0;
93466528b96dSMatthew G. Knepley     key.field = 0;
934706ad1575SMatthew G. Knepley     key.part  = 0;
93489566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL));
93499566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&cellIS));
93509566063dSJacob Faibussowitsch     PetscCall(DMRestoreGlobalVector(dmc, &u));
93519566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&dmc));
93523e9753d6SMatthew G. Knepley   } else {
93539566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dmFine, &gsf));
93549566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m));
93559566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dmCoarse, &gsc));
93569566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n));
9357bd041c0cSMatthew G. Knepley 
93589566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass));
93599566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE));
93609566063dSJacob Faibussowitsch     PetscCall(MatSetType(*mass, dmCoarse->mattype));
93619566063dSJacob Faibussowitsch     PetscCall(DMGetApplicationContext(dmFine, &ctx));
9362bd041c0cSMatthew G. Knepley 
93639566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dmFine, &cdm));
93649566063dSJacob Faibussowitsch     PetscCall(DMPlexGetRegularRefinement(dmFine, &regular));
93659566063dSJacob Faibussowitsch     if (regular && cdm == dmCoarse) PetscCall(DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx));
93669566063dSJacob Faibussowitsch     else                            PetscCall(DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx));
93673e9753d6SMatthew G. Knepley   }
93689566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view"));
9369bd041c0cSMatthew G. Knepley   PetscFunctionReturn(0);
9370bd041c0cSMatthew G. Knepley }
9371bd041c0cSMatthew G. Knepley 
93720aef6b92SMatthew G. Knepley /*@
93730aef6b92SMatthew G. Knepley   DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh
93740aef6b92SMatthew G. Knepley 
93750aef6b92SMatthew G. Knepley   Input Parameter:
93760aef6b92SMatthew G. Knepley . dm - The DMPlex object
93770aef6b92SMatthew G. Knepley 
93780aef6b92SMatthew G. Knepley   Output Parameter:
93790aef6b92SMatthew G. Knepley . regular - The flag
93800aef6b92SMatthew G. Knepley 
93810aef6b92SMatthew G. Knepley   Level: intermediate
93820aef6b92SMatthew G. Knepley 
9383db781477SPatrick Sanan .seealso: `DMPlexSetRegularRefinement()`
93840aef6b92SMatthew G. Knepley @*/
93850aef6b92SMatthew G. Knepley PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular)
93860aef6b92SMatthew G. Knepley {
93870aef6b92SMatthew G. Knepley   PetscFunctionBegin;
93880aef6b92SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9389dadcf809SJacob Faibussowitsch   PetscValidBoolPointer(regular, 2);
93900aef6b92SMatthew G. Knepley   *regular = ((DM_Plex *) dm->data)->regularRefinement;
93910aef6b92SMatthew G. Knepley   PetscFunctionReturn(0);
93920aef6b92SMatthew G. Knepley }
93930aef6b92SMatthew G. Knepley 
93940aef6b92SMatthew G. Knepley /*@
93950aef6b92SMatthew G. Knepley   DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh
93960aef6b92SMatthew G. Knepley 
93970aef6b92SMatthew G. Knepley   Input Parameters:
93980aef6b92SMatthew G. Knepley + dm - The DMPlex object
93990aef6b92SMatthew G. Knepley - regular - The flag
94000aef6b92SMatthew G. Knepley 
94010aef6b92SMatthew G. Knepley   Level: intermediate
94020aef6b92SMatthew G. Knepley 
9403db781477SPatrick Sanan .seealso: `DMPlexGetRegularRefinement()`
94040aef6b92SMatthew G. Knepley @*/
94050aef6b92SMatthew G. Knepley PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular)
94060aef6b92SMatthew G. Knepley {
94070aef6b92SMatthew G. Knepley   PetscFunctionBegin;
94080aef6b92SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
94090aef6b92SMatthew G. Knepley   ((DM_Plex *) dm->data)->regularRefinement = regular;
94100aef6b92SMatthew G. Knepley   PetscFunctionReturn(0);
94110aef6b92SMatthew G. Knepley }
94120aef6b92SMatthew G. Knepley 
9413f7c74593SToby Isaac /* anchors */
9414a68b90caSToby Isaac /*@
9415f7c74593SToby Isaac   DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints.  Typically, the user will not have to
9416ebdb1bfaSJed Brown   call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetDefaultConstraints().
9417a68b90caSToby Isaac 
9418e228b242SToby Isaac   not collective
9419a68b90caSToby Isaac 
9420f899ff85SJose E. Roman   Input Parameter:
9421a68b90caSToby Isaac . dm - The DMPlex object
9422a68b90caSToby Isaac 
9423a68b90caSToby Isaac   Output Parameters:
9424a68b90caSToby Isaac + anchorSection - If not NULL, set to the section describing which points anchor the constrained points.
9425a68b90caSToby Isaac - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection
9426a68b90caSToby Isaac 
9427a68b90caSToby Isaac   Level: intermediate
9428a68b90caSToby Isaac 
9429db781477SPatrick Sanan .seealso: `DMPlexSetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()`
9430a68b90caSToby Isaac @*/
9431a17985deSToby Isaac PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS)
9432a68b90caSToby Isaac {
9433a68b90caSToby Isaac   DM_Plex *plex = (DM_Plex *)dm->data;
9434a68b90caSToby Isaac 
9435a68b90caSToby Isaac   PetscFunctionBegin;
9436a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
94379566063dSJacob Faibussowitsch   if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) PetscCall((*plex->createanchors)(dm));
9438a68b90caSToby Isaac   if (anchorSection) *anchorSection = plex->anchorSection;
9439a68b90caSToby Isaac   if (anchorIS) *anchorIS = plex->anchorIS;
9440a68b90caSToby Isaac   PetscFunctionReturn(0);
9441a68b90caSToby Isaac }
9442a68b90caSToby Isaac 
9443a68b90caSToby Isaac /*@
9444f7c74593SToby Isaac   DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints.  Unlike boundary conditions,
9445f7c74593SToby Isaac   when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a
9446a68b90caSToby Isaac   point's degrees of freedom to be a linear combination of other points' degrees of freedom.
9447a68b90caSToby Isaac 
9448a17985deSToby Isaac   After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling
9449ebdb1bfaSJed Brown   DMGetDefaultConstraints() and filling in the entries in the constraint matrix.
9450a68b90caSToby Isaac 
9451e228b242SToby Isaac   collective on dm
9452a68b90caSToby Isaac 
9453a68b90caSToby Isaac   Input Parameters:
9454a68b90caSToby Isaac + dm - The DMPlex object
9455e228b242SToby 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).
9456e228b242SToby Isaac - anchorIS - The list of all anchor points.  Must have a local communicator (PETSC_COMM_SELF or derivative).
9457a68b90caSToby Isaac 
9458a68b90caSToby Isaac   The reference counts of anchorSection and anchorIS are incremented.
9459a68b90caSToby Isaac 
9460a68b90caSToby Isaac   Level: intermediate
9461a68b90caSToby Isaac 
9462db781477SPatrick Sanan .seealso: `DMPlexGetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()`
9463a68b90caSToby Isaac @*/
9464a17985deSToby Isaac PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS)
9465a68b90caSToby Isaac {
9466a68b90caSToby Isaac   DM_Plex        *plex = (DM_Plex *)dm->data;
9467e228b242SToby Isaac   PetscMPIInt    result;
9468a68b90caSToby Isaac 
9469a68b90caSToby Isaac   PetscFunctionBegin;
9470a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9471e228b242SToby Isaac   if (anchorSection) {
9472e228b242SToby Isaac     PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2);
94739566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result));
94741dca8a05SBarry Smith     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator");
9475e228b242SToby Isaac   }
9476e228b242SToby Isaac   if (anchorIS) {
9477e228b242SToby Isaac     PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3);
94789566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result));
94791dca8a05SBarry Smith     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT,PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator");
9480e228b242SToby Isaac   }
9481a68b90caSToby Isaac 
94829566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)anchorSection));
94839566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&plex->anchorSection));
9484a68b90caSToby Isaac   plex->anchorSection = anchorSection;
9485a68b90caSToby Isaac 
94869566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)anchorIS));
94879566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&plex->anchorIS));
9488a68b90caSToby Isaac   plex->anchorIS = anchorIS;
9489a68b90caSToby Isaac 
9490cf9c20a2SJed Brown   if (PetscUnlikelyDebug(anchorIS && anchorSection)) {
9491a68b90caSToby Isaac     PetscInt size, a, pStart, pEnd;
9492a68b90caSToby Isaac     const PetscInt *anchors;
9493a68b90caSToby Isaac 
94949566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(anchorSection,&pStart,&pEnd));
94959566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(anchorIS,&size));
94969566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(anchorIS,&anchors));
9497a68b90caSToby Isaac     for (a = 0; a < size; a++) {
9498a68b90caSToby Isaac       PetscInt p;
9499a68b90caSToby Isaac 
9500a68b90caSToby Isaac       p = anchors[a];
9501a68b90caSToby Isaac       if (p >= pStart && p < pEnd) {
9502a68b90caSToby Isaac         PetscInt dof;
9503a68b90caSToby Isaac 
95049566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(anchorSection,p,&dof));
9505a68b90caSToby Isaac         if (dof) {
9506a68b90caSToby Isaac 
95079566063dSJacob Faibussowitsch           PetscCall(ISRestoreIndices(anchorIS,&anchors));
950863a3b9bcSJacob Faibussowitsch           SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %" PetscInt_FMT " cannot be constrained and an anchor",p);
9509a68b90caSToby Isaac         }
9510a68b90caSToby Isaac       }
9511a68b90caSToby Isaac     }
95129566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(anchorIS,&anchors));
9513a68b90caSToby Isaac   }
9514f7c74593SToby Isaac   /* reset the generic constraints */
95159566063dSJacob Faibussowitsch   PetscCall(DMSetDefaultConstraints(dm,NULL,NULL,NULL));
9516a68b90caSToby Isaac   PetscFunctionReturn(0);
9517a68b90caSToby Isaac }
9518a68b90caSToby Isaac 
9519f7c74593SToby Isaac static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec)
9520a68b90caSToby Isaac {
9521f7c74593SToby Isaac   PetscSection anchorSection;
95226995de1eSToby Isaac   PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f;
9523a68b90caSToby Isaac 
9524a68b90caSToby Isaac   PetscFunctionBegin;
9525a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
95269566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm,&anchorSection,NULL));
95279566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF,cSec));
95289566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section,&numFields));
95296995de1eSToby Isaac   if (numFields) {
9530719ab38cSToby Isaac     PetscInt f;
95319566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(*cSec,numFields));
9532719ab38cSToby Isaac 
9533719ab38cSToby Isaac     for (f = 0; f < numFields; f++) {
9534719ab38cSToby Isaac       PetscInt numComp;
9535719ab38cSToby Isaac 
95369566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldComponents(section,f,&numComp));
95379566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldComponents(*cSec,f,numComp));
9538719ab38cSToby Isaac     }
95396995de1eSToby Isaac   }
95409566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(anchorSection,&pStart,&pEnd));
95419566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section,&sStart,&sEnd));
95426995de1eSToby Isaac   pStart = PetscMax(pStart,sStart);
95436995de1eSToby Isaac   pEnd   = PetscMin(pEnd,sEnd);
95446995de1eSToby Isaac   pEnd   = PetscMax(pStart,pEnd);
95459566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*cSec,pStart,pEnd));
9546a68b90caSToby Isaac   for (p = pStart; p < pEnd; p++) {
95479566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(anchorSection,p,&dof));
9548a68b90caSToby Isaac     if (dof) {
95499566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section,p,&dof));
95509566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(*cSec,p,dof));
9551a68b90caSToby Isaac       for (f = 0; f < numFields; f++) {
95529566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(section,p,f,&dof));
95539566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetFieldDof(*cSec,p,f,dof));
9554a68b90caSToby Isaac       }
9555a68b90caSToby Isaac     }
9556a68b90caSToby Isaac   }
95579566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(*cSec));
95589566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject) *cSec, "Constraint Section"));
9559a68b90caSToby Isaac   PetscFunctionReturn(0);
9560a68b90caSToby Isaac }
9561a68b90caSToby Isaac 
9562f7c74593SToby Isaac static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat)
9563a68b90caSToby Isaac {
9564f7c74593SToby Isaac   PetscSection   aSec;
9565ae65431dSMatthew G. Knepley   PetscInt       pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j;
95660ac89760SToby Isaac   const PetscInt *anchors;
95670ac89760SToby Isaac   PetscInt       numFields, f;
956866ad2231SToby Isaac   IS             aIS;
9569e19f7ee6SMark Adams   MatType        mtype;
9570e19f7ee6SMark Adams   PetscBool      iscuda,iskokkos;
95710ac89760SToby Isaac 
95720ac89760SToby Isaac   PetscFunctionBegin;
95730ac89760SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
95749566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(cSec, &m));
95759566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(section, &n));
95769566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_SELF,cMat));
95779566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*cMat,m,n,m,n));
95789566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dm->mattype,MATSEQAIJCUSPARSE,&iscuda));
95799566063dSJacob Faibussowitsch   if (!iscuda) PetscCall(PetscStrcmp(dm->mattype,MATMPIAIJCUSPARSE,&iscuda));
95809566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dm->mattype,MATSEQAIJKOKKOS,&iskokkos));
95819566063dSJacob Faibussowitsch   if (!iskokkos) PetscCall(PetscStrcmp(dm->mattype,MATMPIAIJKOKKOS,&iskokkos));
9582e19f7ee6SMark Adams   if (iscuda) mtype = MATSEQAIJCUSPARSE;
9583e19f7ee6SMark Adams   else if (iskokkos) mtype = MATSEQAIJKOKKOS;
9584e19f7ee6SMark Adams   else mtype = MATSEQAIJ;
95859566063dSJacob Faibussowitsch   PetscCall(MatSetType(*cMat,mtype));
95869566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm,&aSec,&aIS));
95879566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(aIS,&anchors));
95886995de1eSToby Isaac   /* cSec will be a subset of aSec and section */
95899566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(cSec,&pStart,&pEnd));
95909566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section,&sStart,&sEnd));
95919566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m+1,&i));
95920ac89760SToby Isaac   i[0] = 0;
95939566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section,&numFields));
95940ac89760SToby Isaac   for (p = pStart; p < pEnd; p++) {
9595f19733c5SToby Isaac     PetscInt rDof, rOff, r;
9596f19733c5SToby Isaac 
95979566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(aSec,p,&rDof));
9598f19733c5SToby Isaac     if (!rDof) continue;
95999566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(aSec,p,&rOff));
96000ac89760SToby Isaac     if (numFields) {
96010ac89760SToby Isaac       for (f = 0; f < numFields; f++) {
96020ac89760SToby Isaac         annz = 0;
9603f19733c5SToby Isaac         for (r = 0; r < rDof; r++) {
9604f19733c5SToby Isaac           a = anchors[rOff + r];
9605ae65431dSMatthew G. Knepley           if (a < sStart || a >= sEnd) continue;
96069566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section,a,f,&aDof));
96070ac89760SToby Isaac           annz += aDof;
96080ac89760SToby Isaac         }
96099566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(cSec,p,f,&dof));
96109566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldOffset(cSec,p,f,&off));
96110ac89760SToby Isaac         for (q = 0; q < dof; q++) {
96120ac89760SToby Isaac           i[off + q + 1] = i[off + q] + annz;
96130ac89760SToby Isaac         }
96140ac89760SToby Isaac       }
96152f7452b8SBarry Smith     } else {
96160ac89760SToby Isaac       annz = 0;
96179566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec,p,&dof));
96180ac89760SToby Isaac       for (q = 0; q < dof; q++) {
9619ae65431dSMatthew G. Knepley         a = anchors[rOff + q];
9620ae65431dSMatthew G. Knepley         if (a < sStart || a >= sEnd) continue;
96219566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section,a,&aDof));
96220ac89760SToby Isaac         annz += aDof;
96230ac89760SToby Isaac       }
96249566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec,p,&dof));
96259566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(cSec,p,&off));
96260ac89760SToby Isaac       for (q = 0; q < dof; q++) {
96270ac89760SToby Isaac         i[off + q + 1] = i[off + q] + annz;
96280ac89760SToby Isaac       }
96290ac89760SToby Isaac     }
96300ac89760SToby Isaac   }
96310ac89760SToby Isaac   nnz = i[m];
96329566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nnz,&j));
96330ac89760SToby Isaac   offset = 0;
96340ac89760SToby Isaac   for (p = pStart; p < pEnd; p++) {
96350ac89760SToby Isaac     if (numFields) {
96360ac89760SToby Isaac       for (f = 0; f < numFields; f++) {
96379566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(cSec,p,f,&dof));
96380ac89760SToby Isaac         for (q = 0; q < dof; q++) {
96390ac89760SToby Isaac           PetscInt rDof, rOff, r;
96409566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(aSec,p,&rDof));
96419566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(aSec,p,&rOff));
96420ac89760SToby Isaac           for (r = 0; r < rDof; r++) {
96430ac89760SToby Isaac             PetscInt s;
96440ac89760SToby Isaac 
96450ac89760SToby Isaac             a = anchors[rOff + r];
9646ae65431dSMatthew G. Knepley             if (a < sStart || a >= sEnd) continue;
96479566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section,a,f,&aDof));
96489566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldOffset(section,a,f,&aOff));
96490ac89760SToby Isaac             for (s = 0; s < aDof; s++) {
96500ac89760SToby Isaac               j[offset++] = aOff + s;
96510ac89760SToby Isaac             }
96520ac89760SToby Isaac           }
96530ac89760SToby Isaac         }
96540ac89760SToby Isaac       }
96552f7452b8SBarry Smith     } else {
96569566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec,p,&dof));
96570ac89760SToby Isaac       for (q = 0; q < dof; q++) {
96580ac89760SToby Isaac         PetscInt rDof, rOff, r;
96599566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(aSec,p,&rDof));
96609566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec,p,&rOff));
96610ac89760SToby Isaac         for (r = 0; r < rDof; r++) {
96620ac89760SToby Isaac           PetscInt s;
96630ac89760SToby Isaac 
96640ac89760SToby Isaac           a = anchors[rOff + r];
9665ae65431dSMatthew G. Knepley           if (a < sStart || a >= sEnd) continue;
96669566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section,a,&aDof));
96679566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(section,a,&aOff));
96680ac89760SToby Isaac           for (s = 0; s < aDof; s++) {
96690ac89760SToby Isaac             j[offset++] = aOff + s;
96700ac89760SToby Isaac           }
96710ac89760SToby Isaac         }
96720ac89760SToby Isaac       }
96730ac89760SToby Isaac     }
96740ac89760SToby Isaac   }
96759566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL));
96769566063dSJacob Faibussowitsch   PetscCall(PetscFree(i));
96779566063dSJacob Faibussowitsch   PetscCall(PetscFree(j));
96789566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(aIS,&anchors));
96790ac89760SToby Isaac   PetscFunctionReturn(0);
96800ac89760SToby Isaac }
96810ac89760SToby Isaac 
968266ad2231SToby Isaac PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm)
968366ad2231SToby Isaac {
9684f7c74593SToby Isaac   DM_Plex        *plex = (DM_Plex *)dm->data;
9685f7c74593SToby Isaac   PetscSection   anchorSection, section, cSec;
968666ad2231SToby Isaac   Mat            cMat;
968766ad2231SToby Isaac 
968866ad2231SToby Isaac   PetscFunctionBegin;
968966ad2231SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
96909566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm,&anchorSection,NULL));
969166ad2231SToby Isaac   if (anchorSection) {
969244a7f3ddSMatthew G. Knepley     PetscInt Nf;
9693e228b242SToby Isaac 
96949566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm,&section));
96959566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateConstraintSection_Anchors(dm,section,&cSec));
96969566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat));
96979566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm,&Nf));
96989566063dSJacob Faibussowitsch     if (Nf && plex->computeanchormatrix) PetscCall((*plex->computeanchormatrix)(dm,section,cSec,cMat));
96999566063dSJacob Faibussowitsch     PetscCall(DMSetDefaultConstraints(dm,cSec,cMat,NULL));
97009566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&cSec));
97019566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&cMat));
970266ad2231SToby Isaac   }
970366ad2231SToby Isaac   PetscFunctionReturn(0);
970466ad2231SToby Isaac }
9705a93c429eSMatthew G. Knepley 
9706a93c429eSMatthew G. Knepley PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm)
9707a93c429eSMatthew G. Knepley {
9708a93c429eSMatthew G. Knepley   IS             subis;
9709a93c429eSMatthew G. Knepley   PetscSection   section, subsection;
9710a93c429eSMatthew G. Knepley 
9711a93c429eSMatthew G. Knepley   PetscFunctionBegin;
97129566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
971328b400f6SJacob Faibussowitsch   PetscCheck(section,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain");
971428b400f6SJacob Faibussowitsch   PetscCheck(subdm,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain");
9715a93c429eSMatthew G. Knepley   /* Create subdomain */
97169566063dSJacob Faibussowitsch   PetscCall(DMPlexFilter(dm, label, value, subdm));
9717a93c429eSMatthew G. Knepley   /* Create submodel */
97189566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSubpointIS(*subdm, &subis));
97199566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreateSubmeshSection(section, subis, &subsection));
97209566063dSJacob Faibussowitsch   PetscCall(DMSetLocalSection(*subdm, subsection));
97219566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&subsection));
97229566063dSJacob Faibussowitsch   PetscCall(DMCopyDisc(dm, *subdm));
9723a93c429eSMatthew G. Knepley   /* Create map from submodel to global model */
9724a93c429eSMatthew G. Knepley   if (is) {
9725a93c429eSMatthew G. Knepley     PetscSection    sectionGlobal, subsectionGlobal;
9726a93c429eSMatthew G. Knepley     IS              spIS;
9727a93c429eSMatthew G. Knepley     const PetscInt *spmap;
9728a93c429eSMatthew G. Knepley     PetscInt       *subIndices;
9729a93c429eSMatthew G. Knepley     PetscInt        subSize = 0, subOff = 0, pStart, pEnd, p;
9730a93c429eSMatthew G. Knepley     PetscInt        Nf, f, bs = -1, bsLocal[2], bsMinMax[2];
9731a93c429eSMatthew G. Knepley 
97329566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSubpointIS(*subdm, &spIS));
97339566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(spIS, &spmap));
97349566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetNumFields(section, &Nf));
97359566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dm, &sectionGlobal));
97369566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(*subdm, &subsectionGlobal));
97379566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(subsection, &pStart, &pEnd));
9738a93c429eSMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
9739a93c429eSMatthew G. Knepley       PetscInt gdof, pSubSize  = 0;
9740a93c429eSMatthew G. Knepley 
97419566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof));
9742a93c429eSMatthew G. Knepley       if (gdof > 0) {
9743a93c429eSMatthew G. Knepley         for (f = 0; f < Nf; ++f) {
9744a93c429eSMatthew G. Knepley           PetscInt fdof, fcdof;
9745a93c429eSMatthew G. Knepley 
97469566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(subsection, p, f, &fdof));
97479566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof));
9748a93c429eSMatthew G. Knepley           pSubSize += fdof-fcdof;
9749a93c429eSMatthew G. Knepley         }
9750a93c429eSMatthew G. Knepley         subSize += pSubSize;
9751a93c429eSMatthew G. Knepley         if (pSubSize) {
9752a93c429eSMatthew G. Knepley           if (bs < 0) {
9753a93c429eSMatthew G. Knepley             bs = pSubSize;
9754a93c429eSMatthew G. Knepley           } else if (bs != pSubSize) {
9755a93c429eSMatthew G. Knepley             /* Layout does not admit a pointwise block size */
9756a93c429eSMatthew G. Knepley             bs = 1;
9757a93c429eSMatthew G. Knepley           }
9758a93c429eSMatthew G. Knepley         }
9759a93c429eSMatthew G. Knepley       }
9760a93c429eSMatthew G. Knepley     }
9761a93c429eSMatthew G. Knepley     /* Must have same blocksize on all procs (some might have no points) */
9762a93c429eSMatthew G. Knepley     bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs;
97639566063dSJacob Faibussowitsch     PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax));
9764a93c429eSMatthew G. Knepley     if (bsMinMax[0] != bsMinMax[1]) {bs = 1;}
9765a93c429eSMatthew G. Knepley     else                            {bs = bsMinMax[0];}
97669566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(subSize, &subIndices));
9767a93c429eSMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
9768a93c429eSMatthew G. Knepley       PetscInt gdof, goff;
9769a93c429eSMatthew G. Knepley 
97709566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(subsectionGlobal, p, &gdof));
9771a93c429eSMatthew G. Knepley       if (gdof > 0) {
9772a93c429eSMatthew G. Knepley         const PetscInt point = spmap[p];
9773a93c429eSMatthew G. Knepley 
97749566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(sectionGlobal, point, &goff));
9775a93c429eSMatthew G. Knepley         for (f = 0; f < Nf; ++f) {
9776a93c429eSMatthew G. Knepley           PetscInt fdof, fcdof, fc, f2, poff = 0;
9777a93c429eSMatthew G. Knepley 
9778a93c429eSMatthew G. Knepley           /* Can get rid of this loop by storing field information in the global section */
9779a93c429eSMatthew G. Knepley           for (f2 = 0; f2 < f; ++f2) {
97809566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, p, f2, &fdof));
97819566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof));
9782a93c429eSMatthew G. Knepley             poff += fdof-fcdof;
9783a93c429eSMatthew G. Knepley           }
97849566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof));
97859566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof));
9786a93c429eSMatthew G. Knepley           for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) {
9787a93c429eSMatthew G. Knepley             subIndices[subOff] = goff+poff+fc;
9788a93c429eSMatthew G. Knepley           }
9789a93c429eSMatthew G. Knepley         }
9790a93c429eSMatthew G. Knepley       }
9791a93c429eSMatthew G. Knepley     }
97929566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(spIS, &spmap));
97939566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is));
9794a93c429eSMatthew G. Knepley     if (bs > 1) {
9795a93c429eSMatthew G. Knepley       /* We need to check that the block size does not come from non-contiguous fields */
9796a93c429eSMatthew G. Knepley       PetscInt i, j, set = 1;
9797a93c429eSMatthew G. Knepley       for (i = 0; i < subSize; i += bs) {
9798a93c429eSMatthew G. Knepley         for (j = 0; j < bs; ++j) {
9799a93c429eSMatthew G. Knepley           if (subIndices[i+j] != subIndices[i]+j) {set = 0; break;}
9800a93c429eSMatthew G. Knepley         }
9801a93c429eSMatthew G. Knepley       }
98029566063dSJacob Faibussowitsch       if (set) PetscCall(ISSetBlockSize(*is, bs));
9803a93c429eSMatthew G. Knepley     }
9804a93c429eSMatthew G. Knepley     /* Attach nullspace */
9805a93c429eSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
9806a93c429eSMatthew G. Knepley       (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f];
9807a93c429eSMatthew G. Knepley       if ((*subdm)->nullspaceConstructors[f]) break;
9808a93c429eSMatthew G. Knepley     }
9809a93c429eSMatthew G. Knepley     if (f < Nf) {
9810a93c429eSMatthew G. Knepley       MatNullSpace nullSpace;
98119566063dSJacob Faibussowitsch       PetscCall((*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace));
98126823f3c5SBlaise Bourdin 
98139566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace));
98149566063dSJacob Faibussowitsch       PetscCall(MatNullSpaceDestroy(&nullSpace));
9815a93c429eSMatthew G. Knepley     }
9816a93c429eSMatthew G. Knepley   }
9817a93c429eSMatthew G. Knepley   PetscFunctionReturn(0);
9818a93c429eSMatthew G. Knepley }
9819c0f0dcc3SMatthew G. Knepley 
9820c0f0dcc3SMatthew G. Knepley /*@
9821c0f0dcc3SMatthew G. Knepley   DMPlexMonitorThroughput - Report the cell throughput of FE integration
9822c0f0dcc3SMatthew G. Knepley 
9823c0f0dcc3SMatthew G. Knepley   Input Parameter:
9824c0f0dcc3SMatthew G. Knepley - dm - The DM
9825c0f0dcc3SMatthew G. Knepley 
9826c0f0dcc3SMatthew G. Knepley   Level: developer
9827c0f0dcc3SMatthew G. Knepley 
9828c0f0dcc3SMatthew G. Knepley   Options Database Keys:
9829c0f0dcc3SMatthew G. Knepley . -dm_plex_monitor_throughput - Activate the monitor
9830c0f0dcc3SMatthew G. Knepley 
9831db781477SPatrick Sanan .seealso: `DMSetFromOptions()`, `DMPlexCreate()`
9832c0f0dcc3SMatthew G. Knepley @*/
9833c0f0dcc3SMatthew G. Knepley PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy)
9834c0f0dcc3SMatthew G. Knepley {
9835e5ed2c37SJose E. Roman #if defined(PETSC_USE_LOG)
9836c0f0dcc3SMatthew G. Knepley   PetscStageLog      stageLog;
9837c0f0dcc3SMatthew G. Knepley   PetscLogEvent      event;
9838c0f0dcc3SMatthew G. Knepley   PetscLogStage      stage;
9839c0f0dcc3SMatthew G. Knepley   PetscEventPerfInfo eventInfo;
9840c0f0dcc3SMatthew G. Knepley   PetscReal          cellRate, flopRate;
9841c0f0dcc3SMatthew G. Knepley   PetscInt           cStart, cEnd, Nf, N;
9842c0f0dcc3SMatthew G. Knepley   const char        *name;
9843e5ed2c37SJose E. Roman #endif
9844c0f0dcc3SMatthew G. Knepley 
9845c0f0dcc3SMatthew G. Knepley   PetscFunctionBegin;
9846c0f0dcc3SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9847c0f0dcc3SMatthew G. Knepley #if defined(PETSC_USE_LOG)
98489566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject) dm, &name));
98499566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
98509566063dSJacob Faibussowitsch   PetscCall(DMGetNumFields(dm, &Nf));
98519566063dSJacob Faibussowitsch   PetscCall(PetscLogGetStageLog(&stageLog));
98529566063dSJacob Faibussowitsch   PetscCall(PetscStageLogGetCurrent(stageLog, &stage));
98539566063dSJacob Faibussowitsch   PetscCall(PetscLogEventGetId("DMPlexResidualFE", &event));
98549566063dSJacob Faibussowitsch   PetscCall(PetscLogEventGetPerfInfo(stage, event, &eventInfo));
9855c0f0dcc3SMatthew G. Knepley   N        = (cEnd - cStart)*Nf*eventInfo.count;
9856c0f0dcc3SMatthew G. Knepley   flopRate = eventInfo.flops/eventInfo.time;
9857c0f0dcc3SMatthew G. Knepley   cellRate = N/eventInfo.time;
985863a3b9bcSJacob 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)));
9859c0f0dcc3SMatthew G. Knepley #else
9860c0f0dcc3SMatthew G. Knepley   SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Plex Throughput Monitor is not supported if logging is turned off. Reconfigure using --with-log.");
9861c0f0dcc3SMatthew G. Knepley #endif
9862c0f0dcc3SMatthew G. Knepley   PetscFunctionReturn(0);
9863c0f0dcc3SMatthew G. Knepley }
9864