xref: /petsc/src/dm/impls/plex/plex.c (revision f39ec7874ab38227f85e1a66dd12007450d0487f)
1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I      "petscdmplex.h"   I*/
2695799ffSMatthew G. Knepley #include <petsc/private/dmlabelimpl.h>
3af0996ceSBarry Smith #include <petsc/private/isimpl.h>
4e5c6e791SKarl Rupp #include <petsc/private/vecimpl.h>
58135c375SStefano Zampini #include <petsc/private/glvisvecimpl.h>
60c312b8eSJed Brown #include <petscsf.h>
7e228b242SToby Isaac #include <petscds.h>
8e412dcbdSMatthew G. Knepley #include <petscdraw.h>
9f19dbd58SToby Isaac #include <petscdmfield.h>
10012bc364SMatthew G. Knepley #include <petscdmplextransform.h>
11552f7358SJed Brown 
12552f7358SJed Brown /* Logging support */
1302f7d72cSksagiyam PetscLogEvent DMPLEX_Interpolate, DMPLEX_Partition, DMPLEX_Distribute, DMPLEX_DistributeCones, DMPLEX_DistributeLabels, DMPLEX_DistributeSF, DMPLEX_DistributeOverlap, DMPLEX_DistributeField, DMPLEX_DistributeData, DMPLEX_Migrate, DMPLEX_InterpolateSF, DMPLEX_GlobalToNaturalBegin, DMPLEX_GlobalToNaturalEnd, DMPLEX_NaturalToGlobalBegin, DMPLEX_NaturalToGlobalEnd, DMPLEX_Stratify, DMPLEX_Symmetrize, DMPLEX_Preallocate, DMPLEX_ResidualFEM, DMPLEX_JacobianFEM, DMPLEX_InterpolatorFEM, DMPLEX_InjectorFEM, DMPLEX_IntegralFEM, DMPLEX_CreateGmsh, DMPLEX_RebalanceSharedPoints, DMPLEX_PartSelf, DMPLEX_PartLabelInvert, DMPLEX_PartLabelCreateSF, DMPLEX_PartStratSF, DMPLEX_CreatePointSF, DMPLEX_LocatePoints, DMPLEX_TopologyView, DMPLEX_LabelsView, DMPLEX_CoordinatesView, DMPLEX_SectionView, DMPLEX_GlobalVectorView, DMPLEX_LocalVectorView, DMPLEX_TopologyLoad, DMPLEX_LabelsLoad, DMPLEX_CoordinatesLoad, DMPLEX_SectionLoad, DMPLEX_GlobalVectorLoad, DMPLEX_LocalVectorLoad;
14172ee266SJed Brown PetscLogEvent DMPLEX_RebalBuildGraph, DMPLEX_RebalRewriteSF, DMPLEX_RebalGatherGraph, DMPLEX_RebalPartition, DMPLEX_RebalScatterPart, DMPLEX_Generate, DMPLEX_Transform, DMPLEX_GetLocalOffsets, DMPLEX_Uninterpolate;
15552f7358SJed Brown 
16*f39ec787SMatthew G. Knepley PetscBool  Plexcite       = PETSC_FALSE;
17*f39ec787SMatthew G. Knepley const char PlexCitation[] = "@article{LangeMitchellKnepleyGorman2015,\n"
18*f39ec787SMatthew G. Knepley                             "title     = {Efficient mesh management in {Firedrake} using {PETSc-DMPlex}},\n"
19*f39ec787SMatthew G. Knepley                             "author    = {Michael Lange and Lawrence Mitchell and Matthew G. Knepley and Gerard J. Gorman},\n"
20*f39ec787SMatthew G. Knepley                             "journal   = {SIAM Journal on Scientific Computing},\n"
21*f39ec787SMatthew G. Knepley                             "volume    = {38},\n"
22*f39ec787SMatthew G. Knepley                             "number    = {5},\n"
23*f39ec787SMatthew G. Knepley                             "pages     = {S143--S155},\n"
24*f39ec787SMatthew G. Knepley                             "eprint    = {http://arxiv.org/abs/1506.07749},\n"
25*f39ec787SMatthew G. Knepley                             "doi       = {10.1137/15M1026092},\n"
26*f39ec787SMatthew G. Knepley                             "year      = {2016},\n"
27*f39ec787SMatthew G. Knepley                             "petsc_uses={DMPlex},\n}\n";
28*f39ec787SMatthew G. Knepley 
295a576424SJed Brown PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer);
30552f7358SJed Brown 
31e5337592SStefano Zampini /*@
329318fe57SMatthew G. Knepley   DMPlexIsSimplex - Is the first cell in this mesh a simplex?
339318fe57SMatthew G. Knepley 
349318fe57SMatthew G. Knepley   Input Parameter:
35a1cb98faSBarry Smith . dm - The `DMPLEX` object
369318fe57SMatthew G. Knepley 
379318fe57SMatthew G. Knepley   Output Parameter:
389318fe57SMatthew G. Knepley . simplex - Flag checking for a simplex
399318fe57SMatthew G. Knepley 
409318fe57SMatthew G. Knepley   Level: intermediate
419318fe57SMatthew G. Knepley 
42a1cb98faSBarry Smith   Note:
43a1cb98faSBarry Smith   This just gives the first range of cells found. If the mesh has several cell types, it will only give the first.
44a1cb98faSBarry Smith   If the mesh has no cells, this returns `PETSC_FALSE`.
45a1cb98faSBarry Smith 
461cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSimplexOrBoxCells()`, `DMPlexGetCellType()`, `DMPlexGetHeightStratum()`, `DMPolytopeTypeGetNumVertices()`
479318fe57SMatthew G. Knepley @*/
48d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexIsSimplex(DM dm, PetscBool *simplex)
49d71ae5a4SJacob Faibussowitsch {
509318fe57SMatthew G. Knepley   DMPolytopeType ct;
519318fe57SMatthew G. Knepley   PetscInt       cStart, cEnd;
529318fe57SMatthew G. Knepley 
539318fe57SMatthew G. Knepley   PetscFunctionBegin;
549566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
559371c9d4SSatish Balay   if (cEnd <= cStart) {
569371c9d4SSatish Balay     *simplex = PETSC_FALSE;
573ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
589371c9d4SSatish Balay   }
599566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cStart, &ct));
609318fe57SMatthew G. Knepley   *simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE;
613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
629318fe57SMatthew G. Knepley }
639318fe57SMatthew G. Knepley 
649318fe57SMatthew G. Knepley /*@
65412e9a14SMatthew G. Knepley   DMPlexGetSimplexOrBoxCells - Get the range of cells which are neither prisms nor ghost FV cells
66e5337592SStefano Zampini 
67d8d19677SJose E. Roman   Input Parameters:
68a1cb98faSBarry Smith + dm     - The `DMPLEX` object
69412e9a14SMatthew G. Knepley - height - The cell height in the Plex, 0 is the default
70e5337592SStefano Zampini 
71e5337592SStefano Zampini   Output Parameters:
72412e9a14SMatthew G. Knepley + cStart - The first "normal" cell
73412e9a14SMatthew G. Knepley - cEnd   - The upper bound on "normal"" cells
74e5337592SStefano Zampini 
75412e9a14SMatthew G. Knepley   Level: developer
76e5337592SStefano Zampini 
77a1cb98faSBarry Smith   Note:
78a1cb98faSBarry Smith   This just gives the first range of cells found. If the mesh has several cell types, it will only give the first.
79a1cb98faSBarry Smith 
802827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexConstructGhostCells()`, `DMPlexGetCellTypeStratum()`
81e5337592SStefano Zampini @*/
82d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSimplexOrBoxCells(DM dm, PetscInt height, PetscInt *cStart, PetscInt *cEnd)
83d71ae5a4SJacob Faibussowitsch {
84412e9a14SMatthew G. Knepley   DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
85412e9a14SMatthew G. Knepley   PetscInt       cS, cE, c;
86e5337592SStefano Zampini 
87e5337592SStefano Zampini   PetscFunctionBegin;
889566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, PetscMax(height, 0), &cS, &cE));
89412e9a14SMatthew G. Knepley   for (c = cS; c < cE; ++c) {
90412e9a14SMatthew G. Knepley     DMPolytopeType cct;
91412e9a14SMatthew G. Knepley 
929566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &cct));
93412e9a14SMatthew G. Knepley     if ((PetscInt)cct < 0) break;
94412e9a14SMatthew G. Knepley     switch (cct) {
95ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_POINT:
96ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_SEGMENT:
97ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_TRIANGLE:
98ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_QUADRILATERAL:
99ba2698f1SMatthew G. Knepley     case DM_POLYTOPE_TETRAHEDRON:
100d71ae5a4SJacob Faibussowitsch     case DM_POLYTOPE_HEXAHEDRON:
101d71ae5a4SJacob Faibussowitsch       ct = cct;
102d71ae5a4SJacob Faibussowitsch       break;
103d71ae5a4SJacob Faibussowitsch     default:
104d71ae5a4SJacob Faibussowitsch       break;
105e5337592SStefano Zampini     }
106412e9a14SMatthew G. Knepley     if (ct != DM_POLYTOPE_UNKNOWN) break;
107e5337592SStefano Zampini   }
108412e9a14SMatthew G. Knepley   if (ct != DM_POLYTOPE_UNKNOWN) {
109412e9a14SMatthew G. Knepley     DMLabel ctLabel;
110412e9a14SMatthew G. Knepley 
1119566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel));
1129566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumBounds(ctLabel, ct, &cS, &cE));
113695799ffSMatthew G. Knepley     // Reset label for fast lookup
114695799ffSMatthew G. Knepley     PetscCall(DMLabelMakeAllInvalid_Internal(ctLabel));
115e5337592SStefano Zampini   }
116412e9a14SMatthew G. Knepley   if (cStart) *cStart = cS;
117412e9a14SMatthew G. Knepley   if (cEnd) *cEnd = cE;
1183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
119e5337592SStefano Zampini }
120e5337592SStefano Zampini 
121d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFieldType_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *sStart, PetscInt *sEnd, PetscViewerVTKFieldType *ft)
122d71ae5a4SJacob Faibussowitsch {
123412e9a14SMatthew G. Knepley   PetscInt cdim, pStart, pEnd, vStart, vEnd, cStart, cEnd;
124a99a26bcSAdrian Croucher   PetscInt vcdof[2] = {0, 0}, globalvcdof[2];
1257e42fee7SMatthew G. Knepley 
1267e42fee7SMatthew G. Knepley   PetscFunctionBegin;
127e630c359SToby Isaac   *ft = PETSC_VTK_INVALID;
1289566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
1299566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
1309566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd));
1319566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
1327e42fee7SMatthew G. Knepley   if (field >= 0) {
1339566063dSJacob Faibussowitsch     if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, vStart, field, &vcdof[0]));
1349566063dSJacob Faibussowitsch     if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetFieldDof(section, cStart, field, &vcdof[1]));
1357e42fee7SMatthew G. Knepley   } else {
1369566063dSJacob Faibussowitsch     if ((vStart >= pStart) && (vStart < pEnd)) PetscCall(PetscSectionGetDof(section, vStart, &vcdof[0]));
1379566063dSJacob Faibussowitsch     if ((cStart >= pStart) && (cStart < pEnd)) PetscCall(PetscSectionGetDof(section, cStart, &vcdof[1]));
1387e42fee7SMatthew G. Knepley   }
139712fec58SPierre Jolivet   PetscCall(MPIU_Allreduce(vcdof, globalvcdof, 2, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
140a99a26bcSAdrian Croucher   if (globalvcdof[0]) {
1417e42fee7SMatthew G. Knepley     *sStart = vStart;
1427e42fee7SMatthew G. Knepley     *sEnd   = vEnd;
143f094498dSMatthew G. Knepley     if (globalvcdof[0] == cdim) *ft = PETSC_VTK_POINT_VECTOR_FIELD;
1447e42fee7SMatthew G. Knepley     else *ft = PETSC_VTK_POINT_FIELD;
145a99a26bcSAdrian Croucher   } else if (globalvcdof[1]) {
1467e42fee7SMatthew G. Knepley     *sStart = cStart;
1477e42fee7SMatthew G. Knepley     *sEnd   = cEnd;
148f094498dSMatthew G. Knepley     if (globalvcdof[1] == cdim) *ft = PETSC_VTK_CELL_VECTOR_FIELD;
1497e42fee7SMatthew G. Knepley     else *ft = PETSC_VTK_CELL_FIELD;
150e630c359SToby Isaac   } else {
151e630c359SToby Isaac     if (field >= 0) {
152e630c359SToby Isaac       const char *fieldname;
153e630c359SToby Isaac 
1549566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldName(section, field, &fieldname));
15563a3b9bcSJacob Faibussowitsch       PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section field %" PetscInt_FMT " \"%s\"\n", field, fieldname));
156e630c359SToby Isaac     } else {
15763a3b9bcSJacob Faibussowitsch       PetscCall(PetscInfo((PetscObject)dm, "Could not classify VTK output type of section\n"));
158e630c359SToby Isaac     }
159e630c359SToby Isaac   }
1603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1617e42fee7SMatthew G. Knepley }
1627e42fee7SMatthew G. Knepley 
1636913077dSMatthew G. Knepley /*@
1646913077dSMatthew G. Knepley   DMPlexVecView1D - Plot many 1D solutions on the same line graph
1656913077dSMatthew G. Knepley 
16620f4b53cSBarry Smith   Collective
1676913077dSMatthew G. Knepley 
1686913077dSMatthew G. Knepley   Input Parameters:
169a1cb98faSBarry Smith + dm     - The `DMPLEX` object
1706913077dSMatthew G. Knepley . n      - The number of vectors
1716913077dSMatthew G. Knepley . u      - The array of local vectors
172a1cb98faSBarry Smith - viewer - The `PetscViewer`
1736913077dSMatthew G. Knepley 
1746913077dSMatthew G. Knepley   Level: advanced
1756913077dSMatthew G. Knepley 
1761cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `VecViewFromOptions()`, `VecView()`
1776913077dSMatthew G. Knepley @*/
178d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecView1D(DM dm, PetscInt n, Vec u[], PetscViewer viewer)
179d71ae5a4SJacob Faibussowitsch {
1806913077dSMatthew G. Knepley   PetscDS            ds;
1816913077dSMatthew G. Knepley   PetscDraw          draw = NULL;
1826913077dSMatthew G. Knepley   PetscDrawLG        lg;
1836913077dSMatthew G. Knepley   Vec                coordinates;
1846913077dSMatthew G. Knepley   const PetscScalar *coords, **sol;
1856913077dSMatthew G. Knepley   PetscReal         *vals;
1866913077dSMatthew G. Knepley   PetscInt          *Nc;
1876913077dSMatthew G. Knepley   PetscInt           Nf, f, c, Nl, l, i, vStart, vEnd, v;
1886913077dSMatthew G. Knepley   char             **names;
1896913077dSMatthew G. Knepley 
1906913077dSMatthew G. Knepley   PetscFunctionBegin;
1919566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &ds));
1929566063dSJacob Faibussowitsch   PetscCall(PetscDSGetNumFields(ds, &Nf));
1939566063dSJacob Faibussowitsch   PetscCall(PetscDSGetTotalComponents(ds, &Nl));
1949566063dSJacob Faibussowitsch   PetscCall(PetscDSGetComponents(ds, &Nc));
1956913077dSMatthew G. Knepley 
1969566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
1973ba16761SJacob Faibussowitsch   if (!draw) PetscFunctionReturn(PETSC_SUCCESS);
1989566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGCreate(draw, n * Nl, &lg));
1996913077dSMatthew G. Knepley 
2009566063dSJacob Faibussowitsch   PetscCall(PetscMalloc3(n, &sol, n * Nl, &names, n * Nl, &vals));
2016913077dSMatthew G. Knepley   for (i = 0, l = 0; i < n; ++i) {
2026913077dSMatthew G. Knepley     const char *vname;
2036913077dSMatthew G. Knepley 
2049566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)u[i], &vname));
2056913077dSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
2066913077dSMatthew G. Knepley       PetscObject disc;
2076913077dSMatthew G. Knepley       const char *fname;
2086913077dSMatthew G. Knepley       char        tmpname[PETSC_MAX_PATH_LEN];
2096913077dSMatthew G. Knepley 
2109566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(ds, f, &disc));
2116913077dSMatthew G. Knepley       /* TODO Create names for components */
2126913077dSMatthew G. Knepley       for (c = 0; c < Nc[f]; ++c, ++l) {
2139566063dSJacob Faibussowitsch         PetscCall(PetscObjectGetName(disc, &fname));
214c6a7a370SJeremy L Thompson         PetscCall(PetscStrncpy(tmpname, vname, sizeof(tmpname)));
215c6a7a370SJeremy L Thompson         PetscCall(PetscStrlcat(tmpname, ":", sizeof(tmpname)));
216c6a7a370SJeremy L Thompson         PetscCall(PetscStrlcat(tmpname, fname, sizeof(tmpname)));
2179566063dSJacob Faibussowitsch         PetscCall(PetscStrallocpy(tmpname, &names[l]));
2186913077dSMatthew G. Knepley       }
2196913077dSMatthew G. Knepley     }
2206913077dSMatthew G. Knepley   }
2219566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGSetLegend(lg, (const char *const *)names));
2226913077dSMatthew G. Knepley   /* Just add P_1 support for now */
2239566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
2249566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
2259566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(coordinates, &coords));
2269566063dSJacob Faibussowitsch   for (i = 0; i < n; ++i) PetscCall(VecGetArrayRead(u[i], &sol[i]));
2276913077dSMatthew G. Knepley   for (v = vStart; v < vEnd; ++v) {
2286913077dSMatthew G. Knepley     PetscScalar *x, *svals;
2296913077dSMatthew G. Knepley 
2309566063dSJacob Faibussowitsch     PetscCall(DMPlexPointLocalRead(dm, v, coords, &x));
2316913077dSMatthew G. Knepley     for (i = 0; i < n; ++i) {
2329566063dSJacob Faibussowitsch       PetscCall(DMPlexPointLocalRead(dm, v, sol[i], &svals));
2336913077dSMatthew G. Knepley       for (l = 0; l < Nl; ++l) vals[i * Nl + l] = PetscRealPart(svals[l]);
2346913077dSMatthew G. Knepley     }
2359566063dSJacob Faibussowitsch     PetscCall(PetscDrawLGAddCommonPoint(lg, PetscRealPart(x[0]), vals));
2366913077dSMatthew G. Knepley   }
2379566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(coordinates, &coords));
2389566063dSJacob Faibussowitsch   for (i = 0; i < n; ++i) PetscCall(VecRestoreArrayRead(u[i], &sol[i]));
2399566063dSJacob Faibussowitsch   for (l = 0; l < n * Nl; ++l) PetscCall(PetscFree(names[l]));
2409566063dSJacob Faibussowitsch   PetscCall(PetscFree3(sol, names, vals));
2416913077dSMatthew G. Knepley 
2429566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGDraw(lg));
2439566063dSJacob Faibussowitsch   PetscCall(PetscDrawLGDestroy(&lg));
2443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2456913077dSMatthew G. Knepley }
2466913077dSMatthew G. Knepley 
247d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw_1D(Vec u, PetscViewer viewer)
248d71ae5a4SJacob Faibussowitsch {
2496913077dSMatthew G. Knepley   DM dm;
2506913077dSMatthew G. Knepley 
2516913077dSMatthew G. Knepley   PetscFunctionBegin;
2529566063dSJacob Faibussowitsch   PetscCall(VecGetDM(u, &dm));
2539566063dSJacob Faibussowitsch   PetscCall(DMPlexVecView1D(dm, 1, &u, viewer));
2543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2556913077dSMatthew G. Knepley }
2566913077dSMatthew G. Knepley 
257d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw_2D(Vec v, PetscViewer viewer)
258d71ae5a4SJacob Faibussowitsch {
259e412dcbdSMatthew G. Knepley   DM                 dm;
260d1df6f1dSMatthew G. Knepley   PetscSection       s;
261e412dcbdSMatthew G. Knepley   PetscDraw          draw, popup;
262e412dcbdSMatthew G. Knepley   DM                 cdm;
263e412dcbdSMatthew G. Knepley   PetscSection       coordSection;
264e412dcbdSMatthew G. Knepley   Vec                coordinates;
265c9c77995SMatthew G. Knepley   const PetscScalar *array;
266c9c77995SMatthew G. Knepley   PetscReal          lbound[3], ubound[3];
267339e3443SMatthew G. Knepley   PetscReal          vbound[2], time;
2686913077dSMatthew G. Knepley   PetscBool          flg;
269d1df6f1dSMatthew G. Knepley   PetscInt           dim, Nf, f, Nc, comp, vStart, vEnd, cStart, cEnd, c, N, level, step, w = 0;
270e412dcbdSMatthew G. Knepley   const char        *name;
271339e3443SMatthew G. Knepley   char               title[PETSC_MAX_PATH_LEN];
272e412dcbdSMatthew G. Knepley 
273e412dcbdSMatthew G. Knepley   PetscFunctionBegin;
2749566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
2759566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
2769566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dim));
2779566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &s));
2789566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(s, &Nf));
2799566063dSJacob Faibussowitsch   PetscCall(DMGetCoarsenLevel(dm, &level));
2809566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
2819566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(cdm, &coordSection));
2829566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
2839566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
2849566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
285e412dcbdSMatthew G. Knepley 
2869566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)v, &name));
2879566063dSJacob Faibussowitsch   PetscCall(DMGetOutputSequenceNumber(dm, &step, &time));
288e412dcbdSMatthew G. Knepley 
2899566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(coordinates, &N));
290c9c77995SMatthew G. Knepley   PetscCall(DMGetBoundingBox(dm, lbound, ubound));
2919566063dSJacob Faibussowitsch   PetscCall(PetscDrawClear(draw));
292e412dcbdSMatthew G. Knepley 
293d1df6f1dSMatthew G. Knepley   /* Could implement something like DMDASelectFields() */
294d1df6f1dSMatthew G. Knepley   for (f = 0; f < Nf; ++f) {
295d1df6f1dSMatthew G. Knepley     DM          fdm = dm;
296d1df6f1dSMatthew G. Knepley     Vec         fv  = v;
297d1df6f1dSMatthew G. Knepley     IS          fis;
298d1df6f1dSMatthew G. Knepley     char        prefix[PETSC_MAX_PATH_LEN];
299d1df6f1dSMatthew G. Knepley     const char *fname;
300d1df6f1dSMatthew G. Knepley 
3019566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldComponents(s, f, &Nc));
3029566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldName(s, f, &fname));
303d1df6f1dSMatthew G. Knepley 
3049566063dSJacob Faibussowitsch     if (v->hdr.prefix) PetscCall(PetscStrncpy(prefix, v->hdr.prefix, sizeof(prefix)));
305ad540459SPierre Jolivet     else prefix[0] = '\0';
306d1df6f1dSMatthew G. Knepley     if (Nf > 1) {
3079566063dSJacob Faibussowitsch       PetscCall(DMCreateSubDM(dm, 1, &f, &fis, &fdm));
3089566063dSJacob Faibussowitsch       PetscCall(VecGetSubVector(v, fis, &fv));
3099566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(prefix, fname, sizeof(prefix)));
3109566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(prefix, "_", sizeof(prefix)));
311d1df6f1dSMatthew G. Knepley     }
312d1df6f1dSMatthew G. Knepley     for (comp = 0; comp < Nc; ++comp, ++w) {
313d1df6f1dSMatthew G. Knepley       PetscInt nmax = 2;
314d1df6f1dSMatthew G. Knepley 
3159566063dSJacob Faibussowitsch       PetscCall(PetscViewerDrawGetDraw(viewer, w, &draw));
31663a3b9bcSJacob Faibussowitsch       if (Nc > 1) PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s_%" PetscInt_FMT " Step: %" PetscInt_FMT " Time: %.4g", name, fname, comp, step, (double)time));
31763a3b9bcSJacob Faibussowitsch       else PetscCall(PetscSNPrintf(title, sizeof(title), "%s:%s Step: %" PetscInt_FMT " Time: %.4g", name, fname, step, (double)time));
3189566063dSJacob Faibussowitsch       PetscCall(PetscDrawSetTitle(draw, title));
319d1df6f1dSMatthew G. Knepley 
320d1df6f1dSMatthew G. Knepley       /* TODO Get max and min only for this component */
3219566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetRealArray(NULL, prefix, "-vec_view_bounds", vbound, &nmax, &flg));
322339e3443SMatthew G. Knepley       if (!flg) {
3239566063dSJacob Faibussowitsch         PetscCall(VecMin(fv, NULL, &vbound[0]));
3249566063dSJacob Faibussowitsch         PetscCall(VecMax(fv, NULL, &vbound[1]));
325d1df6f1dSMatthew G. Knepley         if (vbound[1] <= vbound[0]) vbound[1] = vbound[0] + 1.0;
326339e3443SMatthew G. Knepley       }
327c9c77995SMatthew G. Knepley 
3289566063dSJacob Faibussowitsch       PetscCall(PetscDrawGetPopup(draw, &popup));
3299566063dSJacob Faibussowitsch       PetscCall(PetscDrawScalePopup(popup, vbound[0], vbound[1]));
330c9c77995SMatthew G. Knepley       PetscCall(PetscDrawSetCoordinates(draw, lbound[0], lbound[1], ubound[0], ubound[1]));
3319566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(fv, &array));
332e412dcbdSMatthew G. Knepley       for (c = cStart; c < cEnd; ++c) {
33399a2f7bcSMatthew G. Knepley         PetscScalar       *coords = NULL, *a = NULL;
334c9c77995SMatthew G. Knepley         const PetscScalar *coords_arr;
335c9c77995SMatthew G. Knepley         PetscBool          isDG;
336e56f9228SJed Brown         PetscInt           numCoords, color[4] = {-1, -1, -1, -1};
337e412dcbdSMatthew G. Knepley 
3389566063dSJacob Faibussowitsch         PetscCall(DMPlexPointLocalRead(fdm, c, array, &a));
339339e3443SMatthew G. Knepley         if (a) {
340d1df6f1dSMatthew G. Knepley           color[0] = PetscDrawRealToColor(PetscRealPart(a[comp]), vbound[0], vbound[1]);
341339e3443SMatthew G. Knepley           color[1] = color[2] = color[3] = color[0];
342339e3443SMatthew G. Knepley         } else {
343339e3443SMatthew G. Knepley           PetscScalar *vals = NULL;
344339e3443SMatthew G. Knepley           PetscInt     numVals, va;
345339e3443SMatthew G. Knepley 
3469566063dSJacob Faibussowitsch           PetscCall(DMPlexVecGetClosure(fdm, NULL, fv, c, &numVals, &vals));
34763a3b9bcSJacob 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);
348d1df6f1dSMatthew G. Knepley           switch (numVals / Nc) {
349d1df6f1dSMatthew G. Knepley           case 3: /* P1 Triangle */
350d1df6f1dSMatthew G. Knepley           case 4: /* P1 Quadrangle */
351d1df6f1dSMatthew G. Knepley             for (va = 0; va < numVals / Nc; ++va) color[va] = PetscDrawRealToColor(PetscRealPart(vals[va * Nc + comp]), vbound[0], vbound[1]);
352339e3443SMatthew G. Knepley             break;
353d1df6f1dSMatthew G. Knepley           case 6: /* P2 Triangle */
354d1df6f1dSMatthew G. Knepley           case 8: /* P2 Quadrangle */
355d1df6f1dSMatthew 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]);
356d1df6f1dSMatthew G. Knepley             break;
357d71ae5a4SJacob Faibussowitsch           default:
358d71ae5a4SJacob Faibussowitsch             SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of values for cell closure %" PetscInt_FMT " cannot be handled", numVals / Nc);
359339e3443SMatthew G. Knepley           }
3609566063dSJacob Faibussowitsch           PetscCall(DMPlexVecRestoreClosure(fdm, NULL, fv, c, &numVals, &vals));
361339e3443SMatthew G. Knepley         }
362c9c77995SMatthew G. Knepley         PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords));
363e412dcbdSMatthew G. Knepley         switch (numCoords) {
364e412dcbdSMatthew G. Knepley         case 6:
3659edc3542SMatthew Knepley         case 12: /* Localized triangle */
3669566063dSJacob 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]));
367e412dcbdSMatthew G. Knepley           break;
368e412dcbdSMatthew G. Knepley         case 8:
3699edc3542SMatthew Knepley         case 16: /* Localized quadrilateral */
3709566063dSJacob 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]));
3719566063dSJacob 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]));
372e412dcbdSMatthew G. Knepley           break;
373d71ae5a4SJacob Faibussowitsch         default:
374d71ae5a4SJacob Faibussowitsch           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells with %" PetscInt_FMT " coordinates", numCoords);
375e412dcbdSMatthew G. Knepley         }
376c9c77995SMatthew G. Knepley         PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords));
377e412dcbdSMatthew G. Knepley       }
3789566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(fv, &array));
3799566063dSJacob Faibussowitsch       PetscCall(PetscDrawFlush(draw));
3809566063dSJacob Faibussowitsch       PetscCall(PetscDrawPause(draw));
3819566063dSJacob Faibussowitsch       PetscCall(PetscDrawSave(draw));
382d1df6f1dSMatthew G. Knepley     }
383d1df6f1dSMatthew G. Knepley     if (Nf > 1) {
3849566063dSJacob Faibussowitsch       PetscCall(VecRestoreSubVector(v, fis, &fv));
3859566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&fis));
3869566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&fdm));
387d1df6f1dSMatthew G. Knepley     }
388d1df6f1dSMatthew G. Knepley   }
3893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
390e412dcbdSMatthew G. Knepley }
391e412dcbdSMatthew G. Knepley 
392d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_Draw(Vec v, PetscViewer viewer)
393d71ae5a4SJacob Faibussowitsch {
3946913077dSMatthew G. Knepley   DM        dm;
3956913077dSMatthew G. Knepley   PetscDraw draw;
3966913077dSMatthew G. Knepley   PetscInt  dim;
3976913077dSMatthew G. Knepley   PetscBool isnull;
3986913077dSMatthew G. Knepley 
3996913077dSMatthew G. Knepley   PetscFunctionBegin;
4009566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
4019566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
4023ba16761SJacob Faibussowitsch   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
4036913077dSMatthew G. Knepley 
4049566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
4059566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dim));
4066913077dSMatthew G. Knepley   switch (dim) {
407d71ae5a4SJacob Faibussowitsch   case 1:
408d71ae5a4SJacob Faibussowitsch     PetscCall(VecView_Plex_Local_Draw_1D(v, viewer));
409d71ae5a4SJacob Faibussowitsch     break;
410d71ae5a4SJacob Faibussowitsch   case 2:
411d71ae5a4SJacob Faibussowitsch     PetscCall(VecView_Plex_Local_Draw_2D(v, viewer));
412d71ae5a4SJacob Faibussowitsch     break;
413d71ae5a4SJacob Faibussowitsch   default:
414d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT ". Try PETSCVIEWERGLVIS", dim);
4156913077dSMatthew G. Knepley   }
4163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4176913077dSMatthew G. Knepley }
4186913077dSMatthew G. Knepley 
419d71ae5a4SJacob Faibussowitsch static PetscErrorCode VecView_Plex_Local_VTK(Vec v, PetscViewer viewer)
420d71ae5a4SJacob Faibussowitsch {
421684b87d9SLisandro Dalcin   DM                      dm;
422684b87d9SLisandro Dalcin   Vec                     locv;
423684b87d9SLisandro Dalcin   const char             *name;
424684b87d9SLisandro Dalcin   PetscSection            section;
425684b87d9SLisandro Dalcin   PetscInt                pStart, pEnd;
426e630c359SToby Isaac   PetscInt                numFields;
427684b87d9SLisandro Dalcin   PetscViewerVTKFieldType ft;
428684b87d9SLisandro Dalcin 
429684b87d9SLisandro Dalcin   PetscFunctionBegin;
4309566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
4319566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dm, &locv)); /* VTK viewer requires exclusive ownership of the vector */
4329566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject)v, &name));
4339566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)locv, name));
4349566063dSJacob Faibussowitsch   PetscCall(VecCopy(v, locv));
4359566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
4369566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
437e630c359SToby Isaac   if (!numFields) {
4389566063dSJacob Faibussowitsch     PetscCall(DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft));
4399566063dSJacob Faibussowitsch     PetscCall(PetscViewerVTKAddField(viewer, (PetscObject)dm, DMPlexVTKWriteAll, PETSC_DEFAULT, ft, PETSC_TRUE, (PetscObject)locv));
440e630c359SToby Isaac   } else {
441e630c359SToby Isaac     PetscInt f;
442e630c359SToby Isaac 
443e630c359SToby Isaac     for (f = 0; f < numFields; f++) {
4449566063dSJacob Faibussowitsch       PetscCall(DMPlexGetFieldType_Internal(dm, section, f, &pStart, &pEnd, &ft));
445e630c359SToby Isaac       if (ft == PETSC_VTK_INVALID) continue;
4469566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)locv));
4479566063dSJacob Faibussowitsch       PetscCall(PetscViewerVTKAddField(viewer, (PetscObject)dm, DMPlexVTKWriteAll, f, ft, PETSC_TRUE, (PetscObject)locv));
448e630c359SToby Isaac     }
4499566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&locv));
450e630c359SToby Isaac   }
4513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
452684b87d9SLisandro Dalcin }
453684b87d9SLisandro Dalcin 
454d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer)
455d71ae5a4SJacob Faibussowitsch {
456552f7358SJed Brown   DM        dm;
4575f34f2dcSJed Brown   PetscBool isvtk, ishdf5, isdraw, isglvis, iscgns;
458552f7358SJed Brown 
459552f7358SJed Brown   PetscFunctionBegin;
4609566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
46128b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
4629566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
4639566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
4649566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
4659566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis));
4665f34f2dcSJed Brown   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns));
4675f34f2dcSJed Brown   if (isvtk || ishdf5 || isdraw || isglvis || iscgns) {
468684b87d9SLisandro Dalcin     PetscInt    i, numFields;
469684b87d9SLisandro Dalcin     PetscObject fe;
470ef31f671SMatthew G. Knepley     PetscBool   fem  = PETSC_FALSE;
471684b87d9SLisandro Dalcin     Vec         locv = v;
472684b87d9SLisandro Dalcin     const char *name;
473684b87d9SLisandro Dalcin     PetscInt    step;
474684b87d9SLisandro Dalcin     PetscReal   time;
475ef31f671SMatthew G. Knepley 
4769566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &numFields));
477684b87d9SLisandro Dalcin     for (i = 0; i < numFields; i++) {
4789566063dSJacob Faibussowitsch       PetscCall(DMGetField(dm, i, NULL, &fe));
4799371c9d4SSatish Balay       if (fe->classid == PETSCFE_CLASSID) {
4809371c9d4SSatish Balay         fem = PETSC_TRUE;
4819371c9d4SSatish Balay         break;
4829371c9d4SSatish Balay       }
483ef31f671SMatthew G. Knepley     }
484684b87d9SLisandro Dalcin     if (fem) {
485798534f6SMatthew G. Knepley       PetscObject isZero;
486798534f6SMatthew G. Knepley 
4879566063dSJacob Faibussowitsch       PetscCall(DMGetLocalVector(dm, &locv));
4889566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)v, &name));
4899566063dSJacob Faibussowitsch       PetscCall(PetscObjectSetName((PetscObject)locv, name));
4909566063dSJacob Faibussowitsch       PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero));
4919566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero));
4929566063dSJacob Faibussowitsch       PetscCall(VecCopy(v, locv));
4939566063dSJacob Faibussowitsch       PetscCall(DMGetOutputSequenceNumber(dm, NULL, &time));
4949566063dSJacob Faibussowitsch       PetscCall(DMPlexInsertBoundaryValues(dm, PETSC_TRUE, locv, time, NULL, NULL, NULL));
495ef31f671SMatthew G. Knepley     }
496552f7358SJed Brown     if (isvtk) {
4979566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_VTK(locv, viewer));
498b136c2c9SMatthew G. Knepley     } else if (ishdf5) {
499b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
5009566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_HDF5_Internal(locv, viewer));
501b136c2c9SMatthew G. Knepley #else
502b136c2c9SMatthew G. Knepley       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
503b136c2c9SMatthew G. Knepley #endif
504f13a32a3SMatthew G. Knepley     } else if (isdraw) {
5059566063dSJacob Faibussowitsch       PetscCall(VecView_Plex_Local_Draw(locv, viewer));
506684b87d9SLisandro Dalcin     } else if (isglvis) {
5079566063dSJacob Faibussowitsch       PetscCall(DMGetOutputSequenceNumber(dm, &step, NULL));
5089566063dSJacob Faibussowitsch       PetscCall(PetscViewerGLVisSetSnapId(viewer, step));
5099566063dSJacob Faibussowitsch       PetscCall(VecView_GLVis(locv, viewer));
5105f34f2dcSJed Brown     } else if (iscgns) {
5115f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS)
5125f34f2dcSJed Brown       PetscCall(VecView_Plex_Local_CGNS(locv, viewer));
5135f34f2dcSJed Brown #else
5145f34f2dcSJed Brown       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "CGNS not supported in this build.\nPlease reconfigure using --download-cgns");
5155f34f2dcSJed Brown #endif
516684b87d9SLisandro Dalcin     }
517798534f6SMatthew G. Knepley     if (fem) {
5189566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL));
5199566063dSJacob Faibussowitsch       PetscCall(DMRestoreLocalVector(dm, &locv));
520798534f6SMatthew G. Knepley     }
521552f7358SJed Brown   } else {
522684b87d9SLisandro Dalcin     PetscBool isseq;
523684b87d9SLisandro Dalcin 
5249566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq));
5259566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
5269566063dSJacob Faibussowitsch     else PetscCall(VecView_MPI(v, viewer));
527552f7358SJed Brown   }
5283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
529552f7358SJed Brown }
530552f7358SJed Brown 
531d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer)
532d71ae5a4SJacob Faibussowitsch {
533552f7358SJed Brown   DM        dm;
5345f34f2dcSJed Brown   PetscBool isvtk, ishdf5, isdraw, isglvis, isexodusii, iscgns;
535552f7358SJed Brown 
536552f7358SJed Brown   PetscFunctionBegin;
5379566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
53828b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
5399566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
5409566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
5419566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
5429566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis));
5435f34f2dcSJed Brown   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns));
5449566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodusii));
5455f34f2dcSJed Brown   if (isvtk || isdraw || isglvis || iscgns) {
546552f7358SJed Brown     Vec         locv;
547798534f6SMatthew G. Knepley     PetscObject isZero;
548552f7358SJed Brown     const char *name;
549552f7358SJed Brown 
5509566063dSJacob Faibussowitsch     PetscCall(DMGetLocalVector(dm, &locv));
5519566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)v, &name));
5529566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)locv, name));
5539566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv));
5549566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv));
5559566063dSJacob Faibussowitsch     PetscCall(PetscObjectQuery((PetscObject)v, "__Vec_bc_zero__", &isZero));
5569566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", isZero));
5579566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_Local(locv, viewer));
5589566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)locv, "__Vec_bc_zero__", NULL));
5599566063dSJacob Faibussowitsch     PetscCall(DMRestoreLocalVector(dm, &locv));
560b136c2c9SMatthew G. Knepley   } else if (ishdf5) {
561b136c2c9SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
5629566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_HDF5_Internal(v, viewer));
563b136c2c9SMatthew G. Knepley #else
564b136c2c9SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
565b136c2c9SMatthew G. Knepley #endif
5666823f3c5SBlaise Bourdin   } else if (isexodusii) {
5676823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII)
5689566063dSJacob Faibussowitsch     PetscCall(VecView_PlexExodusII_Internal(v, viewer));
5696823f3c5SBlaise Bourdin #else
5706823f3c5SBlaise Bourdin     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii");
5716823f3c5SBlaise Bourdin #endif
572552f7358SJed Brown   } else {
573684b87d9SLisandro Dalcin     PetscBool isseq;
574684b87d9SLisandro Dalcin 
5759566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq));
5769566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
5779566063dSJacob Faibussowitsch     else PetscCall(VecView_MPI(v, viewer));
578552f7358SJed Brown   }
5793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
580552f7358SJed Brown }
581552f7358SJed Brown 
582d71ae5a4SJacob Faibussowitsch PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer)
583d71ae5a4SJacob Faibussowitsch {
584d930f514SMatthew G. Knepley   DM                dm;
585d930f514SMatthew G. Knepley   MPI_Comm          comm;
586d930f514SMatthew G. Knepley   PetscViewerFormat format;
587d930f514SMatthew G. Knepley   Vec               v;
588d930f514SMatthew G. Knepley   PetscBool         isvtk, ishdf5;
589d930f514SMatthew G. Knepley 
590d930f514SMatthew G. Knepley   PetscFunctionBegin;
5919566063dSJacob Faibussowitsch   PetscCall(VecGetDM(originalv, &dm));
5929566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)originalv, &comm));
59328b400f6SJacob Faibussowitsch   PetscCheck(dm, comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
5949566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
5959566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
5969566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
597d930f514SMatthew G. Knepley   if (format == PETSC_VIEWER_NATIVE) {
598a8ad634aSStefano Zampini     /* Natural ordering is the common case for DMDA, NATIVE means plain vector, for PLEX is the opposite */
599a8ad634aSStefano Zampini     /* this need a better fix */
600a8ad634aSStefano Zampini     if (dm->useNatural) {
601a8ad634aSStefano Zampini       if (dm->sfNatural) {
602d930f514SMatthew G. Knepley         const char *vecname;
603d930f514SMatthew G. Knepley         PetscInt    n, nroots;
604d930f514SMatthew G. Knepley 
6059566063dSJacob Faibussowitsch         PetscCall(VecGetLocalSize(originalv, &n));
6069566063dSJacob Faibussowitsch         PetscCall(PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL));
607d930f514SMatthew G. Knepley         if (n == nroots) {
608f16a8b29SMatthew G. Knepley           PetscCall(DMPlexCreateNaturalVector(dm, &v));
6099566063dSJacob Faibussowitsch           PetscCall(DMPlexGlobalToNaturalBegin(dm, originalv, v));
6109566063dSJacob Faibussowitsch           PetscCall(DMPlexGlobalToNaturalEnd(dm, originalv, v));
6119566063dSJacob Faibussowitsch           PetscCall(PetscObjectGetName((PetscObject)originalv, &vecname));
6129566063dSJacob Faibussowitsch           PetscCall(PetscObjectSetName((PetscObject)v, vecname));
613d930f514SMatthew G. Knepley         } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors");
614d930f514SMatthew G. Knepley       } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created");
615a8ad634aSStefano Zampini     } else v = originalv;
616a8ad634aSStefano Zampini   } else v = originalv;
617a8ad634aSStefano Zampini 
618d930f514SMatthew G. Knepley   if (ishdf5) {
619d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
6209566063dSJacob Faibussowitsch     PetscCall(VecView_Plex_HDF5_Native_Internal(v, viewer));
621d930f514SMatthew G. Knepley #else
622d930f514SMatthew G. Knepley     SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
623d930f514SMatthew G. Knepley #endif
624d930f514SMatthew G. Knepley   } else if (isvtk) {
625d930f514SMatthew G. Knepley     SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5.");
626d930f514SMatthew G. Knepley   } else {
627d930f514SMatthew G. Knepley     PetscBool isseq;
628d930f514SMatthew G. Knepley 
6299566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)v, VECSEQ, &isseq));
6309566063dSJacob Faibussowitsch     if (isseq) PetscCall(VecView_Seq(v, viewer));
6319566063dSJacob Faibussowitsch     else PetscCall(VecView_MPI(v, viewer));
632d930f514SMatthew G. Knepley   }
633f16a8b29SMatthew G. Knepley   if (v != originalv) PetscCall(VecDestroy(&v));
6343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
635d930f514SMatthew G. Knepley }
636d930f514SMatthew G. Knepley 
637d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer)
638d71ae5a4SJacob Faibussowitsch {
6392c40f234SMatthew G. Knepley   DM        dm;
6402c40f234SMatthew G. Knepley   PetscBool ishdf5;
6412c40f234SMatthew G. Knepley 
6422c40f234SMatthew G. Knepley   PetscFunctionBegin;
6439566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
64428b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
6459566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
6462c40f234SMatthew G. Knepley   if (ishdf5) {
6472c40f234SMatthew G. Knepley     DM          dmBC;
6482c40f234SMatthew G. Knepley     Vec         gv;
6492c40f234SMatthew G. Knepley     const char *name;
6502c40f234SMatthew G. Knepley 
6519566063dSJacob Faibussowitsch     PetscCall(DMGetOutputDM(dm, &dmBC));
6529566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalVector(dmBC, &gv));
6539566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)v, &name));
6549566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)gv, name));
6559566063dSJacob Faibussowitsch     PetscCall(VecLoad_Default(gv, viewer));
6569566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v));
6579566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v));
6589566063dSJacob Faibussowitsch     PetscCall(DMRestoreGlobalVector(dmBC, &gv));
6591baa6e33SBarry Smith   } else PetscCall(VecLoad_Default(v, viewer));
6603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6612c40f234SMatthew G. Knepley }
6622c40f234SMatthew G. Knepley 
663d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer)
664d71ae5a4SJacob Faibussowitsch {
6652c40f234SMatthew G. Knepley   DM        dm;
6666823f3c5SBlaise Bourdin   PetscBool ishdf5, isexodusii;
6672c40f234SMatthew G. Knepley 
6682c40f234SMatthew G. Knepley   PetscFunctionBegin;
6699566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
67028b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
6719566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
6729566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodusii));
6732c40f234SMatthew G. Knepley   if (ishdf5) {
674878b459fSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
6759566063dSJacob Faibussowitsch     PetscCall(VecLoad_Plex_HDF5_Internal(v, viewer));
676b136c2c9SMatthew G. Knepley #else
677b136c2c9SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
678878b459fSMatthew G. Knepley #endif
6796823f3c5SBlaise Bourdin   } else if (isexodusii) {
6806823f3c5SBlaise Bourdin #if defined(PETSC_HAVE_EXODUSII)
6819566063dSJacob Faibussowitsch     PetscCall(VecLoad_PlexExodusII_Internal(v, viewer));
6826823f3c5SBlaise Bourdin #else
6836823f3c5SBlaise Bourdin     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "ExodusII not supported in this build.\nPlease reconfigure using --download-exodusii");
6846823f3c5SBlaise Bourdin #endif
6851baa6e33SBarry Smith   } else PetscCall(VecLoad_Default(v, viewer));
6863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
687552f7358SJed Brown }
688552f7358SJed Brown 
689d71ae5a4SJacob Faibussowitsch PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer)
690d71ae5a4SJacob Faibussowitsch {
691d930f514SMatthew G. Knepley   DM                dm;
692d930f514SMatthew G. Knepley   PetscViewerFormat format;
693d930f514SMatthew G. Knepley   PetscBool         ishdf5;
694d930f514SMatthew G. Knepley 
695d930f514SMatthew G. Knepley   PetscFunctionBegin;
6969566063dSJacob Faibussowitsch   PetscCall(VecGetDM(originalv, &dm));
69728b400f6SJacob Faibussowitsch   PetscCheck(dm, PetscObjectComm((PetscObject)originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
6989566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
6999566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
700d930f514SMatthew G. Knepley   if (format == PETSC_VIEWER_NATIVE) {
701a8ad634aSStefano Zampini     if (dm->useNatural) {
702d930f514SMatthew G. Knepley       if (dm->sfNatural) {
703d930f514SMatthew G. Knepley         if (ishdf5) {
704d930f514SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
705d930f514SMatthew G. Knepley           Vec         v;
706d930f514SMatthew G. Knepley           const char *vecname;
707d930f514SMatthew G. Knepley 
708f16a8b29SMatthew G. Knepley           PetscCall(DMPlexCreateNaturalVector(dm, &v));
7099566063dSJacob Faibussowitsch           PetscCall(PetscObjectGetName((PetscObject)originalv, &vecname));
7109566063dSJacob Faibussowitsch           PetscCall(PetscObjectSetName((PetscObject)v, vecname));
7119566063dSJacob Faibussowitsch           PetscCall(VecLoad_Plex_HDF5_Native_Internal(v, viewer));
7129566063dSJacob Faibussowitsch           PetscCall(DMPlexNaturalToGlobalBegin(dm, v, originalv));
7139566063dSJacob Faibussowitsch           PetscCall(DMPlexNaturalToGlobalEnd(dm, v, originalv));
714f16a8b29SMatthew G. Knepley           PetscCall(VecDestroy(&v));
715d930f514SMatthew G. Knepley #else
716d930f514SMatthew G. Knepley           SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
717d930f514SMatthew G. Knepley #endif
718d930f514SMatthew G. Knepley         } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5.");
719d930f514SMatthew G. Knepley       }
7201baa6e33SBarry Smith     } else PetscCall(VecLoad_Default(originalv, viewer));
721d930f514SMatthew G. Knepley   }
7223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
723d930f514SMatthew G. Knepley }
724d930f514SMatthew G. Knepley 
725d71ae5a4SJacob Faibussowitsch PETSC_UNUSED static PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer)
726d71ae5a4SJacob Faibussowitsch {
727731e8ddeSMatthew G. Knepley   PetscSection       coordSection;
728731e8ddeSMatthew G. Knepley   Vec                coordinates;
729ba2698f1SMatthew G. Knepley   DMLabel            depthLabel, celltypeLabel;
730731e8ddeSMatthew G. Knepley   const char        *name[4];
731731e8ddeSMatthew G. Knepley   const PetscScalar *a;
732731e8ddeSMatthew G. Knepley   PetscInt           dim, pStart, pEnd, cStart, cEnd, c;
733731e8ddeSMatthew G. Knepley 
734731e8ddeSMatthew G. Knepley   PetscFunctionBegin;
7359566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
7369566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
7379566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
7389566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
7399566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &celltypeLabel));
7409566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
7419566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(coordSection, &pStart, &pEnd));
7429566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(coordinates, &a));
743731e8ddeSMatthew G. Knepley   name[0]       = "vertex";
744731e8ddeSMatthew G. Knepley   name[1]       = "edge";
745731e8ddeSMatthew G. Knepley   name[dim - 1] = "face";
746731e8ddeSMatthew G. Knepley   name[dim]     = "cell";
747731e8ddeSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
748731e8ddeSMatthew G. Knepley     PetscInt *closure = NULL;
749ba2698f1SMatthew G. Knepley     PetscInt  closureSize, cl, ct;
750731e8ddeSMatthew G. Knepley 
7519566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(celltypeLabel, c, &ct));
75263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Geometry for cell %" PetscInt_FMT " polytope type %s:\n", c, DMPolytopeTypes[ct]));
7539566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
7549566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushTab(viewer));
755731e8ddeSMatthew G. Knepley     for (cl = 0; cl < closureSize * 2; cl += 2) {
756731e8ddeSMatthew G. Knepley       PetscInt point = closure[cl], depth, dof, off, d, p;
757731e8ddeSMatthew G. Knepley 
758731e8ddeSMatthew G. Knepley       if ((point < pStart) || (point >= pEnd)) continue;
7599566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(coordSection, point, &dof));
760731e8ddeSMatthew G. Knepley       if (!dof) continue;
7619566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(depthLabel, point, &depth));
7629566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, point, &off));
76363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s %" PetscInt_FMT " coords:", name[depth], point));
764731e8ddeSMatthew G. Knepley       for (p = 0; p < dof / dim; ++p) {
7659566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " ("));
766731e8ddeSMatthew G. Knepley         for (d = 0; d < dim; ++d) {
7679566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
7689566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIIPrintf(viewer, "%g", (double)PetscRealPart(a[off + p * dim + d])));
769731e8ddeSMatthew G. Knepley         }
7709566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, ")"));
771731e8ddeSMatthew G. Knepley       }
7729566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
773731e8ddeSMatthew G. Knepley     }
7749566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
7759566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopTab(viewer));
776731e8ddeSMatthew G. Knepley   }
7779566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(coordinates, &a));
7783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
779731e8ddeSMatthew G. Knepley }
780731e8ddeSMatthew G. Knepley 
7819371c9d4SSatish Balay typedef enum {
7829371c9d4SSatish Balay   CS_CARTESIAN,
7839371c9d4SSatish Balay   CS_POLAR,
7849371c9d4SSatish Balay   CS_CYLINDRICAL,
7859371c9d4SSatish Balay   CS_SPHERICAL
7869371c9d4SSatish Balay } CoordSystem;
78719ad8254SMatthew G. Knepley const char *CoordSystems[] = {"cartesian", "polar", "cylindrical", "spherical", "CoordSystem", "CS_", NULL};
78819ad8254SMatthew G. Knepley 
789d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Ascii_Coordinates(PetscViewer viewer, CoordSystem cs, PetscInt dim, const PetscScalar x[])
790d71ae5a4SJacob Faibussowitsch {
79119ad8254SMatthew G. Knepley   PetscInt i;
79219ad8254SMatthew G. Knepley 
79319ad8254SMatthew G. Knepley   PetscFunctionBegin;
79419ad8254SMatthew G. Knepley   if (dim > 3) {
7959566063dSJacob Faibussowitsch     for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)PetscRealPart(x[i])));
79619ad8254SMatthew G. Knepley   } else {
797bd83fdcbSStefano Zampini     PetscReal coords[3], trcoords[3] = {0., 0., 0.};
79819ad8254SMatthew G. Knepley 
79919ad8254SMatthew G. Knepley     for (i = 0; i < dim; ++i) coords[i] = PetscRealPart(x[i]);
80019ad8254SMatthew G. Knepley     switch (cs) {
8019371c9d4SSatish Balay     case CS_CARTESIAN:
8029371c9d4SSatish Balay       for (i = 0; i < dim; ++i) trcoords[i] = coords[i];
8039371c9d4SSatish Balay       break;
80419ad8254SMatthew G. Knepley     case CS_POLAR:
80563a3b9bcSJacob Faibussowitsch       PetscCheck(dim == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Polar coordinates are for 2 dimension, not %" PetscInt_FMT, dim);
80619ad8254SMatthew G. Knepley       trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]));
80719ad8254SMatthew G. Knepley       trcoords[1] = PetscAtan2Real(coords[1], coords[0]);
80819ad8254SMatthew G. Knepley       break;
80919ad8254SMatthew G. Knepley     case CS_CYLINDRICAL:
81063a3b9bcSJacob Faibussowitsch       PetscCheck(dim == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cylindrical coordinates are for 3 dimension, not %" PetscInt_FMT, dim);
81119ad8254SMatthew G. Knepley       trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]));
81219ad8254SMatthew G. Knepley       trcoords[1] = PetscAtan2Real(coords[1], coords[0]);
81319ad8254SMatthew G. Knepley       trcoords[2] = coords[2];
81419ad8254SMatthew G. Knepley       break;
81519ad8254SMatthew G. Knepley     case CS_SPHERICAL:
81663a3b9bcSJacob Faibussowitsch       PetscCheck(dim == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Spherical coordinates are for 3 dimension, not %" PetscInt_FMT, dim);
81719ad8254SMatthew G. Knepley       trcoords[0] = PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1]) + PetscSqr(coords[2]));
81819ad8254SMatthew G. Knepley       trcoords[1] = PetscAtan2Real(PetscSqrtReal(PetscSqr(coords[0]) + PetscSqr(coords[1])), coords[2]);
81919ad8254SMatthew G. Knepley       trcoords[2] = PetscAtan2Real(coords[1], coords[0]);
82019ad8254SMatthew G. Knepley       break;
82119ad8254SMatthew G. Knepley     }
8229566063dSJacob Faibussowitsch     for (i = 0; i < dim; ++i) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)trcoords[i]));
82319ad8254SMatthew G. Knepley   }
8243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
82519ad8254SMatthew G. Knepley }
82619ad8254SMatthew G. Knepley 
827d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer)
828d71ae5a4SJacob Faibussowitsch {
829552f7358SJed Brown   DM_Plex          *mesh = (DM_Plex *)dm->data;
8306858538eSMatthew G. Knepley   DM                cdm, cdmCell;
8316858538eSMatthew G. Knepley   PetscSection      coordSection, coordSectionCell;
8326858538eSMatthew G. Knepley   Vec               coordinates, coordinatesCell;
833552f7358SJed Brown   PetscViewerFormat format;
834552f7358SJed Brown 
835552f7358SJed Brown   PetscFunctionBegin;
8369566063dSJacob Faibussowitsch   PetscCall(PetscViewerGetFormat(viewer, &format));
837552f7358SJed Brown   if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
838552f7358SJed Brown     const char *name;
839f73eea6eSMatthew G. Knepley     PetscInt    dim, cellHeight, maxConeSize, maxSupportSize;
8409318fe57SMatthew G. Knepley     PetscInt    pStart, pEnd, p, numLabels, l;
841552f7358SJed Brown     PetscMPIInt rank, size;
842552f7358SJed Brown 
8439f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinateDM(dm, &cdm));
8449f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinateSection(dm, &coordSection));
8459f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
8469f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinateDM(dm, &cdmCell));
8479f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell));
8489f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell));
8499566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
8509566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
8519566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
8529566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
8539566063dSJacob Faibussowitsch     PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
8549566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
8559566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
85663a3b9bcSJacob Faibussowitsch     if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s"));
85763a3b9bcSJacob Faibussowitsch     else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s"));
85863a3b9bcSJacob Faibussowitsch     if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, "  Cells are at height %" PetscInt_FMT "\n", cellHeight));
85963a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Supports:\n"));
8609566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
86163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max support size: %" PetscInt_FMT "\n", rank, maxSupportSize));
862552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
863552f7358SJed Brown       PetscInt dof, off, s;
864552f7358SJed Brown 
8659566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
8669566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
86748a46eb9SPierre Jolivet       for (s = off; s < off + dof; ++s) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " ----> %" PetscInt_FMT "\n", rank, p, mesh->supports[s]));
868552f7358SJed Brown     }
8699566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
87063a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "Cones:\n"));
87163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max cone size: %" PetscInt_FMT "\n", rank, maxConeSize));
872552f7358SJed Brown     for (p = pStart; p < pEnd; ++p) {
873552f7358SJed Brown       PetscInt dof, off, c;
874552f7358SJed Brown 
8759566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
8769566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
87748a46eb9SPierre Jolivet       for (c = off; c < off + dof; ++c) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %" PetscInt_FMT " <---- %" PetscInt_FMT " (%" PetscInt_FMT ")\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]));
878552f7358SJed Brown     }
8799566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
8809566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
8813d2e540fSStefano Zampini     if (coordSection && coordinates) {
88219ad8254SMatthew G. Knepley       CoordSystem        cs = CS_CARTESIAN;
8836858538eSMatthew G. Knepley       const PetscScalar *array, *arrayCell = NULL;
8846858538eSMatthew G. Knepley       PetscInt           Nf, Nc, pvStart, pvEnd, pcStart = PETSC_MAX_INT, pcEnd = PETSC_MIN_INT, pStart, pEnd, p;
88519ad8254SMatthew G. Knepley       PetscMPIInt        rank;
88619ad8254SMatthew G. Knepley       const char        *name;
88719ad8254SMatthew G. Knepley 
8889566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetEnum(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_coord_system", CoordSystems, (PetscEnum *)&cs, NULL));
8899566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
8909566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetNumFields(coordSection, &Nf));
89163a3b9bcSJacob Faibussowitsch       PetscCheck(Nf == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Coordinate section should have 1 field, not %" PetscInt_FMT, Nf);
8929566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldComponents(coordSection, 0, &Nc));
8936858538eSMatthew G. Knepley       PetscCall(PetscSectionGetChart(coordSection, &pvStart, &pvEnd));
8946858538eSMatthew G. Knepley       if (coordSectionCell) PetscCall(PetscSectionGetChart(coordSectionCell, &pcStart, &pcEnd));
8956858538eSMatthew G. Knepley       pStart = PetscMin(pvStart, pcStart);
8966858538eSMatthew G. Knepley       pEnd   = PetscMax(pvEnd, pcEnd);
8979566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName((PetscObject)coordinates, &name));
89863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s with %" PetscInt_FMT " fields\n", name, Nf));
89963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  field 0 with %" PetscInt_FMT " components\n", Nc));
9009566063dSJacob Faibussowitsch       if (cs != CS_CARTESIAN) PetscCall(PetscViewerASCIIPrintf(viewer, "  output coordinate system: %s\n", CoordSystems[cs]));
90119ad8254SMatthew G. Knepley 
9029566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(coordinates, &array));
9036858538eSMatthew G. Knepley       if (coordinatesCell) PetscCall(VecGetArrayRead(coordinatesCell, &arrayCell));
9049566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushSynchronized(viewer));
9059566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank));
90619ad8254SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
90719ad8254SMatthew G. Knepley         PetscInt dof, off;
90819ad8254SMatthew G. Knepley 
9096858538eSMatthew G. Knepley         if (p >= pvStart && p < pvEnd) {
9109566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(coordSection, p, &dof));
9119566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(coordSection, p, &off));
9126858538eSMatthew G. Knepley           if (dof) {
91363a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "  (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off));
9149566063dSJacob Faibussowitsch             PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &array[off]));
9159566063dSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
91619ad8254SMatthew G. Knepley           }
9176858538eSMatthew G. Knepley         }
9186858538eSMatthew G. Knepley         if (cdmCell && p >= pcStart && p < pcEnd) {
9196858538eSMatthew G. Knepley           PetscCall(PetscSectionGetDof(coordSectionCell, p, &dof));
9206858538eSMatthew G. Knepley           PetscCall(PetscSectionGetOffset(coordSectionCell, p, &off));
9216858538eSMatthew G. Knepley           if (dof) {
9226858538eSMatthew G. Knepley             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "  (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p, dof, off));
9236858538eSMatthew G. Knepley             PetscCall(DMPlexView_Ascii_Coordinates(viewer, cs, dof, &arrayCell[off]));
9246858538eSMatthew G. Knepley             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
9256858538eSMatthew G. Knepley           }
9266858538eSMatthew G. Knepley         }
9276858538eSMatthew G. Knepley       }
9289566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
9299566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopSynchronized(viewer));
9309566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(coordinates, &array));
9316858538eSMatthew G. Knepley       if (coordinatesCell) PetscCall(VecRestoreArrayRead(coordinatesCell, &arrayCell));
9323d2e540fSStefano Zampini     }
9339566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
9349566063dSJacob Faibussowitsch     if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n"));
9359318fe57SMatthew G. Knepley     for (l = 0; l < numLabels; ++l) {
9369318fe57SMatthew G. Knepley       DMLabel     label;
9379318fe57SMatthew G. Knepley       PetscBool   isdepth;
9389318fe57SMatthew G. Knepley       const char *name;
9399318fe57SMatthew G. Knepley 
9409566063dSJacob Faibussowitsch       PetscCall(DMGetLabelName(dm, l, &name));
9419566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(name, "depth", &isdepth));
9429318fe57SMatthew G. Knepley       if (isdepth) continue;
9439566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, name, &label));
9449566063dSJacob Faibussowitsch       PetscCall(DMLabelView(label, viewer));
9459318fe57SMatthew G. Knepley     }
946552f7358SJed Brown     if (size > 1) {
947552f7358SJed Brown       PetscSF sf;
948552f7358SJed Brown 
9499566063dSJacob Faibussowitsch       PetscCall(DMGetPointSF(dm, &sf));
9509566063dSJacob Faibussowitsch       PetscCall(PetscSFView(sf, viewer));
951552f7358SJed Brown     }
9524e2e9504SJed Brown     if (mesh->periodic.face_sf) PetscCall(PetscSFView(mesh->periodic.face_sf, viewer));
9539566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
954552f7358SJed Brown   } else if (format == PETSC_VIEWER_ASCII_LATEX) {
9550588280cSMatthew G. Knepley     const char  *name, *color;
9560588280cSMatthew G. Knepley     const char  *defcolors[3]  = {"gray", "orange", "green"};
9570588280cSMatthew G. Knepley     const char  *deflcolors[4] = {"blue", "cyan", "red", "magenta"};
958fe1cc32dSStefano Zampini     char         lname[PETSC_MAX_PATH_LEN];
959552f7358SJed Brown     PetscReal    scale      = 2.0;
96078081901SStefano Zampini     PetscReal    tikzscale  = 1.0;
961b7f6ffafSMatthew G. Knepley     PetscBool    useNumbers = PETSC_TRUE, drawNumbers[4], drawColors[4], useLabels, useColors, plotEdges, drawHasse = PETSC_FALSE;
9620588280cSMatthew G. Knepley     double       tcoords[3];
963552f7358SJed Brown     PetscScalar *coords;
964b7f6ffafSMatthew G. Knepley     PetscInt     numLabels, l, numColors, numLColors, dim, d, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p, n;
965552f7358SJed Brown     PetscMPIInt  rank, size;
9660588280cSMatthew G. Knepley     char       **names, **colors, **lcolors;
967b7f6ffafSMatthew G. Knepley     PetscBool    flg, lflg;
968fe1cc32dSStefano Zampini     PetscBT      wp = NULL;
969fe1cc32dSStefano Zampini     PetscInt     pEnd, pStart;
970552f7358SJed Brown 
9719f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinateDM(dm, &cdm));
9729f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinateSection(dm, &coordSection));
9739f4ada15SMatthew G. Knepley     PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
9749f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinateDM(dm, &cdmCell));
9759f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinateSection(dm, &coordSectionCell));
9769f4ada15SMatthew G. Knepley     PetscCall(DMGetCellCoordinatesLocal(dm, &coordinatesCell));
9779566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
9789566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dm, &depth));
9799566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
9800588280cSMatthew G. Knepley     numLabels  = PetscMax(numLabels, 10);
9810588280cSMatthew G. Knepley     numColors  = 10;
9820588280cSMatthew G. Knepley     numLColors = 10;
9839566063dSJacob Faibussowitsch     PetscCall(PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors));
9849566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetReal(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_scale", &scale, NULL));
9859566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetReal(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_tikzscale", &tikzscale, NULL));
9869566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL));
987b7f6ffafSMatthew G. Knepley     for (d = 0; d < 4; ++d) drawNumbers[d] = useNumbers;
988b7f6ffafSMatthew G. Knepley     for (d = 0; d < 4; ++d) drawColors[d] = PETSC_TRUE;
989b7f6ffafSMatthew G. Knepley     n = 4;
9909566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_numbers_depth", drawNumbers, &n, &flg));
9911dca8a05SBarry 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);
9929566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBoolArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors_depth", drawColors, &n, &flg));
9931dca8a05SBarry 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);
9949566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels));
9950588280cSMatthew G. Knepley     if (!useLabels) numLabels = 0;
9969566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors));
9970588280cSMatthew G. Knepley     if (!useColors) {
9980588280cSMatthew G. Knepley       numColors = 3;
9999566063dSJacob Faibussowitsch       for (c = 0; c < numColors; ++c) PetscCall(PetscStrallocpy(defcolors[c], &colors[c]));
10000588280cSMatthew G. Knepley     }
10019566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetStringArray(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors));
10020588280cSMatthew G. Knepley     if (!useColors) {
10030588280cSMatthew G. Knepley       numLColors = 4;
10049566063dSJacob Faibussowitsch       for (c = 0; c < numLColors; ++c) PetscCall(PetscStrallocpy(deflcolors[c], &lcolors[c]));
10050588280cSMatthew G. Knepley     }
10069566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetString(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_label_filter", lname, sizeof(lname), &lflg));
1007b7f6ffafSMatthew G. Knepley     plotEdges = (PetscBool)(depth > 1 && drawNumbers[1] && dim < 3);
10089566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_edges", &plotEdges, &flg));
10091dca8a05SBarry Smith     PetscCheck(!flg || !plotEdges || depth >= dim, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Mesh must be interpolated");
1010202fd40aSStefano Zampini     if (depth < dim) plotEdges = PETSC_FALSE;
10119566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(((PetscObject)viewer)->options, ((PetscObject)viewer)->prefix, "-dm_plex_view_hasse", &drawHasse, NULL));
1012fe1cc32dSStefano Zampini 
1013fe1cc32dSStefano Zampini     /* filter points with labelvalue != labeldefaultvalue */
10149566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
10159566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
10169566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd));
10179566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
1018fe1cc32dSStefano Zampini     if (lflg) {
1019fe1cc32dSStefano Zampini       DMLabel lbl;
1020fe1cc32dSStefano Zampini 
10219566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, lname, &lbl));
1022fe1cc32dSStefano Zampini       if (lbl) {
1023fe1cc32dSStefano Zampini         PetscInt val, defval;
1024fe1cc32dSStefano Zampini 
10259566063dSJacob Faibussowitsch         PetscCall(DMLabelGetDefaultValue(lbl, &defval));
10269566063dSJacob Faibussowitsch         PetscCall(PetscBTCreate(pEnd - pStart, &wp));
1027fe1cc32dSStefano Zampini         for (c = pStart; c < pEnd; c++) {
1028fe1cc32dSStefano Zampini           PetscInt *closure = NULL;
1029fe1cc32dSStefano Zampini           PetscInt  closureSize;
1030fe1cc32dSStefano Zampini 
10319566063dSJacob Faibussowitsch           PetscCall(DMLabelGetValue(lbl, c, &val));
1032fe1cc32dSStefano Zampini           if (val == defval) continue;
1033fe1cc32dSStefano Zampini 
10349566063dSJacob Faibussowitsch           PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
103548a46eb9SPierre Jolivet           for (p = 0; p < closureSize * 2; p += 2) PetscCall(PetscBTSet(wp, closure[p] - pStart));
10369566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1037fe1cc32dSStefano Zampini         }
1038fe1cc32dSStefano Zampini       }
1039fe1cc32dSStefano Zampini     }
1040fe1cc32dSStefano Zampini 
10419566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
10429566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
10439566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
10449566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\
10450588280cSMatthew G. Knepley \\documentclass[tikz]{standalone}\n\n\
1046552f7358SJed Brown \\usepackage{pgflibraryshapes}\n\
1047552f7358SJed Brown \\usetikzlibrary{backgrounds}\n\
1048552f7358SJed Brown \\usetikzlibrary{arrows}\n\
10495f80ce2aSJacob Faibussowitsch \\begin{document}\n"));
10500588280cSMatthew G. Knepley     if (size > 1) {
10519566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%s for process ", name));
1052770b213bSMatthew G Knepley       for (p = 0; p < size; ++p) {
105363a3b9bcSJacob Faibussowitsch         if (p) PetscCall(PetscViewerASCIIPrintf(viewer, (p == size - 1) ? ", and " : ", "));
105463a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%" PetscInt_FMT "}", colors[p % numColors], p));
1055770b213bSMatthew G Knepley       }
10569566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, ".\n\n\n"));
10570588280cSMatthew G. Knepley     }
1058b7f6ffafSMatthew G. Knepley     if (drawHasse) {
1059b7f6ffafSMatthew G. Knepley       PetscInt maxStratum = PetscMax(vEnd - vStart, PetscMax(eEnd - eStart, cEnd - cStart));
1060b7f6ffafSMatthew G. Knepley 
106163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vStart}{%" PetscInt_FMT "}\n", vStart));
106263a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vEnd}{%" PetscInt_FMT "}\n", vEnd - 1));
106363a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numVertices}{%" PetscInt_FMT "}\n", vEnd - vStart));
10649566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\vShift}{%.2f}\n", 3 + (maxStratum - (vEnd - vStart)) / 2.));
106563a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eStart}{%" PetscInt_FMT "}\n", eStart));
106663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eEnd}{%" PetscInt_FMT "}\n", eEnd - 1));
10679566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\eShift}{%.2f}\n", 3 + (maxStratum - (eEnd - eStart)) / 2.));
106863a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numEdges}{%" PetscInt_FMT "}\n", eEnd - eStart));
106963a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cStart}{%" PetscInt_FMT "}\n", cStart));
107063a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cEnd}{%" PetscInt_FMT "}\n", cEnd - 1));
107163a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\numCells}{%" PetscInt_FMT "}\n", cEnd - cStart));
10729566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\newcommand{\\cShift}{%.2f}\n", 3 + (maxStratum - (cEnd - cStart)) / 2.));
1073b7f6ffafSMatthew G. Knepley     }
10749566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", (double)tikzscale));
1075fe1cc32dSStefano Zampini 
1076552f7358SJed Brown     /* Plot vertices */
10779566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
10789566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPushSynchronized(viewer));
1079552f7358SJed Brown     for (v = vStart; v < vEnd; ++v) {
1080552f7358SJed Brown       PetscInt  off, dof, d;
10810588280cSMatthew G. Knepley       PetscBool isLabeled = PETSC_FALSE;
1082552f7358SJed Brown 
1083fe1cc32dSStefano Zampini       if (wp && !PetscBTLookup(wp, v - pStart)) continue;
10849566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(coordSection, v, &dof));
10859566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, v, &off));
10869566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path ("));
108763a3b9bcSJacob Faibussowitsch       PetscCheck(dof <= 3, PETSC_COMM_SELF, PETSC_ERR_PLIB, "coordSection vertex %" PetscInt_FMT " has dof %" PetscInt_FMT " > 3", v, dof);
10880588280cSMatthew G. Knepley       for (d = 0; d < dof; ++d) {
10890588280cSMatthew G. Knepley         tcoords[d] = (double)(scale * PetscRealPart(coords[off + d]));
1090c068d9bbSLisandro Dalcin         tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
10910588280cSMatthew G. Knepley       }
10920588280cSMatthew G. Knepley       /* Rotate coordinates since PGF makes z point out of the page instead of up */
10939371c9d4SSatish Balay       if (dim == 3) {
10949371c9d4SSatish Balay         PetscReal tmp = tcoords[1];
10959371c9d4SSatish Balay         tcoords[1]    = tcoords[2];
10969371c9d4SSatish Balay         tcoords[2]    = -tmp;
10979371c9d4SSatish Balay       }
1098552f7358SJed Brown       for (d = 0; d < dof; ++d) {
10999566063dSJacob Faibussowitsch         if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
11009566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d]));
1101552f7358SJed Brown       }
1102b7f6ffafSMatthew G. Knepley       if (drawHasse) color = colors[0 % numColors];
1103b7f6ffafSMatthew G. Knepley       else color = colors[rank % numColors];
11040588280cSMatthew G. Knepley       for (l = 0; l < numLabels; ++l) {
11050588280cSMatthew G. Knepley         PetscInt val;
11069566063dSJacob Faibussowitsch         PetscCall(DMGetLabelValue(dm, names[l], v, &val));
11079371c9d4SSatish Balay         if (val >= 0) {
11089371c9d4SSatish Balay           color     = lcolors[l % numLColors];
11099371c9d4SSatish Balay           isLabeled = PETSC_TRUE;
11109371c9d4SSatish Balay           break;
11119371c9d4SSatish Balay         }
11120588280cSMatthew G. Knepley       }
1113b7f6ffafSMatthew G. Knepley       if (drawNumbers[0]) {
111463a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", v, rank, color, v));
1115b7f6ffafSMatthew G. Knepley       } else if (drawColors[0]) {
111663a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color));
11171baa6e33SBarry Smith       } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", v, rank));
1118552f7358SJed Brown     }
11199566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
11209566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
1121b7f6ffafSMatthew G. Knepley     /* Plot edges */
1122b7f6ffafSMatthew G. Knepley     if (plotEdges) {
11239566063dSJacob Faibussowitsch       PetscCall(VecGetArray(coordinates, &coords));
11249566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\path\n"));
1125b7f6ffafSMatthew G. Knepley       for (e = eStart; e < eEnd; ++e) {
1126b7f6ffafSMatthew G. Knepley         const PetscInt *cone;
1127b7f6ffafSMatthew G. Knepley         PetscInt        coneSize, offA, offB, dof, d;
1128b7f6ffafSMatthew G. Knepley 
1129b7f6ffafSMatthew G. Knepley         if (wp && !PetscBTLookup(wp, e - pStart)) continue;
11309566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, e, &coneSize));
113163a3b9bcSJacob Faibussowitsch         PetscCheck(coneSize == 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %" PetscInt_FMT " cone should have two vertices, not %" PetscInt_FMT, e, coneSize);
11329566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, e, &cone));
11339566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(coordSection, cone[0], &dof));
11349566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(coordSection, cone[0], &offA));
11359566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(coordSection, cone[1], &offB));
11369566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "("));
1137b7f6ffafSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
1138b7f6ffafSMatthew G. Knepley           tcoords[d] = (double)(0.5 * scale * PetscRealPart(coords[offA + d] + coords[offB + d]));
1139b7f6ffafSMatthew G. Knepley           tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
1140b7f6ffafSMatthew G. Knepley         }
1141b7f6ffafSMatthew G. Knepley         /* Rotate coordinates since PGF makes z point out of the page instead of up */
11429371c9d4SSatish Balay         if (dim == 3) {
11439371c9d4SSatish Balay           PetscReal tmp = tcoords[1];
11449371c9d4SSatish Balay           tcoords[1]    = tcoords[2];
11459371c9d4SSatish Balay           tcoords[2]    = -tmp;
11469371c9d4SSatish Balay         }
1147b7f6ffafSMatthew G. Knepley         for (d = 0; d < dof; ++d) {
11489566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
11499566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d]));
1150b7f6ffafSMatthew G. Knepley         }
1151b7f6ffafSMatthew G. Knepley         if (drawHasse) color = colors[1 % numColors];
1152b7f6ffafSMatthew G. Knepley         else color = colors[rank % numColors];
1153b7f6ffafSMatthew G. Knepley         for (l = 0; l < numLabels; ++l) {
1154b7f6ffafSMatthew G. Knepley           PetscInt val;
11559566063dSJacob Faibussowitsch           PetscCall(DMGetLabelValue(dm, names[l], v, &val));
11569371c9d4SSatish Balay           if (val >= 0) {
11579371c9d4SSatish Balay             color = lcolors[l % numLColors];
11589371c9d4SSatish Balay             break;
11599371c9d4SSatish Balay           }
1160b7f6ffafSMatthew G. Knepley         }
116163a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "} --\n", e, rank, color, e));
1162b7f6ffafSMatthew G. Knepley       }
11639566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(coordinates, &coords));
11649566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
11659566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "(0,0);\n"));
1166b7f6ffafSMatthew G. Knepley     }
1167846a3e8bSMatthew G. Knepley     /* Plot cells */
1168b7f6ffafSMatthew G. Knepley     if (dim == 3 || !drawNumbers[1]) {
1169846a3e8bSMatthew G. Knepley       for (e = eStart; e < eEnd; ++e) {
1170846a3e8bSMatthew G. Knepley         const PetscInt *cone;
1171846a3e8bSMatthew G. Knepley 
1172fe1cc32dSStefano Zampini         if (wp && !PetscBTLookup(wp, e - pStart)) continue;
1173846a3e8bSMatthew G. Knepley         color = colors[rank % numColors];
1174846a3e8bSMatthew G. Knepley         for (l = 0; l < numLabels; ++l) {
1175846a3e8bSMatthew G. Knepley           PetscInt val;
11769566063dSJacob Faibussowitsch           PetscCall(DMGetLabelValue(dm, names[l], e, &val));
11779371c9d4SSatish Balay           if (val >= 0) {
11789371c9d4SSatish Balay             color = lcolors[l % numLColors];
11799371c9d4SSatish Balay             break;
11809371c9d4SSatish Balay           }
1181846a3e8bSMatthew G. Knepley         }
11829566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, e, &cone));
118363a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", color, cone[0], rank, cone[1], rank));
1184846a3e8bSMatthew G. Knepley       }
1185846a3e8bSMatthew G. Knepley     } else {
1186b7f6ffafSMatthew G. Knepley       DMPolytopeType ct;
1187846a3e8bSMatthew G. Knepley 
1188b7f6ffafSMatthew G. Knepley       /* Drawing a 2D polygon */
1189b7f6ffafSMatthew G. Knepley       for (c = cStart; c < cEnd; ++c) {
1190fe1cc32dSStefano Zampini         if (wp && !PetscBTLookup(wp, c - pStart)) continue;
11919566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, c, &ct));
11929371c9d4SSatish Balay         if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || ct == DM_POLYTOPE_TRI_PRISM_TENSOR || ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) {
1193b7f6ffafSMatthew G. Knepley           const PetscInt *cone;
1194b7f6ffafSMatthew G. Knepley           PetscInt        coneSize, e;
1195b7f6ffafSMatthew G. Knepley 
11969566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCone(dm, c, &cone));
11979566063dSJacob Faibussowitsch           PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
1198b7f6ffafSMatthew G. Knepley           for (e = 0; e < coneSize; ++e) {
1199b7f6ffafSMatthew G. Knepley             const PetscInt *econe;
1200b7f6ffafSMatthew G. Knepley 
12019566063dSJacob Faibussowitsch             PetscCall(DMPlexGetCone(dm, cone[e], &econe));
120263a3b9bcSJacob 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));
1203b7f6ffafSMatthew G. Knepley           }
1204b7f6ffafSMatthew G. Knepley         } else {
1205b7f6ffafSMatthew G. Knepley           PetscInt *closure = NULL;
1206b7f6ffafSMatthew G. Knepley           PetscInt  closureSize, Nv = 0, v;
1207b7f6ffafSMatthew G. Knepley 
12089566063dSJacob Faibussowitsch           PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1209846a3e8bSMatthew G. Knepley           for (p = 0; p < closureSize * 2; p += 2) {
1210846a3e8bSMatthew G. Knepley             const PetscInt point = closure[p];
1211846a3e8bSMatthew G. Knepley 
1212b7f6ffafSMatthew G. Knepley             if ((point >= vStart) && (point < vEnd)) closure[Nv++] = point;
1213846a3e8bSMatthew G. Knepley           }
12149566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank % numColors]));
1215b7f6ffafSMatthew G. Knepley           for (v = 0; v <= Nv; ++v) {
1216b7f6ffafSMatthew G. Knepley             const PetscInt vertex = closure[v % Nv];
1217b7f6ffafSMatthew G. Knepley 
1218b7f6ffafSMatthew G. Knepley             if (v > 0) {
1219b7f6ffafSMatthew G. Knepley               if (plotEdges) {
1220b7f6ffafSMatthew G. Knepley                 const PetscInt *edge;
1221b7f6ffafSMatthew G. Knepley                 PetscInt        endpoints[2], ne;
1222b7f6ffafSMatthew G. Knepley 
12239371c9d4SSatish Balay                 endpoints[0] = closure[v - 1];
12249371c9d4SSatish Balay                 endpoints[1] = vertex;
12259566063dSJacob Faibussowitsch                 PetscCall(DMPlexGetJoin(dm, 2, endpoints, &ne, &edge));
122663a3b9bcSJacob Faibussowitsch                 PetscCheck(ne == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not find edge for vertices %" PetscInt_FMT ", %" PetscInt_FMT, endpoints[0], endpoints[1]);
122763a3b9bcSJacob Faibussowitsch                 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- (%" PetscInt_FMT "_%d) -- ", edge[0], rank));
12289566063dSJacob Faibussowitsch                 PetscCall(DMPlexRestoreJoin(dm, 2, endpoints, &ne, &edge));
12291baa6e33SBarry Smith               } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " -- "));
1230b7f6ffafSMatthew G. Knepley             }
123163a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "(%" PetscInt_FMT "_%d)", vertex, rank));
1232b7f6ffafSMatthew G. Knepley           }
12339566063dSJacob Faibussowitsch           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ";\n"));
12349566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
1235846a3e8bSMatthew G. Knepley         }
1236846a3e8bSMatthew G. Knepley       }
1237b7f6ffafSMatthew G. Knepley     }
1238846a3e8bSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
1239846a3e8bSMatthew G. Knepley       double             ccoords[3] = {0.0, 0.0, 0.0};
1240846a3e8bSMatthew G. Knepley       PetscBool          isLabeled  = PETSC_FALSE;
1241c713ec31SMatthew G. Knepley       PetscScalar       *cellCoords = NULL;
1242c713ec31SMatthew G. Knepley       const PetscScalar *array;
1243c713ec31SMatthew G. Knepley       PetscInt           numCoords, cdim, d;
1244c713ec31SMatthew G. Knepley       PetscBool          isDG;
1245846a3e8bSMatthew G. Knepley 
1246fe1cc32dSStefano Zampini       if (wp && !PetscBTLookup(wp, c - pStart)) continue;
1247c713ec31SMatthew G. Knepley       PetscCall(DMGetCoordinateDim(dm, &cdim));
1248c713ec31SMatthew G. Knepley       PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords));
1249c713ec31SMatthew G. Knepley       PetscCheck(!(numCoords % cdim), PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "coordinate dim %" PetscInt_FMT " does not divide numCoords %" PetscInt_FMT, cdim, numCoords);
12509566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\\path ("));
1251c713ec31SMatthew G. Knepley       for (p = 0; p < numCoords / cdim; ++p) {
1252c713ec31SMatthew G. Knepley         for (d = 0; d < cdim; ++d) {
1253c713ec31SMatthew G. Knepley           tcoords[d] = (double)(scale * PetscRealPart(cellCoords[p * cdim + d]));
1254846a3e8bSMatthew G. Knepley           tcoords[d] = PetscAbs(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d];
1255846a3e8bSMatthew G. Knepley         }
1256846a3e8bSMatthew G. Knepley         /* Rotate coordinates since PGF makes z point out of the page instead of up */
12579371c9d4SSatish Balay         if (cdim == 3) {
12589371c9d4SSatish Balay           PetscReal tmp = tcoords[1];
12599371c9d4SSatish Balay           tcoords[1]    = tcoords[2];
12609371c9d4SSatish Balay           tcoords[2]    = -tmp;
12619371c9d4SSatish Balay         }
1262ad540459SPierre Jolivet         for (d = 0; d < dim; ++d) ccoords[d] += tcoords[d];
1263846a3e8bSMatthew G. Knepley       }
1264ad540459SPierre Jolivet       for (d = 0; d < cdim; ++d) ccoords[d] /= (numCoords / cdim);
1265c713ec31SMatthew G. Knepley       PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &array, &cellCoords));
1266c713ec31SMatthew G. Knepley       for (d = 0; d < cdim; ++d) {
12679566063dSJacob Faibussowitsch         if (d > 0) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ","));
12689566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)ccoords[d]));
1269846a3e8bSMatthew G. Knepley       }
1270b7f6ffafSMatthew G. Knepley       if (drawHasse) color = colors[depth % numColors];
1271b7f6ffafSMatthew G. Knepley       else color = colors[rank % numColors];
1272846a3e8bSMatthew G. Knepley       for (l = 0; l < numLabels; ++l) {
1273846a3e8bSMatthew G. Knepley         PetscInt val;
12749566063dSJacob Faibussowitsch         PetscCall(DMGetLabelValue(dm, names[l], c, &val));
12759371c9d4SSatish Balay         if (val >= 0) {
12769371c9d4SSatish Balay           color     = lcolors[l % numLColors];
12779371c9d4SSatish Balay           isLabeled = PETSC_TRUE;
12789371c9d4SSatish Balay           break;
12799371c9d4SSatish Balay         }
1280846a3e8bSMatthew G. Knepley       }
1281b7f6ffafSMatthew G. Knepley       if (drawNumbers[dim]) {
128263a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [draw,shape=circle,color=%s] {%" PetscInt_FMT "};\n", c, rank, color, c));
1283b7f6ffafSMatthew G. Knepley       } else if (drawColors[dim]) {
128463a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", c, rank, !isLabeled ? 1 : 2, color));
12851baa6e33SBarry Smith       } else PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, ") node(%" PetscInt_FMT "_%d) [] {};\n", c, rank));
1286846a3e8bSMatthew G. Knepley     }
1287b7f6ffafSMatthew G. Knepley     if (drawHasse) {
1288b7f6ffafSMatthew G. Knepley       color = colors[depth % numColors];
12899566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Cells\n"));
12909566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\c in {\\cStart,...,\\cEnd}\n"));
12919566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
12929566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\c_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\cShift+\\c-\\cStart,0) {\\c};\n", rank, color));
12939566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1294552f7358SJed Brown 
1295b7f6ffafSMatthew G. Knepley       color = colors[1 % numColors];
12969566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Edges\n"));
12979566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\e in {\\eStart,...,\\eEnd}\n"));
12989566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
12999566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\e_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\eShift+\\e-\\eStart,1) {\\e};\n", rank, color));
13009566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1301b7f6ffafSMatthew G. Knepley 
1302b7f6ffafSMatthew G. Knepley       color = colors[0 % numColors];
13039566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "%% Vertices\n"));
13049566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\\foreach \\v in {\\vStart,...,\\vEnd}\n"));
13059566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "{\n"));
13069566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  \\node(\\v_%d) [draw,shape=circle,color=%s,minimum size = 6mm] at (\\vShift+\\v-\\vStart,2) {\\v};\n", rank, color));
13079566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "}\n"));
1308b7f6ffafSMatthew G. Knepley 
1309b7f6ffafSMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
1310b7f6ffafSMatthew G. Knepley         const PetscInt *cone;
1311b7f6ffafSMatthew G. Knepley         PetscInt        coneSize, cp;
1312b7f6ffafSMatthew G. Knepley 
13139566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, p, &cone));
13149566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
131548a46eb9SPierre Jolivet         for (cp = 0; cp < coneSize; ++cp) PetscCall(PetscViewerASCIIPrintf(viewer, "\\draw[->, shorten >=1pt] (%" PetscInt_FMT "_%d) -- (%" PetscInt_FMT "_%d);\n", cone[cp], rank, p, rank));
13160588280cSMatthew G. Knepley       }
13170588280cSMatthew G. Knepley     }
13189566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(viewer));
13199566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPopSynchronized(viewer));
13209566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n"));
132163a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\\end{document}\n"));
13229566063dSJacob Faibussowitsch     for (l = 0; l < numLabels; ++l) PetscCall(PetscFree(names[l]));
13239566063dSJacob Faibussowitsch     for (c = 0; c < numColors; ++c) PetscCall(PetscFree(colors[c]));
13249566063dSJacob Faibussowitsch     for (c = 0; c < numLColors; ++c) PetscCall(PetscFree(lcolors[c]));
13259566063dSJacob Faibussowitsch     PetscCall(PetscFree3(names, colors, lcolors));
13269566063dSJacob Faibussowitsch     PetscCall(PetscBTDestroy(&wp));
13270f7d6e4aSStefano Zampini   } else if (format == PETSC_VIEWER_LOAD_BALANCE) {
13280f7d6e4aSStefano Zampini     Vec                    cown, acown;
13290f7d6e4aSStefano Zampini     VecScatter             sct;
13300f7d6e4aSStefano Zampini     ISLocalToGlobalMapping g2l;
13310f7d6e4aSStefano Zampini     IS                     gid, acis;
13320f7d6e4aSStefano Zampini     MPI_Comm               comm, ncomm = MPI_COMM_NULL;
13330f7d6e4aSStefano Zampini     MPI_Group              ggroup, ngroup;
13340f7d6e4aSStefano Zampini     PetscScalar           *array, nid;
13350f7d6e4aSStefano Zampini     const PetscInt        *idxs;
13360f7d6e4aSStefano Zampini     PetscInt              *idxs2, *start, *adjacency, *work;
13370f7d6e4aSStefano Zampini     PetscInt64             lm[3], gm[3];
13380f7d6e4aSStefano Zampini     PetscInt               i, c, cStart, cEnd, cum, numVertices, ect, ectn, cellHeight;
13390f7d6e4aSStefano Zampini     PetscMPIInt            d1, d2, rank;
13400f7d6e4aSStefano Zampini 
13419566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
13429566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
1343b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
13449566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_split_type(comm, MPI_COMM_TYPE_SHARED, rank, MPI_INFO_NULL, &ncomm));
13450f7d6e4aSStefano Zampini #endif
13460f7d6e4aSStefano Zampini     if (ncomm != MPI_COMM_NULL) {
13479566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_group(comm, &ggroup));
13489566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_group(ncomm, &ngroup));
13490f7d6e4aSStefano Zampini       d1 = 0;
13509566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_translate_ranks(ngroup, 1, &d1, ggroup, &d2));
13510f7d6e4aSStefano Zampini       nid = d2;
13529566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_free(&ggroup));
13539566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Group_free(&ngroup));
13549566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_free(&ncomm));
13550f7d6e4aSStefano Zampini     } else nid = 0.0;
13560f7d6e4aSStefano Zampini 
13570f7d6e4aSStefano Zampini     /* Get connectivity */
13589566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
13599566063dSJacob Faibussowitsch     PetscCall(DMPlexCreatePartitionerGraph(dm, cellHeight, &numVertices, &start, &adjacency, &gid));
13600f7d6e4aSStefano Zampini 
13610f7d6e4aSStefano Zampini     /* filter overlapped local cells */
13629566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
13639566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(gid, &idxs));
13649566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(gid, &cum));
13659566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(cum, &idxs2));
13660f7d6e4aSStefano Zampini     for (c = cStart, cum = 0; c < cEnd; c++) {
13670f7d6e4aSStefano Zampini       if (idxs[c - cStart] < 0) continue;
13680f7d6e4aSStefano Zampini       idxs2[cum++] = idxs[c - cStart];
13690f7d6e4aSStefano Zampini     }
13709566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(gid, &idxs));
137163a3b9bcSJacob Faibussowitsch     PetscCheck(numVertices == cum, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected %" PetscInt_FMT " != %" PetscInt_FMT, numVertices, cum);
13729566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&gid));
13739566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm, numVertices, idxs2, PETSC_OWN_POINTER, &gid));
13740f7d6e4aSStefano Zampini 
13750f7d6e4aSStefano Zampini     /* support for node-aware cell locality */
13769566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm, start[numVertices], adjacency, PETSC_USE_POINTER, &acis));
13779566063dSJacob Faibussowitsch     PetscCall(VecCreateSeq(PETSC_COMM_SELF, start[numVertices], &acown));
13789566063dSJacob Faibussowitsch     PetscCall(VecCreateMPI(comm, numVertices, PETSC_DECIDE, &cown));
13799566063dSJacob Faibussowitsch     PetscCall(VecGetArray(cown, &array));
13800f7d6e4aSStefano Zampini     for (c = 0; c < numVertices; c++) array[c] = nid;
13819566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(cown, &array));
13829566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(cown, acis, acown, NULL, &sct));
13839566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD));
13849566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(sct, cown, acown, INSERT_VALUES, SCATTER_FORWARD));
13859566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&acis));
13869566063dSJacob Faibussowitsch     PetscCall(VecScatterDestroy(&sct));
13879566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&cown));
13880f7d6e4aSStefano Zampini 
13890f7d6e4aSStefano Zampini     /* compute edgeCut */
13900f7d6e4aSStefano Zampini     for (c = 0, cum = 0; c < numVertices; c++) cum = PetscMax(cum, start[c + 1] - start[c]);
13919566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(cum, &work));
13929566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(gid, &g2l));
13939566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingSetType(g2l, ISLOCALTOGLOBALMAPPINGHASH));
13949566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&gid));
13959566063dSJacob Faibussowitsch     PetscCall(VecGetArray(acown, &array));
13960f7d6e4aSStefano Zampini     for (c = 0, ect = 0, ectn = 0; c < numVertices; c++) {
13970f7d6e4aSStefano Zampini       PetscInt totl;
13980f7d6e4aSStefano Zampini 
13990f7d6e4aSStefano Zampini       totl = start[c + 1] - start[c];
14009566063dSJacob Faibussowitsch       PetscCall(ISGlobalToLocalMappingApply(g2l, IS_GTOLM_MASK, totl, adjacency + start[c], NULL, work));
14010f7d6e4aSStefano Zampini       for (i = 0; i < totl; i++) {
14020f7d6e4aSStefano Zampini         if (work[i] < 0) {
14030f7d6e4aSStefano Zampini           ect += 1;
14040f7d6e4aSStefano Zampini           ectn += (array[i + start[c]] != nid) ? 0 : 1;
14050f7d6e4aSStefano Zampini         }
14060f7d6e4aSStefano Zampini       }
14070f7d6e4aSStefano Zampini     }
14089566063dSJacob Faibussowitsch     PetscCall(PetscFree(work));
14099566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(acown, &array));
14100f7d6e4aSStefano Zampini     lm[0] = numVertices > 0 ? numVertices : PETSC_MAX_INT;
14110f7d6e4aSStefano Zampini     lm[1] = -numVertices;
14121c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(lm, gm, 2, MPIU_INT64, MPI_MIN, comm));
141363a3b9bcSJacob 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]));
14140f7d6e4aSStefano Zampini     lm[0] = ect;                     /* edgeCut */
14150f7d6e4aSStefano Zampini     lm[1] = ectn;                    /* node-aware edgeCut */
14160f7d6e4aSStefano Zampini     lm[2] = numVertices > 0 ? 0 : 1; /* empty processes */
14171c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(lm, gm, 3, MPIU_INT64, MPI_SUM, comm));
141863a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, ", empty %" PetscInt_FMT ")\n", (PetscInt)gm[2]));
1419b674149eSJunchao Zhang #if defined(PETSC_HAVE_MPI_PROCESS_SHARED_MEMORY)
142063a3b9bcSJacob 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.));
14210f7d6e4aSStefano Zampini #else
142263a3b9bcSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "  Edge Cut: %" PetscInt_FMT " (on node %.3f)\n", (PetscInt)(gm[0] / 2), 0.0));
14230f7d6e4aSStefano Zampini #endif
14249566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&g2l));
14259566063dSJacob Faibussowitsch     PetscCall(PetscFree(start));
14269566063dSJacob Faibussowitsch     PetscCall(PetscFree(adjacency));
14279566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&acown));
1428552f7358SJed Brown   } else {
1429412e9a14SMatthew G. Knepley     const char    *name;
1430d80ece95SMatthew G. Knepley     PetscInt      *sizes, *hybsizes, *ghostsizes;
1431412e9a14SMatthew G. Knepley     PetscInt       locDepth, depth, cellHeight, dim, d;
1432d80ece95SMatthew G. Knepley     PetscInt       pStart, pEnd, p, gcStart, gcEnd, gcNum;
1433ca7bf7eeSMatthew G. Knepley     PetscInt       numLabels, l, maxSize = 17;
14349318fe57SMatthew G. Knepley     DMPolytopeType ct0 = DM_POLYTOPE_UNKNOWN;
1435412e9a14SMatthew G. Knepley     MPI_Comm       comm;
1436412e9a14SMatthew G. Knepley     PetscMPIInt    size, rank;
1437552f7358SJed Brown 
14389566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
14399566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(comm, &size));
14409566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(comm, &rank));
14419566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
14429566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
14439566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
144463a3b9bcSJacob Faibussowitsch     if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "%s in %" PetscInt_FMT " dimension%s:\n", name, dim, dim == 1 ? "" : "s"));
144563a3b9bcSJacob Faibussowitsch     else PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh in %" PetscInt_FMT " dimension%s:\n", dim, dim == 1 ? "" : "s"));
144663a3b9bcSJacob Faibussowitsch     if (cellHeight) PetscCall(PetscViewerASCIIPrintf(viewer, "  Cells are at height %" PetscInt_FMT "\n", cellHeight));
14479566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dm, &locDepth));
14481c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm));
14492827ebadSStefano Zampini     PetscCall(DMPlexGetCellTypeStratum(dm, DM_POLYTOPE_FV_GHOST, &gcStart, &gcEnd));
1450d80ece95SMatthew G. Knepley     gcNum = gcEnd - gcStart;
14519566063dSJacob Faibussowitsch     if (size < maxSize) PetscCall(PetscCalloc3(size, &sizes, size, &hybsizes, size, &ghostsizes));
14529566063dSJacob Faibussowitsch     else PetscCall(PetscCalloc3(3, &sizes, 3, &hybsizes, 3, &ghostsizes));
1453412e9a14SMatthew G. Knepley     for (d = 0; d <= depth; d++) {
1454412e9a14SMatthew G. Knepley       PetscInt Nc[2] = {0, 0}, ict;
1455412e9a14SMatthew G. Knepley 
14569566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
14579566063dSJacob Faibussowitsch       if (pStart < pEnd) PetscCall(DMPlexGetCellType(dm, pStart, &ct0));
1458412e9a14SMatthew G. Knepley       ict = ct0;
14599566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Bcast(&ict, 1, MPIU_INT, 0, comm));
1460412e9a14SMatthew G. Knepley       ct0 = (DMPolytopeType)ict;
1461412e9a14SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
1462412e9a14SMatthew G. Knepley         DMPolytopeType ct;
1463412e9a14SMatthew G. Knepley 
14649566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, p, &ct));
1465412e9a14SMatthew G. Knepley         if (ct == ct0) ++Nc[0];
1466412e9a14SMatthew G. Knepley         else ++Nc[1];
1467412e9a14SMatthew G. Knepley       }
1468ca7bf7eeSMatthew G. Knepley       if (size < maxSize) {
14699566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Gather(&Nc[0], 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm));
14709566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Gather(&Nc[1], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm));
14719566063dSJacob Faibussowitsch         if (d == depth) PetscCallMPI(MPI_Gather(&gcNum, 1, MPIU_INT, ghostsizes, 1, MPIU_INT, 0, comm));
147263a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Number of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d));
1473834065abSMatthew G. Knepley         for (p = 0; p < size; ++p) {
1474dd400576SPatrick Sanan           if (rank == 0) {
147563a3b9bcSJacob Faibussowitsch             PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT, sizes[p] + hybsizes[p]));
147663a3b9bcSJacob Faibussowitsch             if (hybsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT ")", hybsizes[p]));
147763a3b9bcSJacob Faibussowitsch             if (ghostsizes[p] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "]", ghostsizes[p]));
1478834065abSMatthew G. Knepley           }
1479cbb7f117SMark Adams         }
1480ca7bf7eeSMatthew G. Knepley       } else {
1481ca7bf7eeSMatthew G. Knepley         PetscInt locMinMax[2];
1482ca7bf7eeSMatthew G. Knepley 
14839371c9d4SSatish Balay         locMinMax[0] = Nc[0] + Nc[1];
14849371c9d4SSatish Balay         locMinMax[1] = Nc[0] + Nc[1];
14859566063dSJacob Faibussowitsch         PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, sizes));
14869371c9d4SSatish Balay         locMinMax[0] = Nc[1];
14879371c9d4SSatish Balay         locMinMax[1] = Nc[1];
14889566063dSJacob Faibussowitsch         PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, hybsizes));
1489ca7bf7eeSMatthew G. Knepley         if (d == depth) {
14909371c9d4SSatish Balay           locMinMax[0] = gcNum;
14919371c9d4SSatish Balay           locMinMax[1] = gcNum;
14929566063dSJacob Faibussowitsch           PetscCall(PetscGlobalMinMaxInt(comm, locMinMax, ghostsizes));
1493ca7bf7eeSMatthew G. Knepley         }
149463a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "  Min/Max of %" PetscInt_FMT "-cells per rank:", (depth == 1) && d ? dim : d));
14959566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, " %" PetscInt_FMT "/%" PetscInt_FMT, sizes[0], sizes[1]));
14969566063dSJacob Faibussowitsch         if (hybsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " (%" PetscInt_FMT "/%" PetscInt_FMT ")", hybsizes[0], hybsizes[1]));
14979566063dSJacob Faibussowitsch         if (ghostsizes[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, " [%" PetscInt_FMT "/%" PetscInt_FMT "]", ghostsizes[0], ghostsizes[1]));
1498ca7bf7eeSMatthew G. Knepley       }
14999566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
1500552f7358SJed Brown     }
15019566063dSJacob Faibussowitsch     PetscCall(PetscFree3(sizes, hybsizes, ghostsizes));
15029318fe57SMatthew G. Knepley     {
15039318fe57SMatthew G. Knepley       const PetscReal *maxCell;
15049318fe57SMatthew G. Knepley       const PetscReal *L;
15056858538eSMatthew G. Knepley       PetscBool        localized;
15069318fe57SMatthew G. Knepley 
15074fb89dddSMatthew G. Knepley       PetscCall(DMGetPeriodicity(dm, &maxCell, NULL, &L));
15089566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocalized(dm, &localized));
15096858538eSMatthew G. Knepley       if (L || localized) {
15106858538eSMatthew G. Knepley         PetscCall(PetscViewerASCIIPrintf(viewer, "Periodic mesh"));
15119566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
15126858538eSMatthew G. Knepley         if (L) {
15136858538eSMatthew G. Knepley           PetscCall(PetscViewerASCIIPrintf(viewer, " ("));
15149318fe57SMatthew G. Knepley           for (d = 0; d < dim; ++d) {
15156858538eSMatthew G. Knepley             if (d > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
15166858538eSMatthew G. Knepley             PetscCall(PetscViewerASCIIPrintf(viewer, "%s", L[d] > 0.0 ? "PERIODIC" : "NONE"));
15179318fe57SMatthew G. Knepley           }
15186858538eSMatthew G. Knepley           PetscCall(PetscViewerASCIIPrintf(viewer, ")"));
15196858538eSMatthew G. Knepley         }
15206858538eSMatthew G. Knepley         PetscCall(PetscViewerASCIIPrintf(viewer, " coordinates %s\n", localized ? "localized" : "not localized"));
15219566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
15229318fe57SMatthew G. Knepley       }
15239318fe57SMatthew G. Knepley     }
15249566063dSJacob Faibussowitsch     PetscCall(DMGetNumLabels(dm, &numLabels));
15259566063dSJacob Faibussowitsch     if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Labels:\n"));
1526a57dd577SMatthew G Knepley     for (l = 0; l < numLabels; ++l) {
1527a57dd577SMatthew G Knepley       DMLabel         label;
1528a57dd577SMatthew G Knepley       const char     *name;
1529a57dd577SMatthew G Knepley       IS              valueIS;
1530a57dd577SMatthew G Knepley       const PetscInt *values;
1531a57dd577SMatthew G Knepley       PetscInt        numValues, v;
1532a57dd577SMatthew G Knepley 
15339566063dSJacob Faibussowitsch       PetscCall(DMGetLabelName(dm, l, &name));
15349566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, name, &label));
15359566063dSJacob Faibussowitsch       PetscCall(DMLabelGetNumValues(label, &numValues));
153663a3b9bcSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "  %s: %" PetscInt_FMT " strata with value/size (", name, numValues));
15379566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValueIS(label, &valueIS));
15389566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(valueIS, &values));
15399566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_FALSE));
1540a57dd577SMatthew G Knepley       for (v = 0; v < numValues; ++v) {
1541a57dd577SMatthew G Knepley         PetscInt size;
1542a57dd577SMatthew G Knepley 
15439566063dSJacob Faibussowitsch         PetscCall(DMLabelGetStratumSize(label, values[v], &size));
15449566063dSJacob Faibussowitsch         if (v > 0) PetscCall(PetscViewerASCIIPrintf(viewer, ", "));
154563a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPrintf(viewer, "%" PetscInt_FMT " (%" PetscInt_FMT ")", values[v], size));
1546a57dd577SMatthew G Knepley       }
15479566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, ")\n"));
15489566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIUseTabs(viewer, PETSC_TRUE));
15499566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(valueIS, &values));
15509566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&valueIS));
1551a57dd577SMatthew G Knepley     }
1552c1cad2e7SMatthew G. Knepley     {
1553c1cad2e7SMatthew G. Knepley       char    **labelNames;
1554c1cad2e7SMatthew G. Knepley       PetscInt  Nl = numLabels;
1555c1cad2e7SMatthew G. Knepley       PetscBool flg;
1556c1cad2e7SMatthew G. Knepley 
15579566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Nl, &labelNames));
15589566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetStringArray(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_view_labels", labelNames, &Nl, &flg));
1559c1cad2e7SMatthew G. Knepley       for (l = 0; l < Nl; ++l) {
1560c1cad2e7SMatthew G. Knepley         DMLabel label;
1561c1cad2e7SMatthew G. Knepley 
15629566063dSJacob Faibussowitsch         PetscCall(DMHasLabel(dm, labelNames[l], &flg));
1563c1cad2e7SMatthew G. Knepley         if (flg) {
15649566063dSJacob Faibussowitsch           PetscCall(DMGetLabel(dm, labelNames[l], &label));
15659566063dSJacob Faibussowitsch           PetscCall(DMLabelView(label, viewer));
1566c1cad2e7SMatthew G. Knepley         }
15679566063dSJacob Faibussowitsch         PetscCall(PetscFree(labelNames[l]));
1568c1cad2e7SMatthew G. Knepley       }
15699566063dSJacob Faibussowitsch       PetscCall(PetscFree(labelNames));
1570c1cad2e7SMatthew G. Knepley     }
157134aa8a36SMatthew G. Knepley     /* If no fields are specified, people do not want to see adjacency */
157234aa8a36SMatthew G. Knepley     if (dm->Nf) {
157334aa8a36SMatthew G. Knepley       PetscInt f;
157434aa8a36SMatthew G. Knepley 
157534aa8a36SMatthew G. Knepley       for (f = 0; f < dm->Nf; ++f) {
157634aa8a36SMatthew G. Knepley         const char *name;
157734aa8a36SMatthew G. Knepley 
15789566063dSJacob Faibussowitsch         PetscCall(PetscObjectGetName(dm->fields[f].disc, &name));
15799566063dSJacob Faibussowitsch         if (numLabels) PetscCall(PetscViewerASCIIPrintf(viewer, "Field %s:\n", name));
15809566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPushTab(viewer));
15819566063dSJacob Faibussowitsch         if (dm->fields[f].label) PetscCall(DMLabelView(dm->fields[f].label, viewer));
158234aa8a36SMatthew G. Knepley         if (dm->fields[f].adjacency[0]) {
15839566063dSJacob Faibussowitsch           if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM++\n"));
15849566063dSJacob Faibussowitsch           else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FVM\n"));
158534aa8a36SMatthew G. Knepley         } else {
15869566063dSJacob Faibussowitsch           if (dm->fields[f].adjacency[1]) PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FEM\n"));
15879566063dSJacob Faibussowitsch           else PetscCall(PetscViewerASCIIPrintf(viewer, "adjacency FUNKY\n"));
158834aa8a36SMatthew G. Knepley         }
15899566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIPopTab(viewer));
159034aa8a36SMatthew G. Knepley       }
159134aa8a36SMatthew G. Knepley     }
15929566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dm, &cdm));
15938e7ff633SMatthew G. Knepley     if (cdm) {
15949566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushTab(viewer));
15959f4ada15SMatthew G. Knepley       PetscCall(PetscViewerASCIIPrintf(viewer, "Defined by transform from:\n"));
15969566063dSJacob Faibussowitsch       PetscCall(DMPlexView_Ascii(cdm, viewer));
15979566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopTab(viewer));
15988e7ff633SMatthew G. Knepley     }
1599552f7358SJed Brown   }
16003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1601552f7358SJed Brown }
1602552f7358SJed Brown 
1603d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDrawCell(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[])
1604d71ae5a4SJacob Faibussowitsch {
1605e5c487bfSMatthew G. Knepley   DMPolytopeType ct;
1606e5c487bfSMatthew G. Knepley   PetscMPIInt    rank;
1607a12d352dSMatthew G. Knepley   PetscInt       cdim;
1608e5c487bfSMatthew G. Knepley 
1609e5c487bfSMatthew G. Knepley   PetscFunctionBegin;
16109566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
16119566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cell, &ct));
16129566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
1613e5c487bfSMatthew G. Knepley   switch (ct) {
1614a12d352dSMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
1615a12d352dSMatthew G. Knepley   case DM_POLYTOPE_POINT_PRISM_TENSOR:
1616a12d352dSMatthew G. Knepley     switch (cdim) {
16179371c9d4SSatish Balay     case 1: {
1618a12d352dSMatthew G. Knepley       const PetscReal y  = 0.5;  /* TODO Put it in the middle of the viewport */
1619a12d352dSMatthew G. Knepley       const PetscReal dy = 0.05; /* TODO Make it a fraction of the total length */
1620a12d352dSMatthew G. Knepley 
16219566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y, PetscRealPart(coords[1]), y, PETSC_DRAW_BLACK));
16229566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), y + dy, PetscRealPart(coords[0]), y - dy, PETSC_DRAW_BLACK));
16239566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[1]), y + dy, PetscRealPart(coords[1]), y - dy, PETSC_DRAW_BLACK));
16249371c9d4SSatish Balay     } break;
16259371c9d4SSatish Balay     case 2: {
1626a12d352dSMatthew G. Knepley       const PetscReal dx = (PetscRealPart(coords[3]) - PetscRealPart(coords[1]));
1627a12d352dSMatthew G. Knepley       const PetscReal dy = (PetscRealPart(coords[2]) - PetscRealPart(coords[0]));
1628a12d352dSMatthew G. Knepley       const PetscReal l  = 0.1 / PetscSqrtReal(dx * dx + dy * dy);
1629a12d352dSMatthew G. Knepley 
16309566063dSJacob Faibussowitsch       PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
16319566063dSJacob 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));
16329566063dSJacob 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));
16339371c9d4SSatish Balay     } break;
1634d71ae5a4SJacob Faibussowitsch     default:
1635d71ae5a4SJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of dimension %" PetscInt_FMT, cdim);
1636a12d352dSMatthew G. Knepley     }
1637a12d352dSMatthew G. Knepley     break;
1638e5c487bfSMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
16399371c9d4SSatish Balay     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2));
16409566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
16419566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK));
16429566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK));
1643e5c487bfSMatthew G. Knepley     break;
1644e5c487bfSMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
16459371c9d4SSatish Balay     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2));
16469371c9d4SSatish Balay     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2));
16479566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
16489566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK));
16499566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK));
16509566063dSJacob Faibussowitsch     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK));
1651e5c487bfSMatthew G. Knepley     break;
16529f4ada15SMatthew G. Knepley   case DM_POLYTOPE_SEG_PRISM_TENSOR:
16539f4ada15SMatthew G. Knepley     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2));
16549f4ada15SMatthew G. Knepley     PetscCall(PetscDrawTriangle(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2, PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2));
16559f4ada15SMatthew G. Knepley     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[0]), PetscRealPart(coords[1]), PetscRealPart(coords[2]), PetscRealPart(coords[3]), PETSC_DRAW_BLACK));
16569f4ada15SMatthew G. Knepley     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[2]), PetscRealPart(coords[3]), PetscRealPart(coords[6]), PetscRealPart(coords[7]), PETSC_DRAW_BLACK));
16579f4ada15SMatthew G. Knepley     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[6]), PetscRealPart(coords[7]), PetscRealPart(coords[4]), PetscRealPart(coords[5]), PETSC_DRAW_BLACK));
16589f4ada15SMatthew G. Knepley     PetscCall(PetscDrawLine(draw, PetscRealPart(coords[4]), PetscRealPart(coords[5]), PetscRealPart(coords[0]), PetscRealPart(coords[1]), PETSC_DRAW_BLACK));
16599f4ada15SMatthew G. Knepley     break;
1660d71ae5a4SJacob Faibussowitsch   case DM_POLYTOPE_FV_GHOST:
1661d71ae5a4SJacob Faibussowitsch     break;
1662d71ae5a4SJacob Faibussowitsch   default:
1663d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]);
1664e5c487bfSMatthew G. Knepley   }
16653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1666e5c487bfSMatthew G. Knepley }
1667e5c487bfSMatthew G. Knepley 
1668d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexDrawCellHighOrder(DM dm, PetscDraw draw, PetscInt cell, const PetscScalar coords[], PetscInt edgeDiv, PetscReal refCoords[], PetscReal edgeCoords[])
1669d71ae5a4SJacob Faibussowitsch {
1670e5c487bfSMatthew G. Knepley   DMPolytopeType ct;
1671e5c487bfSMatthew G. Knepley   PetscReal      centroid[2] = {0., 0.};
1672e5c487bfSMatthew G. Knepley   PetscMPIInt    rank;
1673e5c487bfSMatthew G. Knepley   PetscInt       fillColor, v, e, d;
1674e5c487bfSMatthew G. Knepley 
1675e5c487bfSMatthew G. Knepley   PetscFunctionBegin;
16769566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
16779566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cell, &ct));
1678e5c487bfSMatthew G. Knepley   fillColor = PETSC_DRAW_WHITE + rank % (PETSC_DRAW_BASIC_COLORS - 2) + 2;
1679e5c487bfSMatthew G. Knepley   switch (ct) {
16809371c9d4SSatish Balay   case DM_POLYTOPE_TRIANGLE: {
1681e5c487bfSMatthew G. Knepley     PetscReal refVertices[6] = {-1., -1., 1., -1., -1., 1.};
1682e5c487bfSMatthew G. Knepley 
16839371c9d4SSatish Balay     for (v = 0; v < 3; ++v) {
16849371c9d4SSatish Balay       centroid[0] += PetscRealPart(coords[v * 2 + 0]) / 3.;
16859371c9d4SSatish Balay       centroid[1] += PetscRealPart(coords[v * 2 + 1]) / 3.;
16869371c9d4SSatish Balay     }
1687e5c487bfSMatthew G. Knepley     for (e = 0; e < 3; ++e) {
1688e5c487bfSMatthew G. Knepley       refCoords[0] = refVertices[e * 2 + 0];
1689e5c487bfSMatthew G. Knepley       refCoords[1] = refVertices[e * 2 + 1];
1690e5c487bfSMatthew G. Knepley       for (d = 1; d <= edgeDiv; ++d) {
1691e5c487bfSMatthew G. Knepley         refCoords[d * 2 + 0] = refCoords[0] + (refVertices[(e + 1) % 3 * 2 + 0] - refCoords[0]) * d / edgeDiv;
1692e5c487bfSMatthew G. Knepley         refCoords[d * 2 + 1] = refCoords[1] + (refVertices[(e + 1) % 3 * 2 + 1] - refCoords[1]) * d / edgeDiv;
1693e5c487bfSMatthew G. Knepley       }
16949566063dSJacob Faibussowitsch       PetscCall(DMPlexReferenceToCoordinates(dm, cell, edgeDiv + 1, refCoords, edgeCoords));
1695e5c487bfSMatthew G. Knepley       for (d = 0; d < edgeDiv; ++d) {
16969566063dSJacob 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));
16979566063dSJacob 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));
1698e5c487bfSMatthew G. Knepley       }
1699e5c487bfSMatthew G. Knepley     }
17009371c9d4SSatish Balay   } break;
1701d71ae5a4SJacob Faibussowitsch   default:
1702d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot draw cells of type %s", DMPolytopeTypes[ct]);
1703e5c487bfSMatthew G. Knepley   }
17043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1705e5c487bfSMatthew G. Knepley }
1706e5c487bfSMatthew G. Knepley 
1707d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexView_Draw(DM dm, PetscViewer viewer)
1708d71ae5a4SJacob Faibussowitsch {
1709e412dcbdSMatthew G. Knepley   PetscDraw    draw;
1710e412dcbdSMatthew G. Knepley   DM           cdm;
1711e412dcbdSMatthew G. Knepley   PetscSection coordSection;
1712e412dcbdSMatthew G. Knepley   Vec          coordinates;
1713c9c77995SMatthew G. Knepley   PetscReal    xyl[3], xyr[3];
1714e5c487bfSMatthew G. Knepley   PetscReal   *refCoords, *edgeCoords;
1715e5c487bfSMatthew G. Knepley   PetscBool    isnull, drawAffine = PETSC_TRUE;
1716c9c77995SMatthew G. Knepley   PetscInt     dim, vStart, vEnd, cStart, cEnd, c, edgeDiv = 4;
1717e412dcbdSMatthew G. Knepley 
1718e412dcbdSMatthew G. Knepley   PetscFunctionBegin;
17199566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dim));
172063a3b9bcSJacob Faibussowitsch   PetscCheck(dim <= 2, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Cannot draw meshes of dimension %" PetscInt_FMT, dim);
17219566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_view_draw_affine", &drawAffine, NULL));
17229566063dSJacob Faibussowitsch   if (!drawAffine) PetscCall(PetscMalloc2((edgeDiv + 1) * dim, &refCoords, (edgeDiv + 1) * dim, &edgeCoords));
17239566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
17249566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(cdm, &coordSection));
17259566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
17269566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
17279566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
1728e412dcbdSMatthew G. Knepley 
17299566063dSJacob Faibussowitsch   PetscCall(PetscViewerDrawGetDraw(viewer, 0, &draw));
17309566063dSJacob Faibussowitsch   PetscCall(PetscDrawIsNull(draw, &isnull));
17313ba16761SJacob Faibussowitsch   if (isnull) PetscFunctionReturn(PETSC_SUCCESS);
17329566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetTitle(draw, "Mesh"));
1733e412dcbdSMatthew G. Knepley 
1734c9c77995SMatthew G. Knepley   PetscCall(DMGetBoundingBox(dm, xyl, xyr));
17359566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetCoordinates(draw, xyl[0], xyl[1], xyr[0], xyr[1]));
17369566063dSJacob Faibussowitsch   PetscCall(PetscDrawClear(draw));
1737e412dcbdSMatthew G. Knepley 
1738cf3064d3SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1739cf3064d3SMatthew G. Knepley     PetscScalar       *coords = NULL;
1740c9c77995SMatthew G. Knepley     const PetscScalar *coords_arr;
1741ba2698f1SMatthew G. Knepley     PetscInt           numCoords;
1742c9c77995SMatthew G. Knepley     PetscBool          isDG;
1743cf3064d3SMatthew G. Knepley 
1744c9c77995SMatthew G. Knepley     PetscCall(DMPlexGetCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords));
17451baa6e33SBarry Smith     if (drawAffine) PetscCall(DMPlexDrawCell(dm, draw, c, coords));
17461baa6e33SBarry Smith     else PetscCall(DMPlexDrawCellHighOrder(dm, draw, c, coords, edgeDiv, refCoords, edgeCoords));
1747c9c77995SMatthew G. Knepley     PetscCall(DMPlexRestoreCellCoordinates(dm, c, &isDG, &numCoords, &coords_arr, &coords));
1748cf3064d3SMatthew G. Knepley   }
17499566063dSJacob Faibussowitsch   if (!drawAffine) PetscCall(PetscFree2(refCoords, edgeCoords));
17509566063dSJacob Faibussowitsch   PetscCall(PetscDrawFlush(draw));
17519566063dSJacob Faibussowitsch   PetscCall(PetscDrawPause(draw));
17529566063dSJacob Faibussowitsch   PetscCall(PetscDrawSave(draw));
17533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1754e412dcbdSMatthew G. Knepley }
1755e412dcbdSMatthew G. Knepley 
17561e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII)
17571e50132fSMatthew G. Knepley   #include <exodusII.h>
17586823f3c5SBlaise Bourdin   #include <petscviewerexodusii.h>
17591e50132fSMatthew G. Knepley #endif
17601e50132fSMatthew G. Knepley 
1761d71ae5a4SJacob Faibussowitsch PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer)
1762d71ae5a4SJacob Faibussowitsch {
17635f34f2dcSJed Brown   PetscBool iascii, ishdf5, isvtk, isdraw, flg, isglvis, isexodus, iscgns;
1764002a2709SMatthew G. Knepley   char      name[PETSC_MAX_PATH_LEN];
1765552f7358SJed Brown 
1766552f7358SJed Brown   PetscFunctionBegin;
1767552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1768552f7358SJed Brown   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
17699566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
17709566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK, &isvtk));
17719566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
17729566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
17739566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERGLVIS, &isglvis));
17749566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWEREXODUSII, &isexodus));
17755f34f2dcSJed Brown   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERCGNS, &iscgns));
1776552f7358SJed Brown   if (iascii) {
17778135c375SStefano Zampini     PetscViewerFormat format;
17789566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
17791baa6e33SBarry Smith     if (format == PETSC_VIEWER_ASCII_GLVIS) PetscCall(DMPlexView_GLVis(dm, viewer));
17801baa6e33SBarry Smith     else PetscCall(DMPlexView_Ascii(dm, viewer));
1781c6ccd67eSMatthew G. Knepley   } else if (ishdf5) {
1782c6ccd67eSMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
17839566063dSJacob Faibussowitsch     PetscCall(DMPlexView_HDF5_Internal(dm, viewer));
1784c6ccd67eSMatthew G. Knepley #else
1785c6ccd67eSMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1786552f7358SJed Brown #endif
1787e412dcbdSMatthew G. Knepley   } else if (isvtk) {
17889566063dSJacob Faibussowitsch     PetscCall(DMPlexVTKWriteAll((PetscObject)dm, viewer));
1789e412dcbdSMatthew G. Knepley   } else if (isdraw) {
17909566063dSJacob Faibussowitsch     PetscCall(DMPlexView_Draw(dm, viewer));
17918135c375SStefano Zampini   } else if (isglvis) {
17929566063dSJacob Faibussowitsch     PetscCall(DMPlexView_GLVis(dm, viewer));
17931e50132fSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII)
17941e50132fSMatthew G. Knepley   } else if (isexodus) {
17956823f3c5SBlaise Bourdin     /*
17966823f3c5SBlaise Bourdin       exodusII requires that all sets be part of exactly one cell set.
17976823f3c5SBlaise Bourdin       If the dm does not have a "Cell Sets" label defined, we create one
1798da81f932SPierre Jolivet       with ID 1, containing all cells.
17996823f3c5SBlaise Bourdin       Note that if the Cell Sets label is defined but does not cover all cells,
18006823f3c5SBlaise Bourdin       we may still have a problem. This should probably be checked here or in the viewer;
18016823f3c5SBlaise Bourdin     */
18026823f3c5SBlaise Bourdin     PetscInt numCS;
18039566063dSJacob Faibussowitsch     PetscCall(DMGetLabelSize(dm, "Cell Sets", &numCS));
18046823f3c5SBlaise Bourdin     if (!numCS) {
18051e50132fSMatthew G. Knepley       PetscInt cStart, cEnd, c;
18069566063dSJacob Faibussowitsch       PetscCall(DMCreateLabel(dm, "Cell Sets"));
18079566063dSJacob Faibussowitsch       PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
18089566063dSJacob Faibussowitsch       for (c = cStart; c < cEnd; ++c) PetscCall(DMSetLabelValue(dm, "Cell Sets", c, 1));
18096823f3c5SBlaise Bourdin     }
18109566063dSJacob Faibussowitsch     PetscCall(DMView_PlexExodusII(dm, viewer));
18111e50132fSMatthew G. Knepley #endif
18125f34f2dcSJed Brown #if defined(PETSC_HAVE_CGNS)
18135f34f2dcSJed Brown   } else if (iscgns) {
18145f34f2dcSJed Brown     PetscCall(DMView_PlexCGNS(dm, viewer));
18155f34f2dcSJed Brown #endif
18161baa6e33SBarry Smith   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex writing", ((PetscObject)viewer)->type_name);
1817cb3ba0daSMatthew G. Knepley   /* Optionally view the partition */
18189566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHasName(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_partition_view", &flg));
1819cb3ba0daSMatthew G. Knepley   if (flg) {
1820cb3ba0daSMatthew G. Knepley     Vec ranks;
18219566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateRankField(dm, &ranks));
18229566063dSJacob Faibussowitsch     PetscCall(VecView(ranks, viewer));
18239566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&ranks));
1824cb3ba0daSMatthew G. Knepley   }
1825002a2709SMatthew G. Knepley   /* Optionally view a label */
18269566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetString(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_label_view", name, sizeof(name), &flg));
1827002a2709SMatthew G. Knepley   if (flg) {
1828002a2709SMatthew G. Knepley     DMLabel label;
1829002a2709SMatthew G. Knepley     Vec     val;
1830002a2709SMatthew G. Knepley 
18319566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, name, &label));
183228b400f6SJacob Faibussowitsch     PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Label %s provided to -dm_label_view does not exist in this DM", name);
18339566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateLabelField(dm, label, &val));
18349566063dSJacob Faibussowitsch     PetscCall(VecView(val, viewer));
18359566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&val));
1836002a2709SMatthew G. Knepley   }
18373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1838552f7358SJed Brown }
1839552f7358SJed Brown 
18407f96f51bSksagiyam /*@
1841a1cb98faSBarry Smith   DMPlexTopologyView - Saves a `DMPLEX` topology into a file
18427f96f51bSksagiyam 
184320f4b53cSBarry Smith   Collective
18447f96f51bSksagiyam 
18457f96f51bSksagiyam   Input Parameters:
1846a1cb98faSBarry Smith + dm     - The `DM` whose topology is to be saved
1847a1cb98faSBarry Smith - viewer - The `PetscViewer` to save it in
18487f96f51bSksagiyam 
18497f96f51bSksagiyam   Level: advanced
18507f96f51bSksagiyam 
18511cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexTopologyLoad()`, `PetscViewer`
18527f96f51bSksagiyam @*/
1853d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTopologyView(DM dm, PetscViewer viewer)
1854d71ae5a4SJacob Faibussowitsch {
18557f96f51bSksagiyam   PetscBool ishdf5;
18567f96f51bSksagiyam 
18577f96f51bSksagiyam   PetscFunctionBegin;
18587f96f51bSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
18597f96f51bSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
18609566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
18619566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_TopologyView, viewer, 0, 0, 0));
18627f96f51bSksagiyam   if (ishdf5) {
18637f96f51bSksagiyam #if defined(PETSC_HAVE_HDF5)
18647f96f51bSksagiyam     PetscViewerFormat format;
18659566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
18667f96f51bSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
18677f96f51bSksagiyam       IS globalPointNumbering;
18687f96f51bSksagiyam 
18699566063dSJacob Faibussowitsch       PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering));
18709566063dSJacob Faibussowitsch       PetscCall(DMPlexTopologyView_HDF5_Internal(dm, globalPointNumbering, viewer));
18719566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&globalPointNumbering));
187298921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]);
18737f96f51bSksagiyam #else
18747f96f51bSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
18757f96f51bSksagiyam #endif
18767f96f51bSksagiyam   }
18779566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_TopologyView, viewer, 0, 0, 0));
18783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18797f96f51bSksagiyam }
18807f96f51bSksagiyam 
188177b8e257Sksagiyam /*@
1882a1cb98faSBarry Smith   DMPlexCoordinatesView - Saves `DMPLEX` coordinates into a file
188377b8e257Sksagiyam 
188420f4b53cSBarry Smith   Collective
188577b8e257Sksagiyam 
188677b8e257Sksagiyam   Input Parameters:
1887a1cb98faSBarry Smith + dm     - The `DM` whose coordinates are to be saved
1888a1cb98faSBarry Smith - viewer - The `PetscViewer` for saving
188977b8e257Sksagiyam 
189077b8e257Sksagiyam   Level: advanced
189177b8e257Sksagiyam 
18921cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexLabelsView()`, `DMPlexCoordinatesLoad()`, `PetscViewer`
189377b8e257Sksagiyam @*/
1894d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCoordinatesView(DM dm, PetscViewer viewer)
1895d71ae5a4SJacob Faibussowitsch {
189677b8e257Sksagiyam   PetscBool ishdf5;
189777b8e257Sksagiyam 
189877b8e257Sksagiyam   PetscFunctionBegin;
189977b8e257Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
190077b8e257Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
19019566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
19029566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesView, viewer, 0, 0, 0));
190377b8e257Sksagiyam   if (ishdf5) {
190477b8e257Sksagiyam #if defined(PETSC_HAVE_HDF5)
190577b8e257Sksagiyam     PetscViewerFormat format;
19069566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
190777b8e257Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
19089566063dSJacob Faibussowitsch       PetscCall(DMPlexCoordinatesView_HDF5_Internal(dm, viewer));
1909fe28d297SMatthew Knepley     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 output.", PetscViewerFormats[format]);
191077b8e257Sksagiyam #else
191177b8e257Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
191277b8e257Sksagiyam #endif
191377b8e257Sksagiyam   }
19149566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesView, viewer, 0, 0, 0));
19153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
191677b8e257Sksagiyam }
191777b8e257Sksagiyam 
1918bd6565f1Sksagiyam /*@
1919a1cb98faSBarry Smith   DMPlexLabelsView - Saves `DMPLEX` labels into a file
1920bd6565f1Sksagiyam 
192120f4b53cSBarry Smith   Collective
1922bd6565f1Sksagiyam 
1923bd6565f1Sksagiyam   Input Parameters:
1924a1cb98faSBarry Smith + dm     - The `DM` whose labels are to be saved
1925a1cb98faSBarry Smith - viewer - The `PetscViewer` for saving
1926bd6565f1Sksagiyam 
1927bd6565f1Sksagiyam   Level: advanced
1928bd6565f1Sksagiyam 
19291cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsLoad()`, `PetscViewer`
1930bd6565f1Sksagiyam @*/
1931d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelsView(DM dm, PetscViewer viewer)
1932d71ae5a4SJacob Faibussowitsch {
1933bd6565f1Sksagiyam   PetscBool ishdf5;
1934bd6565f1Sksagiyam 
1935bd6565f1Sksagiyam   PetscFunctionBegin;
1936bd6565f1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1937bd6565f1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
19389566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
19399566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LabelsView, viewer, 0, 0, 0));
1940bd6565f1Sksagiyam   if (ishdf5) {
1941bd6565f1Sksagiyam #if defined(PETSC_HAVE_HDF5)
1942bd6565f1Sksagiyam     IS                globalPointNumbering;
1943bd6565f1Sksagiyam     PetscViewerFormat format;
1944bd6565f1Sksagiyam 
19459566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
1946bd6565f1Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
19479566063dSJacob Faibussowitsch       PetscCall(DMPlexCreatePointNumbering(dm, &globalPointNumbering));
19489566063dSJacob Faibussowitsch       PetscCall(DMPlexLabelsView_HDF5_Internal(dm, globalPointNumbering, viewer));
19499566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&globalPointNumbering));
195098921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
1951bd6565f1Sksagiyam #else
1952bd6565f1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1953bd6565f1Sksagiyam #endif
1954bd6565f1Sksagiyam   }
19559566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LabelsView, viewer, 0, 0, 0));
19563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1957bd6565f1Sksagiyam }
1958bd6565f1Sksagiyam 
1959021affd3Sksagiyam /*@
1960a1cb98faSBarry Smith   DMPlexSectionView - Saves a section associated with a `DMPLEX`
1961021affd3Sksagiyam 
196220f4b53cSBarry Smith   Collective
1963021affd3Sksagiyam 
1964021affd3Sksagiyam   Input Parameters:
1965a1cb98faSBarry Smith + dm        - The `DM` that contains the topology on which the section to be saved is defined
1966a1cb98faSBarry Smith . viewer    - The `PetscViewer` for saving
1967a1cb98faSBarry Smith - sectiondm - The `DM` that contains the section to be saved
1968021affd3Sksagiyam 
1969021affd3Sksagiyam   Level: advanced
1970021affd3Sksagiyam 
1971021affd3Sksagiyam   Notes:
1972a1cb98faSBarry Smith   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.
1973021affd3Sksagiyam 
1974a1cb98faSBarry Smith   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.
1975021affd3Sksagiyam 
19761cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`, `DMPlexTopologyView()`, `DMPlexCoordinatesView()`, `DMPlexLabelsView()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`, `PetscSectionView()`, `DMPlexSectionLoad()`, `PetscViewer`
1977021affd3Sksagiyam @*/
1978d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSectionView(DM dm, PetscViewer viewer, DM sectiondm)
1979d71ae5a4SJacob Faibussowitsch {
1980021affd3Sksagiyam   PetscBool ishdf5;
1981021affd3Sksagiyam 
1982021affd3Sksagiyam   PetscFunctionBegin;
1983021affd3Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1984021affd3Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1985021affd3Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
19869566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
19879566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_SectionView, viewer, 0, 0, 0));
1988021affd3Sksagiyam   if (ishdf5) {
1989021affd3Sksagiyam #if defined(PETSC_HAVE_HDF5)
19909566063dSJacob Faibussowitsch     PetscCall(DMPlexSectionView_HDF5_Internal(dm, viewer, sectiondm));
1991021affd3Sksagiyam #else
1992021affd3Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1993021affd3Sksagiyam #endif
1994021affd3Sksagiyam   }
19959566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_SectionView, viewer, 0, 0, 0));
19963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1997021affd3Sksagiyam }
1998021affd3Sksagiyam 
19993e97647fSksagiyam /*@
20003e97647fSksagiyam   DMPlexGlobalVectorView - Saves a global vector
20013e97647fSksagiyam 
200220f4b53cSBarry Smith   Collective
20033e97647fSksagiyam 
20043e97647fSksagiyam   Input Parameters:
2005a1cb98faSBarry Smith + dm        - The `DM` that represents the topology
2006a1cb98faSBarry Smith . viewer    - The `PetscViewer` to save data with
2007a1cb98faSBarry Smith . sectiondm - The `DM` that contains the global section on which vec is defined
20083e97647fSksagiyam - vec       - The global vector to be saved
20093e97647fSksagiyam 
20103e97647fSksagiyam   Level: advanced
20113e97647fSksagiyam 
20123e97647fSksagiyam   Notes:
2013a1cb98faSBarry Smith   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.
20143e97647fSksagiyam 
201560225df5SJacob Faibussowitsch   Calling sequence:
2016a1cb98faSBarry Smith .vb
2017a1cb98faSBarry Smith        DMCreate(PETSC_COMM_WORLD, &dm);
2018a1cb98faSBarry Smith        DMSetType(dm, DMPLEX);
2019a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)dm, "topologydm_name");
2020a1cb98faSBarry Smith        DMClone(dm, &sectiondm);
2021a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
2022a1cb98faSBarry Smith        PetscSectionCreate(PETSC_COMM_WORLD, &section);
2023a1cb98faSBarry Smith        DMPlexGetChart(sectiondm, &pStart, &pEnd);
2024a1cb98faSBarry Smith        PetscSectionSetChart(section, pStart, pEnd);
2025a1cb98faSBarry Smith        PetscSectionSetUp(section);
2026a1cb98faSBarry Smith        DMSetLocalSection(sectiondm, section);
2027a1cb98faSBarry Smith        PetscSectionDestroy(&section);
2028a1cb98faSBarry Smith        DMGetGlobalVector(sectiondm, &vec);
2029a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)vec, "vec_name");
2030a1cb98faSBarry Smith        DMPlexTopologyView(dm, viewer);
2031a1cb98faSBarry Smith        DMPlexSectionView(dm, viewer, sectiondm);
2032a1cb98faSBarry Smith        DMPlexGlobalVectorView(dm, viewer, sectiondm, vec);
2033a1cb98faSBarry Smith        DMRestoreGlobalVector(sectiondm, &vec);
2034a1cb98faSBarry Smith        DMDestroy(&sectiondm);
2035a1cb98faSBarry Smith        DMDestroy(&dm);
2036a1cb98faSBarry Smith .ve
20373e97647fSksagiyam 
20381cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexLocalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`
20393e97647fSksagiyam @*/
2040d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec)
2041d71ae5a4SJacob Faibussowitsch {
20423e97647fSksagiyam   PetscBool ishdf5;
20433e97647fSksagiyam 
20443e97647fSksagiyam   PetscFunctionBegin;
20453e97647fSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
20463e97647fSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
20473e97647fSksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
20483e97647fSksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 4);
20493e97647fSksagiyam   /* Check consistency */
20503e97647fSksagiyam   {
20513e97647fSksagiyam     PetscSection section;
20523e97647fSksagiyam     PetscBool    includesConstraints;
20533e97647fSksagiyam     PetscInt     m, m1;
20543e97647fSksagiyam 
20559566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
20569566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(sectiondm, &section));
20579566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
20589566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
20599566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
206063a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m);
20613e97647fSksagiyam   }
20629566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
20639566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorView, viewer, 0, 0, 0));
20643e97647fSksagiyam   if (ishdf5) {
20653e97647fSksagiyam #if defined(PETSC_HAVE_HDF5)
20669566063dSJacob Faibussowitsch     PetscCall(DMPlexGlobalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec));
20673e97647fSksagiyam #else
20683e97647fSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
20693e97647fSksagiyam #endif
20703e97647fSksagiyam   }
20719566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorView, viewer, 0, 0, 0));
20723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20733e97647fSksagiyam }
20743e97647fSksagiyam 
20753e97647fSksagiyam /*@
20763e97647fSksagiyam   DMPlexLocalVectorView - Saves a local vector
20773e97647fSksagiyam 
207820f4b53cSBarry Smith   Collective
20793e97647fSksagiyam 
20803e97647fSksagiyam   Input Parameters:
2081a1cb98faSBarry Smith + dm        - The `DM` that represents the topology
2082a1cb98faSBarry Smith . viewer    - The `PetscViewer` to save data with
208320f4b53cSBarry Smith . sectiondm - The `DM` that contains the local section on which `vec` is defined; may be the same as `dm`
20843e97647fSksagiyam - vec       - The local vector to be saved
20853e97647fSksagiyam 
20863e97647fSksagiyam   Level: advanced
20873e97647fSksagiyam 
2088a1cb98faSBarry Smith   Note:
208920f4b53cSBarry Smith   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.
20903e97647fSksagiyam 
209160225df5SJacob Faibussowitsch   Calling sequence:
2092a1cb98faSBarry Smith .vb
2093a1cb98faSBarry Smith        DMCreate(PETSC_COMM_WORLD, &dm);
2094a1cb98faSBarry Smith        DMSetType(dm, DMPLEX);
2095a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)dm, "topologydm_name");
2096a1cb98faSBarry Smith        DMClone(dm, &sectiondm);
2097a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
2098a1cb98faSBarry Smith        PetscSectionCreate(PETSC_COMM_WORLD, &section);
2099a1cb98faSBarry Smith        DMPlexGetChart(sectiondm, &pStart, &pEnd);
2100a1cb98faSBarry Smith        PetscSectionSetChart(section, pStart, pEnd);
2101a1cb98faSBarry Smith        PetscSectionSetUp(section);
2102a1cb98faSBarry Smith        DMSetLocalSection(sectiondm, section);
2103a1cb98faSBarry Smith        DMGetLocalVector(sectiondm, &vec);
2104a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)vec, "vec_name");
2105a1cb98faSBarry Smith        DMPlexTopologyView(dm, viewer);
2106a1cb98faSBarry Smith        DMPlexSectionView(dm, viewer, sectiondm);
2107a1cb98faSBarry Smith        DMPlexLocalVectorView(dm, viewer, sectiondm, vec);
2108a1cb98faSBarry Smith        DMRestoreLocalVector(sectiondm, &vec);
2109a1cb98faSBarry Smith        DMDestroy(&sectiondm);
2110a1cb98faSBarry Smith        DMDestroy(&dm);
2111a1cb98faSBarry Smith .ve
21123e97647fSksagiyam 
21131cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyView()`, `DMPlexSectionView()`, `DMPlexGlobalVectorView()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`
21143e97647fSksagiyam @*/
2115d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalVectorView(DM dm, PetscViewer viewer, DM sectiondm, Vec vec)
2116d71ae5a4SJacob Faibussowitsch {
21173e97647fSksagiyam   PetscBool ishdf5;
21183e97647fSksagiyam 
21193e97647fSksagiyam   PetscFunctionBegin;
21203e97647fSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
21213e97647fSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
21223e97647fSksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
21233e97647fSksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 4);
21243e97647fSksagiyam   /* Check consistency */
21253e97647fSksagiyam   {
21263e97647fSksagiyam     PetscSection section;
21273e97647fSksagiyam     PetscBool    includesConstraints;
21283e97647fSksagiyam     PetscInt     m, m1;
21293e97647fSksagiyam 
21309566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
21319566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(sectiondm, &section));
21329566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
21339566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
21349566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
213563a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m);
21363e97647fSksagiyam   }
21379566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
21389566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorView, viewer, 0, 0, 0));
21393e97647fSksagiyam   if (ishdf5) {
21403e97647fSksagiyam #if defined(PETSC_HAVE_HDF5)
21419566063dSJacob Faibussowitsch     PetscCall(DMPlexLocalVectorView_HDF5_Internal(dm, viewer, sectiondm, vec));
21423e97647fSksagiyam #else
21433e97647fSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
21443e97647fSksagiyam #endif
21453e97647fSksagiyam   }
21469566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorView, viewer, 0, 0, 0));
21473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
21483e97647fSksagiyam }
21493e97647fSksagiyam 
2150d71ae5a4SJacob Faibussowitsch PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer)
2151d71ae5a4SJacob Faibussowitsch {
2152d4f5a9a0SVaclav Hapla   PetscBool ishdf5;
21532c40f234SMatthew G. Knepley 
21542c40f234SMatthew G. Knepley   PetscFunctionBegin;
21552c40f234SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
21562c40f234SMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
21579566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
2158d4f5a9a0SVaclav Hapla   if (ishdf5) {
21592c40f234SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
21609c48423bSVaclav Hapla     PetscViewerFormat format;
21619566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
21629c48423bSVaclav Hapla     if (format == PETSC_VIEWER_HDF5_XDMF || format == PETSC_VIEWER_HDF5_VIZ) {
21639566063dSJacob Faibussowitsch       PetscCall(DMPlexLoad_HDF5_Xdmf_Internal(dm, viewer));
2164509517efSVaclav Hapla     } else if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
21659566063dSJacob Faibussowitsch       PetscCall(DMPlexLoad_HDF5_Internal(dm, viewer));
216698921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
21673ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
21682c40f234SMatthew G. Knepley #else
21692c40f234SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2170552f7358SJed Brown #endif
217198921bdaSJacob Faibussowitsch   } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMPlex loading", ((PetscObject)viewer)->type_name);
2172552f7358SJed Brown }
2173552f7358SJed Brown 
2174ea8e1828Sksagiyam /*@
2175a1cb98faSBarry Smith   DMPlexTopologyLoad - Loads a topology into a `DMPLEX`
2176ea8e1828Sksagiyam 
217720f4b53cSBarry Smith   Collective
2178ea8e1828Sksagiyam 
2179ea8e1828Sksagiyam   Input Parameters:
2180a1cb98faSBarry Smith + dm     - The `DM` into which the topology is loaded
2181a1cb98faSBarry Smith - viewer - The `PetscViewer` for the saved topology
2182ea8e1828Sksagiyam 
21832fe279fdSBarry Smith   Output Parameter:
218420f4b53cSBarry Smith . globalToLocalPointSF - The `PetscSF` that pushes points in [0, N) to the associated points in the loaded `DMPLEX`, where N is the global number of points; `NULL` if unneeded
2185dec9e869Sksagiyam 
2186ea8e1828Sksagiyam   Level: advanced
2187ea8e1828Sksagiyam 
21881cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`,
2189a1cb98faSBarry Smith           `PetscViewer`, `PetscSF`
2190ea8e1828Sksagiyam @*/
2191d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexTopologyLoad(DM dm, PetscViewer viewer, PetscSF *globalToLocalPointSF)
2192d71ae5a4SJacob Faibussowitsch {
2193ea8e1828Sksagiyam   PetscBool ishdf5;
2194ea8e1828Sksagiyam 
2195ea8e1828Sksagiyam   PetscFunctionBegin;
2196ea8e1828Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2197ea8e1828Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
21984f572ea9SToby Isaac   if (globalToLocalPointSF) PetscAssertPointer(globalToLocalPointSF, 3);
21999566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
22009566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_TopologyLoad, viewer, 0, 0, 0));
2201ea8e1828Sksagiyam   if (ishdf5) {
2202ea8e1828Sksagiyam #if defined(PETSC_HAVE_HDF5)
2203ea8e1828Sksagiyam     PetscViewerFormat format;
22049566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
2205ea8e1828Sksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
22069566063dSJacob Faibussowitsch       PetscCall(DMPlexTopologyLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
220798921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2208ea8e1828Sksagiyam #else
2209ea8e1828Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2210ea8e1828Sksagiyam #endif
2211ea8e1828Sksagiyam   }
22129566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_TopologyLoad, viewer, 0, 0, 0));
22133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2214ea8e1828Sksagiyam }
2215ea8e1828Sksagiyam 
22163e701f1cSksagiyam /*@
2217a1cb98faSBarry Smith   DMPlexCoordinatesLoad - Loads coordinates into a `DMPLEX`
22183e701f1cSksagiyam 
221920f4b53cSBarry Smith   Collective
22203e701f1cSksagiyam 
22213e701f1cSksagiyam   Input Parameters:
2222a1cb98faSBarry Smith + dm                   - The `DM` into which the coordinates are loaded
2223a1cb98faSBarry Smith . viewer               - The `PetscViewer` for the saved coordinates
2224a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad()` when loading dm from viewer
22253e701f1cSksagiyam 
22263e701f1cSksagiyam   Level: advanced
22273e701f1cSksagiyam 
22281cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexLabelsLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`,
2229a1cb98faSBarry Smith           `PetscSF`, `PetscViewer`
22303e701f1cSksagiyam @*/
2231d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCoordinatesLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF)
2232d71ae5a4SJacob Faibussowitsch {
22333e701f1cSksagiyam   PetscBool ishdf5;
22343e701f1cSksagiyam 
22353e701f1cSksagiyam   PetscFunctionBegin;
22363e701f1cSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
22373e701f1cSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2238c9ad657eSksagiyam   PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3);
22399566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
22409566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0));
22413e701f1cSksagiyam   if (ishdf5) {
22423e701f1cSksagiyam #if defined(PETSC_HAVE_HDF5)
22433e701f1cSksagiyam     PetscViewerFormat format;
22449566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
22453e701f1cSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
22469566063dSJacob Faibussowitsch       PetscCall(DMPlexCoordinatesLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
224798921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
22483e701f1cSksagiyam #else
22493e701f1cSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
22503e701f1cSksagiyam #endif
22513e701f1cSksagiyam   }
22529566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CoordinatesLoad, viewer, 0, 0, 0));
22533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
22543e701f1cSksagiyam }
22553e701f1cSksagiyam 
2256b08ad5deSksagiyam /*@
2257a1cb98faSBarry Smith   DMPlexLabelsLoad - Loads labels into a `DMPLEX`
2258b08ad5deSksagiyam 
225920f4b53cSBarry Smith   Collective
2260b08ad5deSksagiyam 
2261b08ad5deSksagiyam   Input Parameters:
2262a1cb98faSBarry Smith + dm                   - The `DM` into which the labels are loaded
2263a1cb98faSBarry Smith . viewer               - The `PetscViewer` for the saved labels
226420f4b53cSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad()` when loading `dm` from viewer
2265b08ad5deSksagiyam 
2266b08ad5deSksagiyam   Level: advanced
2267b08ad5deSksagiyam 
2268a1cb98faSBarry Smith   Note:
2269a1cb98faSBarry Smith   The `PetscSF` argument must not be NULL if the `DM` is distributed, otherwise an error occurs.
2270e6368b79SVaclav Hapla 
22711cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMView()`, `PetscViewerHDF5Open()`, `PetscViewerPushFormat()`,
2272a1cb98faSBarry Smith           `PetscSF`, `PetscViewer`
2273b08ad5deSksagiyam @*/
2274d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLabelsLoad(DM dm, PetscViewer viewer, PetscSF globalToLocalPointSF)
2275d71ae5a4SJacob Faibussowitsch {
2276b08ad5deSksagiyam   PetscBool ishdf5;
2277b08ad5deSksagiyam 
2278b08ad5deSksagiyam   PetscFunctionBegin;
2279b08ad5deSksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2280b08ad5deSksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2281e6368b79SVaclav Hapla   if (globalToLocalPointSF) PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 3);
22829566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
22839566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LabelsLoad, viewer, 0, 0, 0));
2284b08ad5deSksagiyam   if (ishdf5) {
2285b08ad5deSksagiyam #if defined(PETSC_HAVE_HDF5)
2286b08ad5deSksagiyam     PetscViewerFormat format;
2287b08ad5deSksagiyam 
22889566063dSJacob Faibussowitsch     PetscCall(PetscViewerGetFormat(viewer, &format));
2289b08ad5deSksagiyam     if (format == PETSC_VIEWER_HDF5_PETSC || format == PETSC_VIEWER_DEFAULT || format == PETSC_VIEWER_NATIVE) {
22909566063dSJacob Faibussowitsch       PetscCall(DMPlexLabelsLoad_HDF5_Internal(dm, viewer, globalToLocalPointSF));
229198921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "PetscViewerFormat %s not supported for HDF5 input.", PetscViewerFormats[format]);
2292b08ad5deSksagiyam #else
2293b08ad5deSksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2294b08ad5deSksagiyam #endif
2295b08ad5deSksagiyam   }
22969566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LabelsLoad, viewer, 0, 0, 0));
22973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2298b08ad5deSksagiyam }
2299b08ad5deSksagiyam 
2300f84dd6b4Sksagiyam /*@
2301a1cb98faSBarry Smith   DMPlexSectionLoad - Loads section into a `DMPLEX`
2302f84dd6b4Sksagiyam 
230320f4b53cSBarry Smith   Collective
2304f84dd6b4Sksagiyam 
2305f84dd6b4Sksagiyam   Input Parameters:
2306a1cb98faSBarry Smith + dm                   - The `DM` that represents the topology
2307a1cb98faSBarry Smith . viewer               - The `PetscViewer` that represents the on-disk section (sectionA)
2308a1cb98faSBarry Smith . sectiondm            - The `DM` into which the on-disk section (sectionA) is migrated
2309a1cb98faSBarry Smith - globalToLocalPointSF - The `PetscSF` returned by `DMPlexTopologyLoad(`) when loading dm from viewer
2310f84dd6b4Sksagiyam 
2311a4e35b19SJacob Faibussowitsch   Output Parameters:
231220f4b53cSBarry Smith + globalDofSF - The `PetscSF` 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)
231320f4b53cSBarry Smith - localDofSF  - The `PetscSF` 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)
2314f84dd6b4Sksagiyam 
2315f84dd6b4Sksagiyam   Level: advanced
2316f84dd6b4Sksagiyam 
2317f84dd6b4Sksagiyam   Notes:
231820f4b53cSBarry Smith   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.
2319f84dd6b4Sksagiyam 
232020f4b53cSBarry Smith   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.
2321f84dd6b4Sksagiyam 
232220f4b53cSBarry Smith   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.
2323f84dd6b4Sksagiyam 
2324f84dd6b4Sksagiyam   Example using 2 processes:
2325a1cb98faSBarry Smith .vb
2326a1cb98faSBarry Smith   NX (number of points on dm): 4
2327a1cb98faSBarry Smith   sectionA                   : the on-disk section
2328a1cb98faSBarry Smith   vecA                       : a vector associated with sectionA
2329a1cb98faSBarry Smith   sectionB                   : sectiondm's local section constructed in this function
2330a1cb98faSBarry Smith   vecB (local)               : a vector associated with sectiondm's local section
2331a1cb98faSBarry Smith   vecB (global)              : a vector associated with sectiondm's global section
2332f84dd6b4Sksagiyam 
2333a1cb98faSBarry Smith                                      rank 0    rank 1
2334a1cb98faSBarry Smith   vecA (global)                  : [.0 .4 .1 | .2 .3]        <- to be loaded in DMPlexGlobalVectorLoad() or DMPlexLocalVectorLoad()
2335a1cb98faSBarry Smith   sectionA->atlasOff             :       0 2 | 1             <- loaded in PetscSectionLoad()
2336a1cb98faSBarry Smith   sectionA->atlasDof             :       1 3 | 1             <- loaded in PetscSectionLoad()
2337a1cb98faSBarry Smith   sectionA's global point numbers:       0 2 | 3             <- loaded in DMPlexSectionLoad()
2338a1cb98faSBarry Smith   [0, NX)                        :       0 1 | 2 3           <- conceptual partition used in globalToLocalPointSF
2339a1cb98faSBarry Smith   sectionB's global point numbers:     0 1 3 | 3 2           <- associated with [0, NX) by globalToLocalPointSF
2340a1cb98faSBarry Smith   sectionB->atlasDof             :     1 0 1 | 1 3
2341a1cb98faSBarry Smith   sectionB->atlasOff (no perm)   :     0 1 1 | 0 1
2342a1cb98faSBarry Smith   vecB (local)                   :   [.0 .4] | [.4 .1 .2 .3] <- to be constructed by calling DMPlexLocalVectorLoad() with localDofSF
2343a1cb98faSBarry Smith   vecB (global)                  :    [.0 .4 | .1 .2 .3]     <- to be constructed by calling DMPlexGlobalVectorLoad() with globalDofSF
2344a1cb98faSBarry Smith .ve
2345a1cb98faSBarry Smith   where "|" represents a partition of loaded data, and global point 3 is assumed to be owned by rank 0.
2346a1cb98faSBarry Smith 
23471cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMLoad()`, `DMPlexTopologyLoad()`, `DMPlexCoordinatesLoad()`, `DMPlexLabelsLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexLocalVectorLoad()`, `PetscSectionLoad()`, `DMPlexSectionView()`, `PetscSF`, `PetscViewer`
2348f84dd6b4Sksagiyam @*/
2349d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSectionLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF globalToLocalPointSF, PetscSF *globalDofSF, PetscSF *localDofSF)
2350d71ae5a4SJacob Faibussowitsch {
2351f84dd6b4Sksagiyam   PetscBool ishdf5;
2352f84dd6b4Sksagiyam 
2353f84dd6b4Sksagiyam   PetscFunctionBegin;
2354f84dd6b4Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2355f84dd6b4Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
2356f84dd6b4Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
2357f84dd6b4Sksagiyam   PetscValidHeaderSpecific(globalToLocalPointSF, PETSCSF_CLASSID, 4);
23584f572ea9SToby Isaac   if (globalDofSF) PetscAssertPointer(globalDofSF, 5);
23594f572ea9SToby Isaac   if (localDofSF) PetscAssertPointer(localDofSF, 6);
23609566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
23619566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_SectionLoad, viewer, 0, 0, 0));
2362f84dd6b4Sksagiyam   if (ishdf5) {
2363f84dd6b4Sksagiyam #if defined(PETSC_HAVE_HDF5)
23649566063dSJacob Faibussowitsch     PetscCall(DMPlexSectionLoad_HDF5_Internal(dm, viewer, sectiondm, globalToLocalPointSF, globalDofSF, localDofSF));
2365f84dd6b4Sksagiyam #else
2366f84dd6b4Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
2367f84dd6b4Sksagiyam #endif
2368f84dd6b4Sksagiyam   }
23699566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_SectionLoad, viewer, 0, 0, 0));
23703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2371f84dd6b4Sksagiyam }
2372f84dd6b4Sksagiyam 
23738be3dfe1Sksagiyam /*@
23748be3dfe1Sksagiyam   DMPlexGlobalVectorLoad - Loads on-disk vector data into a global vector
23758be3dfe1Sksagiyam 
237620f4b53cSBarry Smith   Collective
23778be3dfe1Sksagiyam 
23788be3dfe1Sksagiyam   Input Parameters:
2379a1cb98faSBarry Smith + dm        - The `DM` that represents the topology
2380a1cb98faSBarry Smith . viewer    - The `PetscViewer` that represents the on-disk vector data
2381a1cb98faSBarry Smith . sectiondm - The `DM` that contains the global section on which vec is defined
2382a1cb98faSBarry Smith . sf        - The `PetscSF` that migrates the on-disk vector data into vec
23838be3dfe1Sksagiyam - vec       - The global vector to set values of
23848be3dfe1Sksagiyam 
23858be3dfe1Sksagiyam   Level: advanced
23868be3dfe1Sksagiyam 
23878be3dfe1Sksagiyam   Notes:
2388a1cb98faSBarry Smith   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.
23898be3dfe1Sksagiyam 
239060225df5SJacob Faibussowitsch   Calling sequence:
2391a1cb98faSBarry Smith .vb
2392a1cb98faSBarry Smith        DMCreate(PETSC_COMM_WORLD, &dm);
2393a1cb98faSBarry Smith        DMSetType(dm, DMPLEX);
2394a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)dm, "topologydm_name");
2395a1cb98faSBarry Smith        DMPlexTopologyLoad(dm, viewer, &sfX);
2396a1cb98faSBarry Smith        DMClone(dm, &sectiondm);
2397a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
2398a1cb98faSBarry Smith        DMPlexSectionLoad(dm, viewer, sectiondm, sfX, &gsf, NULL);
2399a1cb98faSBarry Smith        DMGetGlobalVector(sectiondm, &vec);
2400a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)vec, "vec_name");
2401a1cb98faSBarry Smith        DMPlexGlobalVectorLoad(dm, viewer, sectiondm, gsf, vec);
2402a1cb98faSBarry Smith        DMRestoreGlobalVector(sectiondm, &vec);
2403a1cb98faSBarry Smith        PetscSFDestroy(&gsf);
2404a1cb98faSBarry Smith        PetscSFDestroy(&sfX);
2405a1cb98faSBarry Smith        DMDestroy(&sectiondm);
2406a1cb98faSBarry Smith        DMDestroy(&dm);
2407a1cb98faSBarry Smith .ve
24088be3dfe1Sksagiyam 
24091cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexLocalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`,
2410a1cb98faSBarry Smith           `PetscSF`, `PetscViewer`
24118be3dfe1Sksagiyam @*/
2412d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGlobalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec)
2413d71ae5a4SJacob Faibussowitsch {
24148be3dfe1Sksagiyam   PetscBool ishdf5;
24158be3dfe1Sksagiyam 
24168be3dfe1Sksagiyam   PetscFunctionBegin;
24178be3dfe1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
24188be3dfe1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
24198be3dfe1Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
24208be3dfe1Sksagiyam   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4);
24218be3dfe1Sksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 5);
24228be3dfe1Sksagiyam   /* Check consistency */
24238be3dfe1Sksagiyam   {
24248be3dfe1Sksagiyam     PetscSection section;
24258be3dfe1Sksagiyam     PetscBool    includesConstraints;
24268be3dfe1Sksagiyam     PetscInt     m, m1;
24278be3dfe1Sksagiyam 
24289566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
24299566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(sectiondm, &section));
24309566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
24319566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
24329566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
243363a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Global vector size (%" PetscInt_FMT ") != global section storage size (%" PetscInt_FMT ")", m1, m);
24348be3dfe1Sksagiyam   }
24359566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
24369566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0));
24378be3dfe1Sksagiyam   if (ishdf5) {
24388be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5)
24399566063dSJacob Faibussowitsch     PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec));
24408be3dfe1Sksagiyam #else
24418be3dfe1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
24428be3dfe1Sksagiyam #endif
24438be3dfe1Sksagiyam   }
24449566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_GlobalVectorLoad, viewer, 0, 0, 0));
24453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24468be3dfe1Sksagiyam }
24478be3dfe1Sksagiyam 
24488be3dfe1Sksagiyam /*@
24498be3dfe1Sksagiyam   DMPlexLocalVectorLoad - Loads on-disk vector data into a local vector
24508be3dfe1Sksagiyam 
245120f4b53cSBarry Smith   Collective
24528be3dfe1Sksagiyam 
24538be3dfe1Sksagiyam   Input Parameters:
2454a1cb98faSBarry Smith + dm        - The `DM` that represents the topology
2455a1cb98faSBarry Smith . viewer    - The `PetscViewer` that represents the on-disk vector data
2456a1cb98faSBarry Smith . sectiondm - The `DM` that contains the local section on which vec is defined
2457a1cb98faSBarry Smith . sf        - The `PetscSF` that migrates the on-disk vector data into vec
24588be3dfe1Sksagiyam - vec       - The local vector to set values of
24598be3dfe1Sksagiyam 
24608be3dfe1Sksagiyam   Level: advanced
24618be3dfe1Sksagiyam 
24628be3dfe1Sksagiyam   Notes:
246320f4b53cSBarry Smith   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.
24648be3dfe1Sksagiyam 
246560225df5SJacob Faibussowitsch   Calling sequence:
2466a1cb98faSBarry Smith .vb
2467a1cb98faSBarry Smith        DMCreate(PETSC_COMM_WORLD, &dm);
2468a1cb98faSBarry Smith        DMSetType(dm, DMPLEX);
2469a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)dm, "topologydm_name");
2470a1cb98faSBarry Smith        DMPlexTopologyLoad(dm, viewer, &sfX);
2471a1cb98faSBarry Smith        DMClone(dm, &sectiondm);
2472a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)sectiondm, "sectiondm_name");
2473a1cb98faSBarry Smith        DMPlexSectionLoad(dm, viewer, sectiondm, sfX, NULL, &lsf);
2474a1cb98faSBarry Smith        DMGetLocalVector(sectiondm, &vec);
2475a1cb98faSBarry Smith        PetscObjectSetName((PetscObject)vec, "vec_name");
2476a1cb98faSBarry Smith        DMPlexLocalVectorLoad(dm, viewer, sectiondm, lsf, vec);
2477a1cb98faSBarry Smith        DMRestoreLocalVector(sectiondm, &vec);
2478a1cb98faSBarry Smith        PetscSFDestroy(&lsf);
2479a1cb98faSBarry Smith        PetscSFDestroy(&sfX);
2480a1cb98faSBarry Smith        DMDestroy(&sectiondm);
2481a1cb98faSBarry Smith        DMDestroy(&dm);
2482a1cb98faSBarry Smith .ve
24838be3dfe1Sksagiyam 
24841cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTopologyLoad()`, `DMPlexSectionLoad()`, `DMPlexGlobalVectorLoad()`, `DMPlexGlobalVectorView()`, `DMPlexLocalVectorView()`,
2485a1cb98faSBarry Smith           `PetscSF`, `PetscViewer`
24868be3dfe1Sksagiyam @*/
2487d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexLocalVectorLoad(DM dm, PetscViewer viewer, DM sectiondm, PetscSF sf, Vec vec)
2488d71ae5a4SJacob Faibussowitsch {
24898be3dfe1Sksagiyam   PetscBool ishdf5;
24908be3dfe1Sksagiyam 
24918be3dfe1Sksagiyam   PetscFunctionBegin;
24928be3dfe1Sksagiyam   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
24938be3dfe1Sksagiyam   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
24948be3dfe1Sksagiyam   PetscValidHeaderSpecific(sectiondm, DM_CLASSID, 3);
24958be3dfe1Sksagiyam   PetscValidHeaderSpecific(sf, PETSCSF_CLASSID, 4);
24968be3dfe1Sksagiyam   PetscValidHeaderSpecific(vec, VEC_CLASSID, 5);
24978be3dfe1Sksagiyam   /* Check consistency */
24988be3dfe1Sksagiyam   {
24998be3dfe1Sksagiyam     PetscSection section;
25008be3dfe1Sksagiyam     PetscBool    includesConstraints;
25018be3dfe1Sksagiyam     PetscInt     m, m1;
25028be3dfe1Sksagiyam 
25039566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(vec, &m1));
25049566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(sectiondm, &section));
25059566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetIncludesConstraints(section, &includesConstraints));
25069566063dSJacob Faibussowitsch     if (includesConstraints) PetscCall(PetscSectionGetStorageSize(section, &m));
25079566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetConstrainedStorageSize(section, &m));
250863a3b9bcSJacob Faibussowitsch     PetscCheck(m1 == m, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Local vector size (%" PetscInt_FMT ") != local section storage size (%" PetscInt_FMT ")", m1, m);
25098be3dfe1Sksagiyam   }
25109566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5, &ishdf5));
25119566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0));
25128be3dfe1Sksagiyam   if (ishdf5) {
25138be3dfe1Sksagiyam #if defined(PETSC_HAVE_HDF5)
25149566063dSJacob Faibussowitsch     PetscCall(DMPlexVecLoad_HDF5_Internal(dm, viewer, sectiondm, sf, vec));
25158be3dfe1Sksagiyam #else
25168be3dfe1Sksagiyam     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
25178be3dfe1Sksagiyam #endif
25188be3dfe1Sksagiyam   }
25199566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_LocalVectorLoad, viewer, 0, 0, 0));
25203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
25218be3dfe1Sksagiyam }
25228be3dfe1Sksagiyam 
2523d71ae5a4SJacob Faibussowitsch PetscErrorCode DMDestroy_Plex(DM dm)
2524d71ae5a4SJacob Faibussowitsch {
2525552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2526552f7358SJed Brown 
2527552f7358SJed Brown   PetscFunctionBegin;
25289566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", NULL));
25299566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", NULL));
25309566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", NULL));
25319566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", NULL));
25322e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerviativeBoundaryValues_C", NULL));
25332e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL));
25342e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", NULL));
25352e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", NULL));
25362e956fe4SStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "MatComputeNeumannOverlap_C", NULL));
25376bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", NULL));
25386bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", NULL));
2539c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", NULL));
2540c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", NULL));
25415f06a3ddSJed Brown   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMGetIsoperiodicPointSF_C", NULL));
25423ba16761SJacob Faibussowitsch   if (--mesh->refct > 0) PetscFunctionReturn(PETSC_SUCCESS);
25439566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->coneSection));
25449566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->cones));
25459566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->coneOrientations));
25469566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->supportSection));
25479566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->subdomainSection));
25489566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->supports));
254921027e53SStefano Zampini   PetscCall(PetscFree(mesh->cellTypes));
25509f4ada15SMatthew G. Knepley   PetscCall(DMPlexTransformDestroy(&mesh->tr));
25519566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->tetgenOpts));
25529566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->triangleOpts));
25539566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->transformType));
25541d1f2f2aSksagiyam   PetscCall(PetscFree(mesh->distributionName));
25559566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerDestroy(&mesh->partitioner));
25569566063dSJacob Faibussowitsch   PetscCall(DMLabelDestroy(&mesh->subpointMap));
25579566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->subpointIS));
25589566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->globalVertexNumbers));
25599566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->globalCellNumbers));
25604e2e9504SJed Brown   PetscCall(PetscSFDestroy(&mesh->periodic.face_sf));
25616725e60dSJed Brown   PetscCall(PetscSFDestroy(&mesh->periodic.composed_sf));
25626725e60dSJed Brown   PetscCall(ISDestroy(&mesh->periodic.periodic_points));
25639566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->anchorSection));
25649566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&mesh->anchorIS));
25659566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->parentSection));
25669566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->parents));
25679566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->childIDs));
25689566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&mesh->childSection));
25699566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->children));
25709566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&mesh->referenceTree));
25719566063dSJacob Faibussowitsch   PetscCall(PetscGridHashDestroy(&mesh->lbox));
25729566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh->neighbors));
25739566063dSJacob Faibussowitsch   if (mesh->metricCtx) PetscCall(PetscFree(mesh->metricCtx));
2574552f7358SJed Brown   /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
25759566063dSJacob Faibussowitsch   PetscCall(PetscFree(mesh));
25763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2577552f7358SJed Brown }
2578552f7358SJed Brown 
2579d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J)
2580d71ae5a4SJacob Faibussowitsch {
25818d1174e4SMatthew G. Knepley   PetscSection           sectionGlobal;
2582acd755d7SMatthew G. Knepley   PetscInt               bs = -1, mbs;
25839fca9976SJed Brown   PetscInt               localSize, localStart = 0;
2584837628f4SStefano Zampini   PetscBool              isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isMatIS;
2585b412c318SBarry Smith   MatType                mtype;
25861428887cSShri Abhyankar   ISLocalToGlobalMapping ltog;
2587552f7358SJed Brown 
2588552f7358SJed Brown   PetscFunctionBegin;
25899566063dSJacob Faibussowitsch   PetscCall(MatInitializePackage());
2590b412c318SBarry Smith   mtype = dm->mattype;
25919566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dm, &sectionGlobal));
25929566063dSJacob Faibussowitsch   /* PetscCall(PetscSectionGetStorageSize(sectionGlobal, &localSize)); */
25939566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize));
25949fca9976SJed Brown   PetscCallMPI(MPI_Exscan(&localSize, &localStart, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)dm)));
25959566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), J));
25969566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE));
25979566063dSJacob Faibussowitsch   PetscCall(MatSetType(*J, mtype));
25989566063dSJacob Faibussowitsch   PetscCall(MatSetFromOptions(*J));
25999566063dSJacob Faibussowitsch   PetscCall(MatGetBlockSize(*J, &mbs));
2600acd755d7SMatthew G. Knepley   if (mbs > 1) bs = mbs;
26019566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSHELL, &isShell));
26029566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATBAIJ, &isBlock));
26039566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock));
26049566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock));
26059566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSBAIJ, &isSymBlock));
26069566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock));
26079566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock));
26089566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(mtype, MATIS, &isMatIS));
2609552f7358SJed Brown   if (!isShell) {
2610837628f4SStefano Zampini     PetscBool fillMatrix = (PetscBool)(!dm->prealloc_only && !isMatIS);
26119fca9976SJed Brown     PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal[2], bsMinMax[2], *pblocks;
2612863027abSJed Brown     PetscInt  pStart, pEnd, p, dof, cdof, num_fields;
2613552f7358SJed Brown 
26149566063dSJacob Faibussowitsch     PetscCall(DMGetLocalToGlobalMapping(dm, &ltog));
26159fca9976SJed Brown 
26169fca9976SJed Brown     PetscCall(PetscCalloc1(localSize, &pblocks));
26179566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(sectionGlobal, &pStart, &pEnd));
2618863027abSJed Brown     PetscCall(PetscSectionGetNumFields(sectionGlobal, &num_fields));
2619e432b41dSStefano Zampini     for (p = pStart; p < pEnd; ++p) {
2620863027abSJed Brown       switch (dm->blocking_type) {
26210e762ea3SJed Brown       case DM_BLOCKING_TOPOLOGICAL_POINT: { // One block per topological point
26229fca9976SJed Brown         PetscInt bdof, offset;
2623a9d99c84SMatthew G. Knepley 
26249566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(sectionGlobal, p, &dof));
26259fca9976SJed Brown         PetscCall(PetscSectionGetOffset(sectionGlobal, p, &offset));
26269566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintDof(sectionGlobal, p, &cdof));
26279371c9d4SSatish Balay         for (PetscInt i = 0; i < dof - cdof; i++) pblocks[offset - localStart + i] = dof - cdof;
26281d17a0a3SMatthew G. Knepley         dof  = dof < 0 ? -(dof + 1) : dof;
26291d17a0a3SMatthew G. Knepley         bdof = cdof && (dof - cdof) ? 1 : dof;
26301d17a0a3SMatthew G. Knepley         if (dof) {
26319371c9d4SSatish Balay           if (bs < 0) {
26329371c9d4SSatish Balay             bs = bdof;
26339371c9d4SSatish Balay           } else if (bs != bdof) {
26349371c9d4SSatish Balay             bs = 1;
26359371c9d4SSatish Balay           }
2636552f7358SJed Brown         }
2637863027abSJed Brown       } break;
2638863027abSJed Brown       case DM_BLOCKING_FIELD_NODE: {
2639863027abSJed Brown         for (PetscInt field = 0; field < num_fields; field++) {
2640863027abSJed Brown           PetscInt num_comp, bdof, offset;
2641863027abSJed Brown           PetscCall(PetscSectionGetFieldComponents(sectionGlobal, field, &num_comp));
2642863027abSJed Brown           PetscCall(PetscSectionGetFieldDof(sectionGlobal, p, field, &dof));
2643863027abSJed Brown           if (dof < 0) continue;
2644863027abSJed Brown           PetscCall(PetscSectionGetFieldOffset(sectionGlobal, p, field, &offset));
2645863027abSJed Brown           PetscCall(PetscSectionGetFieldConstraintDof(sectionGlobal, p, field, &cdof));
2646863027abSJed Brown           PetscAssert(dof % num_comp == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Point %" PetscInt_FMT " field %" PetscInt_FMT " has %" PetscInt_FMT " dof, not divisible by %" PetscInt_FMT " component ", p, field, dof, num_comp);
2647863027abSJed Brown           PetscInt num_nodes = dof / num_comp;
2648863027abSJed Brown           for (PetscInt i = 0; i < dof - cdof; i++) pblocks[offset - localStart + i] = (dof - cdof) / num_nodes;
2649863027abSJed Brown           // Handle possibly constant block size (unlikely)
2650863027abSJed Brown           bdof = cdof && (dof - cdof) ? 1 : dof;
2651863027abSJed Brown           if (dof) {
2652863027abSJed Brown             if (bs < 0) {
2653863027abSJed Brown               bs = bdof;
2654863027abSJed Brown             } else if (bs != bdof) {
2655863027abSJed Brown               bs = 1;
2656863027abSJed Brown             }
2657863027abSJed Brown           }
2658863027abSJed Brown         }
2659863027abSJed Brown       } break;
2660863027abSJed Brown       }
26612a28c762SMatthew G Knepley     }
26622a28c762SMatthew G Knepley     /* Must have same blocksize on all procs (some might have no points) */
2663e432b41dSStefano Zampini     bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs;
2664e432b41dSStefano Zampini     bsLocal[1] = bs;
26659566063dSJacob Faibussowitsch     PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax));
2666e432b41dSStefano Zampini     if (bsMinMax[0] != bsMinMax[1]) bs = 1;
2667e432b41dSStefano Zampini     else bs = bsMinMax[0];
26686fd5c86aSStefano Zampini     bs = PetscMax(1, bs);
26699566063dSJacob Faibussowitsch     PetscCall(MatSetLocalToGlobalMapping(*J, ltog, ltog));
26700682b8bbSJed Brown     if (dm->prealloc_skip) { // User will likely use MatSetPreallocationCOO(), but still set structural parameters
26719566063dSJacob Faibussowitsch       PetscCall(MatSetBlockSize(*J, bs));
26729566063dSJacob Faibussowitsch       PetscCall(MatSetUp(*J));
26730682b8bbSJed Brown     } else {
26749566063dSJacob Faibussowitsch       PetscCall(PetscCalloc4(localSize / bs, &dnz, localSize / bs, &onz, localSize / bs, &dnzu, localSize / bs, &onzu));
26759566063dSJacob Faibussowitsch       PetscCall(DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix));
26769566063dSJacob Faibussowitsch       PetscCall(PetscFree4(dnz, onz, dnzu, onzu));
2677552f7358SJed Brown     }
26789fca9976SJed Brown     { // Consolidate blocks
26799fca9976SJed Brown       PetscInt nblocks = 0;
26809fca9976SJed Brown       for (PetscInt i = 0; i < localSize; i += PetscMax(1, pblocks[i])) {
26819fca9976SJed Brown         if (pblocks[i] == 0) continue;
26829fca9976SJed Brown         pblocks[nblocks++] = pblocks[i]; // nblocks always <= i
2683ad540459SPierre Jolivet         for (PetscInt j = 1; j < pblocks[i]; j++) PetscCheck(pblocks[i + j] == pblocks[i], PETSC_COMM_SELF, PETSC_ERR_PLIB, "Block of size %" PetscInt_FMT " mismatches entry %" PetscInt_FMT, pblocks[i], pblocks[i + j]);
26849fca9976SJed Brown       }
26859fca9976SJed Brown       PetscCall(MatSetVariableBlockSizes(*J, nblocks, pblocks));
26869fca9976SJed Brown     }
26879fca9976SJed Brown     PetscCall(PetscFree(pblocks));
2688aa0f6e3cSJed Brown   }
26899566063dSJacob Faibussowitsch   PetscCall(MatSetDM(*J, dm));
26903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2691552f7358SJed Brown }
2692552f7358SJed Brown 
26937cd05799SMatthew G. Knepley /*@
2694a8f00d21SMatthew G. Knepley   DMPlexGetSubdomainSection - Returns the section associated with the subdomain
2695be36d101SStefano Zampini 
2696a1cb98faSBarry Smith   Not Collective
2697be36d101SStefano Zampini 
2698be36d101SStefano Zampini   Input Parameter:
269960225df5SJacob Faibussowitsch . dm - The `DMPLEX`
2700be36d101SStefano Zampini 
27012fe279fdSBarry Smith   Output Parameter:
2702be36d101SStefano Zampini . subsection - The subdomain section
2703be36d101SStefano Zampini 
2704be36d101SStefano Zampini   Level: developer
2705be36d101SStefano Zampini 
27061cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscSection`
27077cd05799SMatthew G. Knepley @*/
2708d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSubdomainSection(DM dm, PetscSection *subsection)
2709d71ae5a4SJacob Faibussowitsch {
2710be36d101SStefano Zampini   DM_Plex *mesh = (DM_Plex *)dm->data;
2711be36d101SStefano Zampini 
2712be36d101SStefano Zampini   PetscFunctionBegin;
2713be36d101SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2714be36d101SStefano Zampini   if (!mesh->subdomainSection) {
2715be36d101SStefano Zampini     PetscSection section;
2716be36d101SStefano Zampini     PetscSF      sf;
2717be36d101SStefano Zampini 
27189566063dSJacob Faibussowitsch     PetscCall(PetscSFCreate(PETSC_COMM_SELF, &sf));
27199566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
27209566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_TRUE, &mesh->subdomainSection));
27219566063dSJacob Faibussowitsch     PetscCall(PetscSFDestroy(&sf));
2722be36d101SStefano Zampini   }
2723be36d101SStefano Zampini   *subsection = mesh->subdomainSection;
27243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2725be36d101SStefano Zampini }
2726be36d101SStefano Zampini 
2727552f7358SJed Brown /*@
272820f4b53cSBarry Smith   DMPlexGetChart - Return the interval for all mesh points [`pStart`, `pEnd`)
2729552f7358SJed Brown 
2730a1cb98faSBarry Smith   Not Collective
2731552f7358SJed Brown 
2732552f7358SJed Brown   Input Parameter:
273360225df5SJacob Faibussowitsch . dm - The `DMPLEX`
2734552f7358SJed Brown 
2735552f7358SJed Brown   Output Parameters:
2736552f7358SJed Brown + pStart - The first mesh point
2737552f7358SJed Brown - pEnd   - The upper bound for mesh points
2738552f7358SJed Brown 
2739552f7358SJed Brown   Level: beginner
2740552f7358SJed Brown 
27411cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()`
2742552f7358SJed Brown @*/
2743d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd)
2744d71ae5a4SJacob Faibussowitsch {
2745552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2746552f7358SJed Brown 
2747552f7358SJed Brown   PetscFunctionBegin;
2748552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
27499f4ada15SMatthew G. Knepley   if (mesh->tr) PetscCall(DMPlexTransformGetChart(mesh->tr, pStart, pEnd));
27509f4ada15SMatthew G. Knepley   else PetscCall(PetscSectionGetChart(mesh->coneSection, pStart, pEnd));
27513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2752552f7358SJed Brown }
2753552f7358SJed Brown 
2754552f7358SJed Brown /*@
275520f4b53cSBarry Smith   DMPlexSetChart - Set the interval for all mesh points [`pStart`, `pEnd`)
2756552f7358SJed Brown 
2757a1cb98faSBarry Smith   Not Collective
2758552f7358SJed Brown 
2759552f7358SJed Brown   Input Parameters:
276060225df5SJacob Faibussowitsch + dm     - The `DMPLEX`
2761552f7358SJed Brown . pStart - The first mesh point
2762552f7358SJed Brown - pEnd   - The upper bound for mesh points
2763552f7358SJed Brown 
2764552f7358SJed Brown   Level: beginner
2765552f7358SJed Brown 
27661cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetChart()`
2767552f7358SJed Brown @*/
2768d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd)
2769d71ae5a4SJacob Faibussowitsch {
2770552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2771552f7358SJed Brown 
2772552f7358SJed Brown   PetscFunctionBegin;
2773552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
27749566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(mesh->coneSection, pStart, pEnd));
27759566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(mesh->supportSection, pStart, pEnd));
277621027e53SStefano Zampini   PetscCall(PetscFree(mesh->cellTypes));
27773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2778552f7358SJed Brown }
2779552f7358SJed Brown 
2780552f7358SJed Brown /*@
2781eaf898f9SPatrick Sanan   DMPlexGetConeSize - Return the number of in-edges for this point in the DAG
2782552f7358SJed Brown 
2783a1cb98faSBarry Smith   Not Collective
2784552f7358SJed Brown 
2785552f7358SJed Brown   Input Parameters:
278660225df5SJacob Faibussowitsch + dm - The `DMPLEX`
2787a1cb98faSBarry Smith - p  - The point, which must lie in the chart set with `DMPlexSetChart()`
2788552f7358SJed Brown 
2789552f7358SJed Brown   Output Parameter:
279020f4b53cSBarry Smith . size - The cone size for point `p`
2791552f7358SJed Brown 
2792552f7358SJed Brown   Level: beginner
2793552f7358SJed Brown 
27941cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`
2795552f7358SJed Brown @*/
2796d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size)
2797d71ae5a4SJacob Faibussowitsch {
2798552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2799552f7358SJed Brown 
2800552f7358SJed Brown   PetscFunctionBegin;
2801552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
28024f572ea9SToby Isaac   PetscAssertPointer(size, 3);
28039f4ada15SMatthew G. Knepley   if (mesh->tr) PetscCall(DMPlexTransformGetConeSize(mesh->tr, p, size));
28049f4ada15SMatthew G. Knepley   else PetscCall(PetscSectionGetDof(mesh->coneSection, p, size));
28053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2806552f7358SJed Brown }
2807552f7358SJed Brown 
2808552f7358SJed Brown /*@
2809eaf898f9SPatrick Sanan   DMPlexSetConeSize - Set the number of in-edges for this point in the DAG
2810552f7358SJed Brown 
2811a1cb98faSBarry Smith   Not Collective
2812552f7358SJed Brown 
2813552f7358SJed Brown   Input Parameters:
281460225df5SJacob Faibussowitsch + dm   - The `DMPLEX`
2815a1cb98faSBarry Smith . p    - The point, which must lie in the chart set with `DMPlexSetChart()`
281620f4b53cSBarry Smith - size - The cone size for point `p`
2817552f7358SJed Brown 
2818552f7358SJed Brown   Level: beginner
2819552f7358SJed Brown 
2820a1cb98faSBarry Smith   Note:
2821a1cb98faSBarry Smith   This should be called after `DMPlexSetChart()`.
2822a1cb98faSBarry Smith 
28231cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeSize()`, `DMPlexSetChart()`
2824552f7358SJed Brown @*/
2825d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size)
2826d71ae5a4SJacob Faibussowitsch {
2827552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2828552f7358SJed Brown 
2829552f7358SJed Brown   PetscFunctionBegin;
2830552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
28319f4ada15SMatthew G. Knepley   PetscCheck(!mesh->tr, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Cannot call DMPlexSetConeSize() on a mesh with a transform defined.");
28329566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetDof(mesh->coneSection, p, size));
28333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2834552f7358SJed Brown }
2835552f7358SJed Brown 
2836552f7358SJed Brown /*@C
2837eaf898f9SPatrick Sanan   DMPlexGetCone - Return the points on the in-edges for this point in the DAG
2838552f7358SJed Brown 
2839a1cb98faSBarry Smith   Not Collective
2840552f7358SJed Brown 
2841552f7358SJed Brown   Input Parameters:
2842a1cb98faSBarry Smith + dm - The `DMPLEX`
2843a1cb98faSBarry Smith - p  - The point, which must lie in the chart set with `DMPlexSetChart()`
2844552f7358SJed Brown 
2845552f7358SJed Brown   Output Parameter:
284620f4b53cSBarry Smith . cone - An array of points which are on the in-edges for point `p`
2847552f7358SJed Brown 
2848552f7358SJed Brown   Level: beginner
2849552f7358SJed Brown 
285060225df5SJacob Faibussowitsch   Fortran Notes:
2851a1cb98faSBarry Smith   You must also call `DMPlexRestoreCone()` after you finish using the returned array.
2852a1cb98faSBarry Smith   `DMPlexRestoreCone()` is not needed/available in C.
28533813dfbdSMatthew G Knepley 
28541cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSize()`, `DMPlexSetCone()`, `DMPlexGetConeTuple()`, `DMPlexSetChart()`, `DMPlexRestoreCone()`
2855552f7358SJed Brown @*/
2856d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[])
2857d71ae5a4SJacob Faibussowitsch {
2858552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
2859552f7358SJed Brown   PetscInt off;
2860552f7358SJed Brown 
2861552f7358SJed Brown   PetscFunctionBegin;
2862552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
28634f572ea9SToby Isaac   PetscAssertPointer(cone, 3);
28649566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
2865552f7358SJed Brown   *cone = &mesh->cones[off];
28663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2867552f7358SJed Brown }
2868552f7358SJed Brown 
28690ce7577fSVaclav Hapla /*@C
28700ce7577fSVaclav Hapla   DMPlexGetConeTuple - Return the points on the in-edges of several points in the DAG
28710ce7577fSVaclav Hapla 
2872a1cb98faSBarry Smith   Not Collective
28730ce7577fSVaclav Hapla 
28740ce7577fSVaclav Hapla   Input Parameters:
2875a1cb98faSBarry Smith + dm - The `DMPLEX`
2876a1cb98faSBarry Smith - p  - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()`
28770ce7577fSVaclav Hapla 
2878d8d19677SJose E. Roman   Output Parameters:
287920f4b53cSBarry Smith + pConesSection - `PetscSection` describing the layout of `pCones`
288020f4b53cSBarry Smith - pCones        - An array of points which are on the in-edges for the point set `p`
28810ce7577fSVaclav Hapla 
28820ce7577fSVaclav Hapla   Level: intermediate
28830ce7577fSVaclav Hapla 
28841cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeRecursive()`, `DMPlexSetChart()`, `PetscSection`, `IS`
28850ce7577fSVaclav Hapla @*/
2886d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeTuple(DM dm, IS p, PetscSection *pConesSection, IS *pCones)
2887d71ae5a4SJacob Faibussowitsch {
28880ce7577fSVaclav Hapla   PetscSection cs, newcs;
28890ce7577fSVaclav Hapla   PetscInt    *cones;
28900ce7577fSVaclav Hapla   PetscInt    *newarr = NULL;
28910ce7577fSVaclav Hapla   PetscInt     n;
28920ce7577fSVaclav Hapla 
28930ce7577fSVaclav Hapla   PetscFunctionBegin;
28949566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCones(dm, &cones));
28959566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSection(dm, &cs));
28969566063dSJacob Faibussowitsch   PetscCall(PetscSectionExtractDofsFromArray(cs, MPIU_INT, cones, p, &newcs, pCones ? ((void **)&newarr) : NULL));
28970ce7577fSVaclav Hapla   if (pConesSection) *pConesSection = newcs;
28980ce7577fSVaclav Hapla   if (pCones) {
28999566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(newcs, &n));
29009566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)p), n, newarr, PETSC_OWN_POINTER, pCones));
29010ce7577fSVaclav Hapla   }
29023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29030ce7577fSVaclav Hapla }
29040ce7577fSVaclav Hapla 
2905af9eab45SVaclav Hapla /*@
2906af9eab45SVaclav Hapla   DMPlexGetConeRecursiveVertices - Expand each given point into its cone points and do that recursively until we end up just with vertices.
2907d4636a37SVaclav Hapla 
2908a1cb98faSBarry Smith   Not Collective
2909d4636a37SVaclav Hapla 
2910d4636a37SVaclav Hapla   Input Parameters:
2911a1cb98faSBarry Smith + dm     - The `DMPLEX`
2912a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()`
2913d4636a37SVaclav Hapla 
2914d4636a37SVaclav Hapla   Output Parameter:
2915af9eab45SVaclav Hapla . expandedPoints - An array of vertices recursively expanded from input points
2916d4636a37SVaclav Hapla 
2917d4636a37SVaclav Hapla   Level: advanced
2918d4636a37SVaclav Hapla 
2919af9eab45SVaclav Hapla   Notes:
292020f4b53cSBarry Smith   Like `DMPlexGetConeRecursive()` but returns only the 0-depth `IS` (i.e. vertices only) and no sections.
2921af9eab45SVaclav Hapla 
2922a1cb98faSBarry Smith   There is no corresponding Restore function, just call `ISDestroy()` on the returned `IS` to deallocate.
2923a1cb98faSBarry Smith 
29241cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexRestoreConeRecursive()`,
2925a1cb98faSBarry Smith           `DMPlexGetDepth()`, `IS`
2926d4636a37SVaclav Hapla @*/
2927d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursiveVertices(DM dm, IS points, IS *expandedPoints)
2928d71ae5a4SJacob Faibussowitsch {
2929af9eab45SVaclav Hapla   IS      *expandedPointsAll;
2930af9eab45SVaclav Hapla   PetscInt depth;
2931d4636a37SVaclav Hapla 
2932d4636a37SVaclav Hapla   PetscFunctionBegin;
2933af9eab45SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2934af9eab45SVaclav Hapla   PetscValidHeaderSpecific(points, IS_CLASSID, 2);
29354f572ea9SToby Isaac   PetscAssertPointer(expandedPoints, 3);
29369566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeRecursive(dm, points, &depth, &expandedPointsAll, NULL));
2937af9eab45SVaclav Hapla   *expandedPoints = expandedPointsAll[0];
29389566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)expandedPointsAll[0]));
29399566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreConeRecursive(dm, points, &depth, &expandedPointsAll, NULL));
29403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2941af9eab45SVaclav Hapla }
2942af9eab45SVaclav Hapla 
2943af9eab45SVaclav Hapla /*@
2944af9eab45SVaclav 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).
2945af9eab45SVaclav Hapla 
2946a1cb98faSBarry Smith   Not Collective
2947af9eab45SVaclav Hapla 
2948af9eab45SVaclav Hapla   Input Parameters:
2949a1cb98faSBarry Smith + dm     - The `DMPLEX`
2950a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()`
2951af9eab45SVaclav Hapla 
2952d8d19677SJose E. Roman   Output Parameters:
2953a1cb98faSBarry Smith + depth          - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()`
2954af9eab45SVaclav Hapla . expandedPoints - (optional) An array of index sets with recursively expanded cones
2955af9eab45SVaclav Hapla - sections       - (optional) An array of sections which describe mappings from points to their cone points
2956af9eab45SVaclav Hapla 
2957af9eab45SVaclav Hapla   Level: advanced
2958af9eab45SVaclav Hapla 
2959af9eab45SVaclav Hapla   Notes:
2960a1cb98faSBarry Smith   Like `DMPlexGetConeTuple()` but recursive.
2961af9eab45SVaclav Hapla 
2962a4e35b19SJacob Faibussowitsch   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.
2963af9eab45SVaclav Hapla   For example, for d=0 it contains only vertices, for d=1 it can contain vertices and edges, etc.
2964af9eab45SVaclav Hapla 
2965a4e35b19SJacob Faibussowitsch   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\:
2966a4e35b19SJacob Faibussowitsch   (1) DAG points in `expandedPoints`[d+1] with `depth` d+1 to their cone points in `expandedPoints`[d];
2967a4e35b19SJacob Faibussowitsch   (2) DAG points in `expandedPoints`[d+1] with `depth` in [0,d] to the same points in `expandedPoints`[d].
2968af9eab45SVaclav Hapla 
29691cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexRestoreConeRecursive()`, `DMPlexGetConeRecursiveVertices()`,
2970a1cb98faSBarry Smith           `DMPlexGetDepth()`, `PetscSection`, `IS`
2971af9eab45SVaclav Hapla @*/
2972d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[])
2973d71ae5a4SJacob Faibussowitsch {
2974af9eab45SVaclav Hapla   const PetscInt *arr0 = NULL, *cone = NULL;
2975af9eab45SVaclav Hapla   PetscInt       *arr = NULL, *newarr = NULL;
2976af9eab45SVaclav Hapla   PetscInt        d, depth_, i, n, newn, cn, co, start, end;
2977af9eab45SVaclav Hapla   IS             *expandedPoints_;
2978af9eab45SVaclav Hapla   PetscSection   *sections_;
2979af9eab45SVaclav Hapla 
2980af9eab45SVaclav Hapla   PetscFunctionBegin;
2981af9eab45SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
2982af9eab45SVaclav Hapla   PetscValidHeaderSpecific(points, IS_CLASSID, 2);
29834f572ea9SToby Isaac   if (depth) PetscAssertPointer(depth, 3);
29844f572ea9SToby Isaac   if (expandedPoints) PetscAssertPointer(expandedPoints, 4);
29854f572ea9SToby Isaac   if (sections) PetscAssertPointer(sections, 5);
29869566063dSJacob Faibussowitsch   PetscCall(ISGetLocalSize(points, &n));
29879566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(points, &arr0));
29889566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth_));
29899566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(depth_, &expandedPoints_));
29909566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(depth_, &sections_));
2991af9eab45SVaclav Hapla   arr = (PetscInt *)arr0; /* this is ok because first generation of arr is not modified */
2992af9eab45SVaclav Hapla   for (d = depth_ - 1; d >= 0; d--) {
29939566063dSJacob Faibussowitsch     PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &sections_[d]));
29949566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(sections_[d], 0, n));
2995af9eab45SVaclav Hapla     for (i = 0; i < n; i++) {
29969566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d + 1, &start, &end));
2997af9eab45SVaclav Hapla       if (arr[i] >= start && arr[i] < end) {
29989566063dSJacob Faibussowitsch         PetscCall(DMPlexGetConeSize(dm, arr[i], &cn));
29999566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetDof(sections_[d], i, cn));
3000af9eab45SVaclav Hapla       } else {
30019566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetDof(sections_[d], i, 1));
3002af9eab45SVaclav Hapla       }
3003af9eab45SVaclav Hapla     }
30049566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(sections_[d]));
30059566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(sections_[d], &newn));
30069566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(newn, &newarr));
3007af9eab45SVaclav Hapla     for (i = 0; i < n; i++) {
30089566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sections_[d], i, &cn));
30099566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(sections_[d], i, &co));
3010af9eab45SVaclav Hapla       if (cn > 1) {
30119566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCone(dm, arr[i], &cone));
30129566063dSJacob Faibussowitsch         PetscCall(PetscMemcpy(&newarr[co], cone, cn * sizeof(PetscInt)));
3013af9eab45SVaclav Hapla       } else {
3014af9eab45SVaclav Hapla         newarr[co] = arr[i];
3015af9eab45SVaclav Hapla       }
3016af9eab45SVaclav Hapla     }
30179566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, newn, newarr, PETSC_OWN_POINTER, &expandedPoints_[d]));
3018af9eab45SVaclav Hapla     arr = newarr;
3019af9eab45SVaclav Hapla     n   = newn;
3020af9eab45SVaclav Hapla   }
30219566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(points, &arr0));
3022af9eab45SVaclav Hapla   *depth = depth_;
3023af9eab45SVaclav Hapla   if (expandedPoints) *expandedPoints = expandedPoints_;
3024af9eab45SVaclav Hapla   else {
30259566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&expandedPoints_[d]));
30269566063dSJacob Faibussowitsch     PetscCall(PetscFree(expandedPoints_));
3027af9eab45SVaclav Hapla   }
3028af9eab45SVaclav Hapla   if (sections) *sections = sections_;
3029af9eab45SVaclav Hapla   else {
30309566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(&sections_[d]));
30319566063dSJacob Faibussowitsch     PetscCall(PetscFree(sections_));
3032af9eab45SVaclav Hapla   }
30333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3034af9eab45SVaclav Hapla }
3035af9eab45SVaclav Hapla 
3036af9eab45SVaclav Hapla /*@
3037a1cb98faSBarry Smith   DMPlexRestoreConeRecursive - Deallocates arrays created by `DMPlexGetConeRecursive()`
3038af9eab45SVaclav Hapla 
3039a1cb98faSBarry Smith   Not Collective
3040af9eab45SVaclav Hapla 
3041af9eab45SVaclav Hapla   Input Parameters:
3042a1cb98faSBarry Smith + dm     - The `DMPLEX`
3043a1cb98faSBarry Smith - points - The `IS` of points, which must lie in the chart set with `DMPlexSetChart()`
3044af9eab45SVaclav Hapla 
3045d8d19677SJose E. Roman   Output Parameters:
3046a1cb98faSBarry Smith + depth          - (optional) Size of the output arrays, equal to `DMPLEX` depth, returned by `DMPlexGetDepth()`
3047af9eab45SVaclav Hapla . expandedPoints - (optional) An array of recursively expanded cones
3048af9eab45SVaclav Hapla - sections       - (optional) An array of sections which describe mappings from points to their cone points
3049af9eab45SVaclav Hapla 
3050af9eab45SVaclav Hapla   Level: advanced
3051af9eab45SVaclav Hapla 
3052a1cb98faSBarry Smith   Note:
3053a1cb98faSBarry Smith   See `DMPlexGetConeRecursive()`
3054af9eab45SVaclav Hapla 
30551cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexGetConeTuple()`, `DMPlexGetConeRecursive()`, `DMPlexGetConeRecursiveVertices()`,
3056a1cb98faSBarry Smith           `DMPlexGetDepth()`, `IS`, `PetscSection`
3057af9eab45SVaclav Hapla @*/
3058d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreConeRecursive(DM dm, IS points, PetscInt *depth, IS *expandedPoints[], PetscSection *sections[])
3059d71ae5a4SJacob Faibussowitsch {
3060af9eab45SVaclav Hapla   PetscInt d, depth_;
3061af9eab45SVaclav Hapla 
3062af9eab45SVaclav Hapla   PetscFunctionBegin;
30639566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth_));
30641dca8a05SBarry Smith   PetscCheck(!depth || *depth == depth_, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "depth changed since last call to DMPlexGetConeRecursive");
3065af9eab45SVaclav Hapla   if (depth) *depth = 0;
3066af9eab45SVaclav Hapla   if (expandedPoints) {
30679566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(ISDestroy(&((*expandedPoints)[d])));
30689566063dSJacob Faibussowitsch     PetscCall(PetscFree(*expandedPoints));
3069af9eab45SVaclav Hapla   }
3070af9eab45SVaclav Hapla   if (sections) {
30719566063dSJacob Faibussowitsch     for (d = 0; d < depth_; d++) PetscCall(PetscSectionDestroy(&((*sections)[d])));
30729566063dSJacob Faibussowitsch     PetscCall(PetscFree(*sections));
3073af9eab45SVaclav Hapla   }
30743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3075d4636a37SVaclav Hapla }
3076d4636a37SVaclav Hapla 
3077552f7358SJed Brown /*@
307892371b87SBarry 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
3079552f7358SJed Brown 
3080a1cb98faSBarry Smith   Not Collective
3081552f7358SJed Brown 
3082552f7358SJed Brown   Input Parameters:
308360225df5SJacob Faibussowitsch + dm   - The `DMPLEX`
3084a1cb98faSBarry Smith . p    - The point, which must lie in the chart set with `DMPlexSetChart()`
308520f4b53cSBarry Smith - cone - An array of points which are on the in-edges for point `p`
3086552f7358SJed Brown 
3087552f7358SJed Brown   Level: beginner
3088552f7358SJed Brown 
3089a1cb98faSBarry Smith   Note:
3090a1cb98faSBarry Smith   This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`.
3091a1cb98faSBarry Smith 
30921cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`, `DMPlexSetSupport()`, `DMPlexSetSupportSize()`
3093552f7358SJed Brown @*/
3094d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[])
3095d71ae5a4SJacob Faibussowitsch {
3096552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3097552f7358SJed Brown   PetscInt dof, off, c;
3098552f7358SJed Brown 
3099552f7358SJed Brown   PetscFunctionBegin;
3100552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
31019566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
31024f572ea9SToby Isaac   if (dof) PetscAssertPointer(cone, 3);
31039566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
3104db485b19SStefano Zampini   if (PetscDefined(USE_DEBUG)) {
3105db485b19SStefano Zampini     PetscInt pStart, pEnd;
3106db485b19SStefano Zampini     PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
310763a3b9bcSJacob 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);
3108552f7358SJed Brown     for (c = 0; c < dof; ++c) {
310963a3b9bcSJacob 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);
3110552f7358SJed Brown       mesh->cones[off + c] = cone[c];
3111552f7358SJed Brown     }
3112db485b19SStefano Zampini   } else {
3113db485b19SStefano Zampini     for (c = 0; c < dof; ++c) mesh->cones[off + c] = cone[c];
3114db485b19SStefano Zampini   }
31153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3116552f7358SJed Brown }
3117552f7358SJed Brown 
3118552f7358SJed Brown /*@C
3119eaf898f9SPatrick Sanan   DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the DAG
3120552f7358SJed Brown 
3121a1cb98faSBarry Smith   Not Collective
3122552f7358SJed Brown 
3123552f7358SJed Brown   Input Parameters:
312460225df5SJacob Faibussowitsch + dm - The `DMPLEX`
3125a1cb98faSBarry Smith - p  - The point, which must lie in the chart set with `DMPlexSetChart()`
3126552f7358SJed Brown 
3127552f7358SJed Brown   Output Parameter:
312820f4b53cSBarry Smith . coneOrientation - An array of orientations which are on the in-edges for point `p`. An orientation is an
3129b5a892a1SMatthew G. Knepley                     integer giving the prescription for cone traversal.
3130552f7358SJed Brown 
3131552f7358SJed Brown   Level: beginner
3132552f7358SJed Brown 
3133a1cb98faSBarry Smith   Note:
3134b5a892a1SMatthew G. Knepley   The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always
3135b5a892a1SMatthew G. Knepley   the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection
3136a1cb98faSBarry Smith   of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()`
3137b5a892a1SMatthew G. Knepley   with the identity.
3138b5a892a1SMatthew G. Knepley 
313960225df5SJacob Faibussowitsch   Fortran Notes:
3140a1cb98faSBarry Smith   You must also call `DMPlexRestoreConeOrientation()` after you finish using the returned array.
3141a1cb98faSBarry Smith   `DMPlexRestoreConeOrientation()` is not needed/available in C.
31423813dfbdSMatthew G Knepley 
31431cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPolytopeTypeComposeOrientation()`, `DMPolytopeTypeComposeOrientationInv()`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetCone()`, `DMPlexSetChart()`
3144552f7358SJed Brown @*/
3145d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[])
3146d71ae5a4SJacob Faibussowitsch {
3147552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3148552f7358SJed Brown   PetscInt off;
3149552f7358SJed Brown 
3150552f7358SJed Brown   PetscFunctionBegin;
3151552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
315276bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
3153552f7358SJed Brown     PetscInt dof;
31549566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
31554f572ea9SToby Isaac     if (dof) PetscAssertPointer(coneOrientation, 3);
3156552f7358SJed Brown   }
31579566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
31580d644c17SKarl Rupp 
3159552f7358SJed Brown   *coneOrientation = &mesh->coneOrientations[off];
31603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3161552f7358SJed Brown }
3162552f7358SJed Brown 
3163552f7358SJed Brown /*@
3164eaf898f9SPatrick Sanan   DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the DAG
3165552f7358SJed Brown 
3166a1cb98faSBarry Smith   Not Collective
3167552f7358SJed Brown 
3168552f7358SJed Brown   Input Parameters:
316960225df5SJacob Faibussowitsch + dm              - The `DMPLEX`
3170a1cb98faSBarry Smith . p               - The point, which must lie in the chart set with `DMPlexSetChart()`
3171b5a892a1SMatthew G. Knepley - coneOrientation - An array of orientations
3172b5a892a1SMatthew G. Knepley 
3173552f7358SJed Brown   Level: beginner
3174552f7358SJed Brown 
3175a1cb98faSBarry Smith   Notes:
3176a1cb98faSBarry Smith   This should be called after all calls to `DMPlexSetConeSize()` and `DMSetUp()`.
3177a1cb98faSBarry Smith 
3178a1cb98faSBarry Smith   The meaning of coneOrientation is detailed in `DMPlexGetConeOrientation()`.
3179a1cb98faSBarry Smith 
31801cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetConeOrientation()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
3181552f7358SJed Brown @*/
3182d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[])
3183d71ae5a4SJacob Faibussowitsch {
3184552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3185552f7358SJed Brown   PetscInt pStart, pEnd;
3186552f7358SJed Brown   PetscInt dof, off, c;
3187552f7358SJed Brown 
3188552f7358SJed Brown   PetscFunctionBegin;
3189552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
31909566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
31914f572ea9SToby Isaac   if (dof) PetscAssertPointer(coneOrientation, 3);
31929566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
3193db485b19SStefano Zampini   if (PetscDefined(USE_DEBUG)) {
3194db485b19SStefano Zampini     PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
319563a3b9bcSJacob Faibussowitsch     PetscCheck(!(p < pStart) && !(p >= pEnd), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %" PetscInt_FMT " is not in the valid range [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, pStart, pEnd);
3196552f7358SJed Brown     for (c = 0; c < dof; ++c) {
3197552f7358SJed Brown       PetscInt cdof, o = coneOrientation[c];
3198552f7358SJed Brown 
31999566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(mesh->coneSection, mesh->cones[off + c], &cdof));
32001dca8a05SBarry 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);
3201552f7358SJed Brown       mesh->coneOrientations[off + c] = o;
3202552f7358SJed Brown     }
3203db485b19SStefano Zampini   } else {
3204db485b19SStefano Zampini     for (c = 0; c < dof; ++c) mesh->coneOrientations[off + c] = coneOrientation[c];
3205db485b19SStefano Zampini   }
32063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3207552f7358SJed Brown }
3208552f7358SJed Brown 
32097cd05799SMatthew G. Knepley /*@
3210eaf898f9SPatrick Sanan   DMPlexInsertCone - Insert a point into the in-edges for the point p in the DAG
32117cd05799SMatthew G. Knepley 
3212a1cb98faSBarry Smith   Not Collective
32137cd05799SMatthew G. Knepley 
32147cd05799SMatthew G. Knepley   Input Parameters:
321560225df5SJacob Faibussowitsch + dm        - The `DMPLEX`
3216a1cb98faSBarry Smith . p         - The point, which must lie in the chart set with `DMPlexSetChart()`
32177cd05799SMatthew G. Knepley . conePos   - The local index in the cone where the point should be put
32187cd05799SMatthew G. Knepley - conePoint - The mesh point to insert
32197cd05799SMatthew G. Knepley 
32207cd05799SMatthew G. Knepley   Level: beginner
32217cd05799SMatthew G. Knepley 
32221cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
32237cd05799SMatthew G. Knepley @*/
3224d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint)
3225d71ae5a4SJacob Faibussowitsch {
3226552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3227552f7358SJed Brown   PetscInt pStart, pEnd;
3228552f7358SJed Brown   PetscInt dof, off;
3229552f7358SJed Brown 
3230552f7358SJed Brown   PetscFunctionBegin;
3231552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3232a03d55ffSStefano Zampini   if (PetscDefined(USE_DEBUG)) {
32339566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
323463a3b9bcSJacob 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);
323563a3b9bcSJacob 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);
32369566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
323763a3b9bcSJacob 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);
3238a03d55ffSStefano Zampini   }
3239a03d55ffSStefano Zampini   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
3240552f7358SJed Brown   mesh->cones[off + conePos] = conePoint;
32413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3242552f7358SJed Brown }
3243552f7358SJed Brown 
32447cd05799SMatthew G. Knepley /*@
3245eaf898f9SPatrick Sanan   DMPlexInsertConeOrientation - Insert a point orientation for the in-edge for the point p in the DAG
32467cd05799SMatthew G. Knepley 
3247a1cb98faSBarry Smith   Not Collective
32487cd05799SMatthew G. Knepley 
32497cd05799SMatthew G. Knepley   Input Parameters:
325060225df5SJacob Faibussowitsch + dm              - The `DMPLEX`
3251a1cb98faSBarry Smith . p               - The point, which must lie in the chart set with `DMPlexSetChart()`
32527cd05799SMatthew G. Knepley . conePos         - The local index in the cone where the point should be put
32537cd05799SMatthew G. Knepley - coneOrientation - The point orientation to insert
32547cd05799SMatthew G. Knepley 
32557cd05799SMatthew G. Knepley   Level: beginner
32567cd05799SMatthew G. Knepley 
3257a1cb98faSBarry Smith   Note:
3258a1cb98faSBarry Smith   The meaning of coneOrientation values is detailed in `DMPlexGetConeOrientation()`.
3259b5a892a1SMatthew G. Knepley 
32601cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
32617cd05799SMatthew G. Knepley @*/
3262d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation)
3263d71ae5a4SJacob Faibussowitsch {
326477c88f5bSMatthew G Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
326577c88f5bSMatthew G Knepley   PetscInt pStart, pEnd;
326677c88f5bSMatthew G Knepley   PetscInt dof, off;
326777c88f5bSMatthew G Knepley 
326877c88f5bSMatthew G Knepley   PetscFunctionBegin;
326977c88f5bSMatthew G Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
3270a03d55ffSStefano Zampini   if (PetscDefined(USE_DEBUG)) {
32719566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
327263a3b9bcSJacob 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);
32739566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
327463a3b9bcSJacob 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);
3275a03d55ffSStefano Zampini   }
3276a03d55ffSStefano Zampini   PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
327777c88f5bSMatthew G Knepley   mesh->coneOrientations[off + conePos] = coneOrientation;
32783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
327977c88f5bSMatthew G Knepley }
328077c88f5bSMatthew G Knepley 
32819f4ada15SMatthew G. Knepley /*@C
32829f4ada15SMatthew G. Knepley   DMPlexGetOrientedCone - Return the points and orientations on the in-edges for this point in the DAG
32839f4ada15SMatthew G. Knepley 
32849f4ada15SMatthew G. Knepley   Not collective
32859f4ada15SMatthew G. Knepley 
32869f4ada15SMatthew G. Knepley   Input Parameters:
32879f4ada15SMatthew G. Knepley + dm - The DMPlex
32889f4ada15SMatthew G. Knepley - p  - The point, which must lie in the chart set with DMPlexSetChart()
32899f4ada15SMatthew G. Knepley 
32909f4ada15SMatthew G. Knepley   Output Parameters:
329120f4b53cSBarry Smith + cone - An array of points which are on the in-edges for point `p`
329220f4b53cSBarry Smith - ornt - An array of orientations which are on the in-edges for point `p`. An orientation is an
32939f4ada15SMatthew G. Knepley         integer giving the prescription for cone traversal.
32949f4ada15SMatthew G. Knepley 
32959f4ada15SMatthew G. Knepley   Level: beginner
32969f4ada15SMatthew G. Knepley 
32979f4ada15SMatthew G. Knepley   Notes:
32989f4ada15SMatthew G. Knepley   The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always
32999f4ada15SMatthew G. Knepley   the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection
330020f4b53cSBarry Smith   of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()`
33019f4ada15SMatthew G. Knepley   with the identity.
33029f4ada15SMatthew G. Knepley 
33039f4ada15SMatthew G. Knepley   Fortran Notes:
330420f4b53cSBarry Smith   You must also call `DMPlexRestoreCone()` after you finish using the returned array.
330520f4b53cSBarry Smith   `DMPlexRestoreCone()` is not needed/available in C.
33069f4ada15SMatthew G. Knepley 
33071cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()`
33089f4ada15SMatthew G. Knepley @*/
33099f4ada15SMatthew G. Knepley PetscErrorCode DMPlexGetOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[])
33109f4ada15SMatthew G. Knepley {
33119f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
33129f4ada15SMatthew G. Knepley 
33139f4ada15SMatthew G. Knepley   PetscFunctionBegin;
33149f4ada15SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
33159f4ada15SMatthew G. Knepley   if (mesh->tr) {
33169f4ada15SMatthew G. Knepley     PetscCall(DMPlexTransformGetCone(mesh->tr, p, cone, ornt));
33179f4ada15SMatthew G. Knepley   } else {
33189f4ada15SMatthew G. Knepley     PetscInt off;
33199f4ada15SMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) {
33209f4ada15SMatthew G. Knepley       PetscInt dof;
33219f4ada15SMatthew G. Knepley       PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
33229f4ada15SMatthew G. Knepley       if (dof) {
33234f572ea9SToby Isaac         if (cone) PetscAssertPointer(cone, 3);
33244f572ea9SToby Isaac         if (ornt) PetscAssertPointer(ornt, 4);
33259f4ada15SMatthew G. Knepley       }
33269f4ada15SMatthew G. Knepley     }
33279f4ada15SMatthew G. Knepley     PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
3328072f5ffdSStefano Zampini     if (cone) *cone = mesh->cones ? mesh->cones + off : NULL; // NULL + 0 is UB
3329072f5ffdSStefano Zampini     if (ornt) *ornt = mesh->coneOrientations ? mesh->coneOrientations + off : NULL;
33309f4ada15SMatthew G. Knepley   }
33313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33329f4ada15SMatthew G. Knepley }
33339f4ada15SMatthew G. Knepley 
33349f4ada15SMatthew G. Knepley /*@C
33359f4ada15SMatthew G. Knepley   DMPlexRestoreOrientedCone - Restore the points and orientations on the in-edges for this point in the DAG
33369f4ada15SMatthew G. Knepley 
333720f4b53cSBarry Smith   Not Collective
33389f4ada15SMatthew G. Knepley 
33399f4ada15SMatthew G. Knepley   Input Parameters:
33409f4ada15SMatthew G. Knepley + dm   - The DMPlex
334120f4b53cSBarry Smith . p    - The point, which must lie in the chart set with `DMPlexSetChart()`
33429f4ada15SMatthew G. Knepley . cone - An array of points which are on the in-edges for point p
334320f4b53cSBarry Smith - ornt - An array of orientations which are on the in-edges for point `p`. An orientation is an
33449f4ada15SMatthew G. Knepley         integer giving the prescription for cone traversal.
33459f4ada15SMatthew G. Knepley 
33469f4ada15SMatthew G. Knepley   Level: beginner
33479f4ada15SMatthew G. Knepley 
33489f4ada15SMatthew G. Knepley   Notes:
33499f4ada15SMatthew G. Knepley   The number indexes the symmetry transformations for the cell type (see manual). Orientation 0 is always
33509f4ada15SMatthew G. Knepley   the identity transformation. Negative orientation indicates reflection so that -(o+1) is the reflection
335120f4b53cSBarry Smith   of o, however it is not necessarily the inverse. To get the inverse, use `DMPolytopeTypeComposeOrientationInv()`
33529f4ada15SMatthew G. Knepley   with the identity.
33539f4ada15SMatthew G. Knepley 
335460225df5SJacob Faibussowitsch   Fortran Notes:
335520f4b53cSBarry Smith   You must also call `DMPlexRestoreCone()` after you finish using the returned array.
335620f4b53cSBarry Smith   `DMPlexRestoreCone()` is not needed/available in C.
33579f4ada15SMatthew G. Knepley 
33581cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetOrientedCone()`, `DMPlexGetConeSize()`, `DMPlexGetCone()`, `DMPlexGetChart()`
33599f4ada15SMatthew G. Knepley @*/
33609f4ada15SMatthew G. Knepley PetscErrorCode DMPlexRestoreOrientedCone(DM dm, PetscInt p, const PetscInt *cone[], const PetscInt *ornt[])
33619f4ada15SMatthew G. Knepley {
33629f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
33639f4ada15SMatthew G. Knepley 
33649f4ada15SMatthew G. Knepley   PetscFunctionBegin;
33659f4ada15SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
33669f4ada15SMatthew G. Knepley   if (mesh->tr) PetscCall(DMPlexTransformRestoreCone(mesh->tr, p, cone, ornt));
33673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
33689f4ada15SMatthew G. Knepley }
33699f4ada15SMatthew G. Knepley 
3370552f7358SJed Brown /*@
3371eaf898f9SPatrick Sanan   DMPlexGetSupportSize - Return the number of out-edges for this point in the DAG
3372552f7358SJed Brown 
3373a1cb98faSBarry Smith   Not Collective
3374552f7358SJed Brown 
3375552f7358SJed Brown   Input Parameters:
337660225df5SJacob Faibussowitsch + dm - The `DMPLEX`
3377a1cb98faSBarry Smith - p  - The point, which must lie in the chart set with `DMPlexSetChart()`
3378552f7358SJed Brown 
3379552f7358SJed Brown   Output Parameter:
338020f4b53cSBarry Smith . size - The support size for point `p`
3381552f7358SJed Brown 
3382552f7358SJed Brown   Level: beginner
3383552f7358SJed Brown 
33841cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`, `DMPlexGetConeSize()`
3385552f7358SJed Brown @*/
3386d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size)
3387d71ae5a4SJacob Faibussowitsch {
3388552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3389552f7358SJed Brown 
3390552f7358SJed Brown   PetscFunctionBegin;
3391552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
33924f572ea9SToby Isaac   PetscAssertPointer(size, 3);
33939566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, size));
33943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3395552f7358SJed Brown }
3396552f7358SJed Brown 
3397552f7358SJed Brown /*@
3398eaf898f9SPatrick Sanan   DMPlexSetSupportSize - Set the number of out-edges for this point in the DAG
3399552f7358SJed Brown 
3400a1cb98faSBarry Smith   Not Collective
3401552f7358SJed Brown 
3402552f7358SJed Brown   Input Parameters:
340360225df5SJacob Faibussowitsch + dm   - The `DMPLEX`
3404a1cb98faSBarry Smith . p    - The point, which must lie in the chart set with `DMPlexSetChart()`
340520f4b53cSBarry Smith - size - The support size for point `p`
3406552f7358SJed Brown 
3407a1cb98faSBarry Smith   Level: beginner
3408552f7358SJed Brown 
3409552f7358SJed Brown   Note:
341020f4b53cSBarry Smith   This should be called after `DMPlexSetChart()`.
3411552f7358SJed Brown 
34121cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetSupportSize()`, `DMPlexSetChart()`
3413552f7358SJed Brown @*/
3414d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size)
3415d71ae5a4SJacob Faibussowitsch {
3416552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3417552f7358SJed Brown 
3418552f7358SJed Brown   PetscFunctionBegin;
3419552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
34209566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetDof(mesh->supportSection, p, size));
34213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3422552f7358SJed Brown }
3423552f7358SJed Brown 
3424552f7358SJed Brown /*@C
3425eaf898f9SPatrick Sanan   DMPlexGetSupport - Return the points on the out-edges for this point in the DAG
3426552f7358SJed Brown 
3427a1cb98faSBarry Smith   Not Collective
3428552f7358SJed Brown 
3429552f7358SJed Brown   Input Parameters:
343060225df5SJacob Faibussowitsch + dm - The `DMPLEX`
3431a1cb98faSBarry Smith - p  - The point, which must lie in the chart set with `DMPlexSetChart()`
3432552f7358SJed Brown 
3433552f7358SJed Brown   Output Parameter:
343420f4b53cSBarry Smith . support - An array of points which are on the out-edges for point `p`
3435552f7358SJed Brown 
3436552f7358SJed Brown   Level: beginner
3437552f7358SJed Brown 
343860225df5SJacob Faibussowitsch   Fortran Notes:
3439a1cb98faSBarry Smith   You must also call `DMPlexRestoreSupport()` after you finish using the returned array.
3440a1cb98faSBarry Smith   `DMPlexRestoreSupport()` is not needed/available in C.
34413813dfbdSMatthew G Knepley 
34421cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSize()`, `DMPlexSetSupport()`, `DMPlexGetCone()`, `DMPlexSetChart()`
3443552f7358SJed Brown @*/
3444d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[])
3445d71ae5a4SJacob Faibussowitsch {
3446552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3447552f7358SJed Brown   PetscInt off;
3448552f7358SJed Brown 
3449552f7358SJed Brown   PetscFunctionBegin;
3450552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
34514f572ea9SToby Isaac   PetscAssertPointer(support, 3);
34529566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
3453072f5ffdSStefano Zampini   *support = mesh->supports ? mesh->supports + off : NULL; //NULL + 0 is UB
34543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3455552f7358SJed Brown }
3456552f7358SJed Brown 
3457552f7358SJed Brown /*@
345892371b87SBarry 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
3459552f7358SJed Brown 
3460a1cb98faSBarry Smith   Not Collective
3461552f7358SJed Brown 
3462552f7358SJed Brown   Input Parameters:
346360225df5SJacob Faibussowitsch + dm      - The `DMPLEX`
3464a1cb98faSBarry Smith . p       - The point, which must lie in the chart set with `DMPlexSetChart()`
346520f4b53cSBarry Smith - support - An array of points which are on the out-edges for point `p`
3466552f7358SJed Brown 
3467552f7358SJed Brown   Level: beginner
3468552f7358SJed Brown 
3469a1cb98faSBarry Smith   Note:
3470a1cb98faSBarry Smith   This should be called after all calls to `DMPlexSetSupportSize()` and `DMSetUp()`.
3471a1cb98faSBarry Smith 
34721cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetCone()`, `DMPlexSetConeSize()`, `DMPlexCreate()`, `DMPlexGetSupport()`, `DMPlexSetChart()`, `DMPlexSetSupportSize()`, `DMSetUp()`
3473552f7358SJed Brown @*/
3474d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[])
3475d71ae5a4SJacob Faibussowitsch {
3476552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3477552f7358SJed Brown   PetscInt pStart, pEnd;
3478552f7358SJed Brown   PetscInt dof, off, c;
3479552f7358SJed Brown 
3480552f7358SJed Brown   PetscFunctionBegin;
3481552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
34829566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd));
34839566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
34844f572ea9SToby Isaac   if (dof) PetscAssertPointer(support, 3);
34859566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
348663a3b9bcSJacob 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);
3487552f7358SJed Brown   for (c = 0; c < dof; ++c) {
348863a3b9bcSJacob 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);
3489552f7358SJed Brown     mesh->supports[off + c] = support[c];
3490552f7358SJed Brown   }
34913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3492552f7358SJed Brown }
3493552f7358SJed Brown 
34947cd05799SMatthew G. Knepley /*@
3495eaf898f9SPatrick Sanan   DMPlexInsertSupport - Insert a point into the out-edges for the point p in the DAG
34967cd05799SMatthew G. Knepley 
3497a1cb98faSBarry Smith   Not Collective
34987cd05799SMatthew G. Knepley 
34997cd05799SMatthew G. Knepley   Input Parameters:
350060225df5SJacob Faibussowitsch + dm           - The `DMPLEX`
3501a1cb98faSBarry Smith . p            - The point, which must lie in the chart set with `DMPlexSetChart()`
35027cd05799SMatthew G. Knepley . supportPos   - The local index in the cone where the point should be put
35037cd05799SMatthew G. Knepley - supportPoint - The mesh point to insert
35047cd05799SMatthew G. Knepley 
35057cd05799SMatthew G. Knepley   Level: beginner
35067cd05799SMatthew G. Knepley 
35071cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexGetCone()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMSetUp()`
35087cd05799SMatthew G. Knepley @*/
3509d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint)
3510d71ae5a4SJacob Faibussowitsch {
3511552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3512552f7358SJed Brown   PetscInt pStart, pEnd;
3513552f7358SJed Brown   PetscInt dof, off;
3514552f7358SJed Brown 
3515552f7358SJed Brown   PetscFunctionBegin;
3516552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
35179566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd));
35189566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, p, &dof));
35199566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, p, &off));
352063a3b9bcSJacob 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);
352163a3b9bcSJacob 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);
352263a3b9bcSJacob 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);
3523552f7358SJed Brown   mesh->supports[off + supportPos] = supportPoint;
35243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3525552f7358SJed Brown }
3526552f7358SJed Brown 
3527b5a892a1SMatthew G. Knepley /* Converts an orientation o in the current numbering to the previous scheme used in Plex */
3528d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertNewOrientation_Internal(DMPolytopeType ct, PetscInt o)
3529d71ae5a4SJacob Faibussowitsch {
3530b5a892a1SMatthew G. Knepley   switch (ct) {
3531b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
3532b5a892a1SMatthew G. Knepley     if (o == -1) return -2;
3533b5a892a1SMatthew G. Knepley     break;
3534b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
3535b5a892a1SMatthew G. Knepley     if (o == -3) return -1;
3536b5a892a1SMatthew G. Knepley     if (o == -2) return -3;
3537b5a892a1SMatthew G. Knepley     if (o == -1) return -2;
3538b5a892a1SMatthew G. Knepley     break;
3539b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
3540b5a892a1SMatthew G. Knepley     if (o == -4) return -2;
3541b5a892a1SMatthew G. Knepley     if (o == -3) return -1;
3542b5a892a1SMatthew G. Knepley     if (o == -2) return -4;
3543b5a892a1SMatthew G. Knepley     if (o == -1) return -3;
3544b5a892a1SMatthew G. Knepley     break;
3545d71ae5a4SJacob Faibussowitsch   default:
3546d71ae5a4SJacob Faibussowitsch     return o;
3547b5a892a1SMatthew G. Knepley   }
3548b5a892a1SMatthew G. Knepley   return o;
3549b5a892a1SMatthew G. Knepley }
3550b5a892a1SMatthew G. Knepley 
3551b5a892a1SMatthew G. Knepley /* Converts an orientation o in the previous scheme used in Plex to the current numbering */
3552d71ae5a4SJacob Faibussowitsch PetscInt DMPolytopeConvertOldOrientation_Internal(DMPolytopeType ct, PetscInt o)
3553d71ae5a4SJacob Faibussowitsch {
3554b5a892a1SMatthew G. Knepley   switch (ct) {
3555b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
3556b5a892a1SMatthew G. Knepley     if ((o == -2) || (o == 1)) return -1;
3557b5a892a1SMatthew G. Knepley     if (o == -1) return 0;
3558b5a892a1SMatthew G. Knepley     break;
3559b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
3560b5a892a1SMatthew G. Knepley     if (o == -3) return -2;
3561b5a892a1SMatthew G. Knepley     if (o == -2) return -1;
3562b5a892a1SMatthew G. Knepley     if (o == -1) return -3;
3563b5a892a1SMatthew G. Knepley     break;
3564b5a892a1SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
3565b5a892a1SMatthew G. Knepley     if (o == -4) return -2;
3566b5a892a1SMatthew G. Knepley     if (o == -3) return -1;
3567b5a892a1SMatthew G. Knepley     if (o == -2) return -4;
3568b5a892a1SMatthew G. Knepley     if (o == -1) return -3;
3569b5a892a1SMatthew G. Knepley     break;
3570d71ae5a4SJacob Faibussowitsch   default:
3571d71ae5a4SJacob Faibussowitsch     return o;
3572b5a892a1SMatthew G. Knepley   }
3573b5a892a1SMatthew G. Knepley   return o;
3574b5a892a1SMatthew G. Knepley }
3575b5a892a1SMatthew G. Knepley 
3576b5a892a1SMatthew G. Knepley /* Takes in a mesh whose orientations are in the previous scheme and converts them all to the current numbering */
3577d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexConvertOldOrientations_Internal(DM dm)
3578d71ae5a4SJacob Faibussowitsch {
3579b5a892a1SMatthew G. Knepley   PetscInt pStart, pEnd, p;
3580b5a892a1SMatthew G. Knepley 
3581b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
35829566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
3583b5a892a1SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
3584b5a892a1SMatthew G. Knepley     const PetscInt *cone, *ornt;
3585b5a892a1SMatthew G. Knepley     PetscInt        coneSize, c;
3586b5a892a1SMatthew G. Knepley 
35879566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
35889566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
35899566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dm, p, &ornt));
3590b5a892a1SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
3591b5a892a1SMatthew G. Knepley       DMPolytopeType ct;
3592b5a892a1SMatthew G. Knepley       const PetscInt o = ornt[c];
3593b5a892a1SMatthew G. Knepley 
35949566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, cone[c], &ct));
3595b5a892a1SMatthew G. Knepley       switch (ct) {
3596b5a892a1SMatthew G. Knepley       case DM_POLYTOPE_SEGMENT:
35979566063dSJacob Faibussowitsch         if ((o == -2) || (o == 1)) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
35989566063dSJacob Faibussowitsch         if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, 0));
3599b5a892a1SMatthew G. Knepley         break;
3600b5a892a1SMatthew G. Knepley       case DM_POLYTOPE_TRIANGLE:
36019566063dSJacob Faibussowitsch         if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2));
36029566063dSJacob Faibussowitsch         if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
36039566063dSJacob Faibussowitsch         if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3));
3604b5a892a1SMatthew G. Knepley         break;
3605b5a892a1SMatthew G. Knepley       case DM_POLYTOPE_QUADRILATERAL:
36069566063dSJacob Faibussowitsch         if (o == -4) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -2));
36079566063dSJacob Faibussowitsch         if (o == -3) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -1));
36089566063dSJacob Faibussowitsch         if (o == -2) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -4));
36099566063dSJacob Faibussowitsch         if (o == -1) PetscCall(DMPlexInsertConeOrientation(dm, p, c, -3));
3610b5a892a1SMatthew G. Knepley         break;
3611d71ae5a4SJacob Faibussowitsch       default:
3612d71ae5a4SJacob Faibussowitsch         break;
3613b5a892a1SMatthew G. Knepley       }
3614b5a892a1SMatthew G. Knepley     }
3615b5a892a1SMatthew G. Knepley   }
36163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3617b5a892a1SMatthew G. Knepley }
3618b5a892a1SMatthew G. Knepley 
361909015e70SStefano Zampini static inline PetscErrorCode DMPlexGetTransitiveClosure_Hot_Private(DM dm, PetscInt p, PetscBool useCone, PetscInt *size, const PetscInt *arr[], const PetscInt *ornt[])
362009015e70SStefano Zampini {
362109015e70SStefano Zampini   DM_Plex *mesh = (DM_Plex *)dm->data;
362209015e70SStefano Zampini 
362309015e70SStefano Zampini   PetscFunctionBeginHot;
362409015e70SStefano Zampini   if (PetscDefined(USE_DEBUG) || mesh->tr) {
362509015e70SStefano Zampini     if (useCone) {
362609015e70SStefano Zampini       PetscCall(DMPlexGetConeSize(dm, p, size));
362709015e70SStefano Zampini       PetscCall(DMPlexGetOrientedCone(dm, p, arr, ornt));
362809015e70SStefano Zampini     } else {
362909015e70SStefano Zampini       PetscCall(DMPlexGetSupportSize(dm, p, size));
363009015e70SStefano Zampini       PetscCall(DMPlexGetSupport(dm, p, arr));
363109015e70SStefano Zampini     }
363209015e70SStefano Zampini   } else {
363309015e70SStefano Zampini     if (useCone) {
363409015e70SStefano Zampini       const PetscSection s   = mesh->coneSection;
363509015e70SStefano Zampini       const PetscInt     ps  = p - s->pStart;
363609015e70SStefano Zampini       const PetscInt     off = s->atlasOff[ps];
363709015e70SStefano Zampini 
363809015e70SStefano Zampini       *size = s->atlasDof[ps];
363909015e70SStefano Zampini       *arr  = mesh->cones + off;
364009015e70SStefano Zampini       *ornt = mesh->coneOrientations + off;
364109015e70SStefano Zampini     } else {
364209015e70SStefano Zampini       const PetscSection s   = mesh->supportSection;
364309015e70SStefano Zampini       const PetscInt     ps  = p - s->pStart;
364409015e70SStefano Zampini       const PetscInt     off = s->atlasOff[ps];
364509015e70SStefano Zampini 
364609015e70SStefano Zampini       *size = s->atlasDof[ps];
364709015e70SStefano Zampini       *arr  = mesh->supports + off;
364809015e70SStefano Zampini     }
364909015e70SStefano Zampini   }
365009015e70SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
365109015e70SStefano Zampini }
365209015e70SStefano Zampini 
365309015e70SStefano Zampini static inline PetscErrorCode DMPlexRestoreTransitiveClosure_Hot_Private(DM dm, PetscInt p, PetscBool useCone, PetscInt *size, const PetscInt *arr[], const PetscInt *ornt[])
365409015e70SStefano Zampini {
365509015e70SStefano Zampini   DM_Plex *mesh = (DM_Plex *)dm->data;
365609015e70SStefano Zampini 
365709015e70SStefano Zampini   PetscFunctionBeginHot;
365809015e70SStefano Zampini   if (PetscDefined(USE_DEBUG) || mesh->tr) {
365909015e70SStefano Zampini     if (useCone) PetscCall(DMPlexRestoreOrientedCone(dm, p, arr, ornt));
366009015e70SStefano Zampini   }
366109015e70SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
366209015e70SStefano Zampini }
366309015e70SStefano Zampini 
3664d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetTransitiveClosure_Depth1_Private(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3665d71ae5a4SJacob Faibussowitsch {
3666b5a892a1SMatthew G. Knepley   DMPolytopeType  ct = DM_POLYTOPE_UNKNOWN;
3667b5a892a1SMatthew G. Knepley   PetscInt       *closure;
3668b5a892a1SMatthew G. Knepley   const PetscInt *tmp = NULL, *tmpO = NULL;
3669b5a892a1SMatthew G. Knepley   PetscInt        off = 0, tmpSize, t;
3670b5a892a1SMatthew G. Knepley 
3671b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3672b5a892a1SMatthew G. Knepley   if (ornt) {
36739566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, p, &ct));
3674b5a892a1SMatthew G. Knepley     if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN;
3675b5a892a1SMatthew G. Knepley   }
3676b5a892a1SMatthew G. Knepley   if (*points) {
3677b5a892a1SMatthew G. Knepley     closure = *points;
3678b5a892a1SMatthew G. Knepley   } else {
3679b5a892a1SMatthew G. Knepley     PetscInt maxConeSize, maxSupportSize;
36809566063dSJacob Faibussowitsch     PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
36819566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, 2 * (PetscMax(maxConeSize, maxSupportSize) + 1), MPIU_INT, &closure));
3682b5a892a1SMatthew G. Knepley   }
368309015e70SStefano Zampini   PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, p, useCone, &tmpSize, &tmp, &tmpO));
3684b5a892a1SMatthew G. Knepley   if (ct == DM_POLYTOPE_UNKNOWN) {
3685b5a892a1SMatthew G. Knepley     closure[off++] = p;
3686b5a892a1SMatthew G. Knepley     closure[off++] = 0;
3687b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3688b5a892a1SMatthew G. Knepley       closure[off++] = tmp[t];
3689b5a892a1SMatthew G. Knepley       closure[off++] = tmpO ? tmpO[t] : 0;
3690b5a892a1SMatthew G. Knepley     }
3691b5a892a1SMatthew G. Knepley   } else {
36925f80ce2aSJacob Faibussowitsch     const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, ornt);
3693b5a892a1SMatthew G. Knepley 
3694b5a892a1SMatthew G. Knepley     /* We assume that cells with a valid type have faces with a valid type */
3695b5a892a1SMatthew G. Knepley     closure[off++] = p;
3696b5a892a1SMatthew G. Knepley     closure[off++] = ornt;
3697b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3698b5a892a1SMatthew G. Knepley       DMPolytopeType ft;
3699b5a892a1SMatthew G. Knepley 
37009566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, tmp[t], &ft));
3701b5a892a1SMatthew G. Knepley       closure[off++] = tmp[arr[t]];
3702b5a892a1SMatthew G. Knepley       closure[off++] = tmpO ? DMPolytopeTypeComposeOrientation(ft, ornt, tmpO[t]) : 0;
3703b5a892a1SMatthew G. Knepley     }
3704b5a892a1SMatthew G. Knepley   }
370509015e70SStefano Zampini   PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, p, useCone, &tmpSize, &tmp, &tmpO));
3706b5a892a1SMatthew G. Knepley   if (numPoints) *numPoints = tmpSize + 1;
3707b5a892a1SMatthew G. Knepley   if (points) *points = closure;
37083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3709b5a892a1SMatthew G. Knepley }
3710b5a892a1SMatthew G. Knepley 
3711d5b43468SJose E. Roman /* We need a special tensor version because we want to allow duplicate points in the endcaps for hybrid cells */
3712d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexTransitiveClosure_Tensor_Internal(DM dm, PetscInt point, DMPolytopeType ct, PetscInt o, PetscBool useCone, PetscInt *numPoints, PetscInt **points)
3713d71ae5a4SJacob Faibussowitsch {
3714b5a892a1SMatthew G. Knepley   const PetscInt *arr = DMPolytopeTypeGetArrangment(ct, o);
3715b5a892a1SMatthew G. Knepley   const PetscInt *cone, *ornt;
3716b5a892a1SMatthew G. Knepley   PetscInt       *pts, *closure = NULL;
3717b5a892a1SMatthew G. Knepley   DMPolytopeType  ft;
3718b5a892a1SMatthew G. Knepley   PetscInt        maxConeSize, maxSupportSize, coneSeries, supportSeries, maxSize;
3719b5a892a1SMatthew G. Knepley   PetscInt        dim, coneSize, c, d, clSize, cl;
3720b5a892a1SMatthew G. Knepley 
3721b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
37229566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
372309015e70SStefano Zampini   PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, point, PETSC_TRUE, &coneSize, &cone, &ornt));
37249566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
3725b5a892a1SMatthew G. Knepley   coneSeries    = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, dim + 1) - 1) / (maxConeSize - 1)) : dim + 1;
3726b5a892a1SMatthew G. Knepley   supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, dim + 1) - 1) / (maxSupportSize - 1)) : dim + 1;
3727b5a892a1SMatthew G. Knepley   maxSize       = PetscMax(coneSeries, supportSeries);
37289371c9d4SSatish Balay   if (*points) {
37299371c9d4SSatish Balay     pts = *points;
37309371c9d4SSatish Balay   } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &pts));
3731b5a892a1SMatthew G. Knepley   c        = 0;
3732b5a892a1SMatthew G. Knepley   pts[c++] = point;
3733b5a892a1SMatthew G. Knepley   pts[c++] = o;
37349566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cone[arr[0 * 2 + 0]], &ft));
37359566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[0 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[0 * 2 + 1], ornt[0]), useCone, &clSize, &closure));
37369371c9d4SSatish Balay   for (cl = 0; cl < clSize * 2; cl += 2) {
37379371c9d4SSatish Balay     pts[c++] = closure[cl];
37389371c9d4SSatish Balay     pts[c++] = closure[cl + 1];
37399371c9d4SSatish Balay   }
37409566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[arr[1 * 2 + 0]], DMPolytopeTypeComposeOrientation(ft, arr[1 * 2 + 1], ornt[1]), useCone, &clSize, &closure));
37419371c9d4SSatish Balay   for (cl = 0; cl < clSize * 2; cl += 2) {
37429371c9d4SSatish Balay     pts[c++] = closure[cl];
37439371c9d4SSatish Balay     pts[c++] = closure[cl + 1];
37449371c9d4SSatish Balay   }
37459566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[0], useCone, &clSize, &closure));
3746b5a892a1SMatthew G. Knepley   for (d = 2; d < coneSize; ++d) {
37479566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, cone[arr[d * 2 + 0]], &ft));
3748b5a892a1SMatthew G. Knepley     pts[c++] = cone[arr[d * 2 + 0]];
3749b5a892a1SMatthew G. Knepley     pts[c++] = DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d]);
3750b5a892a1SMatthew G. Knepley   }
375109015e70SStefano Zampini   PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, point, PETSC_TRUE, &coneSize, &cone, &ornt));
3752b5a892a1SMatthew G. Knepley   if (dim >= 3) {
3753b5a892a1SMatthew G. Knepley     for (d = 2; d < coneSize; ++d) {
3754b5a892a1SMatthew G. Knepley       const PetscInt  fpoint = cone[arr[d * 2 + 0]];
3755b5a892a1SMatthew G. Knepley       const PetscInt *fcone, *fornt;
3756b5a892a1SMatthew G. Knepley       PetscInt        fconeSize, fc, i;
3757b5a892a1SMatthew G. Knepley 
37589566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, fpoint, &ft));
3759b5a892a1SMatthew G. Knepley       const PetscInt *farr = DMPolytopeTypeGetArrangment(ft, DMPolytopeTypeComposeOrientation(ft, arr[d * 2 + 1], ornt[d]));
376009015e70SStefano Zampini       PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, fpoint, PETSC_TRUE, &fconeSize, &fcone, &fornt));
3761b5a892a1SMatthew G. Knepley       for (fc = 0; fc < fconeSize; ++fc) {
3762b5a892a1SMatthew G. Knepley         const PetscInt cp = fcone[farr[fc * 2 + 0]];
3763b5a892a1SMatthew G. Knepley         const PetscInt co = farr[fc * 2 + 1];
3764b5a892a1SMatthew G. Knepley 
37659371c9d4SSatish Balay         for (i = 0; i < c; i += 2)
37669371c9d4SSatish Balay           if (pts[i] == cp) break;
3767b5a892a1SMatthew G. Knepley         if (i == c) {
37689566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCellType(dm, cp, &ft));
3769b5a892a1SMatthew G. Knepley           pts[c++] = cp;
3770b5a892a1SMatthew G. Knepley           pts[c++] = DMPolytopeTypeComposeOrientation(ft, co, fornt[farr[fc * 2 + 0]]);
3771b5a892a1SMatthew G. Knepley         }
3772b5a892a1SMatthew G. Knepley       }
377309015e70SStefano Zampini       PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, fpoint, PETSC_TRUE, &fconeSize, &fcone, &fornt));
3774b5a892a1SMatthew G. Knepley     }
3775b5a892a1SMatthew G. Knepley   }
3776b5a892a1SMatthew G. Knepley   *numPoints = c / 2;
3777b5a892a1SMatthew G. Knepley   *points    = pts;
37783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3779b5a892a1SMatthew G. Knepley }
3780b5a892a1SMatthew G. Knepley 
3781d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3782d71ae5a4SJacob Faibussowitsch {
3783b5a892a1SMatthew G. Knepley   DMPolytopeType ct;
3784b5a892a1SMatthew G. Knepley   PetscInt      *closure, *fifo;
3785b5a892a1SMatthew G. Knepley   PetscInt       closureSize = 0, fifoStart = 0, fifoSize = 0;
3786b5a892a1SMatthew G. Knepley   PetscInt       maxConeSize, maxSupportSize, coneSeries, supportSeries;
3787b5a892a1SMatthew G. Knepley   PetscInt       depth, maxSize;
3788b5a892a1SMatthew G. Knepley 
3789b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
37909566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
3791b5a892a1SMatthew G. Knepley   if (depth == 1) {
37929566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure_Depth1_Private(dm, p, ornt, useCone, numPoints, points));
37933ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
3794b5a892a1SMatthew G. Knepley   }
37959566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, p, &ct));
3796b5a892a1SMatthew G. Knepley   if (ct == DM_POLYTOPE_FV_GHOST || ct == DM_POLYTOPE_INTERIOR_GHOST || ct == DM_POLYTOPE_UNKNOWN) ct = DM_POLYTOPE_UNKNOWN;
3797b5a892a1SMatthew G. Knepley   if (ct == DM_POLYTOPE_SEG_PRISM_TENSOR || ct == DM_POLYTOPE_TRI_PRISM_TENSOR || ct == DM_POLYTOPE_QUAD_PRISM_TENSOR) {
37989566063dSJacob Faibussowitsch     PetscCall(DMPlexTransitiveClosure_Tensor_Internal(dm, p, ct, ornt, useCone, numPoints, points));
37993ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
3800b5a892a1SMatthew G. Knepley   }
38019566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize));
3802b5a892a1SMatthew G. Knepley   coneSeries    = (maxConeSize > 1) ? ((PetscPowInt(maxConeSize, depth + 1) - 1) / (maxConeSize - 1)) : depth + 1;
3803b5a892a1SMatthew G. Knepley   supportSeries = (maxSupportSize > 1) ? ((PetscPowInt(maxSupportSize, depth + 1) - 1) / (maxSupportSize - 1)) : depth + 1;
3804b5a892a1SMatthew G. Knepley   maxSize       = PetscMax(coneSeries, supportSeries);
38059566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo));
38069371c9d4SSatish Balay   if (*points) {
38079371c9d4SSatish Balay     closure = *points;
38089371c9d4SSatish Balay   } else PetscCall(DMGetWorkArray(dm, 2 * maxSize, MPIU_INT, &closure));
3809b5a892a1SMatthew G. Knepley   closure[closureSize++] = p;
3810b5a892a1SMatthew G. Knepley   closure[closureSize++] = ornt;
3811b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = p;
3812b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = ornt;
3813b5a892a1SMatthew G. Knepley   fifo[fifoSize++]       = ct;
3814b5a892a1SMatthew G. Knepley   /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */
3815b5a892a1SMatthew G. Knepley   while (fifoSize - fifoStart) {
3816b5a892a1SMatthew G. Knepley     const PetscInt       q    = fifo[fifoStart++];
3817b5a892a1SMatthew G. Knepley     const PetscInt       o    = fifo[fifoStart++];
3818b5a892a1SMatthew G. Knepley     const DMPolytopeType qt   = (DMPolytopeType)fifo[fifoStart++];
3819b5a892a1SMatthew G. Knepley     const PetscInt      *qarr = DMPolytopeTypeGetArrangment(qt, o);
382009015e70SStefano Zampini     const PetscInt      *tmp, *tmpO = NULL;
3821b5a892a1SMatthew G. Knepley     PetscInt             tmpSize, t;
3822b5a892a1SMatthew G. Knepley 
3823b5a892a1SMatthew G. Knepley     if (PetscDefined(USE_DEBUG)) {
3824b5a892a1SMatthew G. Knepley       PetscInt nO = DMPolytopeTypeGetNumArrangments(qt) / 2;
382563a3b9bcSJacob 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);
3826b5a892a1SMatthew G. Knepley     }
382709015e70SStefano Zampini     PetscCall(DMPlexGetTransitiveClosure_Hot_Private(dm, q, useCone, &tmpSize, &tmp, &tmpO));
3828b5a892a1SMatthew G. Knepley     for (t = 0; t < tmpSize; ++t) {
3829b5a892a1SMatthew G. Knepley       const PetscInt ip = useCone && qarr ? qarr[t * 2] : t;
3830b5a892a1SMatthew G. Knepley       const PetscInt io = useCone && qarr ? qarr[t * 2 + 1] : 0;
3831b5a892a1SMatthew G. Knepley       const PetscInt cp = tmp[ip];
38329566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, cp, &ct));
3833b5a892a1SMatthew G. Knepley       const PetscInt co = tmpO ? DMPolytopeTypeComposeOrientation(ct, io, tmpO[ip]) : 0;
3834b5a892a1SMatthew G. Knepley       PetscInt       c;
3835b5a892a1SMatthew G. Knepley 
3836b5a892a1SMatthew G. Knepley       /* Check for duplicate */
3837b5a892a1SMatthew G. Knepley       for (c = 0; c < closureSize; c += 2) {
3838b5a892a1SMatthew G. Knepley         if (closure[c] == cp) break;
3839b5a892a1SMatthew G. Knepley       }
3840b5a892a1SMatthew G. Knepley       if (c == closureSize) {
3841b5a892a1SMatthew G. Knepley         closure[closureSize++] = cp;
3842b5a892a1SMatthew G. Knepley         closure[closureSize++] = co;
3843b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = cp;
3844b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = co;
3845b5a892a1SMatthew G. Knepley         fifo[fifoSize++]       = ct;
3846b5a892a1SMatthew G. Knepley       }
3847b5a892a1SMatthew G. Knepley     }
384809015e70SStefano Zampini     PetscCall(DMPlexRestoreTransitiveClosure_Hot_Private(dm, q, useCone, &tmpSize, &tmp, &tmpO));
3849b5a892a1SMatthew G. Knepley   }
38509566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 3 * maxSize, MPIU_INT, &fifo));
3851b5a892a1SMatthew G. Knepley   if (numPoints) *numPoints = closureSize / 2;
3852b5a892a1SMatthew G. Knepley   if (points) *points = closure;
38533ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3854b5a892a1SMatthew G. Knepley }
3855b5a892a1SMatthew G. Knepley 
3856552f7358SJed Brown /*@C
3857eaf898f9SPatrick Sanan   DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the DAG
3858552f7358SJed Brown 
3859a1cb98faSBarry Smith   Not Collective
3860552f7358SJed Brown 
3861552f7358SJed Brown   Input Parameters:
3862a1cb98faSBarry Smith + dm      - The `DMPLEX`
3863b5a892a1SMatthew G. Knepley . p       - The mesh point
3864a1cb98faSBarry Smith - useCone - `PETSC_TRUE` for the closure, otherwise return the star
3865552f7358SJed Brown 
38666b867d5aSJose E. Roman   Input/Output Parameter:
38676b867d5aSJose E. Roman . points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...];
386820f4b53cSBarry Smith            if `NULL` on input, internal storage will be returned, otherwise the provided array is used
38696b867d5aSJose E. Roman 
38706b867d5aSJose E. Roman   Output Parameter:
387120f4b53cSBarry Smith . numPoints - The number of points in the closure, so points[] is of size 2*`numPoints`
3872552f7358SJed Brown 
3873a1cb98faSBarry Smith   Level: beginner
3874a1cb98faSBarry Smith 
3875552f7358SJed Brown   Note:
387620f4b53cSBarry Smith   If using internal storage (points is `NULL` on input), each call overwrites the last output.
3877552f7358SJed Brown 
387860225df5SJacob Faibussowitsch   Fortran Notes:
387920f4b53cSBarry Smith   The `numPoints` argument is not present in the Fortran binding since it is internal to the array.
38803813dfbdSMatthew G Knepley 
38811cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()`
3882552f7358SJed Brown @*/
3883d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3884d71ae5a4SJacob Faibussowitsch {
3885b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3886552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
38874f572ea9SToby Isaac   if (numPoints) PetscAssertPointer(numPoints, 4);
38884f572ea9SToby Isaac   if (points) PetscAssertPointer(points, 5);
38899566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure_Internal(dm, p, 0, useCone, numPoints, points));
38903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38919bf0dad6SMatthew G. Knepley }
38929bf0dad6SMatthew G. Knepley 
3893552f7358SJed Brown /*@C
3894eaf898f9SPatrick Sanan   DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the DAG
3895552f7358SJed Brown 
3896a1cb98faSBarry Smith   Not Collective
3897552f7358SJed Brown 
3898552f7358SJed Brown   Input Parameters:
3899a1cb98faSBarry Smith + dm        - The `DMPLEX`
3900b5a892a1SMatthew G. Knepley . p         - The mesh point
3901a1cb98faSBarry Smith . useCone   - `PETSC_TRUE` for the closure, otherwise return the star
390220f4b53cSBarry Smith . numPoints - The number of points in the closure, so points[] is of size 2*`numPoints`
3903b5a892a1SMatthew G. Knepley - points    - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...]
3904552f7358SJed Brown 
3905a1cb98faSBarry Smith   Level: beginner
3906a1cb98faSBarry Smith 
3907552f7358SJed Brown   Note:
390820f4b53cSBarry Smith   If not using internal storage (points is not `NULL` on input), this call is unnecessary
3909552f7358SJed Brown 
39101cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetTransitiveClosure()`, `DMPlexCreate()`, `DMPlexSetCone()`, `DMPlexSetChart()`, `DMPlexGetCone()`
3911552f7358SJed Brown @*/
3912d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[])
3913d71ae5a4SJacob Faibussowitsch {
3914b5a892a1SMatthew G. Knepley   PetscFunctionBeginHot;
3915552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
39164ff43b2cSJed Brown   if (numPoints) *numPoints = 0;
39179566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, points));
39183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3919552f7358SJed Brown }
3920552f7358SJed Brown 
3921552f7358SJed Brown /*@
3922eaf898f9SPatrick Sanan   DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the DAG
3923552f7358SJed Brown 
3924a1cb98faSBarry Smith   Not Collective
3925552f7358SJed Brown 
3926552f7358SJed Brown   Input Parameter:
392760225df5SJacob Faibussowitsch . dm - The `DMPLEX`
3928552f7358SJed Brown 
3929552f7358SJed Brown   Output Parameters:
3930552f7358SJed Brown + maxConeSize    - The maximum number of in-edges
3931552f7358SJed Brown - maxSupportSize - The maximum number of out-edges
3932552f7358SJed Brown 
3933552f7358SJed Brown   Level: beginner
3934552f7358SJed Brown 
39351cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetConeSize()`, `DMPlexSetChart()`
3936552f7358SJed Brown @*/
3937d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize)
3938d71ae5a4SJacob Faibussowitsch {
3939552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
3940552f7358SJed Brown 
3941552f7358SJed Brown   PetscFunctionBegin;
3942552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
39431baa6e33SBarry Smith   if (maxConeSize) PetscCall(PetscSectionGetMaxDof(mesh->coneSection, maxConeSize));
39441baa6e33SBarry Smith   if (maxSupportSize) PetscCall(PetscSectionGetMaxDof(mesh->supportSection, maxSupportSize));
39453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3946552f7358SJed Brown }
3947552f7358SJed Brown 
3948d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetUp_Plex(DM dm)
3949d71ae5a4SJacob Faibussowitsch {
3950552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
39516302a7fbSVaclav Hapla   PetscInt size, maxSupportSize;
3952552f7358SJed Brown 
3953552f7358SJed Brown   PetscFunctionBegin;
3954552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
39559566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(mesh->coneSection));
39569566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(mesh->coneSection, &size));
39579566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(size, &mesh->cones));
39589566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(size, &mesh->coneOrientations));
39596302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize));
39606302a7fbSVaclav Hapla   if (maxSupportSize) {
39619566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(mesh->supportSection));
39629566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &size));
39639566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(size, &mesh->supports));
3964552f7358SJed Brown   }
39653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3966552f7358SJed Brown }
3967552f7358SJed Brown 
3968d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm)
3969d71ae5a4SJacob Faibussowitsch {
3970552f7358SJed Brown   PetscFunctionBegin;
39719566063dSJacob Faibussowitsch   if (subdm) PetscCall(DMClone(dm, subdm));
39729566063dSJacob Faibussowitsch   PetscCall(DMCreateSectionSubDM(dm, numFields, fields, is, subdm));
3973ad540459SPierre Jolivet   if (subdm) (*subdm)->useNatural = dm->useNatural;
3974736995cdSBlaise Bourdin   if (dm->useNatural && dm->sfMigration) {
397595602cf2SAlexis Marboeuf     PetscSF sfNatural;
3976f94b4a02SBlaise Bourdin 
39773dcd263cSBlaise Bourdin     (*subdm)->sfMigration = dm->sfMigration;
39789566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm->sfMigration));
397995602cf2SAlexis Marboeuf     PetscCall(DMPlexCreateGlobalToNaturalSF(*subdm, NULL, (*subdm)->sfMigration, &sfNatural));
3980c40e9495SBlaise Bourdin     (*subdm)->sfNatural = sfNatural;
3981f94b4a02SBlaise Bourdin   }
39823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3983552f7358SJed Brown }
3984552f7358SJed Brown 
3985d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSuperDM_Plex(DM dms[], PetscInt len, IS **is, DM *superdm)
3986d71ae5a4SJacob Faibussowitsch {
39873dcd263cSBlaise Bourdin   PetscInt i = 0;
39882adcc780SMatthew G. Knepley 
39892adcc780SMatthew G. Knepley   PetscFunctionBegin;
39909566063dSJacob Faibussowitsch   PetscCall(DMClone(dms[0], superdm));
39919566063dSJacob Faibussowitsch   PetscCall(DMCreateSectionSuperDM(dms, len, is, superdm));
3992c40e9495SBlaise Bourdin   (*superdm)->useNatural = PETSC_FALSE;
39933dcd263cSBlaise Bourdin   for (i = 0; i < len; i++) {
39943dcd263cSBlaise Bourdin     if (dms[i]->useNatural && dms[i]->sfMigration) {
399595602cf2SAlexis Marboeuf       PetscSF sfNatural;
39963dcd263cSBlaise Bourdin 
39973dcd263cSBlaise Bourdin       (*superdm)->sfMigration = dms[i]->sfMigration;
39989566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)dms[i]->sfMigration));
3999c40e9495SBlaise Bourdin       (*superdm)->useNatural = PETSC_TRUE;
400095602cf2SAlexis Marboeuf       PetscCall(DMPlexCreateGlobalToNaturalSF(*superdm, NULL, (*superdm)->sfMigration, &sfNatural));
4001c40e9495SBlaise Bourdin       (*superdm)->sfNatural = sfNatural;
40023dcd263cSBlaise Bourdin       break;
40033dcd263cSBlaise Bourdin     }
40043dcd263cSBlaise Bourdin   }
40053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
40062adcc780SMatthew G. Knepley }
40072adcc780SMatthew G. Knepley 
4008552f7358SJed Brown /*@
4009eaf898f9SPatrick Sanan   DMPlexSymmetrize - Create support (out-edge) information from cone (in-edge) information
4010552f7358SJed Brown 
4011a1cb98faSBarry Smith   Not Collective
4012552f7358SJed Brown 
4013552f7358SJed Brown   Input Parameter:
401460225df5SJacob Faibussowitsch . dm - The `DMPLEX`
4015552f7358SJed Brown 
4016552f7358SJed Brown   Level: beginner
4017552f7358SJed Brown 
4018a1cb98faSBarry Smith   Note:
4019a1cb98faSBarry Smith   This should be called after all calls to `DMPlexSetCone()`
4020a1cb98faSBarry Smith 
40211cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSetChart()`, `DMPlexSetConeSize()`, `DMPlexSetCone()`
4022552f7358SJed Brown @*/
4023d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSymmetrize(DM dm)
4024d71ae5a4SJacob Faibussowitsch {
4025552f7358SJed Brown   DM_Plex  *mesh = (DM_Plex *)dm->data;
4026552f7358SJed Brown   PetscInt *offsets;
4027552f7358SJed Brown   PetscInt  supportSize;
4028552f7358SJed Brown   PetscInt  pStart, pEnd, p;
4029552f7358SJed Brown 
4030552f7358SJed Brown   PetscFunctionBegin;
4031552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
403228b400f6SJacob Faibussowitsch   PetscCheck(!mesh->supports, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex");
40339566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_Symmetrize, dm, 0, 0, 0));
4034552f7358SJed Brown   /* Calculate support sizes */
40359566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
4036552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
4037552f7358SJed Brown     PetscInt dof, off, c;
4038552f7358SJed Brown 
40399566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
40409566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
404148a46eb9SPierre Jolivet     for (c = off; c < off + dof; ++c) PetscCall(PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1));
4042552f7358SJed Brown   }
40439566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(mesh->supportSection));
4044552f7358SJed Brown   /* Calculate supports */
40459566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(mesh->supportSection, &supportSize));
40469566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(supportSize, &mesh->supports));
40479566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(pEnd - pStart, &offsets));
4048552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
4049552f7358SJed Brown     PetscInt dof, off, c;
4050552f7358SJed Brown 
40519566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, p, &dof));
40529566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, p, &off));
4053552f7358SJed Brown     for (c = off; c < off + dof; ++c) {
4054552f7358SJed Brown       const PetscInt q = mesh->cones[c];
4055552f7358SJed Brown       PetscInt       offS;
4056552f7358SJed Brown 
40579566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(mesh->supportSection, q, &offS));
40580d644c17SKarl Rupp 
4059552f7358SJed Brown       mesh->supports[offS + offsets[q]] = p;
4060552f7358SJed Brown       ++offsets[q];
4061552f7358SJed Brown     }
4062552f7358SJed Brown   }
40639566063dSJacob Faibussowitsch   PetscCall(PetscFree(offsets));
40649566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_Symmetrize, dm, 0, 0, 0));
40653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4066552f7358SJed Brown }
4067552f7358SJed Brown 
4068d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateDepthStratum(DM dm, DMLabel label, PetscInt depth, PetscInt pStart, PetscInt pEnd)
4069d71ae5a4SJacob Faibussowitsch {
4070277ea44aSLisandro Dalcin   IS stratumIS;
4071277ea44aSLisandro Dalcin 
4072277ea44aSLisandro Dalcin   PetscFunctionBegin;
40733ba16761SJacob Faibussowitsch   if (pStart >= pEnd) PetscFunctionReturn(PETSC_SUCCESS);
407476bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
4075277ea44aSLisandro Dalcin     PetscInt  qStart, qEnd, numLevels, level;
4076277ea44aSLisandro Dalcin     PetscBool overlap = PETSC_FALSE;
40779566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &numLevels));
4078277ea44aSLisandro Dalcin     for (level = 0; level < numLevels; level++) {
40799566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
40809371c9d4SSatish Balay       if ((pStart >= qStart && pStart < qEnd) || (pEnd > qStart && pEnd <= qEnd)) {
40819371c9d4SSatish Balay         overlap = PETSC_TRUE;
40829371c9d4SSatish Balay         break;
40839371c9d4SSatish Balay       }
4084277ea44aSLisandro Dalcin     }
408563a3b9bcSJacob 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);
4086277ea44aSLisandro Dalcin   }
40879566063dSJacob Faibussowitsch   PetscCall(ISCreateStride(PETSC_COMM_SELF, pEnd - pStart, pStart, 1, &stratumIS));
40889566063dSJacob Faibussowitsch   PetscCall(DMLabelSetStratumIS(label, depth, stratumIS));
40899566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&stratumIS));
40903ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4091277ea44aSLisandro Dalcin }
4092277ea44aSLisandro Dalcin 
4093552f7358SJed Brown /*@
4094a4e35b19SJacob Faibussowitsch   DMPlexStratify - Computes the strata for all points in the `DMPLEX`
4095552f7358SJed Brown 
409620f4b53cSBarry Smith   Collective
4097552f7358SJed Brown 
4098552f7358SJed Brown   Input Parameter:
409960225df5SJacob Faibussowitsch . dm - The `DMPLEX`
4100552f7358SJed Brown 
4101a1cb98faSBarry Smith   Level: beginner
4102552f7358SJed Brown 
4103552f7358SJed Brown   Notes:
4104a4e35b19SJacob Faibussowitsch   The strata group all points of the same grade, and this function calculates the strata. This
4105a4e35b19SJacob Faibussowitsch   grade can be seen as the height (or depth) of the point in the DAG.
4106a4e35b19SJacob Faibussowitsch 
4107a4e35b19SJacob Faibussowitsch   The DAG for most topologies is a graded poset (https://en.wikipedia.org/wiki/Graded_poset), and
4108a4e35b19SJacob Faibussowitsch   can be illustrated by a Hasse Diagram (https://en.wikipedia.org/wiki/Hasse_diagram).
4109a1cb98faSBarry Smith   Concretely, `DMPlexStratify()` creates a new label named "depth" containing the depth in the DAG of each point. For cell-vertex
4110b1bb481bSMatthew 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
4111a1cb98faSBarry Smith   until cells have depth equal to the dimension of the mesh. The depth label can be accessed through `DMPlexGetDepthLabel()` or `DMPlexGetDepthStratum()`, or
4112a1cb98faSBarry Smith   manually via `DMGetLabel()`.  The height is defined implicitly by height = maxDimension - depth, and can be accessed
4113a1cb98faSBarry Smith   via `DMPlexGetHeightStratum()`.  For example, cells have height 0 and faces have height 1.
4114552f7358SJed Brown 
4115b1bb481bSMatthew Knepley   The depth of a point is calculated by executing a breadth-first search (BFS) on the DAG. This could produce surprising results
4116b1bb481bSMatthew Knepley   if run on a partially interpolated mesh, meaning one that had some edges and faces, but not others. For example, suppose that
4117b1bb481bSMatthew 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
4118b1bb481bSMatthew Knepley   to interpolate only that one (e0), so that
4119a1cb98faSBarry Smith .vb
4120a1cb98faSBarry Smith   cone(c0) = {e0, v2}
4121a1cb98faSBarry Smith   cone(e0) = {v0, v1}
4122a1cb98faSBarry Smith .ve
4123a1cb98faSBarry Smith   If `DMPlexStratify()` is run on this mesh, it will give depths
4124a1cb98faSBarry Smith .vb
4125a1cb98faSBarry Smith    depth 0 = {v0, v1, v2}
4126a1cb98faSBarry Smith    depth 1 = {e0, c0}
4127a1cb98faSBarry Smith .ve
4128b1bb481bSMatthew Knepley   where the triangle has been given depth 1, instead of 2, because it is reachable from vertex v2.
4129b1bb481bSMatthew Knepley 
4130a1cb98faSBarry Smith   `DMPlexStratify()` should be called after all calls to `DMPlexSymmetrize()`
4131552f7358SJed Brown 
41321cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexComputeCellTypes()`
4133552f7358SJed Brown @*/
4134d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexStratify(DM dm)
4135d71ae5a4SJacob Faibussowitsch {
4136df0420ecSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
4137aa50250dSMatthew G. Knepley   DMLabel  label;
4138552f7358SJed Brown   PetscInt pStart, pEnd, p;
4139552f7358SJed Brown   PetscInt numRoots = 0, numLeaves = 0;
4140552f7358SJed Brown 
4141552f7358SJed Brown   PetscFunctionBegin;
4142552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
41439566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_Stratify, dm, 0, 0, 0));
4144277ea44aSLisandro Dalcin 
4145277ea44aSLisandro Dalcin   /* Create depth label */
41469566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
41479566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "depth"));
41489566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
4149277ea44aSLisandro Dalcin 
4150277ea44aSLisandro Dalcin   {
4151552f7358SJed Brown     /* Initialize roots and count leaves */
4152277ea44aSLisandro Dalcin     PetscInt sMin = PETSC_MAX_INT;
4153277ea44aSLisandro Dalcin     PetscInt sMax = PETSC_MIN_INT;
4154552f7358SJed Brown     PetscInt coneSize, supportSize;
4155552f7358SJed Brown 
4156277ea44aSLisandro Dalcin     for (p = pStart; p < pEnd; ++p) {
41579566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
41589566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
4159552f7358SJed Brown       if (!coneSize && supportSize) {
4160277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
4161277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
4162552f7358SJed Brown         ++numRoots;
4163552f7358SJed Brown       } else if (!supportSize && coneSize) {
4164552f7358SJed Brown         ++numLeaves;
4165552f7358SJed Brown       } else if (!supportSize && !coneSize) {
4166552f7358SJed Brown         /* Isolated points */
4167277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
4168277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
4169552f7358SJed Brown       }
4170552f7358SJed Brown     }
41719566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateDepthStratum(dm, label, 0, sMin, sMax + 1));
4172277ea44aSLisandro Dalcin   }
4173277ea44aSLisandro Dalcin 
4174552f7358SJed Brown   if (numRoots + numLeaves == (pEnd - pStart)) {
4175277ea44aSLisandro Dalcin     PetscInt sMin = PETSC_MAX_INT;
4176277ea44aSLisandro Dalcin     PetscInt sMax = PETSC_MIN_INT;
4177552f7358SJed Brown     PetscInt coneSize, supportSize;
4178552f7358SJed Brown 
4179277ea44aSLisandro Dalcin     for (p = pStart; p < pEnd; ++p) {
41809566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
41819566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
4182552f7358SJed Brown       if (!supportSize && coneSize) {
4183277ea44aSLisandro Dalcin         sMin = PetscMin(p, sMin);
4184277ea44aSLisandro Dalcin         sMax = PetscMax(p, sMax);
4185552f7358SJed Brown       }
4186552f7358SJed Brown     }
41879566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateDepthStratum(dm, label, 1, sMin, sMax + 1));
4188552f7358SJed Brown   } else {
4189277ea44aSLisandro Dalcin     PetscInt level = 0;
4190277ea44aSLisandro Dalcin     PetscInt qStart, qEnd, q;
4191552f7358SJed Brown 
41929566063dSJacob Faibussowitsch     PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
4193277ea44aSLisandro Dalcin     while (qEnd > qStart) {
4194277ea44aSLisandro Dalcin       PetscInt sMin = PETSC_MAX_INT;
4195277ea44aSLisandro Dalcin       PetscInt sMax = PETSC_MIN_INT;
419674ef644bSMatthew G. Knepley 
4197277ea44aSLisandro Dalcin       for (q = qStart; q < qEnd; ++q) {
419874ef644bSMatthew G. Knepley         const PetscInt *support;
419974ef644bSMatthew G. Knepley         PetscInt        supportSize, s;
420074ef644bSMatthew G. Knepley 
42019566063dSJacob Faibussowitsch         PetscCall(DMPlexGetSupportSize(dm, q, &supportSize));
42029566063dSJacob Faibussowitsch         PetscCall(DMPlexGetSupport(dm, q, &support));
420374ef644bSMatthew G. Knepley         for (s = 0; s < supportSize; ++s) {
4204277ea44aSLisandro Dalcin           sMin = PetscMin(support[s], sMin);
4205277ea44aSLisandro Dalcin           sMax = PetscMax(support[s], sMax);
4206552f7358SJed Brown         }
4207552f7358SJed Brown       }
42089566063dSJacob Faibussowitsch       PetscCall(DMLabelGetNumValues(label, &level));
42099566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateDepthStratum(dm, label, level, sMin, sMax + 1));
42109566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumBounds(label, level, &qStart, &qEnd));
421174ef644bSMatthew G. Knepley     }
421274ef644bSMatthew G. Knepley   }
4213bf4602e4SToby Isaac   { /* just in case there is an empty process */
4214bf4602e4SToby Isaac     PetscInt numValues, maxValues = 0, v;
4215bf4602e4SToby Isaac 
42169566063dSJacob Faibussowitsch     PetscCall(DMLabelGetNumValues(label, &numValues));
4217712fec58SPierre Jolivet     PetscCall(MPIU_Allreduce(&numValues, &maxValues, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
421848a46eb9SPierre Jolivet     for (v = numValues; v < maxValues; v++) PetscCall(DMLabelAddStratum(label, v));
4219bf4602e4SToby Isaac   }
42209566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateGet((PetscObject)label, &mesh->depthState));
42219566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_Stratify, dm, 0, 0, 0));
42223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4223552f7358SJed Brown }
4224552f7358SJed Brown 
4225d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellType_Internal(DM dm, PetscInt p, PetscInt pdepth, DMPolytopeType *pt)
4226d71ae5a4SJacob Faibussowitsch {
4227412e9a14SMatthew G. Knepley   DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
4228412e9a14SMatthew G. Knepley   PetscInt       dim, depth, pheight, coneSize;
4229ba2698f1SMatthew G. Knepley 
4230412e9a14SMatthew G. Knepley   PetscFunctionBeginHot;
42319566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
42329566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
42339566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
4234ba2698f1SMatthew G. Knepley   pheight = depth - pdepth;
4235ba2698f1SMatthew G. Knepley   if (depth <= 1) {
4236ba2698f1SMatthew G. Knepley     switch (pdepth) {
4237d71ae5a4SJacob Faibussowitsch     case 0:
4238d71ae5a4SJacob Faibussowitsch       ct = DM_POLYTOPE_POINT;
4239d71ae5a4SJacob Faibussowitsch       break;
4240ba2698f1SMatthew G. Knepley     case 1:
4241ba2698f1SMatthew G. Knepley       switch (coneSize) {
4242d71ae5a4SJacob Faibussowitsch       case 2:
4243d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_SEGMENT;
4244d71ae5a4SJacob Faibussowitsch         break;
4245d71ae5a4SJacob Faibussowitsch       case 3:
4246d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_TRIANGLE;
4247d71ae5a4SJacob Faibussowitsch         break;
4248ba2698f1SMatthew G. Knepley       case 4:
4249ba2698f1SMatthew G. Knepley         switch (dim) {
4250d71ae5a4SJacob Faibussowitsch         case 2:
4251d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_QUADRILATERAL;
4252d71ae5a4SJacob Faibussowitsch           break;
4253d71ae5a4SJacob Faibussowitsch         case 3:
4254d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_TETRAHEDRON;
4255d71ae5a4SJacob Faibussowitsch           break;
4256d71ae5a4SJacob Faibussowitsch         default:
4257d71ae5a4SJacob Faibussowitsch           break;
4258ba2698f1SMatthew G. Knepley         }
4259ba2698f1SMatthew G. Knepley         break;
4260d71ae5a4SJacob Faibussowitsch       case 5:
4261d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_PYRAMID;
4262d71ae5a4SJacob Faibussowitsch         break;
4263d71ae5a4SJacob Faibussowitsch       case 6:
4264d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_TRI_PRISM_TENSOR;
4265d71ae5a4SJacob Faibussowitsch         break;
4266d71ae5a4SJacob Faibussowitsch       case 8:
4267d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_HEXAHEDRON;
4268d71ae5a4SJacob Faibussowitsch         break;
4269d71ae5a4SJacob Faibussowitsch       default:
4270d71ae5a4SJacob Faibussowitsch         break;
4271ba2698f1SMatthew G. Knepley       }
4272ba2698f1SMatthew G. Knepley     }
4273ba2698f1SMatthew G. Knepley   } else {
4274ba2698f1SMatthew G. Knepley     if (pdepth == 0) {
4275ba2698f1SMatthew G. Knepley       ct = DM_POLYTOPE_POINT;
4276ba2698f1SMatthew G. Knepley     } else if (pheight == 0) {
4277ba2698f1SMatthew G. Knepley       switch (dim) {
4278ba2698f1SMatthew G. Knepley       case 1:
4279ba2698f1SMatthew G. Knepley         switch (coneSize) {
4280d71ae5a4SJacob Faibussowitsch         case 2:
4281d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_SEGMENT;
4282d71ae5a4SJacob Faibussowitsch           break;
4283d71ae5a4SJacob Faibussowitsch         default:
4284d71ae5a4SJacob Faibussowitsch           break;
4285ba2698f1SMatthew G. Knepley         }
4286ba2698f1SMatthew G. Knepley         break;
4287ba2698f1SMatthew G. Knepley       case 2:
4288ba2698f1SMatthew G. Knepley         switch (coneSize) {
4289d71ae5a4SJacob Faibussowitsch         case 3:
4290d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_TRIANGLE;
4291d71ae5a4SJacob Faibussowitsch           break;
4292d71ae5a4SJacob Faibussowitsch         case 4:
4293d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_QUADRILATERAL;
4294d71ae5a4SJacob Faibussowitsch           break;
4295d71ae5a4SJacob Faibussowitsch         default:
4296d71ae5a4SJacob Faibussowitsch           break;
4297ba2698f1SMatthew G. Knepley         }
4298ba2698f1SMatthew G. Knepley         break;
4299ba2698f1SMatthew G. Knepley       case 3:
4300ba2698f1SMatthew G. Knepley         switch (coneSize) {
4301d71ae5a4SJacob Faibussowitsch         case 4:
4302d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_TETRAHEDRON;
4303d71ae5a4SJacob Faibussowitsch           break;
43049371c9d4SSatish Balay         case 5: {
4305da9060c4SMatthew G. Knepley           const PetscInt *cone;
4306da9060c4SMatthew G. Knepley           PetscInt        faceConeSize;
4307da9060c4SMatthew G. Knepley 
43089566063dSJacob Faibussowitsch           PetscCall(DMPlexGetCone(dm, p, &cone));
43099566063dSJacob Faibussowitsch           PetscCall(DMPlexGetConeSize(dm, cone[0], &faceConeSize));
4310da9060c4SMatthew G. Knepley           switch (faceConeSize) {
4311d71ae5a4SJacob Faibussowitsch           case 3:
4312d71ae5a4SJacob Faibussowitsch             ct = DM_POLYTOPE_TRI_PRISM_TENSOR;
4313d71ae5a4SJacob Faibussowitsch             break;
4314d71ae5a4SJacob Faibussowitsch           case 4:
4315d71ae5a4SJacob Faibussowitsch             ct = DM_POLYTOPE_PYRAMID;
4316d71ae5a4SJacob Faibussowitsch             break;
4317da9060c4SMatthew G. Knepley           }
43189371c9d4SSatish Balay         } break;
4319d71ae5a4SJacob Faibussowitsch         case 6:
4320d71ae5a4SJacob Faibussowitsch           ct = DM_POLYTOPE_HEXAHEDRON;
4321d71ae5a4SJacob Faibussowitsch           break;
4322d71ae5a4SJacob Faibussowitsch         default:
4323d71ae5a4SJacob Faibussowitsch           break;
4324ba2698f1SMatthew G. Knepley         }
4325ba2698f1SMatthew G. Knepley         break;
4326d71ae5a4SJacob Faibussowitsch       default:
4327d71ae5a4SJacob Faibussowitsch         break;
4328ba2698f1SMatthew G. Knepley       }
4329ba2698f1SMatthew G. Knepley     } else if (pheight > 0) {
4330ba2698f1SMatthew G. Knepley       switch (coneSize) {
4331d71ae5a4SJacob Faibussowitsch       case 2:
4332d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_SEGMENT;
4333d71ae5a4SJacob Faibussowitsch         break;
4334d71ae5a4SJacob Faibussowitsch       case 3:
4335d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_TRIANGLE;
4336d71ae5a4SJacob Faibussowitsch         break;
4337d71ae5a4SJacob Faibussowitsch       case 4:
4338d71ae5a4SJacob Faibussowitsch         ct = DM_POLYTOPE_QUADRILATERAL;
4339d71ae5a4SJacob Faibussowitsch         break;
4340d71ae5a4SJacob Faibussowitsch       default:
4341d71ae5a4SJacob Faibussowitsch         break;
4342ba2698f1SMatthew G. Knepley       }
4343ba2698f1SMatthew G. Knepley     }
4344ba2698f1SMatthew G. Knepley   }
4345412e9a14SMatthew G. Knepley   *pt = ct;
43463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4347ba2698f1SMatthew G. Knepley }
4348412e9a14SMatthew G. Knepley 
4349412e9a14SMatthew G. Knepley /*@
4350412e9a14SMatthew G. Knepley   DMPlexComputeCellTypes - Infer the polytope type of every cell using its dimension and cone size.
4351412e9a14SMatthew G. Knepley 
435220f4b53cSBarry Smith   Collective
4353412e9a14SMatthew G. Knepley 
4354412e9a14SMatthew G. Knepley   Input Parameter:
435560225df5SJacob Faibussowitsch . dm - The `DMPLEX`
4356412e9a14SMatthew G. Knepley 
4357412e9a14SMatthew G. Knepley   Level: developer
4358412e9a14SMatthew G. Knepley 
4359a1cb98faSBarry Smith   Note:
4360a1cb98faSBarry Smith   This function is normally called automatically when a cell type is requested. It creates an
4361a1cb98faSBarry Smith   internal `DMLabel` named "celltype" which can be directly accessed using `DMGetLabel()`. A user may disable
4362a1cb98faSBarry Smith   automatic creation by creating the label manually, using `DMCreateLabel`(dm, "celltype").
4363412e9a14SMatthew G. Knepley 
4364a1cb98faSBarry Smith   `DMPlexComputeCellTypes()` should be called after all calls to `DMPlexSymmetrize()` and `DMPlexStratify()`
4365a1cb98faSBarry Smith 
43661cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreate()`, `DMPlexSymmetrize()`, `DMPlexStratify()`, `DMGetLabel()`, `DMCreateLabel()`
4367412e9a14SMatthew G. Knepley @*/
4368d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeCellTypes(DM dm)
4369d71ae5a4SJacob Faibussowitsch {
4370412e9a14SMatthew G. Knepley   DM_Plex *mesh;
4371412e9a14SMatthew G. Knepley   DMLabel  ctLabel;
4372412e9a14SMatthew G. Knepley   PetscInt pStart, pEnd, p;
4373412e9a14SMatthew G. Knepley 
4374412e9a14SMatthew G. Knepley   PetscFunctionBegin;
4375412e9a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
4376412e9a14SMatthew G. Knepley   mesh = (DM_Plex *)dm->data;
43779566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "celltype"));
43789566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &ctLabel));
43799566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
438021027e53SStefano Zampini   PetscCall(PetscFree(mesh->cellTypes));
438121027e53SStefano Zampini   PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes));
4382412e9a14SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
4383327c2912SStefano Zampini     DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
4384412e9a14SMatthew G. Knepley     PetscInt       pdepth;
4385412e9a14SMatthew G. Knepley 
43869566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPointDepth(dm, p, &pdepth));
43879566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellType_Internal(dm, p, pdepth, &ct));
438863a3b9bcSJacob Faibussowitsch     PetscCheck(ct != DM_POLYTOPE_UNKNOWN, PETSC_COMM_SELF, PETSC_ERR_SUP, "Point %" PetscInt_FMT " is screwed up", p);
43899566063dSJacob Faibussowitsch     PetscCall(DMLabelSetValue(ctLabel, p, ct));
439021027e53SStefano Zampini     mesh->cellTypes[p - pStart].value_as_uint8 = ct;
4391412e9a14SMatthew G. Knepley   }
43929566063dSJacob Faibussowitsch   PetscCall(PetscObjectStateGet((PetscObject)ctLabel, &mesh->celltypeState));
43939566063dSJacob Faibussowitsch   PetscCall(PetscObjectViewFromOptions((PetscObject)ctLabel, NULL, "-dm_plex_celltypes_view"));
43943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4395ba2698f1SMatthew G. Knepley }
4396ba2698f1SMatthew G. Knepley 
4397552f7358SJed Brown /*@C
4398552f7358SJed Brown   DMPlexGetJoin - Get an array for the join of the set of points
4399552f7358SJed Brown 
4400552f7358SJed Brown   Not Collective
4401552f7358SJed Brown 
4402552f7358SJed Brown   Input Parameters:
4403a1cb98faSBarry Smith + dm        - The `DMPLEX` object
4404552f7358SJed Brown . numPoints - The number of input points for the join
4405552f7358SJed Brown - points    - The input points
4406552f7358SJed Brown 
4407552f7358SJed Brown   Output Parameters:
4408552f7358SJed Brown + numCoveredPoints - The number of points in the join
4409552f7358SJed Brown - coveredPoints    - The points in the join
4410552f7358SJed Brown 
4411552f7358SJed Brown   Level: intermediate
4412552f7358SJed Brown 
4413a1cb98faSBarry Smith   Note:
4414a1cb98faSBarry Smith   Currently, this is restricted to a single level join
4415552f7358SJed Brown 
441660225df5SJacob Faibussowitsch   Fortran Notes:
441720f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
44183813dfbdSMatthew G Knepley 
44191cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()`
4420552f7358SJed Brown @*/
4421d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4422d71ae5a4SJacob Faibussowitsch {
4423552f7358SJed Brown   DM_Plex  *mesh = (DM_Plex *)dm->data;
4424552f7358SJed Brown   PetscInt *join[2];
4425552f7358SJed Brown   PetscInt  joinSize, i = 0;
4426552f7358SJed Brown   PetscInt  dof, off, p, c, m;
44276302a7fbSVaclav Hapla   PetscInt  maxSupportSize;
4428552f7358SJed Brown 
4429552f7358SJed Brown   PetscFunctionBegin;
4430552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
44314f572ea9SToby Isaac   PetscAssertPointer(points, 3);
44324f572ea9SToby Isaac   PetscAssertPointer(numCoveredPoints, 4);
44334f572ea9SToby Isaac   PetscAssertPointer(coveredPoints, 5);
44346302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->supportSection, &maxSupportSize));
44356302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[0]));
44366302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxSupportSize, MPIU_INT, &join[1]));
4437552f7358SJed Brown   /* Copy in support of first point */
44389566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->supportSection, points[0], &dof));
44399566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->supportSection, points[0], &off));
4440ad540459SPierre Jolivet   for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = mesh->supports[off + joinSize];
4441552f7358SJed Brown   /* Check each successive support */
4442552f7358SJed Brown   for (p = 1; p < numPoints; ++p) {
4443552f7358SJed Brown     PetscInt newJoinSize = 0;
4444552f7358SJed Brown 
44459566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->supportSection, points[p], &dof));
44469566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->supportSection, points[p], &off));
4447552f7358SJed Brown     for (c = 0; c < dof; ++c) {
4448552f7358SJed Brown       const PetscInt point = mesh->supports[off + c];
4449552f7358SJed Brown 
4450552f7358SJed Brown       for (m = 0; m < joinSize; ++m) {
4451552f7358SJed Brown         if (point == join[i][m]) {
4452552f7358SJed Brown           join[1 - i][newJoinSize++] = point;
4453552f7358SJed Brown           break;
4454552f7358SJed Brown         }
4455552f7358SJed Brown       }
4456552f7358SJed Brown     }
4457552f7358SJed Brown     joinSize = newJoinSize;
4458552f7358SJed Brown     i        = 1 - i;
4459552f7358SJed Brown   }
4460552f7358SJed Brown   *numCoveredPoints = joinSize;
4461552f7358SJed Brown   *coveredPoints    = join[i];
44626302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, maxSupportSize, MPIU_INT, &join[1 - i]));
44633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4464552f7358SJed Brown }
4465552f7358SJed Brown 
4466552f7358SJed Brown /*@C
4467552f7358SJed Brown   DMPlexRestoreJoin - Restore an array for the join of the set of points
4468552f7358SJed Brown 
4469552f7358SJed Brown   Not Collective
4470552f7358SJed Brown 
4471552f7358SJed Brown   Input Parameters:
4472a1cb98faSBarry Smith + dm        - The `DMPLEX` object
4473552f7358SJed Brown . numPoints - The number of input points for the join
4474552f7358SJed Brown - points    - The input points
4475552f7358SJed Brown 
4476552f7358SJed Brown   Output Parameters:
4477552f7358SJed Brown + numCoveredPoints - The number of points in the join
4478552f7358SJed Brown - coveredPoints    - The points in the join
4479552f7358SJed Brown 
4480552f7358SJed Brown   Level: intermediate
4481552f7358SJed Brown 
448260225df5SJacob Faibussowitsch   Fortran Notes:
448320f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
4484a1cb98faSBarry Smith 
44851cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexGetFullJoin()`, `DMPlexGetMeet()`
4486552f7358SJed Brown @*/
4487d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4488d71ae5a4SJacob Faibussowitsch {
4489552f7358SJed Brown   PetscFunctionBegin;
4490552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
44914f572ea9SToby Isaac   if (points) PetscAssertPointer(points, 3);
44924f572ea9SToby Isaac   if (numCoveredPoints) PetscAssertPointer(numCoveredPoints, 4);
44934f572ea9SToby Isaac   PetscAssertPointer(coveredPoints, 5);
44949566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints));
4495d7902bd2SMatthew G. Knepley   if (numCoveredPoints) *numCoveredPoints = 0;
44963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4497552f7358SJed Brown }
4498552f7358SJed Brown 
4499552f7358SJed Brown /*@C
4500552f7358SJed Brown   DMPlexGetFullJoin - Get an array for the join of the set of points
4501552f7358SJed Brown 
4502552f7358SJed Brown   Not Collective
4503552f7358SJed Brown 
4504552f7358SJed Brown   Input Parameters:
4505a1cb98faSBarry Smith + dm        - The `DMPLEX` object
4506552f7358SJed Brown . numPoints - The number of input points for the join
4507552f7358SJed Brown - points    - The input points
4508552f7358SJed Brown 
4509552f7358SJed Brown   Output Parameters:
4510552f7358SJed Brown + numCoveredPoints - The number of points in the join
4511552f7358SJed Brown - coveredPoints    - The points in the join
4512552f7358SJed Brown 
4513552f7358SJed Brown   Level: intermediate
4514552f7358SJed Brown 
451560225df5SJacob Faibussowitsch   Fortran Notes:
451620f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
4517a1cb98faSBarry Smith 
45181cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetJoin()`, `DMPlexRestoreJoin()`, `DMPlexGetMeet()`
4519552f7358SJed Brown @*/
4520d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4521d71ae5a4SJacob Faibussowitsch {
4522552f7358SJed Brown   PetscInt *offsets, **closures;
4523552f7358SJed Brown   PetscInt *join[2];
4524552f7358SJed Brown   PetscInt  depth = 0, maxSize, joinSize = 0, i = 0;
452524c766afSToby Isaac   PetscInt  p, d, c, m, ms;
4526552f7358SJed Brown 
4527552f7358SJed Brown   PetscFunctionBegin;
4528552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
45294f572ea9SToby Isaac   PetscAssertPointer(points, 3);
45304f572ea9SToby Isaac   PetscAssertPointer(numCoveredPoints, 4);
45314f572ea9SToby Isaac   PetscAssertPointer(coveredPoints, 5);
4532552f7358SJed Brown 
45339566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
45349566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(numPoints, &closures));
45359566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets));
45366302a7fbSVaclav Hapla   PetscCall(DMPlexGetMaxSizes(dm, NULL, &ms));
453724c766afSToby Isaac   maxSize = (ms > 1) ? ((PetscPowInt(ms, depth + 1) - 1) / (ms - 1)) : depth + 1;
45389566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[0]));
45399566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &join[1]));
4540552f7358SJed Brown 
4541552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
4542552f7358SJed Brown     PetscInt closureSize;
4543552f7358SJed Brown 
45449566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]));
45450d644c17SKarl Rupp 
4546552f7358SJed Brown     offsets[p * (depth + 2) + 0] = 0;
4547552f7358SJed Brown     for (d = 0; d < depth + 1; ++d) {
4548552f7358SJed Brown       PetscInt pStart, pEnd, i;
4549552f7358SJed Brown 
45509566063dSJacob Faibussowitsch       PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
4551552f7358SJed Brown       for (i = offsets[p * (depth + 2) + d]; i < closureSize; ++i) {
4552552f7358SJed Brown         if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) {
4553552f7358SJed Brown           offsets[p * (depth + 2) + d + 1] = i;
4554552f7358SJed Brown           break;
4555552f7358SJed Brown         }
4556552f7358SJed Brown       }
4557552f7358SJed Brown       if (i == closureSize) offsets[p * (depth + 2) + d + 1] = i;
4558552f7358SJed Brown     }
455963a3b9bcSJacob 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);
4560552f7358SJed Brown   }
4561552f7358SJed Brown   for (d = 0; d < depth + 1; ++d) {
4562552f7358SJed Brown     PetscInt dof;
4563552f7358SJed Brown 
4564552f7358SJed Brown     /* Copy in support of first point */
4565552f7358SJed Brown     dof = offsets[d + 1] - offsets[d];
4566ad540459SPierre Jolivet     for (joinSize = 0; joinSize < dof; ++joinSize) join[i][joinSize] = closures[0][(offsets[d] + joinSize) * 2];
4567552f7358SJed Brown     /* Check each successive cone */
4568552f7358SJed Brown     for (p = 1; p < numPoints && joinSize; ++p) {
4569552f7358SJed Brown       PetscInt newJoinSize = 0;
4570552f7358SJed Brown 
4571552f7358SJed Brown       dof = offsets[p * (depth + 2) + d + 1] - offsets[p * (depth + 2) + d];
4572552f7358SJed Brown       for (c = 0; c < dof; ++c) {
4573552f7358SJed Brown         const PetscInt point = closures[p][(offsets[p * (depth + 2) + d] + c) * 2];
4574552f7358SJed Brown 
4575552f7358SJed Brown         for (m = 0; m < joinSize; ++m) {
4576552f7358SJed Brown           if (point == join[i][m]) {
4577552f7358SJed Brown             join[1 - i][newJoinSize++] = point;
4578552f7358SJed Brown             break;
4579552f7358SJed Brown           }
4580552f7358SJed Brown         }
4581552f7358SJed Brown       }
4582552f7358SJed Brown       joinSize = newJoinSize;
4583552f7358SJed Brown       i        = 1 - i;
4584552f7358SJed Brown     }
4585552f7358SJed Brown     if (joinSize) break;
4586552f7358SJed Brown   }
4587552f7358SJed Brown   *numCoveredPoints = joinSize;
4588552f7358SJed Brown   *coveredPoints    = join[i];
458948a46eb9SPierre Jolivet   for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]));
45909566063dSJacob Faibussowitsch   PetscCall(PetscFree(closures));
45919566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, numPoints * (depth + 2), MPIU_INT, &offsets));
45926302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, ms, MPIU_INT, &join[1 - i]));
45933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4594552f7358SJed Brown }
4595552f7358SJed Brown 
4596552f7358SJed Brown /*@C
4597552f7358SJed Brown   DMPlexGetMeet - Get an array for the meet of the set of points
4598552f7358SJed Brown 
4599552f7358SJed Brown   Not Collective
4600552f7358SJed Brown 
4601552f7358SJed Brown   Input Parameters:
4602a1cb98faSBarry Smith + dm        - The `DMPLEX` object
4603552f7358SJed Brown . numPoints - The number of input points for the meet
4604552f7358SJed Brown - points    - The input points
4605552f7358SJed Brown 
4606552f7358SJed Brown   Output Parameters:
460760225df5SJacob Faibussowitsch + numCoveringPoints - The number of points in the meet
460860225df5SJacob Faibussowitsch - coveringPoints    - The points in the meet
4609552f7358SJed Brown 
4610552f7358SJed Brown   Level: intermediate
4611552f7358SJed Brown 
4612a1cb98faSBarry Smith   Note:
4613a1cb98faSBarry Smith   Currently, this is restricted to a single level meet
4614552f7358SJed Brown 
46153813dfbdSMatthew G Knepley   Fortran Notes:
461620f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
46173813dfbdSMatthew G Knepley 
46181cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()`
4619552f7358SJed Brown @*/
4620d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints)
4621d71ae5a4SJacob Faibussowitsch {
4622552f7358SJed Brown   DM_Plex  *mesh = (DM_Plex *)dm->data;
4623552f7358SJed Brown   PetscInt *meet[2];
4624552f7358SJed Brown   PetscInt  meetSize, i = 0;
4625552f7358SJed Brown   PetscInt  dof, off, p, c, m;
46266302a7fbSVaclav Hapla   PetscInt  maxConeSize;
4627552f7358SJed Brown 
4628552f7358SJed Brown   PetscFunctionBegin;
4629552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
46304f572ea9SToby Isaac   PetscAssertPointer(points, 3);
46314f572ea9SToby Isaac   PetscAssertPointer(numCoveringPoints, 4);
46324f572ea9SToby Isaac   PetscAssertPointer(coveringPoints, 5);
46336302a7fbSVaclav Hapla   PetscCall(PetscSectionGetMaxDof(mesh->coneSection, &maxConeSize));
46346302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[0]));
46356302a7fbSVaclav Hapla   PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &meet[1]));
4636552f7358SJed Brown   /* Copy in cone of first point */
46379566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(mesh->coneSection, points[0], &dof));
46389566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(mesh->coneSection, points[0], &off));
4639ad540459SPierre Jolivet   for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = mesh->cones[off + meetSize];
4640552f7358SJed Brown   /* Check each successive cone */
4641552f7358SJed Brown   for (p = 1; p < numPoints; ++p) {
4642552f7358SJed Brown     PetscInt newMeetSize = 0;
4643552f7358SJed Brown 
46449566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(mesh->coneSection, points[p], &dof));
46459566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(mesh->coneSection, points[p], &off));
4646552f7358SJed Brown     for (c = 0; c < dof; ++c) {
4647552f7358SJed Brown       const PetscInt point = mesh->cones[off + c];
4648552f7358SJed Brown 
4649552f7358SJed Brown       for (m = 0; m < meetSize; ++m) {
4650552f7358SJed Brown         if (point == meet[i][m]) {
4651552f7358SJed Brown           meet[1 - i][newMeetSize++] = point;
4652552f7358SJed Brown           break;
4653552f7358SJed Brown         }
4654552f7358SJed Brown       }
4655552f7358SJed Brown     }
4656552f7358SJed Brown     meetSize = newMeetSize;
4657552f7358SJed Brown     i        = 1 - i;
4658552f7358SJed Brown   }
4659552f7358SJed Brown   *numCoveringPoints = meetSize;
4660552f7358SJed Brown   *coveringPoints    = meet[i];
46616302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, maxConeSize, MPIU_INT, &meet[1 - i]));
46623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4663552f7358SJed Brown }
4664552f7358SJed Brown 
4665552f7358SJed Brown /*@C
4666552f7358SJed Brown   DMPlexRestoreMeet - Restore an array for the meet of the set of points
4667552f7358SJed Brown 
4668552f7358SJed Brown   Not Collective
4669552f7358SJed Brown 
4670552f7358SJed Brown   Input Parameters:
4671a1cb98faSBarry Smith + dm        - The `DMPLEX` object
4672552f7358SJed Brown . numPoints - The number of input points for the meet
4673552f7358SJed Brown - points    - The input points
4674552f7358SJed Brown 
4675552f7358SJed Brown   Output Parameters:
4676552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4677552f7358SJed Brown - coveredPoints    - The points in the meet
4678552f7358SJed Brown 
4679552f7358SJed Brown   Level: intermediate
4680552f7358SJed Brown 
468160225df5SJacob Faibussowitsch   Fortran Notes:
468220f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
46833813dfbdSMatthew G Knepley 
46841cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexGetFullMeet()`, `DMPlexGetJoin()`
4685552f7358SJed Brown @*/
4686d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4687d71ae5a4SJacob Faibussowitsch {
4688552f7358SJed Brown   PetscFunctionBegin;
4689552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
46904f572ea9SToby Isaac   if (points) PetscAssertPointer(points, 3);
46914f572ea9SToby Isaac   if (numCoveredPoints) PetscAssertPointer(numCoveredPoints, 4);
46924f572ea9SToby Isaac   PetscAssertPointer(coveredPoints, 5);
46939566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, (void *)coveredPoints));
4694d7902bd2SMatthew G. Knepley   if (numCoveredPoints) *numCoveredPoints = 0;
46953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4696552f7358SJed Brown }
4697552f7358SJed Brown 
4698552f7358SJed Brown /*@C
4699552f7358SJed Brown   DMPlexGetFullMeet - Get an array for the meet of the set of points
4700552f7358SJed Brown 
4701552f7358SJed Brown   Not Collective
4702552f7358SJed Brown 
4703552f7358SJed Brown   Input Parameters:
4704a1cb98faSBarry Smith + dm        - The `DMPLEX` object
4705552f7358SJed Brown . numPoints - The number of input points for the meet
4706552f7358SJed Brown - points    - The input points
4707552f7358SJed Brown 
4708552f7358SJed Brown   Output Parameters:
4709552f7358SJed Brown + numCoveredPoints - The number of points in the meet
4710552f7358SJed Brown - coveredPoints    - The points in the meet
4711552f7358SJed Brown 
4712552f7358SJed Brown   Level: intermediate
4713552f7358SJed Brown 
471460225df5SJacob Faibussowitsch   Fortran Notes:
471520f4b53cSBarry Smith   The `numCoveredPoints` argument is not present in the Fortran binding since it is internal to the array.
47163813dfbdSMatthew G Knepley 
47171cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetMeet()`, `DMPlexRestoreMeet()`, `DMPlexGetJoin()`
4718552f7358SJed Brown @*/
4719d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints)
4720d71ae5a4SJacob Faibussowitsch {
4721552f7358SJed Brown   PetscInt *offsets, **closures;
4722552f7358SJed Brown   PetscInt *meet[2];
4723552f7358SJed Brown   PetscInt  height = 0, maxSize, meetSize = 0, i = 0;
472424c766afSToby Isaac   PetscInt  p, h, c, m, mc;
4725552f7358SJed Brown 
4726552f7358SJed Brown   PetscFunctionBegin;
4727552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
47284f572ea9SToby Isaac   PetscAssertPointer(points, 3);
47294f572ea9SToby Isaac   PetscAssertPointer(numCoveredPoints, 4);
47304f572ea9SToby Isaac   PetscAssertPointer(coveredPoints, 5);
4731552f7358SJed Brown 
47329566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &height));
47339566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(numPoints, &closures));
47349566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets));
47356302a7fbSVaclav Hapla   PetscCall(DMPlexGetMaxSizes(dm, &mc, NULL));
473624c766afSToby Isaac   maxSize = (mc > 1) ? ((PetscPowInt(mc, height + 1) - 1) / (mc - 1)) : height + 1;
47379566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[0]));
47389566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxSize, MPIU_INT, &meet[1]));
4739552f7358SJed Brown 
4740552f7358SJed Brown   for (p = 0; p < numPoints; ++p) {
4741552f7358SJed Brown     PetscInt closureSize;
4742552f7358SJed Brown 
47439566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]));
47440d644c17SKarl Rupp 
4745552f7358SJed Brown     offsets[p * (height + 2) + 0] = 0;
4746552f7358SJed Brown     for (h = 0; h < height + 1; ++h) {
4747552f7358SJed Brown       PetscInt pStart, pEnd, i;
4748552f7358SJed Brown 
47499566063dSJacob Faibussowitsch       PetscCall(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd));
4750552f7358SJed Brown       for (i = offsets[p * (height + 2) + h]; i < closureSize; ++i) {
4751552f7358SJed Brown         if ((pStart > closures[p][i * 2]) || (pEnd <= closures[p][i * 2])) {
4752552f7358SJed Brown           offsets[p * (height + 2) + h + 1] = i;
4753552f7358SJed Brown           break;
4754552f7358SJed Brown         }
4755552f7358SJed Brown       }
4756552f7358SJed Brown       if (i == closureSize) offsets[p * (height + 2) + h + 1] = i;
4757552f7358SJed Brown     }
475863a3b9bcSJacob 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);
4759552f7358SJed Brown   }
4760552f7358SJed Brown   for (h = 0; h < height + 1; ++h) {
4761552f7358SJed Brown     PetscInt dof;
4762552f7358SJed Brown 
4763552f7358SJed Brown     /* Copy in cone of first point */
4764552f7358SJed Brown     dof = offsets[h + 1] - offsets[h];
4765ad540459SPierre Jolivet     for (meetSize = 0; meetSize < dof; ++meetSize) meet[i][meetSize] = closures[0][(offsets[h] + meetSize) * 2];
4766552f7358SJed Brown     /* Check each successive cone */
4767552f7358SJed Brown     for (p = 1; p < numPoints && meetSize; ++p) {
4768552f7358SJed Brown       PetscInt newMeetSize = 0;
4769552f7358SJed Brown 
4770552f7358SJed Brown       dof = offsets[p * (height + 2) + h + 1] - offsets[p * (height + 2) + h];
4771552f7358SJed Brown       for (c = 0; c < dof; ++c) {
4772552f7358SJed Brown         const PetscInt point = closures[p][(offsets[p * (height + 2) + h] + c) * 2];
4773552f7358SJed Brown 
4774552f7358SJed Brown         for (m = 0; m < meetSize; ++m) {
4775552f7358SJed Brown           if (point == meet[i][m]) {
4776552f7358SJed Brown             meet[1 - i][newMeetSize++] = point;
4777552f7358SJed Brown             break;
4778552f7358SJed Brown           }
4779552f7358SJed Brown         }
4780552f7358SJed Brown       }
4781552f7358SJed Brown       meetSize = newMeetSize;
4782552f7358SJed Brown       i        = 1 - i;
4783552f7358SJed Brown     }
4784552f7358SJed Brown     if (meetSize) break;
4785552f7358SJed Brown   }
4786552f7358SJed Brown   *numCoveredPoints = meetSize;
4787552f7358SJed Brown   *coveredPoints    = meet[i];
478848a46eb9SPierre Jolivet   for (p = 0; p < numPoints; ++p) PetscCall(DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]));
47899566063dSJacob Faibussowitsch   PetscCall(PetscFree(closures));
47909566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, numPoints * (height + 2), MPIU_INT, &offsets));
47916302a7fbSVaclav Hapla   PetscCall(DMRestoreWorkArray(dm, mc, MPIU_INT, &meet[1 - i]));
47923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4793552f7358SJed Brown }
4794552f7358SJed Brown 
47954e3744c5SMatthew G. Knepley /*@C
4796a1cb98faSBarry Smith   DMPlexEqual - Determine if two `DM` have the same topology
47974e3744c5SMatthew G. Knepley 
47984e3744c5SMatthew G. Knepley   Not Collective
47994e3744c5SMatthew G. Knepley 
48004e3744c5SMatthew G. Knepley   Input Parameters:
4801a1cb98faSBarry Smith + dmA - A `DMPLEX` object
4802a1cb98faSBarry Smith - dmB - A `DMPLEX` object
48034e3744c5SMatthew G. Knepley 
48042fe279fdSBarry Smith   Output Parameter:
4805a1cb98faSBarry Smith . equal - `PETSC_TRUE` if the topologies are identical
48064e3744c5SMatthew G. Knepley 
48074e3744c5SMatthew G. Knepley   Level: intermediate
48084e3744c5SMatthew G. Knepley 
4809a1cb98faSBarry Smith   Note:
48103c7db156SBarry Smith   We are not solving graph isomorphism, so we do not permute.
48114e3744c5SMatthew G. Knepley 
48121cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()`
48134e3744c5SMatthew G. Knepley @*/
4814d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal)
4815d71ae5a4SJacob Faibussowitsch {
48164e3744c5SMatthew G. Knepley   PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p;
48174e3744c5SMatthew G. Knepley 
48184e3744c5SMatthew G. Knepley   PetscFunctionBegin;
48194e3744c5SMatthew G. Knepley   PetscValidHeaderSpecific(dmA, DM_CLASSID, 1);
48204e3744c5SMatthew G. Knepley   PetscValidHeaderSpecific(dmB, DM_CLASSID, 2);
48214f572ea9SToby Isaac   PetscAssertPointer(equal, 3);
48224e3744c5SMatthew G. Knepley 
48234e3744c5SMatthew G. Knepley   *equal = PETSC_FALSE;
48249566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmA, &depth));
48259566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmB, &depthB));
48263ba16761SJacob Faibussowitsch   if (depth != depthB) PetscFunctionReturn(PETSC_SUCCESS);
48279566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dmA, &pStart, &pEnd));
48289566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dmB, &pStartB, &pEndB));
48293ba16761SJacob Faibussowitsch   if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(PETSC_SUCCESS);
48304e3744c5SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
48314e3744c5SMatthew G. Knepley     const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB;
48324e3744c5SMatthew G. Knepley     PetscInt        coneSize, coneSizeB, c, supportSize, supportSizeB, s;
48334e3744c5SMatthew G. Knepley 
48349566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dmA, p, &coneSize));
48359566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dmA, p, &cone));
48369566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dmA, p, &ornt));
48379566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dmB, p, &coneSizeB));
48389566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dmB, p, &coneB));
48399566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeOrientation(dmB, p, &orntB));
48403ba16761SJacob Faibussowitsch     if (coneSize != coneSizeB) PetscFunctionReturn(PETSC_SUCCESS);
48414e3744c5SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
48423ba16761SJacob Faibussowitsch       if (cone[c] != coneB[c]) PetscFunctionReturn(PETSC_SUCCESS);
48433ba16761SJacob Faibussowitsch       if (ornt[c] != orntB[c]) PetscFunctionReturn(PETSC_SUCCESS);
48444e3744c5SMatthew G. Knepley     }
48459566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dmA, p, &supportSize));
48469566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dmA, p, &support));
48479566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dmB, p, &supportSizeB));
48489566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dmB, p, &supportB));
48493ba16761SJacob Faibussowitsch     if (supportSize != supportSizeB) PetscFunctionReturn(PETSC_SUCCESS);
48504e3744c5SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
48513ba16761SJacob Faibussowitsch       if (support[s] != supportB[s]) PetscFunctionReturn(PETSC_SUCCESS);
48524e3744c5SMatthew G. Knepley     }
48534e3744c5SMatthew G. Knepley   }
48544e3744c5SMatthew G. Knepley   *equal = PETSC_TRUE;
48553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48564e3744c5SMatthew G. Knepley }
48574e3744c5SMatthew G. Knepley 
48587cd05799SMatthew G. Knepley /*@C
48597cd05799SMatthew G. Knepley   DMPlexGetNumFaceVertices - Returns the number of vertices on a face
48607cd05799SMatthew G. Knepley 
48617cd05799SMatthew G. Knepley   Not Collective
48627cd05799SMatthew G. Knepley 
48637cd05799SMatthew G. Knepley   Input Parameters:
4864a1cb98faSBarry Smith + dm         - The `DMPLEX`
48657cd05799SMatthew G. Knepley . cellDim    - The cell dimension
48667cd05799SMatthew G. Knepley - numCorners - The number of vertices on a cell
48677cd05799SMatthew G. Knepley 
48682fe279fdSBarry Smith   Output Parameter:
48697cd05799SMatthew G. Knepley . numFaceVertices - The number of vertices on a face
48707cd05799SMatthew G. Knepley 
48717cd05799SMatthew G. Knepley   Level: developer
48727cd05799SMatthew G. Knepley 
4873a1cb98faSBarry Smith   Note:
48747cd05799SMatthew G. Knepley   Of course this can only work for a restricted set of symmetric shapes
48757cd05799SMatthew G. Knepley 
48761cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCone()`
48777cd05799SMatthew G. Knepley @*/
4878d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices)
4879d71ae5a4SJacob Faibussowitsch {
488082f516ccSBarry Smith   MPI_Comm comm;
4881552f7358SJed Brown 
4882552f7358SJed Brown   PetscFunctionBegin;
48839566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
48844f572ea9SToby Isaac   PetscAssertPointer(numFaceVertices, 4);
4885552f7358SJed Brown   switch (cellDim) {
4886d71ae5a4SJacob Faibussowitsch   case 0:
4887d71ae5a4SJacob Faibussowitsch     *numFaceVertices = 0;
4888d71ae5a4SJacob Faibussowitsch     break;
4889d71ae5a4SJacob Faibussowitsch   case 1:
4890d71ae5a4SJacob Faibussowitsch     *numFaceVertices = 1;
4891d71ae5a4SJacob Faibussowitsch     break;
4892552f7358SJed Brown   case 2:
4893552f7358SJed Brown     switch (numCorners) {
489419436ca2SJed Brown     case 3:                 /* triangle */
489519436ca2SJed Brown       *numFaceVertices = 2; /* Edge has 2 vertices */
4896552f7358SJed Brown       break;
489719436ca2SJed Brown     case 4:                 /* quadrilateral */
489819436ca2SJed Brown       *numFaceVertices = 2; /* Edge has 2 vertices */
4899552f7358SJed Brown       break;
490019436ca2SJed Brown     case 6:                 /* quadratic triangle, tri and quad cohesive Lagrange cells */
490119436ca2SJed Brown       *numFaceVertices = 3; /* Edge has 3 vertices */
4902552f7358SJed Brown       break;
490319436ca2SJed Brown     case 9:                 /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */
490419436ca2SJed Brown       *numFaceVertices = 3; /* Edge has 3 vertices */
4905552f7358SJed Brown       break;
4906d71ae5a4SJacob Faibussowitsch     default:
4907d71ae5a4SJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim);
4908552f7358SJed Brown     }
4909552f7358SJed Brown     break;
4910552f7358SJed Brown   case 3:
4911552f7358SJed Brown     switch (numCorners) {
491219436ca2SJed Brown     case 4:                 /* tetradehdron */
491319436ca2SJed Brown       *numFaceVertices = 3; /* Face has 3 vertices */
4914552f7358SJed Brown       break;
491519436ca2SJed Brown     case 6:                 /* tet cohesive cells */
491619436ca2SJed Brown       *numFaceVertices = 4; /* Face has 4 vertices */
4917552f7358SJed Brown       break;
491819436ca2SJed Brown     case 8:                 /* hexahedron */
491919436ca2SJed Brown       *numFaceVertices = 4; /* Face has 4 vertices */
4920552f7358SJed Brown       break;
492119436ca2SJed Brown     case 9:                 /* tet cohesive Lagrange cells */
492219436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4923552f7358SJed Brown       break;
492419436ca2SJed Brown     case 10:                /* quadratic tetrahedron */
492519436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4926552f7358SJed Brown       break;
492719436ca2SJed Brown     case 12:                /* hex cohesive Lagrange cells */
492819436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4929552f7358SJed Brown       break;
493019436ca2SJed Brown     case 18:                /* quadratic tet cohesive Lagrange cells */
493119436ca2SJed Brown       *numFaceVertices = 6; /* Face has 6 vertices */
4932552f7358SJed Brown       break;
493319436ca2SJed Brown     case 27:                /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */
493419436ca2SJed Brown       *numFaceVertices = 9; /* Face has 9 vertices */
4935552f7358SJed Brown       break;
4936d71ae5a4SJacob Faibussowitsch     default:
4937d71ae5a4SJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %" PetscInt_FMT " for dimension %" PetscInt_FMT, numCorners, cellDim);
4938552f7358SJed Brown     }
4939552f7358SJed Brown     break;
4940d71ae5a4SJacob Faibussowitsch   default:
4941d71ae5a4SJacob Faibussowitsch     SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %" PetscInt_FMT, cellDim);
4942552f7358SJed Brown   }
49433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4944552f7358SJed Brown }
4945552f7358SJed Brown 
4946552f7358SJed Brown /*@
4947a1cb98faSBarry Smith   DMPlexGetDepthLabel - Get the `DMLabel` recording the depth of each point
4948552f7358SJed Brown 
4949552f7358SJed Brown   Not Collective
4950552f7358SJed Brown 
4951aa50250dSMatthew G. Knepley   Input Parameter:
4952a1cb98faSBarry Smith . dm - The `DMPLEX` object
4953552f7358SJed Brown 
4954aa50250dSMatthew G. Knepley   Output Parameter:
4955a1cb98faSBarry Smith . depthLabel - The `DMLabel` recording point depth
4956552f7358SJed Brown 
4957552f7358SJed Brown   Level: developer
4958552f7358SJed Brown 
49591cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepth()`, `DMPlexGetHeightStratum()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`,
4960aa50250dSMatthew G. Knepley @*/
4961d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel)
4962d71ae5a4SJacob Faibussowitsch {
4963aa50250dSMatthew G. Knepley   PetscFunctionBegin;
4964aa50250dSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
49654f572ea9SToby Isaac   PetscAssertPointer(depthLabel, 2);
4966c58f1c22SToby Isaac   *depthLabel = dm->depthLabel;
49673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4968aa50250dSMatthew G. Knepley }
4969aa50250dSMatthew G. Knepley 
4970aa50250dSMatthew G. Knepley /*@
4971aa50250dSMatthew G. Knepley   DMPlexGetDepth - Get the depth of the DAG representing this mesh
4972aa50250dSMatthew G. Knepley 
4973aa50250dSMatthew G. Knepley   Not Collective
4974aa50250dSMatthew G. Knepley 
4975aa50250dSMatthew G. Knepley   Input Parameter:
4976a1cb98faSBarry Smith . dm - The `DMPLEX` object
4977aa50250dSMatthew G. Knepley 
4978aa50250dSMatthew G. Knepley   Output Parameter:
4979aa50250dSMatthew G. Knepley . depth - The number of strata (breadth first levels) in the DAG
4980aa50250dSMatthew G. Knepley 
4981aa50250dSMatthew G. Knepley   Level: developer
4982552f7358SJed Brown 
4983b1bb481bSMatthew Knepley   Notes:
4984a1cb98faSBarry Smith   This returns maximum of point depths over all points, i.e. maximum value of the label returned by `DMPlexGetDepthLabel()`.
4985a1cb98faSBarry Smith 
4986a1cb98faSBarry Smith   The point depth is described more in detail in `DMPlexGetDepthStratum()`.
4987a1cb98faSBarry Smith 
4988dc287ab2SVaclav Hapla   An empty mesh gives -1.
4989b1bb481bSMatthew Knepley 
49901cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthLabel()`, `DMPlexGetDepthStratum()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`
4991552f7358SJed Brown @*/
4992d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth)
4993d71ae5a4SJacob Faibussowitsch {
49949f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
4995aa50250dSMatthew G. Knepley   DMLabel  label;
4996aa50250dSMatthew G. Knepley   PetscInt d = 0;
4997552f7358SJed Brown 
4998552f7358SJed Brown   PetscFunctionBegin;
4999552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
50004f572ea9SToby Isaac   PetscAssertPointer(depth, 2);
50019f4ada15SMatthew G. Knepley   if (mesh->tr) {
50029f4ada15SMatthew G. Knepley     PetscCall(DMPlexTransformGetDepth(mesh->tr, depth));
50039f4ada15SMatthew G. Knepley   } else {
50049566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthLabel(dm, &label));
50059566063dSJacob Faibussowitsch     if (label) PetscCall(DMLabelGetNumValues(label, &d));
5006552f7358SJed Brown     *depth = d - 1;
50079f4ada15SMatthew G. Knepley   }
50083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5009552f7358SJed Brown }
5010552f7358SJed Brown 
5011552f7358SJed Brown /*@
501220f4b53cSBarry Smith   DMPlexGetDepthStratum - Get the bounds [`start`, `end`) for all points at a certain depth.
5013552f7358SJed Brown 
5014552f7358SJed Brown   Not Collective
5015552f7358SJed Brown 
5016552f7358SJed Brown   Input Parameters:
5017a1cb98faSBarry Smith + dm    - The `DMPLEX` object
5018570fa34dSVaclav Hapla - depth - The requested depth
5019552f7358SJed Brown 
5020552f7358SJed Brown   Output Parameters:
502120f4b53cSBarry Smith + start - The first point at this `depth`
502220f4b53cSBarry Smith - end   - One beyond the last point at this `depth`
5023552f7358SJed Brown 
5024552f7358SJed Brown   Level: developer
5025552f7358SJed Brown 
5026a1cb98faSBarry Smith   Notes:
5027a1cb98faSBarry Smith   Depth indexing is related to topological dimension.  Depth stratum 0 contains the lowest topological dimension points,
5028a1cb98faSBarry Smith   often "vertices".  If the mesh is "interpolated" (see `DMPlexInterpolate()`), then depth stratum 1 contains the next
5029a1cb98faSBarry Smith   higher dimension, e.g., "edges".
5030a1cb98faSBarry Smith 
50312827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetHeightStratum()`, `DMPlexGetCellTypeStratum()`, `DMPlexGetDepth()`, `DMPlexGetDepthLabel()`, `DMPlexGetPointDepth()`, `DMPlexSymmetrize()`, `DMPlexInterpolate()`
5032552f7358SJed Brown @*/
5033d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt depth, PetscInt *start, PetscInt *end)
5034d71ae5a4SJacob Faibussowitsch {
50359f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
5036aa50250dSMatthew G. Knepley   DMLabel  label;
503763d1a920SMatthew G. Knepley   PetscInt pStart, pEnd;
5038552f7358SJed Brown 
5039552f7358SJed Brown   PetscFunctionBegin;
5040552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
50419371c9d4SSatish Balay   if (start) {
50424f572ea9SToby Isaac     PetscAssertPointer(start, 3);
50439371c9d4SSatish Balay     *start = 0;
50449371c9d4SSatish Balay   }
50459371c9d4SSatish Balay   if (end) {
50464f572ea9SToby Isaac     PetscAssertPointer(end, 4);
50479371c9d4SSatish Balay     *end = 0;
50489371c9d4SSatish Balay   }
50499566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
50503ba16761SJacob Faibussowitsch   if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS);
5051570fa34dSVaclav Hapla   if (depth < 0) {
505263d1a920SMatthew G. Knepley     if (start) *start = pStart;
505363d1a920SMatthew G. Knepley     if (end) *end = pEnd;
50543ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
5055552f7358SJed Brown   }
50569f4ada15SMatthew G. Knepley   if (mesh->tr) {
50579f4ada15SMatthew G. Knepley     PetscCall(DMPlexTransformGetDepthStratum(mesh->tr, depth, start, end));
50589f4ada15SMatthew G. Knepley   } else {
50599566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthLabel(dm, &label));
506028b400f6SJacob Faibussowitsch     PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");
5061570fa34dSVaclav Hapla     PetscCall(DMLabelGetStratumBounds(label, depth, start, end));
50629f4ada15SMatthew G. Knepley   }
50633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5064552f7358SJed Brown }
5065552f7358SJed Brown 
5066552f7358SJed Brown /*@
506720f4b53cSBarry Smith   DMPlexGetHeightStratum - Get the bounds [`start`, `end`) for all points at a certain height.
5068552f7358SJed Brown 
5069552f7358SJed Brown   Not Collective
5070552f7358SJed Brown 
5071552f7358SJed Brown   Input Parameters:
5072a1cb98faSBarry Smith + dm     - The `DMPLEX` object
5073570fa34dSVaclav Hapla - height - The requested height
5074552f7358SJed Brown 
5075552f7358SJed Brown   Output Parameters:
507620f4b53cSBarry Smith + start - The first point at this `height`
507720f4b53cSBarry Smith - end   - One beyond the last point at this `height`
5078552f7358SJed Brown 
5079552f7358SJed Brown   Level: developer
5080552f7358SJed Brown 
5081a1cb98faSBarry Smith   Notes:
5082a1cb98faSBarry Smith   Height indexing is related to topological codimension.  Height stratum 0 contains the highest topological dimension
5083a1cb98faSBarry Smith   points, often called "cells" or "elements".  If the mesh is "interpolated" (see `DMPlexInterpolate()`), then height
5084a1cb98faSBarry Smith   stratum 1 contains the boundary of these "cells", often called "faces" or "facets".
5085a1cb98faSBarry Smith 
50862827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetDepthStratum()`, `DMPlexGetCellTypeStratum()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()`
5087552f7358SJed Brown @*/
5088d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt height, PetscInt *start, PetscInt *end)
5089d71ae5a4SJacob Faibussowitsch {
5090aa50250dSMatthew G. Knepley   DMLabel  label;
509163d1a920SMatthew G. Knepley   PetscInt depth, pStart, pEnd;
5092552f7358SJed Brown 
5093552f7358SJed Brown   PetscFunctionBegin;
5094552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
50959371c9d4SSatish Balay   if (start) {
50964f572ea9SToby Isaac     PetscAssertPointer(start, 3);
50979371c9d4SSatish Balay     *start = 0;
50989371c9d4SSatish Balay   }
50999371c9d4SSatish Balay   if (end) {
51004f572ea9SToby Isaac     PetscAssertPointer(end, 4);
51019371c9d4SSatish Balay     *end = 0;
51029371c9d4SSatish Balay   }
51039566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
51043ba16761SJacob Faibussowitsch   if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS);
5105570fa34dSVaclav Hapla   if (height < 0) {
510663d1a920SMatthew G. Knepley     if (start) *start = pStart;
510763d1a920SMatthew G. Knepley     if (end) *end = pEnd;
51083ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
5109552f7358SJed Brown   }
51109566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
511159e4dc13SStefano Zampini   if (label) PetscCall(DMLabelGetNumValues(label, &depth));
511259e4dc13SStefano Zampini   else PetscCall(DMGetDimension(dm, &depth));
511359e4dc13SStefano Zampini   PetscCheck(depth >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Depth not yet computed");
511459e4dc13SStefano Zampini   PetscCall(DMPlexGetDepthStratum(dm, depth - 1 - height, start, end));
51153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5116552f7358SJed Brown }
5117552f7358SJed Brown 
5118ba2698f1SMatthew G. Knepley /*@
511920f4b53cSBarry Smith   DMPlexGetPointDepth - Get the `depth` of a given point
5120ba2698f1SMatthew G. Knepley 
5121ba2698f1SMatthew G. Knepley   Not Collective
5122ba2698f1SMatthew G. Knepley 
5123d8d19677SJose E. Roman   Input Parameters:
5124a1cb98faSBarry Smith + dm    - The `DMPLEX` object
5125ba2698f1SMatthew G. Knepley - point - The point
5126ba2698f1SMatthew G. Knepley 
5127ba2698f1SMatthew G. Knepley   Output Parameter:
512820f4b53cSBarry Smith . depth - The depth of the `point`
5129ba2698f1SMatthew G. Knepley 
5130ba2698f1SMatthew G. Knepley   Level: intermediate
5131ba2698f1SMatthew G. Knepley 
51321cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointHeight()`
5133ba2698f1SMatthew G. Knepley @*/
5134d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDepth(DM dm, PetscInt point, PetscInt *depth)
5135d71ae5a4SJacob Faibussowitsch {
5136ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
5137ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
51384f572ea9SToby Isaac   PetscAssertPointer(depth, 3);
51399566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(dm->depthLabel, point, depth));
51403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5141ba2698f1SMatthew G. Knepley }
5142ba2698f1SMatthew G. Knepley 
5143ba2698f1SMatthew G. Knepley /*@
514420f4b53cSBarry Smith   DMPlexGetPointHeight - Get the `height` of a given point
51450c0a32dcSVaclav Hapla 
51460c0a32dcSVaclav Hapla   Not Collective
51470c0a32dcSVaclav Hapla 
5148d8d19677SJose E. Roman   Input Parameters:
5149a1cb98faSBarry Smith + dm    - The `DMPLEX` object
51500c0a32dcSVaclav Hapla - point - The point
51510c0a32dcSVaclav Hapla 
51520c0a32dcSVaclav Hapla   Output Parameter:
515320f4b53cSBarry Smith . height - The height of the `point`
51540c0a32dcSVaclav Hapla 
51550c0a32dcSVaclav Hapla   Level: intermediate
51560c0a32dcSVaclav Hapla 
51571cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexGetPointDepth()`
51580c0a32dcSVaclav Hapla @*/
5159d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointHeight(DM dm, PetscInt point, PetscInt *height)
5160d71ae5a4SJacob Faibussowitsch {
51610c0a32dcSVaclav Hapla   PetscInt n, pDepth;
51620c0a32dcSVaclav Hapla 
51630c0a32dcSVaclav Hapla   PetscFunctionBegin;
51640c0a32dcSVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
51654f572ea9SToby Isaac   PetscAssertPointer(height, 3);
51669566063dSJacob Faibussowitsch   PetscCall(DMLabelGetNumValues(dm->depthLabel, &n));
51679566063dSJacob Faibussowitsch   PetscCall(DMLabelGetValue(dm->depthLabel, point, &pDepth));
51680c0a32dcSVaclav Hapla   *height = n - 1 - pDepth; /* DAG depth is n-1 */
51693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
51700c0a32dcSVaclav Hapla }
51710c0a32dcSVaclav Hapla 
51720c0a32dcSVaclav Hapla /*@
5173a1cb98faSBarry Smith   DMPlexGetCellTypeLabel - Get the `DMLabel` recording the polytope type of each cell
5174ba2698f1SMatthew G. Knepley 
5175ba2698f1SMatthew G. Knepley   Not Collective
5176ba2698f1SMatthew G. Knepley 
5177ba2698f1SMatthew G. Knepley   Input Parameter:
5178a1cb98faSBarry Smith . dm - The `DMPLEX` object
5179ba2698f1SMatthew G. Knepley 
5180ba2698f1SMatthew G. Knepley   Output Parameter:
5181a1cb98faSBarry Smith . celltypeLabel - The `DMLabel` recording cell polytope type
5182412e9a14SMatthew G. Knepley 
5183ba2698f1SMatthew G. Knepley   Level: developer
5184ba2698f1SMatthew G. Knepley 
5185a1cb98faSBarry Smith   Note:
5186a1cb98faSBarry Smith   This function will trigger automatica computation of cell types. This can be disabled by calling
5187a1cb98faSBarry Smith   `DMCreateLabel`(dm, "celltype") beforehand.
5188a1cb98faSBarry Smith 
51891cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellType()`, `DMPlexGetDepthLabel()`, `DMCreateLabel()`
5190ba2698f1SMatthew G. Knepley @*/
5191d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellTypeLabel(DM dm, DMLabel *celltypeLabel)
5192d71ae5a4SJacob Faibussowitsch {
5193ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
5194ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
51954f572ea9SToby Isaac   PetscAssertPointer(celltypeLabel, 2);
51969566063dSJacob Faibussowitsch   if (!dm->celltypeLabel) PetscCall(DMPlexComputeCellTypes(dm));
5197ba2698f1SMatthew G. Knepley   *celltypeLabel = dm->celltypeLabel;
51983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5199ba2698f1SMatthew G. Knepley }
5200ba2698f1SMatthew G. Knepley 
5201ba2698f1SMatthew G. Knepley /*@
5202ba2698f1SMatthew G. Knepley   DMPlexGetCellType - Get the polytope type of a given cell
5203ba2698f1SMatthew G. Knepley 
5204ba2698f1SMatthew G. Knepley   Not Collective
5205ba2698f1SMatthew G. Knepley 
5206d8d19677SJose E. Roman   Input Parameters:
5207a1cb98faSBarry Smith + dm   - The `DMPLEX` object
5208ba2698f1SMatthew G. Knepley - cell - The cell
5209ba2698f1SMatthew G. Knepley 
5210ba2698f1SMatthew G. Knepley   Output Parameter:
5211ba2698f1SMatthew G. Knepley . celltype - The polytope type of the cell
5212ba2698f1SMatthew G. Knepley 
5213ba2698f1SMatthew G. Knepley   Level: intermediate
5214ba2698f1SMatthew G. Knepley 
52151cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPolytopeType`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`
5216ba2698f1SMatthew G. Knepley @*/
5217d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellType(DM dm, PetscInt cell, DMPolytopeType *celltype)
5218d71ae5a4SJacob Faibussowitsch {
52199f4ada15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
5220ba2698f1SMatthew G. Knepley   DMLabel  label;
5221ba2698f1SMatthew G. Knepley   PetscInt ct;
5222ba2698f1SMatthew G. Knepley 
5223ba2698f1SMatthew G. Knepley   PetscFunctionBegin;
5224ba2698f1SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
52254f572ea9SToby Isaac   PetscAssertPointer(celltype, 3);
52269f4ada15SMatthew G. Knepley   if (mesh->tr) {
52279f4ada15SMatthew G. Knepley     PetscCall(DMPlexTransformGetCellType(mesh->tr, cell, celltype));
52289f4ada15SMatthew G. Knepley   } else {
522921027e53SStefano Zampini     PetscInt pStart, pEnd;
523021027e53SStefano Zampini 
523121027e53SStefano Zampini     PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, NULL));
523221027e53SStefano Zampini     if (!mesh->cellTypes) { /* XXX remove? optimize? */
523321027e53SStefano Zampini       PetscCall(PetscSectionGetChart(mesh->coneSection, NULL, &pEnd));
523421027e53SStefano Zampini       PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes));
523521027e53SStefano Zampini       PetscCall(DMPlexGetCellTypeLabel(dm, &label));
523621027e53SStefano Zampini       for (PetscInt p = pStart; p < pEnd; p++) {
523721027e53SStefano Zampini         PetscCall(DMLabelGetValue(label, p, &ct));
523821027e53SStefano Zampini         mesh->cellTypes[p - pStart].value_as_uint8 = (DMPolytopeType)ct;
523921027e53SStefano Zampini       }
524021027e53SStefano Zampini     }
524121027e53SStefano Zampini     *celltype = (DMPolytopeType)mesh->cellTypes[cell - pStart].value_as_uint8;
524221027e53SStefano Zampini     if (PetscDefined(USE_DEBUG)) {
52439566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellTypeLabel(dm, &label));
52449566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(label, cell, &ct));
524563a3b9bcSJacob Faibussowitsch       PetscCheck(ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell %" PetscInt_FMT " has not been assigned a cell type", cell);
5246936381afSPierre Jolivet       PetscCheck(ct == (PetscInt)*celltype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid cellType for %" PetscInt_FMT ": %d != %" PetscInt_FMT, cell, (int)*celltype, ct);
524721027e53SStefano Zampini     }
52489f4ada15SMatthew G. Knepley   }
52493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5250ba2698f1SMatthew G. Knepley }
5251ba2698f1SMatthew G. Knepley 
5252412e9a14SMatthew G. Knepley /*@
5253412e9a14SMatthew G. Knepley   DMPlexSetCellType - Set the polytope type of a given cell
5254412e9a14SMatthew G. Knepley 
5255412e9a14SMatthew G. Knepley   Not Collective
5256412e9a14SMatthew G. Knepley 
5257412e9a14SMatthew G. Knepley   Input Parameters:
5258a1cb98faSBarry Smith + dm       - The `DMPLEX` object
5259412e9a14SMatthew G. Knepley . cell     - The cell
5260412e9a14SMatthew G. Knepley - celltype - The polytope type of the cell
5261412e9a14SMatthew G. Knepley 
5262a1cb98faSBarry Smith   Level: advanced
5263a1cb98faSBarry Smith 
5264a1cb98faSBarry Smith   Note:
5265a1cb98faSBarry Smith   By default, cell types will be automatically computed using `DMPlexComputeCellTypes()` before this function
5266412e9a14SMatthew G. Knepley   is executed. This function will override the computed type. However, if automatic classification will not succeed
5267412e9a14SMatthew G. Knepley   and a user wants to manually specify all types, the classification must be disabled by calling
5268db485b19SStefano Zampini   DMCreateLabel(dm, "celltype") before getting or setting any cell types.
5269412e9a14SMatthew G. Knepley 
52701cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellTypeLabel()`, `DMPlexGetDepthLabel()`, `DMPlexGetDepth()`, `DMPlexComputeCellTypes()`, `DMCreateLabel()`
5271412e9a14SMatthew G. Knepley @*/
5272d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetCellType(DM dm, PetscInt cell, DMPolytopeType celltype)
5273d71ae5a4SJacob Faibussowitsch {
527421027e53SStefano Zampini   DM_Plex *mesh = (DM_Plex *)dm->data;
5275412e9a14SMatthew G. Knepley   DMLabel  label;
527621027e53SStefano Zampini   PetscInt pStart, pEnd;
5277412e9a14SMatthew G. Knepley 
5278412e9a14SMatthew G. Knepley   PetscFunctionBegin;
5279412e9a14SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
528021027e53SStefano Zampini   PetscCall(PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd));
52819566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellTypeLabel(dm, &label));
52829566063dSJacob Faibussowitsch   PetscCall(DMLabelSetValue(label, cell, celltype));
528321027e53SStefano Zampini   if (!mesh->cellTypes) PetscCall(PetscMalloc1(pEnd - pStart, &mesh->cellTypes));
528421027e53SStefano Zampini   mesh->cellTypes[cell - pStart].value_as_uint8 = celltype;
52853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5286412e9a14SMatthew G. Knepley }
5287412e9a14SMatthew G. Knepley 
5288d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm)
5289d71ae5a4SJacob Faibussowitsch {
5290efe440bfSMatthew G. Knepley   PetscSection section, s;
5291efe440bfSMatthew G. Knepley   Mat          m;
52923e922f36SToby Isaac   PetscInt     maxHeight;
5293dd4c3f67SMatthew G. Knepley   const char  *prefix;
5294552f7358SJed Brown 
5295552f7358SJed Brown   PetscFunctionBegin;
52969566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, cdm));
5297dd4c3f67SMatthew G. Knepley   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
5298dd4c3f67SMatthew G. Knepley   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*cdm, prefix));
5299dd4c3f67SMatthew G. Knepley   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)*cdm, "cdm_"));
53009566063dSJacob Faibussowitsch   PetscCall(DMPlexGetMaxProjectionHeight(dm, &maxHeight));
53019566063dSJacob Faibussowitsch   PetscCall(DMPlexSetMaxProjectionHeight(*cdm, maxHeight));
53029566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section));
53039566063dSJacob Faibussowitsch   PetscCall(DMSetLocalSection(*cdm, section));
53049566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&section));
53059566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF, &s));
53069566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_SELF, &m));
53079566063dSJacob Faibussowitsch   PetscCall(DMSetDefaultConstraints(*cdm, s, m, NULL));
53089566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&s));
53099566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&m));
53108f4c458bSMatthew G. Knepley 
53119566063dSJacob Faibussowitsch   PetscCall(DMSetNumFields(*cdm, 1));
53129566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(*cdm));
5313dd4c3f67SMatthew G. Knepley   (*cdm)->cloneOpts = PETSC_TRUE;
5314dd4c3f67SMatthew G. Knepley   if (dm->setfromoptionscalled) PetscCall(DMSetFromOptions(*cdm));
53153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5316552f7358SJed Brown }
5317552f7358SJed Brown 
5318d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateCoordinateField_Plex(DM dm, DMField *field)
5319d71ae5a4SJacob Faibussowitsch {
53206858538eSMatthew G. Knepley   Vec coordsLocal, cellCoordsLocal;
53216858538eSMatthew G. Knepley   DM  coordsDM, cellCoordsDM;
5322f19dbd58SToby Isaac 
5323f19dbd58SToby Isaac   PetscFunctionBegin;
5324f19dbd58SToby Isaac   *field = NULL;
53259566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal));
53269566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &coordsDM));
53276858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dm, &cellCoordsLocal));
53286858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dm, &cellCoordsDM));
5329f19dbd58SToby Isaac   if (coordsLocal && coordsDM) {
53306858538eSMatthew G. Knepley     if (cellCoordsLocal && cellCoordsDM) PetscCall(DMFieldCreateDSWithDG(coordsDM, cellCoordsDM, 0, coordsLocal, cellCoordsLocal, field));
53316858538eSMatthew G. Knepley     else PetscCall(DMFieldCreateDS(coordsDM, 0, coordsLocal, field));
5332f19dbd58SToby Isaac   }
53333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5334f19dbd58SToby Isaac }
5335f19dbd58SToby Isaac 
53367cd05799SMatthew G. Knepley /*@C
53377cd05799SMatthew G. Knepley   DMPlexGetConeSection - Return a section which describes the layout of cone data
53387cd05799SMatthew G. Knepley 
53397cd05799SMatthew G. Knepley   Not Collective
53407cd05799SMatthew G. Knepley 
53412fe279fdSBarry Smith   Input Parameter:
5342a1cb98faSBarry Smith . dm - The `DMPLEX` object
53437cd05799SMatthew G. Knepley 
53447cd05799SMatthew G. Knepley   Output Parameter:
5345a1cb98faSBarry Smith . section - The `PetscSection` object
53467cd05799SMatthew G. Knepley 
53477cd05799SMatthew G. Knepley   Level: developer
53487cd05799SMatthew G. Knepley 
53491cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetSupportSection()`, `DMPlexGetCones()`, `DMPlexGetConeOrientations()`, `PetscSection`
53507cd05799SMatthew G. Knepley @*/
5351d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section)
5352d71ae5a4SJacob Faibussowitsch {
5353552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
5354552f7358SJed Brown 
5355552f7358SJed Brown   PetscFunctionBegin;
5356552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5357552f7358SJed Brown   if (section) *section = mesh->coneSection;
53583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5359552f7358SJed Brown }
5360552f7358SJed Brown 
53617cd05799SMatthew G. Knepley /*@C
53627cd05799SMatthew G. Knepley   DMPlexGetSupportSection - Return a section which describes the layout of support data
53637cd05799SMatthew G. Knepley 
53647cd05799SMatthew G. Knepley   Not Collective
53657cd05799SMatthew G. Knepley 
53662fe279fdSBarry Smith   Input Parameter:
5367a1cb98faSBarry Smith . dm - The `DMPLEX` object
53687cd05799SMatthew G. Knepley 
53697cd05799SMatthew G. Knepley   Output Parameter:
5370a1cb98faSBarry Smith . section - The `PetscSection` object
53717cd05799SMatthew G. Knepley 
53727cd05799SMatthew G. Knepley   Level: developer
53737cd05799SMatthew G. Knepley 
53741cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `PetscSection`
53757cd05799SMatthew G. Knepley @*/
5376d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section)
5377d71ae5a4SJacob Faibussowitsch {
53788cb4d582SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
53798cb4d582SMatthew G. Knepley 
53808cb4d582SMatthew G. Knepley   PetscFunctionBegin;
53818cb4d582SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
53828cb4d582SMatthew G. Knepley   if (section) *section = mesh->supportSection;
53833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
53848cb4d582SMatthew G. Knepley }
53858cb4d582SMatthew G. Knepley 
53867cd05799SMatthew G. Knepley /*@C
53877cd05799SMatthew G. Knepley   DMPlexGetCones - Return cone data
53887cd05799SMatthew G. Knepley 
53897cd05799SMatthew G. Knepley   Not Collective
53907cd05799SMatthew G. Knepley 
53912fe279fdSBarry Smith   Input Parameter:
5392a1cb98faSBarry Smith . dm - The `DMPLEX` object
53937cd05799SMatthew G. Knepley 
53947cd05799SMatthew G. Knepley   Output Parameter:
53957cd05799SMatthew G. Knepley . cones - The cone for each point
53967cd05799SMatthew G. Knepley 
53977cd05799SMatthew G. Knepley   Level: developer
53987cd05799SMatthew G. Knepley 
53991cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`
54007cd05799SMatthew G. Knepley @*/
5401d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[])
5402d71ae5a4SJacob Faibussowitsch {
5403552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
5404552f7358SJed Brown 
5405552f7358SJed Brown   PetscFunctionBegin;
5406552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5407552f7358SJed Brown   if (cones) *cones = mesh->cones;
54083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5409552f7358SJed Brown }
5410552f7358SJed Brown 
54117cd05799SMatthew G. Knepley /*@C
54127cd05799SMatthew G. Knepley   DMPlexGetConeOrientations - Return cone orientation data
54137cd05799SMatthew G. Knepley 
54147cd05799SMatthew G. Knepley   Not Collective
54157cd05799SMatthew G. Knepley 
54162fe279fdSBarry Smith   Input Parameter:
5417a1cb98faSBarry Smith . dm - The `DMPLEX` object
54187cd05799SMatthew G. Knepley 
54197cd05799SMatthew G. Knepley   Output Parameter:
5420b5a892a1SMatthew G. Knepley . coneOrientations - The array of cone orientations for all points
54217cd05799SMatthew G. Knepley 
54227cd05799SMatthew G. Knepley   Level: developer
54237cd05799SMatthew G. Knepley 
5424b5a892a1SMatthew G. Knepley   Notes:
5425a1cb98faSBarry Smith   The `PetscSection` returned by `DMPlexGetConeSection()` partitions coneOrientations into cone orientations of particular points as returned by `DMPlexGetConeOrientation()`.
5426b5a892a1SMatthew G. Knepley 
5427a1cb98faSBarry Smith   The meaning of coneOrientations values is detailed in `DMPlexGetConeOrientation()`.
5428b5a892a1SMatthew G. Knepley 
54291cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetConeSection()`, `DMPlexGetConeOrientation()`, `PetscSection`
54307cd05799SMatthew G. Knepley @*/
5431d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[])
5432d71ae5a4SJacob Faibussowitsch {
5433552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
5434552f7358SJed Brown 
5435552f7358SJed Brown   PetscFunctionBegin;
5436552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
5437552f7358SJed Brown   if (coneOrientations) *coneOrientations = mesh->coneOrientations;
54383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5439552f7358SJed Brown }
5440552f7358SJed Brown 
5441552f7358SJed Brown /******************************** FEM Support **********************************/
5442552f7358SJed Brown 
54439e8305c2SJed Brown /*
54449e8305c2SJed Brown  Returns number of components and tensor degree for the field.  For interpolated meshes, line should be a point
54459e8305c2SJed Brown  representing a line in the section.
54469e8305c2SJed Brown */
5447d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSectionFieldGetTensorDegree_Private(PetscSection section, PetscInt field, PetscInt line, PetscBool vertexchart, PetscInt *Nc, PetscInt *k)
5448d71ae5a4SJacob Faibussowitsch {
54499e8305c2SJed Brown   PetscFunctionBeginHot;
54509566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldComponents(section, field, Nc));
5451a433471fSStefano Zampini   if (line < 0) {
5452a433471fSStefano Zampini     *k  = 0;
5453a433471fSStefano Zampini     *Nc = 0;
5454a433471fSStefano Zampini   } else if (vertexchart) { /* If we only have a vertex chart, we must have degree k=1 */
54559e8305c2SJed Brown     *k = 1;
54569e8305c2SJed Brown   } else { /* Assume the full interpolated mesh is in the chart; lines in particular */
54579e8305c2SJed Brown     /* An order k SEM disc has k-1 dofs on an edge */
54589566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, line, field, k));
54599e8305c2SJed Brown     *k = *k / *Nc + 1;
54609e8305c2SJed Brown   }
54613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
54629e8305c2SJed Brown }
54639e8305c2SJed Brown 
5464a4355906SMatthew Knepley /*@
5465bc1eb3faSJed Brown 
5466bc1eb3faSJed Brown   DMPlexSetClosurePermutationTensor - Create a permutation from the default (BFS) point ordering in the closure, to a
5467bc1eb3faSJed Brown   lexicographic ordering over the tensor product cell (i.e., line, quad, hex, etc.), and set this permutation in the
546820f4b53cSBarry Smith   section provided (or the section of the `DM`).
5469a4355906SMatthew Knepley 
5470a4355906SMatthew Knepley   Input Parameters:
547120f4b53cSBarry Smith + dm      - The `DM`
547220f4b53cSBarry Smith . point   - Either a cell (highest dim point) or an edge (dim 1 point), or `PETSC_DETERMINE`
547320f4b53cSBarry Smith - section - The `PetscSection` to reorder, or `NULL` for the default section
5474a4355906SMatthew Knepley 
5475bc1eb3faSJed Brown   Example:
5476bc1eb3faSJed Brown   A typical interpolated single-quad mesh might order points as
5477bc1eb3faSJed Brown .vb
5478bc1eb3faSJed Brown   [c0, v1, v2, v3, v4, e5, e6, e7, e8]
5479bc1eb3faSJed Brown 
5480bc1eb3faSJed Brown   v4 -- e6 -- v3
5481bc1eb3faSJed Brown   |           |
5482bc1eb3faSJed Brown   e7    c0    e8
5483bc1eb3faSJed Brown   |           |
5484bc1eb3faSJed Brown   v1 -- e5 -- v2
5485bc1eb3faSJed Brown .ve
5486bc1eb3faSJed Brown 
5487bc1eb3faSJed Brown   (There is no significance to the ordering described here.)  The default section for a Q3 quad might typically assign
5488bc1eb3faSJed Brown   dofs in the order of points, e.g.,
5489bc1eb3faSJed Brown .vb
5490bc1eb3faSJed Brown     c0 -> [0,1,2,3]
5491bc1eb3faSJed Brown     v1 -> [4]
5492bc1eb3faSJed Brown     ...
5493bc1eb3faSJed Brown     e5 -> [8, 9]
5494bc1eb3faSJed Brown .ve
5495bc1eb3faSJed Brown 
5496bc1eb3faSJed Brown   which corresponds to the dofs
5497bc1eb3faSJed Brown .vb
5498bc1eb3faSJed Brown     6   10  11  7
5499bc1eb3faSJed Brown     13  2   3   15
5500bc1eb3faSJed Brown     12  0   1   14
5501bc1eb3faSJed Brown     4   8   9   5
5502bc1eb3faSJed Brown .ve
5503bc1eb3faSJed Brown 
5504bc1eb3faSJed Brown   The closure in BFS ordering works through height strata (cells, edges, vertices) to produce the ordering
5505bc1eb3faSJed Brown .vb
5506bc1eb3faSJed Brown   0 1 2 3 8 9 14 15 11 10 13 12 4 5 7 6
5507bc1eb3faSJed Brown .ve
5508bc1eb3faSJed Brown 
5509bc1eb3faSJed Brown   After calling DMPlexSetClosurePermutationTensor(), the closure will be ordered lexicographically,
5510bc1eb3faSJed Brown .vb
5511bc1eb3faSJed Brown    4 8 9 5 12 0 1 14 13 2 3 15 6 10 11 7
5512bc1eb3faSJed Brown .ve
5513bc1eb3faSJed Brown 
5514a4355906SMatthew Knepley   Level: developer
5515a4355906SMatthew Knepley 
5516da9ac489SAlbert Cowie   Notes:
5517a1cb98faSBarry Smith   The point is used to determine the number of dofs/field on an edge. For SEM, this is related to the polynomial
5518a1cb98faSBarry Smith   degree of the basis.
5519a1cb98faSBarry Smith 
5520da9ac489SAlbert Cowie   This is required to run with libCEED.
5521da9ac489SAlbert Cowie 
55221cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetLocalSection()`, `PetscSectionSetClosurePermutation()`, `DMSetGlobalSection()`
5523a4355906SMatthew Knepley @*/
5524d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetClosurePermutationTensor(DM dm, PetscInt point, PetscSection section)
5525d71ae5a4SJacob Faibussowitsch {
55267391a63aSMatthew G. Knepley   DMLabel   label;
5527bb197d40SJed Brown   PetscInt  dim, depth = -1, eStart = -1, Nf;
55289e8305c2SJed Brown   PetscBool vertexchart;
55293194fc30SMatthew G. Knepley 
55303194fc30SMatthew G. Knepley   PetscFunctionBegin;
55319566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
55323ba16761SJacob Faibussowitsch   if (dim < 1) PetscFunctionReturn(PETSC_SUCCESS);
5533a433471fSStefano Zampini   if (point < 0) {
5534a433471fSStefano Zampini     PetscInt sStart, sEnd;
5535a433471fSStefano Zampini 
55369566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 1, &sStart, &sEnd));
5537a433471fSStefano Zampini     point = sEnd - sStart ? sStart : point;
5538a433471fSStefano Zampini   }
55399566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &label));
55409566063dSJacob Faibussowitsch   if (point >= 0) PetscCall(DMLabelGetValue(label, point, &depth));
55419566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
55429371c9d4SSatish Balay   if (depth == 1) {
55439371c9d4SSatish Balay     eStart = point;
55449371c9d4SSatish Balay   } else if (depth == dim) {
55457391a63aSMatthew G. Knepley     const PetscInt *cone;
55467391a63aSMatthew G. Knepley 
55479566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, point, &cone));
5548d4e6627bSStefano Zampini     if (dim == 2) eStart = cone[0];
5549d4e6627bSStefano Zampini     else if (dim == 3) {
5550d4e6627bSStefano Zampini       const PetscInt *cone2;
55519566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, cone[0], &cone2));
5552d4e6627bSStefano Zampini       eStart = cone2[0];
555363a3b9bcSJacob 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);
555463a3b9bcSJacob 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);
55559e8305c2SJed Brown   { /* Determine whether the chart covers all points or just vertices. */
55569e8305c2SJed Brown     PetscInt pStart, pEnd, cStart, cEnd;
55579566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 0, &pStart, &pEnd));
55589566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(section, &cStart, &cEnd));
5559796d0a68SJed Brown     if (pStart == cStart && pEnd == cEnd) vertexchart = PETSC_TRUE;      /* Only vertices are in the chart */
5560796d0a68SJed Brown     else if (cStart <= point && point < cEnd) vertexchart = PETSC_FALSE; /* Some interpolated points exist in the chart */
5561796d0a68SJed Brown     else vertexchart = PETSC_TRUE;                                       /* Some interpolated points are not in chart; assume dofs only at cells and vertices */
55629e8305c2SJed Brown   }
55639566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &Nf));
5564bb197d40SJed Brown   for (PetscInt d = 1; d <= dim; d++) {
5565bb197d40SJed Brown     PetscInt  k, f, Nc, c, i, j, size = 0, offset = 0, foffset = 0;
5566bb197d40SJed Brown     PetscInt *perm;
5567bb197d40SJed Brown 
55683194fc30SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
55699566063dSJacob Faibussowitsch       PetscCall(PetscSectionFieldGetTensorDegree_Private(section, f, eStart, vertexchart, &Nc, &k));
5570bb197d40SJed Brown       size += PetscPowInt(k + 1, d) * Nc;
55713194fc30SMatthew G. Knepley     }
55729566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(size, &perm));
55733194fc30SMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
5574bb197d40SJed Brown       switch (d) {
5575babf31e0SJed Brown       case 1:
55769566063dSJacob Faibussowitsch         PetscCall(PetscSectionFieldGetTensorDegree_Private(section, f, eStart, vertexchart, &Nc, &k));
5577babf31e0SJed Brown         /*
5578babf31e0SJed Brown          Original ordering is [ edge of length k-1; vtx0; vtx1 ]
5579babf31e0SJed Brown          We want              [ vtx0; edge of length k-1; vtx1 ]
5580babf31e0SJed Brown          */
5581babf31e0SJed Brown         for (c = 0; c < Nc; c++, offset++) perm[offset] = (k - 1) * Nc + c + foffset;
55829371c9d4SSatish Balay         for (i = 0; i < k - 1; i++)
55839371c9d4SSatish Balay           for (c = 0; c < Nc; c++, offset++) perm[offset] = i * Nc + c + foffset;
5584babf31e0SJed Brown         for (c = 0; c < Nc; c++, offset++) perm[offset] = k * Nc + c + foffset;
5585babf31e0SJed Brown         foffset = offset;
5586babf31e0SJed Brown         break;
558789eabcffSMatthew G. Knepley       case 2:
55883194fc30SMatthew 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} */
55899566063dSJacob Faibussowitsch         PetscCall(PetscSectionFieldGetTensorDegree_Private(section, f, eStart, vertexchart, &Nc, &k));
55903194fc30SMatthew G. Knepley         /* The SEM order is
55913194fc30SMatthew G. Knepley 
55923194fc30SMatthew G. Knepley          v_lb, {e_b}, v_rb,
559389eabcffSMatthew G. Knepley          e^{(k-1)-i}_l, {f^{i*(k-1)}}, e^i_r,
55943194fc30SMatthew G. Knepley          v_lt, reverse {e_t}, v_rt
55953194fc30SMatthew G. Knepley          */
55963194fc30SMatthew G. Knepley         {
55973194fc30SMatthew G. Knepley           const PetscInt of   = 0;
55983194fc30SMatthew G. Knepley           const PetscInt oeb  = of + PetscSqr(k - 1);
55993194fc30SMatthew G. Knepley           const PetscInt oer  = oeb + (k - 1);
56003194fc30SMatthew G. Knepley           const PetscInt oet  = oer + (k - 1);
56013194fc30SMatthew G. Knepley           const PetscInt oel  = oet + (k - 1);
56023194fc30SMatthew G. Knepley           const PetscInt ovlb = oel + (k - 1);
56033194fc30SMatthew G. Knepley           const PetscInt ovrb = ovlb + 1;
56043194fc30SMatthew G. Knepley           const PetscInt ovrt = ovrb + 1;
56053194fc30SMatthew G. Knepley           const PetscInt ovlt = ovrt + 1;
56063194fc30SMatthew G. Knepley           PetscInt       o;
56073194fc30SMatthew G. Knepley 
56083194fc30SMatthew G. Knepley           /* bottom */
56093194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlb * Nc + c + foffset;
56109371c9d4SSatish Balay           for (o = oeb; o < oer; ++o)
56119371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
56123194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrb * Nc + c + foffset;
56133194fc30SMatthew G. Knepley           /* middle */
56143194fc30SMatthew G. Knepley           for (i = 0; i < k - 1; ++i) {
56153194fc30SMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oel + (k - 2) - i) * Nc + c + foffset;
56169371c9d4SSatish Balay             for (o = of + (k - 1) * i; o < of + (k - 1) * (i + 1); ++o)
56179371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
56183194fc30SMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oer + i) * Nc + c + foffset;
56193194fc30SMatthew G. Knepley           }
56203194fc30SMatthew G. Knepley           /* top */
56213194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovlt * Nc + c + foffset;
56229371c9d4SSatish Balay           for (o = oel - 1; o >= oet; --o)
56239371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
56243194fc30SMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovrt * Nc + c + foffset;
56253194fc30SMatthew G. Knepley           foffset = offset;
56263194fc30SMatthew G. Knepley         }
562789eabcffSMatthew G. Knepley         break;
562889eabcffSMatthew G. Knepley       case 3:
562989eabcffSMatthew G. Knepley         /* The original hex closure is
563089eabcffSMatthew G. Knepley 
563189eabcffSMatthew G. Knepley          {c,
563289eabcffSMatthew G. Knepley          f_b, f_t, f_f, f_b, f_r, f_l,
563389eabcffSMatthew 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,
563489eabcffSMatthew G. Knepley          v_blf, v_blb, v_brb, v_brf, v_tlf, v_trf, v_trb, v_tlb}
563589eabcffSMatthew G. Knepley          */
56369566063dSJacob Faibussowitsch         PetscCall(PetscSectionFieldGetTensorDegree_Private(section, f, eStart, vertexchart, &Nc, &k));
563789eabcffSMatthew G. Knepley         /* The SEM order is
563889eabcffSMatthew G. Knepley          Bottom Slice
563989eabcffSMatthew G. Knepley          v_blf, {e^{(k-1)-n}_bf}, v_brf,
564089eabcffSMatthew G. Knepley          e^{i}_bl, f^{n*(k-1)+(k-1)-i}_b, e^{(k-1)-i}_br,
564189eabcffSMatthew G. Knepley          v_blb, {e_bb}, v_brb,
564289eabcffSMatthew G. Knepley 
564389eabcffSMatthew G. Knepley          Middle Slice (j)
564489eabcffSMatthew G. Knepley          {e^{(k-1)-j}_lf}, {f^{j*(k-1)+n}_f}, e^j_rf,
564589eabcffSMatthew G. Knepley          f^{i*(k-1)+j}_l, {c^{(j*(k-1) + i)*(k-1)+n}_t}, f^{j*(k-1)+i}_r,
564689eabcffSMatthew G. Knepley          e^j_lb, {f^{j*(k-1)+(k-1)-n}_b}, e^{(k-1)-j}_rb,
564789eabcffSMatthew G. Knepley 
564889eabcffSMatthew G. Knepley          Top Slice
564989eabcffSMatthew G. Knepley          v_tlf, {e_tf}, v_trf,
565089eabcffSMatthew G. Knepley          e^{(k-1)-i}_tl, {f^{i*(k-1)}_t}, e^{i}_tr,
565189eabcffSMatthew G. Knepley          v_tlb, {e^{(k-1)-n}_tb}, v_trb,
565289eabcffSMatthew G. Knepley          */
565389eabcffSMatthew G. Knepley         {
565489eabcffSMatthew G. Knepley           const PetscInt oc    = 0;
565589eabcffSMatthew G. Knepley           const PetscInt ofb   = oc + PetscSqr(k - 1) * (k - 1);
565689eabcffSMatthew G. Knepley           const PetscInt oft   = ofb + PetscSqr(k - 1);
565789eabcffSMatthew G. Knepley           const PetscInt off   = oft + PetscSqr(k - 1);
565889eabcffSMatthew G. Knepley           const PetscInt ofk   = off + PetscSqr(k - 1);
565989eabcffSMatthew G. Knepley           const PetscInt ofr   = ofk + PetscSqr(k - 1);
566089eabcffSMatthew G. Knepley           const PetscInt ofl   = ofr + PetscSqr(k - 1);
566189eabcffSMatthew G. Knepley           const PetscInt oebl  = ofl + PetscSqr(k - 1);
566289eabcffSMatthew G. Knepley           const PetscInt oebb  = oebl + (k - 1);
566389eabcffSMatthew G. Knepley           const PetscInt oebr  = oebb + (k - 1);
566489eabcffSMatthew G. Knepley           const PetscInt oebf  = oebr + (k - 1);
566589eabcffSMatthew G. Knepley           const PetscInt oetf  = oebf + (k - 1);
566689eabcffSMatthew G. Knepley           const PetscInt oetr  = oetf + (k - 1);
566789eabcffSMatthew G. Knepley           const PetscInt oetb  = oetr + (k - 1);
566889eabcffSMatthew G. Knepley           const PetscInt oetl  = oetb + (k - 1);
566989eabcffSMatthew G. Knepley           const PetscInt oerf  = oetl + (k - 1);
567089eabcffSMatthew G. Knepley           const PetscInt oelf  = oerf + (k - 1);
567189eabcffSMatthew G. Knepley           const PetscInt oelb  = oelf + (k - 1);
567289eabcffSMatthew G. Knepley           const PetscInt oerb  = oelb + (k - 1);
567389eabcffSMatthew G. Knepley           const PetscInt ovblf = oerb + (k - 1);
567489eabcffSMatthew G. Knepley           const PetscInt ovblb = ovblf + 1;
567589eabcffSMatthew G. Knepley           const PetscInt ovbrb = ovblb + 1;
567689eabcffSMatthew G. Knepley           const PetscInt ovbrf = ovbrb + 1;
567789eabcffSMatthew G. Knepley           const PetscInt ovtlf = ovbrf + 1;
567889eabcffSMatthew G. Knepley           const PetscInt ovtrf = ovtlf + 1;
567989eabcffSMatthew G. Knepley           const PetscInt ovtrb = ovtrf + 1;
568089eabcffSMatthew G. Knepley           const PetscInt ovtlb = ovtrb + 1;
568189eabcffSMatthew G. Knepley           PetscInt       o, n;
568289eabcffSMatthew G. Knepley 
568389eabcffSMatthew G. Knepley           /* Bottom Slice */
568489eabcffSMatthew G. Knepley           /*   bottom */
568589eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblf * Nc + c + foffset;
56869371c9d4SSatish Balay           for (o = oetf - 1; o >= oebf; --o)
56879371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
568889eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrf * Nc + c + foffset;
568989eabcffSMatthew G. Knepley           /*   middle */
569089eabcffSMatthew G. Knepley           for (i = 0; i < k - 1; ++i) {
569189eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebl + i) * Nc + c + foffset;
56929371c9d4SSatish Balay             for (n = 0; n < k - 1; ++n) {
56939371c9d4SSatish Balay               o = ofb + n * (k - 1) + i;
56949371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
56959371c9d4SSatish Balay             }
569689eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oebr + (k - 2) - i) * Nc + c + foffset;
56973194fc30SMatthew G. Knepley           }
569889eabcffSMatthew G. Knepley           /*   top */
569989eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovblb * Nc + c + foffset;
57009371c9d4SSatish Balay           for (o = oebb; o < oebr; ++o)
57019371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
570289eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovbrb * Nc + c + foffset;
570389eabcffSMatthew G. Knepley 
570489eabcffSMatthew G. Knepley           /* Middle Slice */
570589eabcffSMatthew G. Knepley           for (j = 0; j < k - 1; ++j) {
570689eabcffSMatthew G. Knepley             /*   bottom */
570789eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelf + (k - 2) - j) * Nc + c + foffset;
57089371c9d4SSatish Balay             for (o = off + j * (k - 1); o < off + (j + 1) * (k - 1); ++o)
57099371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
571089eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerf + j) * Nc + c + foffset;
571189eabcffSMatthew G. Knepley             /*   middle */
571289eabcffSMatthew G. Knepley             for (i = 0; i < k - 1; ++i) {
571389eabcffSMatthew G. Knepley               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofl + i * (k - 1) + j) * Nc + c + foffset;
57149371c9d4SSatish Balay               for (n = 0; n < k - 1; ++n)
57159371c9d4SSatish Balay                 for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oc + (j * (k - 1) + i) * (k - 1) + n) * Nc + c + foffset;
571689eabcffSMatthew G. Knepley               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (ofr + j * (k - 1) + i) * Nc + c + foffset;
571789eabcffSMatthew G. Knepley             }
571889eabcffSMatthew G. Knepley             /*   top */
571989eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oelb + j) * Nc + c + foffset;
57209371c9d4SSatish Balay             for (o = ofk + j * (k - 1) + (k - 2); o >= ofk + j * (k - 1); --o)
57219371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
572289eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oerb + (k - 2) - j) * Nc + c + foffset;
572389eabcffSMatthew G. Knepley           }
572489eabcffSMatthew G. Knepley 
572589eabcffSMatthew G. Knepley           /* Top Slice */
572689eabcffSMatthew G. Knepley           /*   bottom */
572789eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlf * Nc + c + foffset;
57289371c9d4SSatish Balay           for (o = oetf; o < oetr; ++o)
57299371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
573089eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrf * Nc + c + foffset;
573189eabcffSMatthew G. Knepley           /*   middle */
573289eabcffSMatthew G. Knepley           for (i = 0; i < k - 1; ++i) {
573389eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetl + (k - 2) - i) * Nc + c + foffset;
57349371c9d4SSatish Balay             for (n = 0; n < k - 1; ++n)
57359371c9d4SSatish Balay               for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oft + i * (k - 1) + n) * Nc + c + foffset;
573689eabcffSMatthew G. Knepley             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = (oetr + i) * Nc + c + foffset;
573789eabcffSMatthew G. Knepley           }
573889eabcffSMatthew G. Knepley           /*   top */
573989eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtlb * Nc + c + foffset;
57409371c9d4SSatish Balay           for (o = oetl - 1; o >= oetb; --o)
57419371c9d4SSatish Balay             for (c = 0; c < Nc; ++c, ++offset) perm[offset] = o * Nc + c + foffset;
574289eabcffSMatthew G. Knepley           for (c = 0; c < Nc; ++c, ++offset) perm[offset] = ovtrb * Nc + c + foffset;
574389eabcffSMatthew G. Knepley 
574489eabcffSMatthew G. Knepley           foffset = offset;
574589eabcffSMatthew G. Knepley         }
574689eabcffSMatthew G. Knepley         break;
5747d71ae5a4SJacob Faibussowitsch       default:
5748d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "No spectral ordering for dimension %" PetscInt_FMT, d);
574989eabcffSMatthew G. Knepley       }
575089eabcffSMatthew G. Knepley     }
575163a3b9bcSJacob Faibussowitsch     PetscCheck(offset == size, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Number of permutation entries %" PetscInt_FMT " != %" PetscInt_FMT, offset, size);
57523194fc30SMatthew G. Knepley     /* Check permutation */
57533194fc30SMatthew G. Knepley     {
57543194fc30SMatthew G. Knepley       PetscInt *check;
57553194fc30SMatthew G. Knepley 
57569566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(size, &check));
57571dca8a05SBarry Smith       for (i = 0; i < size; ++i) {
57581dca8a05SBarry Smith         check[i] = -1;
57591dca8a05SBarry 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]);
57601dca8a05SBarry Smith       }
57613194fc30SMatthew G. Knepley       for (i = 0; i < size; ++i) check[perm[i]] = i;
57621dca8a05SBarry Smith       for (i = 0; i < size; ++i) PetscCheck(check[i] >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing permutation index %" PetscInt_FMT, i);
57639566063dSJacob Faibussowitsch       PetscCall(PetscFree(check));
57643194fc30SMatthew G. Knepley     }
57659566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size, PETSC_OWN_POINTER, perm));
5766a05c9aa3SJed Brown     if (d == dim) { // Add permutation for localized (in case this is a coordinate DM)
5767a05c9aa3SJed Brown       PetscInt *loc_perm;
57689566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(size * 2, &loc_perm));
5769a05c9aa3SJed Brown       for (PetscInt i = 0; i < size; i++) {
5770a05c9aa3SJed Brown         loc_perm[i]        = perm[i];
5771a05c9aa3SJed Brown         loc_perm[size + i] = size + perm[i];
5772a05c9aa3SJed Brown       }
57739566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetClosurePermutation_Internal(section, (PetscObject)dm, d, size * 2, PETSC_OWN_POINTER, loc_perm));
5774a05c9aa3SJed Brown     }
5775bb197d40SJed Brown   }
57763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57773194fc30SMatthew G. Knepley }
57783194fc30SMatthew G. Knepley 
5779d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetPointDualSpaceFEM(DM dm, PetscInt point, PetscInt field, PetscDualSpace *dspace)
5780d71ae5a4SJacob Faibussowitsch {
5781e071409bSToby Isaac   PetscDS  prob;
5782e071409bSToby Isaac   PetscInt depth, Nf, h;
5783e071409bSToby Isaac   DMLabel  label;
5784e071409bSToby Isaac 
5785e071409bSToby Isaac   PetscFunctionBeginHot;
57869566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dm, &prob));
5787e071409bSToby Isaac   Nf      = prob->Nf;
5788e071409bSToby Isaac   label   = dm->depthLabel;
5789e071409bSToby Isaac   *dspace = NULL;
5790e071409bSToby Isaac   if (field < Nf) {
5791e071409bSToby Isaac     PetscObject disc = prob->disc[field];
5792e071409bSToby Isaac 
5793e071409bSToby Isaac     if (disc->classid == PETSCFE_CLASSID) {
5794e071409bSToby Isaac       PetscDualSpace dsp;
5795e071409bSToby Isaac 
57969566063dSJacob Faibussowitsch       PetscCall(PetscFEGetDualSpace((PetscFE)disc, &dsp));
57979566063dSJacob Faibussowitsch       PetscCall(DMLabelGetNumValues(label, &depth));
57989566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValue(label, point, &h));
5799e071409bSToby Isaac       h = depth - 1 - h;
5800e071409bSToby Isaac       if (h) {
58019566063dSJacob Faibussowitsch         PetscCall(PetscDualSpaceGetHeightSubspace(dsp, h, dspace));
5802e071409bSToby Isaac       } else {
5803e071409bSToby Isaac         *dspace = dsp;
5804e071409bSToby Isaac       }
5805e071409bSToby Isaac     }
5806e071409bSToby Isaac   }
58073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5808e071409bSToby Isaac }
5809e071409bSToby Isaac 
5810d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
5811d71ae5a4SJacob Faibussowitsch {
581228351e22SJed Brown   PetscScalar       *array;
581328351e22SJed Brown   const PetscScalar *vArray;
5814d9917b9dSMatthew G. Knepley   const PetscInt    *cone, *coneO;
58151a271a75SMatthew G. Knepley   PetscInt           pStart, pEnd, p, numPoints, size = 0, offset = 0;
5816552f7358SJed Brown 
58171b406b76SMatthew G. Knepley   PetscFunctionBeginHot;
58189566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
58199566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, point, &numPoints));
58209566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, point, &cone));
58219566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeOrientation(dm, point, &coneO));
58223f7cbbe7SMatthew G. Knepley   if (!values || !*values) {
58239df71ca4SMatthew G. Knepley     if ((point >= pStart) && (point < pEnd)) {
58249df71ca4SMatthew G. Knepley       PetscInt dof;
5825d9917b9dSMatthew G. Knepley 
58269566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, point, &dof));
58279df71ca4SMatthew G. Knepley       size += dof;
58289df71ca4SMatthew G. Knepley     }
58299df71ca4SMatthew G. Knepley     for (p = 0; p < numPoints; ++p) {
58309df71ca4SMatthew G. Knepley       const PetscInt cp = cone[p];
58312a3aaacfSMatthew G. Knepley       PetscInt       dof;
58325a1bb5cfSMatthew G. Knepley 
58335a1bb5cfSMatthew G. Knepley       if ((cp < pStart) || (cp >= pEnd)) continue;
58349566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, cp, &dof));
58355a1bb5cfSMatthew G. Knepley       size += dof;
58365a1bb5cfSMatthew G. Knepley     }
58373f7cbbe7SMatthew G. Knepley     if (!values) {
58383f7cbbe7SMatthew G. Knepley       if (csize) *csize = size;
58393ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
58403f7cbbe7SMatthew G. Knepley     }
58419566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, size, MPIU_SCALAR, &array));
5842982e9ed1SMatthew G. Knepley   } else {
5843982e9ed1SMatthew G. Knepley     array = *values;
5844982e9ed1SMatthew G. Knepley   }
58459df71ca4SMatthew G. Knepley   size = 0;
584628351e22SJed Brown   PetscCall(VecGetArrayRead(v, &vArray));
58479df71ca4SMatthew G. Knepley   if ((point >= pStart) && (point < pEnd)) {
58489df71ca4SMatthew G. Knepley     PetscInt           dof, off, d;
584928351e22SJed Brown     const PetscScalar *varr;
5850d9917b9dSMatthew G. Knepley 
58519566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, point, &dof));
58529566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, point, &off));
58539df71ca4SMatthew G. Knepley     varr = &vArray[off];
5854ad540459SPierre Jolivet     for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d];
58559df71ca4SMatthew G. Knepley     size += dof;
58569df71ca4SMatthew G. Knepley   }
58579df71ca4SMatthew G. Knepley   for (p = 0; p < numPoints; ++p) {
58589df71ca4SMatthew G. Knepley     const PetscInt     cp = cone[p];
58599df71ca4SMatthew G. Knepley     PetscInt           o  = coneO[p];
58605a1bb5cfSMatthew G. Knepley     PetscInt           dof, off, d;
586128351e22SJed Brown     const PetscScalar *varr;
58625a1bb5cfSMatthew G. Knepley 
586352ed52e8SMatthew G. Knepley     if ((cp < pStart) || (cp >= pEnd)) continue;
58649566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, cp, &dof));
58659566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, cp, &off));
58665a1bb5cfSMatthew G. Knepley     varr = &vArray[off];
58675a1bb5cfSMatthew G. Knepley     if (o >= 0) {
5868ad540459SPierre Jolivet       for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d];
58695a1bb5cfSMatthew G. Knepley     } else {
5870ad540459SPierre Jolivet       for (d = dof - 1; d >= 0; --d, ++offset) array[offset] = varr[d];
58715a1bb5cfSMatthew G. Knepley     }
58729df71ca4SMatthew G. Knepley     size += dof;
58735a1bb5cfSMatthew G. Knepley   }
587428351e22SJed Brown   PetscCall(VecRestoreArrayRead(v, &vArray));
58759df71ca4SMatthew G. Knepley   if (!*values) {
58765a1bb5cfSMatthew G. Knepley     if (csize) *csize = size;
58775a1bb5cfSMatthew G. Knepley     *values = array;
58789df71ca4SMatthew G. Knepley   } else {
587963a3b9bcSJacob Faibussowitsch     PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size);
58808c312ff3SMatthew G. Knepley     *csize = size;
58819df71ca4SMatthew G. Knepley   }
58823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
58835a1bb5cfSMatthew G. Knepley }
5884d9917b9dSMatthew G. Knepley 
588527f02ce8SMatthew G. Knepley /* Compress out points not in the section */
5886d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CompressPoints_Private(PetscSection section, PetscInt *numPoints, PetscInt points[])
5887d71ae5a4SJacob Faibussowitsch {
588827f02ce8SMatthew G. Knepley   const PetscInt np = *numPoints;
588927f02ce8SMatthew G. Knepley   PetscInt       pStart, pEnd, p, q;
589027f02ce8SMatthew G. Knepley 
58919566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
589227f02ce8SMatthew G. Knepley   for (p = 0, q = 0; p < np; ++p) {
589327f02ce8SMatthew G. Knepley     const PetscInt r = points[p * 2];
589427f02ce8SMatthew G. Knepley     if ((r >= pStart) && (r < pEnd)) {
589527f02ce8SMatthew G. Knepley       points[q * 2]     = r;
589627f02ce8SMatthew G. Knepley       points[q * 2 + 1] = points[p * 2 + 1];
589727f02ce8SMatthew G. Knepley       ++q;
589827f02ce8SMatthew G. Knepley     }
589927f02ce8SMatthew G. Knepley   }
590027f02ce8SMatthew G. Knepley   *numPoints = q;
59013ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
590227f02ce8SMatthew G. Knepley }
590327f02ce8SMatthew G. Knepley 
590497529cf3SJed Brown /* Compressed closure does not apply closure permutation */
590507218a29SMatthew G. Knepley PetscErrorCode DMPlexGetCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt ornt, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp)
5906d71ae5a4SJacob Faibussowitsch {
590727f02ce8SMatthew G. Knepley   const PetscInt *cla = NULL;
5908923c78e0SToby Isaac   PetscInt        np, *pts = NULL;
5909923c78e0SToby Isaac 
5910923c78e0SToby Isaac   PetscFunctionBeginHot;
59119566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureIndex(section, (PetscObject)dm, clSec, clPoints));
591207218a29SMatthew G. Knepley   if (!ornt && *clPoints) {
5913923c78e0SToby Isaac     PetscInt dof, off;
5914923c78e0SToby Isaac 
59159566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(*clSec, point, &dof));
59169566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(*clSec, point, &off));
59179566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(*clPoints, &cla));
5918923c78e0SToby Isaac     np  = dof / 2;
5919923c78e0SToby Isaac     pts = (PetscInt *)&cla[off];
592027f02ce8SMatthew G. Knepley   } else {
592107218a29SMatthew G. Knepley     PetscCall(DMPlexGetTransitiveClosure_Internal(dm, point, ornt, PETSC_TRUE, &np, &pts));
59229566063dSJacob Faibussowitsch     PetscCall(CompressPoints_Private(section, &np, pts));
5923923c78e0SToby Isaac   }
5924923c78e0SToby Isaac   *numPoints = np;
5925923c78e0SToby Isaac   *points    = pts;
5926923c78e0SToby Isaac   *clp       = cla;
59273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5928923c78e0SToby Isaac }
5929923c78e0SToby Isaac 
5930d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreCompressedClosure(DM dm, PetscSection section, PetscInt point, PetscInt *numPoints, PetscInt **points, PetscSection *clSec, IS *clPoints, const PetscInt **clp)
5931d71ae5a4SJacob Faibussowitsch {
5932923c78e0SToby Isaac   PetscFunctionBeginHot;
5933923c78e0SToby Isaac   if (!*clPoints) {
59349566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, numPoints, points));
5935923c78e0SToby Isaac   } else {
59369566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(*clPoints, clp));
5937923c78e0SToby Isaac   }
5938923c78e0SToby Isaac   *numPoints = 0;
5939923c78e0SToby Isaac   *points    = NULL;
5940923c78e0SToby Isaac   *clSec     = NULL;
5941923c78e0SToby Isaac   *clPoints  = NULL;
5942923c78e0SToby Isaac   *clp       = NULL;
59433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5944923c78e0SToby Isaac }
5945923c78e0SToby Isaac 
5946d71ae5a4SJacob 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[])
5947d71ae5a4SJacob Faibussowitsch {
59481a271a75SMatthew G. Knepley   PetscInt            offset = 0, p;
594997e99dd9SToby Isaac   const PetscInt    **perms  = NULL;
595097e99dd9SToby Isaac   const PetscScalar **flips  = NULL;
59511a271a75SMatthew G. Knepley 
59521a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
5953fe02ba77SJed Brown   *size = 0;
59549566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips));
595597e99dd9SToby Isaac   for (p = 0; p < numPoints; p++) {
595697e99dd9SToby Isaac     const PetscInt     point = points[2 * p];
595797e99dd9SToby Isaac     const PetscInt    *perm  = perms ? perms[p] : NULL;
595897e99dd9SToby Isaac     const PetscScalar *flip  = flips ? flips[p] : NULL;
59591a271a75SMatthew G. Knepley     PetscInt           dof, off, d;
59601a271a75SMatthew G. Knepley     const PetscScalar *varr;
59611a271a75SMatthew G. Knepley 
59629566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, point, &dof));
59639566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(section, point, &off));
59641a271a75SMatthew G. Knepley     varr = &vArray[off];
596597e99dd9SToby Isaac     if (clperm) {
596697e99dd9SToby Isaac       if (perm) {
596797e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset + perm[d]]] = varr[d];
59681a271a75SMatthew G. Knepley       } else {
596997e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset + d]] = varr[d];
597097e99dd9SToby Isaac       }
597197e99dd9SToby Isaac       if (flip) {
597297e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[clperm[offset + d]] *= flip[d];
597397e99dd9SToby Isaac       }
597497e99dd9SToby Isaac     } else {
597597e99dd9SToby Isaac       if (perm) {
597697e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset + perm[d]] = varr[d];
597797e99dd9SToby Isaac       } else {
597897e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset + d] = varr[d];
597997e99dd9SToby Isaac       }
598097e99dd9SToby Isaac       if (flip) {
598197e99dd9SToby Isaac         for (d = 0; d < dof; d++) array[offset + d] *= flip[d];
59821a271a75SMatthew G. Knepley       }
59831a271a75SMatthew G. Knepley     }
598497e99dd9SToby Isaac     offset += dof;
598597e99dd9SToby Isaac   }
59869566063dSJacob Faibussowitsch   PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips));
59871a271a75SMatthew G. Knepley   *size = offset;
59883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
59891a271a75SMatthew G. Knepley }
59901a271a75SMatthew G. Knepley 
5991d71ae5a4SJacob 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[])
5992d71ae5a4SJacob Faibussowitsch {
59931a271a75SMatthew G. Knepley   PetscInt offset = 0, f;
59941a271a75SMatthew G. Knepley 
59951a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
5996fe02ba77SJed Brown   *size = 0;
59971a271a75SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
599897e99dd9SToby Isaac     PetscInt            p;
599997e99dd9SToby Isaac     const PetscInt    **perms = NULL;
600097e99dd9SToby Isaac     const PetscScalar **flips = NULL;
60011a271a75SMatthew G. Knepley 
60029566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips));
600397e99dd9SToby Isaac     for (p = 0; p < numPoints; p++) {
600497e99dd9SToby Isaac       const PetscInt     point = points[2 * p];
600597e99dd9SToby Isaac       PetscInt           fdof, foff, b;
60061a271a75SMatthew G. Knepley       const PetscScalar *varr;
600797e99dd9SToby Isaac       const PetscInt    *perm = perms ? perms[p] : NULL;
600897e99dd9SToby Isaac       const PetscScalar *flip = flips ? flips[p] : NULL;
60091a271a75SMatthew G. Knepley 
60109566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
60119566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
60121a271a75SMatthew G. Knepley       varr = &vArray[foff];
601397e99dd9SToby Isaac       if (clperm) {
60149371c9d4SSatish Balay         if (perm) {
6015ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[clperm[offset + perm[b]]] = varr[b];
60161a271a75SMatthew G. Knepley         } else {
6017ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[clperm[offset + b]] = varr[b];
60189371c9d4SSatish Balay         }
60199371c9d4SSatish Balay         if (flip) {
6020ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[clperm[offset + b]] *= flip[b];
60219371c9d4SSatish Balay         }
60229371c9d4SSatish Balay       } else {
60239371c9d4SSatish Balay         if (perm) {
6024ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[offset + perm[b]] = varr[b];
60259371c9d4SSatish Balay         } else {
6026ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[offset + b] = varr[b];
60279371c9d4SSatish Balay         }
60289371c9d4SSatish Balay         if (flip) {
6029ad540459SPierre Jolivet           for (b = 0; b < fdof; b++) array[offset + b] *= flip[b];
60309371c9d4SSatish Balay         }
60311a271a75SMatthew G. Knepley       }
603297e99dd9SToby Isaac       offset += fdof;
60331a271a75SMatthew G. Knepley     }
60349566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips));
60351a271a75SMatthew G. Knepley   }
60361a271a75SMatthew G. Knepley   *size = offset;
60373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
60381a271a75SMatthew G. Knepley }
60391a271a75SMatthew G. Knepley 
604007218a29SMatthew G. Knepley PetscErrorCode DMPlexVecGetOrientedClosure_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt ornt, PetscInt *csize, PetscScalar *values[])
604107218a29SMatthew G. Knepley {
604207218a29SMatthew G. Knepley   PetscSection    clSection;
604307218a29SMatthew G. Knepley   IS              clPoints;
604407218a29SMatthew G. Knepley   PetscInt       *points = NULL;
604507218a29SMatthew G. Knepley   const PetscInt *clp, *perm;
604607218a29SMatthew G. Knepley   PetscInt        depth, numFields, numPoints, asize;
604707218a29SMatthew G. Knepley 
604807218a29SMatthew G. Knepley   PetscFunctionBeginHot;
604907218a29SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
605007218a29SMatthew G. Knepley   if (!section) PetscCall(DMGetLocalSection(dm, &section));
605107218a29SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
605207218a29SMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
605307218a29SMatthew G. Knepley   PetscCall(DMPlexGetDepth(dm, &depth));
605407218a29SMatthew G. Knepley   PetscCall(PetscSectionGetNumFields(section, &numFields));
605507218a29SMatthew G. Knepley   if (depth == 1 && numFields < 2) {
605607218a29SMatthew G. Knepley     PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values));
605707218a29SMatthew G. Knepley     PetscFunctionReturn(PETSC_SUCCESS);
605807218a29SMatthew G. Knepley   }
605907218a29SMatthew G. Knepley   /* Get points */
606007218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, ornt, &numPoints, &points, &clSection, &clPoints, &clp));
606107218a29SMatthew G. Knepley   /* Get sizes */
606207218a29SMatthew G. Knepley   asize = 0;
606307218a29SMatthew G. Knepley   for (PetscInt p = 0; p < numPoints * 2; p += 2) {
606407218a29SMatthew G. Knepley     PetscInt dof;
606507218a29SMatthew G. Knepley     PetscCall(PetscSectionGetDof(section, points[p], &dof));
606607218a29SMatthew G. Knepley     asize += dof;
606707218a29SMatthew G. Knepley   }
606807218a29SMatthew G. Knepley   if (values) {
606907218a29SMatthew G. Knepley     const PetscScalar *vArray;
607007218a29SMatthew G. Knepley     PetscInt           size;
607107218a29SMatthew G. Knepley 
607207218a29SMatthew G. Knepley     if (*values) {
607307218a29SMatthew G. Knepley       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);
607407218a29SMatthew G. Knepley     } else PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, values));
607507218a29SMatthew G. Knepley     PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, asize, &perm));
607607218a29SMatthew G. Knepley     PetscCall(VecGetArrayRead(v, &vArray));
607707218a29SMatthew G. Knepley     /* Get values */
607807218a29SMatthew G. Knepley     if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, numPoints, points, numFields, perm, vArray, &size, *values));
607907218a29SMatthew G. Knepley     else PetscCall(DMPlexVecGetClosure_Static(dm, section, numPoints, points, perm, vArray, &size, *values));
608007218a29SMatthew G. Knepley     PetscCheck(asize == size, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Section size %" PetscInt_FMT " does not match Vec closure size %" PetscInt_FMT, asize, size);
608107218a29SMatthew G. Knepley     /* Cleanup array */
608207218a29SMatthew G. Knepley     PetscCall(VecRestoreArrayRead(v, &vArray));
608307218a29SMatthew G. Knepley   }
608407218a29SMatthew G. Knepley   if (csize) *csize = asize;
608507218a29SMatthew G. Knepley   /* Cleanup points */
608607218a29SMatthew G. Knepley   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
608707218a29SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
608807218a29SMatthew G. Knepley }
608907218a29SMatthew G. Knepley 
6090552f7358SJed Brown /*@C
6091552f7358SJed Brown   DMPlexVecGetClosure - Get an array of the values on the closure of 'point'
6092552f7358SJed Brown 
6093552f7358SJed Brown   Not collective
6094552f7358SJed Brown 
6095552f7358SJed Brown   Input Parameters:
6096a1cb98faSBarry Smith + dm      - The `DM`
609720f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section
6098552f7358SJed Brown . v       - The local vector
6099a1cb98faSBarry Smith - point   - The point in the `DM`
6100552f7358SJed Brown 
61016b867d5aSJose E. Roman   Input/Output Parameters:
610220f4b53cSBarry Smith + csize  - The size of the input values array, or `NULL`; on output the number of values in the closure
610320f4b53cSBarry Smith - values - An array to use for the values, or `NULL` to have it allocated automatically;
610420f4b53cSBarry Smith            if the user provided `NULL`, it is a borrowed array and should not be freed
610522c1ee49SMatthew G. Knepley 
6106552f7358SJed Brown   Level: intermediate
6107552f7358SJed Brown 
6108a1cb98faSBarry Smith   Notes:
610920f4b53cSBarry Smith   `DMPlexVecGetClosure()`/`DMPlexVecRestoreClosure()` only allocates the values array if it set to `NULL` in the
6110a1cb98faSBarry Smith   calling function. This is because `DMPlexVecGetClosure()` is typically called in the inner loop of a `Vec` or `Mat`
6111a1cb98faSBarry Smith   assembly function, and a user may already have allocated storage for this operation.
6112a1cb98faSBarry Smith 
6113a1cb98faSBarry Smith   A typical use could be
6114a1cb98faSBarry Smith .vb
6115a1cb98faSBarry Smith    values = NULL;
6116a1cb98faSBarry Smith    PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values));
6117a1cb98faSBarry Smith    for (cl = 0; cl < clSize; ++cl) {
6118a1cb98faSBarry Smith      <Compute on closure>
6119a1cb98faSBarry Smith    }
6120a1cb98faSBarry Smith    PetscCall(DMPlexVecRestoreClosure(dm, NULL, v, p, &clSize, &values));
6121a1cb98faSBarry Smith .ve
6122a1cb98faSBarry Smith   or
6123a1cb98faSBarry Smith .vb
6124a1cb98faSBarry Smith    PetscMalloc1(clMaxSize, &values);
6125a1cb98faSBarry Smith    for (p = pStart; p < pEnd; ++p) {
6126a1cb98faSBarry Smith      clSize = clMaxSize;
6127a1cb98faSBarry Smith      PetscCall(DMPlexVecGetClosure(dm, NULL, v, p, &clSize, &values));
6128a1cb98faSBarry Smith      for (cl = 0; cl < clSize; ++cl) {
6129a1cb98faSBarry Smith        <Compute on closure>
6130a1cb98faSBarry Smith      }
6131a1cb98faSBarry Smith    }
6132a1cb98faSBarry Smith    PetscFree(values);
6133a1cb98faSBarry Smith .ve
6134a1cb98faSBarry Smith 
613560225df5SJacob Faibussowitsch   Fortran Notes:
613620f4b53cSBarry Smith   The `csize` argument is not present in the Fortran binding since it is internal to the array.
6137a1cb98faSBarry Smith 
61381cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecRestoreClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()`
6139552f7358SJed Brown @*/
6140d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
6141d71ae5a4SJacob Faibussowitsch {
6142d9917b9dSMatthew G. Knepley   PetscFunctionBeginHot;
614307218a29SMatthew G. Knepley   PetscCall(DMPlexVecGetOrientedClosure_Internal(dm, section, v, point, 0, csize, values));
61443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6145552f7358SJed Brown }
6146552f7358SJed Brown 
6147d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecGetClosureAtDepth_Internal(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt depth, PetscInt *csize, PetscScalar *values[])
6148d71ae5a4SJacob Faibussowitsch {
6149e5c487bfSMatthew G. Knepley   DMLabel            depthLabel;
6150e5c487bfSMatthew G. Knepley   PetscSection       clSection;
6151e5c487bfSMatthew G. Knepley   IS                 clPoints;
6152e5c487bfSMatthew G. Knepley   PetscScalar       *array;
6153e5c487bfSMatthew G. Knepley   const PetscScalar *vArray;
6154e5c487bfSMatthew G. Knepley   PetscInt          *points = NULL;
6155c459fbc1SJed Brown   const PetscInt    *clp, *perm = NULL;
6156c459fbc1SJed Brown   PetscInt           mdepth, numFields, numPoints, Np = 0, p, clsize, size;
6157e5c487bfSMatthew G. Knepley 
6158e5c487bfSMatthew G. Knepley   PetscFunctionBeginHot;
6159e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
61609566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
6161e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
6162e5c487bfSMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
61639566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &mdepth));
61649566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthLabel(dm, &depthLabel));
61659566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
6166e5c487bfSMatthew G. Knepley   if (mdepth == 1 && numFields < 2) {
61679566063dSJacob Faibussowitsch     PetscCall(DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values));
61683ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
6169e5c487bfSMatthew G. Knepley   }
6170e5c487bfSMatthew G. Knepley   /* Get points */
617107218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp));
6172c459fbc1SJed Brown   for (clsize = 0, p = 0; p < Np; p++) {
6173c459fbc1SJed Brown     PetscInt dof;
61749566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[2 * p], &dof));
6175c459fbc1SJed Brown     clsize += dof;
6176c459fbc1SJed Brown   }
61779566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &perm));
6178e5c487bfSMatthew G. Knepley   /* Filter points */
6179e5c487bfSMatthew G. Knepley   for (p = 0; p < numPoints * 2; p += 2) {
6180e5c487bfSMatthew G. Knepley     PetscInt dep;
6181e5c487bfSMatthew G. Knepley 
61829566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(depthLabel, points[p], &dep));
6183e5c487bfSMatthew G. Knepley     if (dep != depth) continue;
6184e5c487bfSMatthew G. Knepley     points[Np * 2 + 0] = points[p];
6185e5c487bfSMatthew G. Knepley     points[Np * 2 + 1] = points[p + 1];
6186e5c487bfSMatthew G. Knepley     ++Np;
6187e5c487bfSMatthew G. Knepley   }
6188e5c487bfSMatthew G. Knepley   /* Get array */
6189e5c487bfSMatthew G. Knepley   if (!values || !*values) {
6190e5c487bfSMatthew G. Knepley     PetscInt asize = 0, dof;
6191e5c487bfSMatthew G. Knepley 
6192e5c487bfSMatthew G. Knepley     for (p = 0; p < Np * 2; p += 2) {
61939566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, points[p], &dof));
6194e5c487bfSMatthew G. Knepley       asize += dof;
6195e5c487bfSMatthew G. Knepley     }
6196e5c487bfSMatthew G. Knepley     if (!values) {
61979566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
6198e5c487bfSMatthew G. Knepley       if (csize) *csize = asize;
61993ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
6200e5c487bfSMatthew G. Knepley     }
62019566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, asize, MPIU_SCALAR, &array));
6202e5c487bfSMatthew G. Knepley   } else {
6203e5c487bfSMatthew G. Knepley     array = *values;
6204e5c487bfSMatthew G. Knepley   }
62059566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(v, &vArray));
6206e5c487bfSMatthew G. Knepley   /* Get values */
62079566063dSJacob Faibussowitsch   if (numFields > 0) PetscCall(DMPlexVecGetClosure_Fields_Static(dm, section, Np, points, numFields, perm, vArray, &size, array));
62089566063dSJacob Faibussowitsch   else PetscCall(DMPlexVecGetClosure_Static(dm, section, Np, points, perm, vArray, &size, array));
6209e5c487bfSMatthew G. Knepley   /* Cleanup points */
62109566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
6211e5c487bfSMatthew G. Knepley   /* Cleanup array */
62129566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(v, &vArray));
6213e5c487bfSMatthew G. Knepley   if (!*values) {
6214e5c487bfSMatthew G. Knepley     if (csize) *csize = size;
6215e5c487bfSMatthew G. Knepley     *values = array;
6216e5c487bfSMatthew G. Knepley   } else {
621763a3b9bcSJacob Faibussowitsch     PetscCheck(size <= *csize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %" PetscInt_FMT " < actual size %" PetscInt_FMT, *csize, size);
6218e5c487bfSMatthew G. Knepley     *csize = size;
6219e5c487bfSMatthew G. Knepley   }
62203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6221e5c487bfSMatthew G. Knepley }
6222e5c487bfSMatthew G. Knepley 
6223552f7358SJed Brown /*@C
6224552f7358SJed Brown   DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point'
6225552f7358SJed Brown 
6226552f7358SJed Brown   Not collective
6227552f7358SJed Brown 
6228552f7358SJed Brown   Input Parameters:
6229a1cb98faSBarry Smith + dm      - The `DM`
623020f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section
6231552f7358SJed Brown . v       - The local vector
6232a1cb98faSBarry Smith . point   - The point in the `DM`
623320f4b53cSBarry Smith . csize   - The number of values in the closure, or `NULL`
6234552f7358SJed Brown - values  - The array of values, which is a borrowed array and should not be freed
6235552f7358SJed Brown 
6236552f7358SJed Brown   Level: intermediate
6237552f7358SJed Brown 
6238a1cb98faSBarry Smith   Note:
623920f4b53cSBarry Smith   The array values are discarded and not copied back into `v`. In order to copy values back to `v`, use `DMPlexVecSetClosure()`
6240a1cb98faSBarry Smith 
624160225df5SJacob Faibussowitsch   Fortran Notes:
624220f4b53cSBarry Smith   The `csize` argument is not present in the Fortran binding since it is internal to the array.
6243a1cb98faSBarry Smith 
62441cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`, `DMPlexMatSetClosure()`
6245552f7358SJed Brown @*/
6246d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[])
6247d71ae5a4SJacob Faibussowitsch {
6248552f7358SJed Brown   PetscInt size = 0;
6249552f7358SJed Brown 
6250552f7358SJed Brown   PetscFunctionBegin;
6251552f7358SJed Brown   /* Should work without recalculating size */
62529566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, size, MPIU_SCALAR, (void *)values));
6253c9fdaa05SMatthew G. Knepley   *values = NULL;
62543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6255552f7358SJed Brown }
6256552f7358SJed Brown 
6257d71ae5a4SJacob Faibussowitsch static inline void add(PetscScalar *x, PetscScalar y)
6258d71ae5a4SJacob Faibussowitsch {
62599371c9d4SSatish Balay   *x += y;
62609371c9d4SSatish Balay }
6261d71ae5a4SJacob Faibussowitsch static inline void insert(PetscScalar *x, PetscScalar y)
6262d71ae5a4SJacob Faibussowitsch {
62639371c9d4SSatish Balay   *x = y;
62649371c9d4SSatish Balay }
6265552f7358SJed Brown 
6266d71ae5a4SJacob 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[])
6267d71ae5a4SJacob Faibussowitsch {
6268552f7358SJed Brown   PetscInt        cdof;  /* The number of constraints on this point */
6269552f7358SJed Brown   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6270552f7358SJed Brown   PetscScalar    *a;
6271552f7358SJed Brown   PetscInt        off, cind = 0, k;
6272552f7358SJed Brown 
6273552f7358SJed Brown   PetscFunctionBegin;
62749566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
62759566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(section, point, &off));
6276552f7358SJed Brown   a = &array[off];
6277552f7358SJed Brown   if (!cdof || setBC) {
627897e99dd9SToby Isaac     if (clperm) {
62799371c9d4SSatish Balay       if (perm) {
6280ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.));
6281552f7358SJed Brown       } else {
6282ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.));
62839371c9d4SSatish Balay       }
62849371c9d4SSatish Balay     } else {
62859371c9d4SSatish Balay       if (perm) {
6286ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.));
62879371c9d4SSatish Balay       } else {
6288ad540459SPierre Jolivet         for (k = 0; k < dof; ++k) fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.));
62899371c9d4SSatish Balay       }
6290552f7358SJed Brown     }
6291552f7358SJed Brown   } else {
62929566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
629397e99dd9SToby Isaac     if (clperm) {
62949371c9d4SSatish Balay       if (perm) {
62959371c9d4SSatish Balay         for (k = 0; k < dof; ++k) {
62969371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
62979371c9d4SSatish Balay             ++cind;
62989371c9d4SSatish Balay             continue;
62999371c9d4SSatish Balay           }
630097e99dd9SToby Isaac           fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.));
6301552f7358SJed Brown         }
6302552f7358SJed Brown       } else {
6303552f7358SJed Brown         for (k = 0; k < dof; ++k) {
63049371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
63059371c9d4SSatish Balay             ++cind;
63069371c9d4SSatish Balay             continue;
63079371c9d4SSatish Balay           }
630897e99dd9SToby Isaac           fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.));
630997e99dd9SToby Isaac         }
631097e99dd9SToby Isaac       }
631197e99dd9SToby Isaac     } else {
631297e99dd9SToby Isaac       if (perm) {
631397e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
63149371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
63159371c9d4SSatish Balay             ++cind;
63169371c9d4SSatish Balay             continue;
63179371c9d4SSatish Balay           }
631897e99dd9SToby Isaac           fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.));
631997e99dd9SToby Isaac         }
632097e99dd9SToby Isaac       } else {
632197e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
63229371c9d4SSatish Balay           if ((cind < cdof) && (k == cdofs[cind])) {
63239371c9d4SSatish Balay             ++cind;
63249371c9d4SSatish Balay             continue;
63259371c9d4SSatish Balay           }
632697e99dd9SToby Isaac           fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.));
632797e99dd9SToby Isaac         }
6328552f7358SJed Brown       }
6329552f7358SJed Brown     }
6330552f7358SJed Brown   }
63313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6332552f7358SJed Brown }
6333552f7358SJed Brown 
6334d71ae5a4SJacob 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[])
6335d71ae5a4SJacob Faibussowitsch {
6336a5e93ea8SMatthew G. Knepley   PetscInt        cdof;  /* The number of constraints on this point */
6337a5e93ea8SMatthew G. Knepley   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6338a5e93ea8SMatthew G. Knepley   PetscScalar    *a;
6339a5e93ea8SMatthew G. Knepley   PetscInt        off, cind = 0, k;
6340a5e93ea8SMatthew G. Knepley 
6341a5e93ea8SMatthew G. Knepley   PetscFunctionBegin;
63429566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
63439566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetOffset(section, point, &off));
6344a5e93ea8SMatthew G. Knepley   a = &array[off];
6345a5e93ea8SMatthew G. Knepley   if (cdof) {
63469566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
634797e99dd9SToby Isaac     if (clperm) {
634897e99dd9SToby Isaac       if (perm) {
6349a5e93ea8SMatthew G. Knepley         for (k = 0; k < dof; ++k) {
6350a5e93ea8SMatthew G. Knepley           if ((cind < cdof) && (k == cdofs[cind])) {
635197e99dd9SToby Isaac             fuse(&a[k], values[clperm[offset + perm[k]]] * (flip ? flip[perm[k]] : 1.));
635297e99dd9SToby Isaac             cind++;
6353a5e93ea8SMatthew G. Knepley           }
6354a5e93ea8SMatthew G. Knepley         }
6355a5e93ea8SMatthew G. Knepley       } else {
6356a5e93ea8SMatthew G. Knepley         for (k = 0; k < dof; ++k) {
6357a5e93ea8SMatthew G. Knepley           if ((cind < cdof) && (k == cdofs[cind])) {
635897e99dd9SToby Isaac             fuse(&a[k], values[clperm[offset + k]] * (flip ? flip[k] : 1.));
635997e99dd9SToby Isaac             cind++;
636097e99dd9SToby Isaac           }
636197e99dd9SToby Isaac         }
636297e99dd9SToby Isaac       }
636397e99dd9SToby Isaac     } else {
636497e99dd9SToby Isaac       if (perm) {
636597e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
636697e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {
636797e99dd9SToby Isaac             fuse(&a[k], values[offset + perm[k]] * (flip ? flip[perm[k]] : 1.));
636897e99dd9SToby Isaac             cind++;
636997e99dd9SToby Isaac           }
637097e99dd9SToby Isaac         }
637197e99dd9SToby Isaac       } else {
637297e99dd9SToby Isaac         for (k = 0; k < dof; ++k) {
637397e99dd9SToby Isaac           if ((cind < cdof) && (k == cdofs[cind])) {
637497e99dd9SToby Isaac             fuse(&a[k], values[offset + k] * (flip ? flip[k] : 1.));
637597e99dd9SToby Isaac             cind++;
637697e99dd9SToby Isaac           }
6377a5e93ea8SMatthew G. Knepley         }
6378a5e93ea8SMatthew G. Knepley       }
6379a5e93ea8SMatthew G. Knepley     }
6380a5e93ea8SMatthew G. Knepley   }
63813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6382a5e93ea8SMatthew G. Knepley }
6383a5e93ea8SMatthew G. Knepley 
6384d71ae5a4SJacob 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[])
6385d71ae5a4SJacob Faibussowitsch {
6386552f7358SJed Brown   PetscScalar    *a;
63871a271a75SMatthew G. Knepley   PetscInt        fdof, foff, fcdof, foffset = *offset;
63881a271a75SMatthew G. Knepley   const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
638997e99dd9SToby Isaac   PetscInt        cind = 0, b;
6390552f7358SJed Brown 
6391552f7358SJed Brown   PetscFunctionBegin;
63929566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
63939566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof));
63949566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
63951a271a75SMatthew G. Knepley   a = &array[foff];
6396552f7358SJed Brown   if (!fcdof || setBC) {
639797e99dd9SToby Isaac     if (clperm) {
63989371c9d4SSatish Balay       if (perm) {
6399ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6400552f7358SJed Brown       } else {
6401ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
64029371c9d4SSatish Balay       }
64039371c9d4SSatish Balay     } else {
64049371c9d4SSatish Balay       if (perm) {
6405ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
64069371c9d4SSatish Balay       } else {
6407ad540459SPierre Jolivet         for (b = 0; b < fdof; b++) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
64089371c9d4SSatish Balay       }
6409552f7358SJed Brown     }
6410552f7358SJed Brown   } else {
64119566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
641297e99dd9SToby Isaac     if (clperm) {
641397e99dd9SToby Isaac       if (perm) {
641497e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
64159371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
64169371c9d4SSatish Balay             ++cind;
64179371c9d4SSatish Balay             continue;
64189371c9d4SSatish Balay           }
641997e99dd9SToby Isaac           fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6420552f7358SJed Brown         }
6421552f7358SJed Brown       } else {
642297e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
64239371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
64249371c9d4SSatish Balay             ++cind;
64259371c9d4SSatish Balay             continue;
64269371c9d4SSatish Balay           }
642797e99dd9SToby Isaac           fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
642897e99dd9SToby Isaac         }
642997e99dd9SToby Isaac       }
643097e99dd9SToby Isaac     } else {
643197e99dd9SToby Isaac       if (perm) {
643297e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
64339371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
64349371c9d4SSatish Balay             ++cind;
64359371c9d4SSatish Balay             continue;
64369371c9d4SSatish Balay           }
643797e99dd9SToby Isaac           fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
643897e99dd9SToby Isaac         }
643997e99dd9SToby Isaac       } else {
644097e99dd9SToby Isaac         for (b = 0; b < fdof; b++) {
64419371c9d4SSatish Balay           if ((cind < fcdof) && (b == fcdofs[cind])) {
64429371c9d4SSatish Balay             ++cind;
64439371c9d4SSatish Balay             continue;
64449371c9d4SSatish Balay           }
644597e99dd9SToby Isaac           fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
6446552f7358SJed Brown         }
6447552f7358SJed Brown       }
6448552f7358SJed Brown     }
6449552f7358SJed Brown   }
64501a271a75SMatthew G. Knepley   *offset += fdof;
64513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6452552f7358SJed Brown }
6453552f7358SJed Brown 
6454d71ae5a4SJacob 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[])
6455d71ae5a4SJacob Faibussowitsch {
6456a5e93ea8SMatthew G. Knepley   PetscScalar    *a;
64571a271a75SMatthew G. Knepley   PetscInt        fdof, foff, fcdof, foffset = *offset;
64581a271a75SMatthew G. Knepley   const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
64595da9d227SMatthew G. Knepley   PetscInt        Nc, cind = 0, ncind = 0, b;
6460ba322698SMatthew G. Knepley   PetscBool       ncSet, fcSet;
6461a5e93ea8SMatthew G. Knepley 
6462a5e93ea8SMatthew G. Knepley   PetscFunctionBegin;
64639566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldComponents(section, f, &Nc));
64649566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
64659566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &fcdof));
64669566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetFieldOffset(section, point, f, &foff));
64671a271a75SMatthew G. Knepley   a = &array[foff];
6468a5e93ea8SMatthew G. Knepley   if (fcdof) {
6469ba322698SMatthew G. Knepley     /* We just override fcdof and fcdofs with Ncc and comps */
64709566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
647197e99dd9SToby Isaac     if (clperm) {
647297e99dd9SToby Isaac       if (perm) {
6473ba322698SMatthew G. Knepley         if (comps) {
6474ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6475ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
64769371c9d4SSatish Balay             if (b % Nc == comps[ncind]) {
64779371c9d4SSatish Balay               ncind = (ncind + 1) % Ncc;
64789371c9d4SSatish Balay               ncSet = PETSC_TRUE;
64799371c9d4SSatish Balay             }
64809371c9d4SSatish Balay             if ((cind < fcdof) && (b == fcdofs[cind])) {
64819371c9d4SSatish Balay               ++cind;
64829371c9d4SSatish Balay               fcSet = PETSC_TRUE;
64839371c9d4SSatish Balay             }
6484ad540459SPierre Jolivet             if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6485ba322698SMatthew G. Knepley           }
6486ba322698SMatthew G. Knepley         } else {
648797e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
648897e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
648997e99dd9SToby Isaac               fuse(&a[b], values[clperm[foffset + perm[b]]] * (flip ? flip[perm[b]] : 1.));
6490a5e93ea8SMatthew G. Knepley               ++cind;
6491a5e93ea8SMatthew G. Knepley             }
6492a5e93ea8SMatthew G. Knepley           }
6493ba322698SMatthew G. Knepley         }
6494ba322698SMatthew G. Knepley       } else {
6495ba322698SMatthew G. Knepley         if (comps) {
6496ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6497ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
64989371c9d4SSatish Balay             if (b % Nc == comps[ncind]) {
64999371c9d4SSatish Balay               ncind = (ncind + 1) % Ncc;
65009371c9d4SSatish Balay               ncSet = PETSC_TRUE;
65019371c9d4SSatish Balay             }
65029371c9d4SSatish Balay             if ((cind < fcdof) && (b == fcdofs[cind])) {
65039371c9d4SSatish Balay               ++cind;
65049371c9d4SSatish Balay               fcSet = PETSC_TRUE;
65059371c9d4SSatish Balay             }
6506ad540459SPierre Jolivet             if (ncSet && fcSet) fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
6507ba322698SMatthew G. Knepley           }
6508a5e93ea8SMatthew G. Knepley         } else {
650997e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
651097e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
651197e99dd9SToby Isaac               fuse(&a[b], values[clperm[foffset + b]] * (flip ? flip[b] : 1.));
651297e99dd9SToby Isaac               ++cind;
651397e99dd9SToby Isaac             }
651497e99dd9SToby Isaac           }
651597e99dd9SToby Isaac         }
6516ba322698SMatthew G. Knepley       }
651797e99dd9SToby Isaac     } else {
651897e99dd9SToby Isaac       if (perm) {
6519ba322698SMatthew G. Knepley         if (comps) {
6520ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6521ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
65229371c9d4SSatish Balay             if (b % Nc == comps[ncind]) {
65239371c9d4SSatish Balay               ncind = (ncind + 1) % Ncc;
65249371c9d4SSatish Balay               ncSet = PETSC_TRUE;
65259371c9d4SSatish Balay             }
65269371c9d4SSatish Balay             if ((cind < fcdof) && (b == fcdofs[cind])) {
65279371c9d4SSatish Balay               ++cind;
65289371c9d4SSatish Balay               fcSet = PETSC_TRUE;
65299371c9d4SSatish Balay             }
6530ad540459SPierre Jolivet             if (ncSet && fcSet) fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
6531ba322698SMatthew G. Knepley           }
6532ba322698SMatthew G. Knepley         } else {
653397e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
653497e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
653597e99dd9SToby Isaac               fuse(&a[b], values[foffset + perm[b]] * (flip ? flip[perm[b]] : 1.));
653697e99dd9SToby Isaac               ++cind;
653797e99dd9SToby Isaac             }
653897e99dd9SToby Isaac           }
6539ba322698SMatthew G. Knepley         }
6540ba322698SMatthew G. Knepley       } else {
6541ba322698SMatthew G. Knepley         if (comps) {
6542ba322698SMatthew G. Knepley           for (b = 0; b < fdof; b++) {
6543ba322698SMatthew G. Knepley             ncSet = fcSet = PETSC_FALSE;
65449371c9d4SSatish Balay             if (b % Nc == comps[ncind]) {
65459371c9d4SSatish Balay               ncind = (ncind + 1) % Ncc;
65469371c9d4SSatish Balay               ncSet = PETSC_TRUE;
65479371c9d4SSatish Balay             }
65489371c9d4SSatish Balay             if ((cind < fcdof) && (b == fcdofs[cind])) {
65499371c9d4SSatish Balay               ++cind;
65509371c9d4SSatish Balay               fcSet = PETSC_TRUE;
65519371c9d4SSatish Balay             }
6552ad540459SPierre Jolivet             if (ncSet && fcSet) fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
6553ba322698SMatthew G. Knepley           }
655497e99dd9SToby Isaac         } else {
655597e99dd9SToby Isaac           for (b = 0; b < fdof; b++) {
655697e99dd9SToby Isaac             if ((cind < fcdof) && (b == fcdofs[cind])) {
655797e99dd9SToby Isaac               fuse(&a[b], values[foffset + b] * (flip ? flip[b] : 1.));
6558a5e93ea8SMatthew G. Knepley               ++cind;
6559a5e93ea8SMatthew G. Knepley             }
6560a5e93ea8SMatthew G. Knepley           }
6561a5e93ea8SMatthew G. Knepley         }
6562a5e93ea8SMatthew G. Knepley       }
6563a5e93ea8SMatthew G. Knepley     }
6564ba322698SMatthew G. Knepley   }
65651a271a75SMatthew G. Knepley   *offset += fdof;
65663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6567a5e93ea8SMatthew G. Knepley }
6568a5e93ea8SMatthew G. Knepley 
6569d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode DMPlexVecSetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode)
6570d71ae5a4SJacob Faibussowitsch {
6571552f7358SJed Brown   PetscScalar    *array;
65721b406b76SMatthew G. Knepley   const PetscInt *cone, *coneO;
65731b406b76SMatthew G. Knepley   PetscInt        pStart, pEnd, p, numPoints, off, dof;
6574552f7358SJed Brown 
65751b406b76SMatthew G. Knepley   PetscFunctionBeginHot;
65769566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &pStart, &pEnd));
65779566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSize(dm, point, &numPoints));
65789566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCone(dm, point, &cone));
65799566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeOrientation(dm, point, &coneO));
65809566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
6581b6ebb6e6SMatthew G. Knepley   for (p = 0, off = 0; p <= numPoints; ++p, off += dof) {
6582b6ebb6e6SMatthew G. Knepley     const PetscInt cp = !p ? point : cone[p - 1];
6583b6ebb6e6SMatthew G. Knepley     const PetscInt o  = !p ? 0 : coneO[p - 1];
6584b6ebb6e6SMatthew G. Knepley 
65859371c9d4SSatish Balay     if ((cp < pStart) || (cp >= pEnd)) {
65869371c9d4SSatish Balay       dof = 0;
65879371c9d4SSatish Balay       continue;
65889371c9d4SSatish Balay     }
65899566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, cp, &dof));
6590b6ebb6e6SMatthew G. Knepley     /* ADD_VALUES */
6591b6ebb6e6SMatthew G. Knepley     {
6592b6ebb6e6SMatthew G. Knepley       const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6593b6ebb6e6SMatthew G. Knepley       PetscScalar    *a;
6594b6ebb6e6SMatthew G. Knepley       PetscInt        cdof, coff, cind = 0, k;
6595b6ebb6e6SMatthew G. Knepley 
65969566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetConstraintDof(section, cp, &cdof));
65979566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(section, cp, &coff));
6598b6ebb6e6SMatthew G. Knepley       a = &array[coff];
6599b6ebb6e6SMatthew G. Knepley       if (!cdof) {
6600b6ebb6e6SMatthew G. Knepley         if (o >= 0) {
6601ad540459SPierre Jolivet           for (k = 0; k < dof; ++k) a[k] += values[off + k];
6602b6ebb6e6SMatthew G. Knepley         } else {
6603ad540459SPierre Jolivet           for (k = 0; k < dof; ++k) a[k] += values[off + dof - k - 1];
6604b6ebb6e6SMatthew G. Knepley         }
6605b6ebb6e6SMatthew G. Knepley       } else {
66069566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetConstraintIndices(section, cp, &cdofs));
6607b6ebb6e6SMatthew G. Knepley         if (o >= 0) {
6608b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
66099371c9d4SSatish Balay             if ((cind < cdof) && (k == cdofs[cind])) {
66109371c9d4SSatish Balay               ++cind;
66119371c9d4SSatish Balay               continue;
66129371c9d4SSatish Balay             }
6613b6ebb6e6SMatthew G. Knepley             a[k] += values[off + k];
6614b6ebb6e6SMatthew G. Knepley           }
6615b6ebb6e6SMatthew G. Knepley         } else {
6616b6ebb6e6SMatthew G. Knepley           for (k = 0; k < dof; ++k) {
66179371c9d4SSatish Balay             if ((cind < cdof) && (k == cdofs[cind])) {
66189371c9d4SSatish Balay               ++cind;
66199371c9d4SSatish Balay               continue;
66209371c9d4SSatish Balay             }
6621b6ebb6e6SMatthew G. Knepley             a[k] += values[off + dof - k - 1];
6622b6ebb6e6SMatthew G. Knepley           }
6623b6ebb6e6SMatthew G. Knepley         }
6624b6ebb6e6SMatthew G. Knepley       }
6625b6ebb6e6SMatthew G. Knepley     }
6626b6ebb6e6SMatthew G. Knepley   }
66279566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
66283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6629b6ebb6e6SMatthew G. Knepley }
66301b406b76SMatthew G. Knepley 
66311b406b76SMatthew G. Knepley /*@C
663220f4b53cSBarry Smith   DMPlexVecSetClosure - Set an array of the values on the closure of `point`
66331b406b76SMatthew G. Knepley 
66341b406b76SMatthew G. Knepley   Not collective
66351b406b76SMatthew G. Knepley 
66361b406b76SMatthew G. Knepley   Input Parameters:
6637a1cb98faSBarry Smith + dm      - The `DM`
663820f4b53cSBarry Smith . section - The section describing the layout in `v`, or `NULL` to use the default section
66391b406b76SMatthew G. Knepley . v       - The local vector
664020f4b53cSBarry Smith . point   - The point in the `DM`
66411b406b76SMatthew G. Knepley . values  - The array of values
6642a1cb98faSBarry Smith - mode    - The insert mode. One of `INSERT_ALL_VALUES`, `ADD_ALL_VALUES`, `INSERT_VALUES`, `ADD_VALUES`, `INSERT_BC_VALUES`, and `ADD_BC_VALUES`,
6643a1cb98faSBarry Smith          where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions.
66441b406b76SMatthew G. Knepley 
66451b406b76SMatthew G. Knepley   Level: intermediate
66461b406b76SMatthew G. Knepley 
66471cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`
66481b406b76SMatthew G. Knepley @*/
6649d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode)
6650d71ae5a4SJacob Faibussowitsch {
66511b406b76SMatthew G. Knepley   PetscSection    clSection;
66521b406b76SMatthew G. Knepley   IS              clPoints;
66531b406b76SMatthew G. Knepley   PetscScalar    *array;
66541b406b76SMatthew G. Knepley   PetscInt       *points = NULL;
665527f02ce8SMatthew G. Knepley   const PetscInt *clp, *clperm = NULL;
6656c459fbc1SJed Brown   PetscInt        depth, numFields, numPoints, p, clsize;
66571b406b76SMatthew G. Knepley 
66581a271a75SMatthew G. Knepley   PetscFunctionBeginHot;
66591b406b76SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
66609566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
66611a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
66621a271a75SMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
66639566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
66649566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
66651b406b76SMatthew G. Knepley   if (depth == 1 && numFields < 2 && mode == ADD_VALUES) {
66669566063dSJacob Faibussowitsch     PetscCall(DMPlexVecSetClosure_Depth1_Static(dm, section, v, point, values, mode));
66673ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
66681b406b76SMatthew G. Knepley   }
66691a271a75SMatthew G. Knepley   /* Get points */
667007218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp));
6671c459fbc1SJed Brown   for (clsize = 0, p = 0; p < numPoints; p++) {
6672c459fbc1SJed Brown     PetscInt dof;
66739566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[2 * p], &dof));
6674c459fbc1SJed Brown     clsize += dof;
6675c459fbc1SJed Brown   }
66769566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm));
66771a271a75SMatthew G. Knepley   /* Get array */
66789566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
66791a271a75SMatthew G. Knepley   /* Get values */
6680ef90cfe2SMatthew G. Knepley   if (numFields > 0) {
668197e99dd9SToby Isaac     PetscInt offset = 0, f;
6682552f7358SJed Brown     for (f = 0; f < numFields; ++f) {
668397e99dd9SToby Isaac       const PetscInt    **perms = NULL;
668497e99dd9SToby Isaac       const PetscScalar **flips = NULL;
668597e99dd9SToby Isaac 
66869566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips));
6687552f7358SJed Brown       switch (mode) {
6688552f7358SJed Brown       case INSERT_VALUES:
668997e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
669097e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
669197e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
669297e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
66933ba16761SJacob Faibussowitsch           PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, clperm, values, &offset, array));
66949371c9d4SSatish Balay         }
66959371c9d4SSatish Balay         break;
6696552f7358SJed Brown       case INSERT_ALL_VALUES:
669797e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
669897e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
669997e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
670097e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
67013ba16761SJacob Faibussowitsch           PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, clperm, values, &offset, array));
67029371c9d4SSatish Balay         }
67039371c9d4SSatish Balay         break;
6704a5e93ea8SMatthew G. Knepley       case INSERT_BC_VALUES:
670597e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
670697e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
670797e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
670897e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
67093ba16761SJacob Faibussowitsch           PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, insert, clperm, values, &offset, array));
67109371c9d4SSatish Balay         }
67119371c9d4SSatish Balay         break;
6712552f7358SJed Brown       case ADD_VALUES:
671397e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
671497e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
671597e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
671697e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
67173ba16761SJacob Faibussowitsch           PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, clperm, values, &offset, array));
67189371c9d4SSatish Balay         }
67199371c9d4SSatish Balay         break;
6720552f7358SJed Brown       case ADD_ALL_VALUES:
672197e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
672297e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
672397e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
672497e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
67253ba16761SJacob Faibussowitsch           PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, clperm, values, &offset, array));
67269371c9d4SSatish Balay         }
67279371c9d4SSatish Balay         break;
6728304ab55fSMatthew G. Knepley       case ADD_BC_VALUES:
672997e99dd9SToby Isaac         for (p = 0; p < numPoints; p++) {
673097e99dd9SToby Isaac           const PetscInt     point = points[2 * p];
673197e99dd9SToby Isaac           const PetscInt    *perm  = perms ? perms[p] : NULL;
673297e99dd9SToby Isaac           const PetscScalar *flip  = flips ? flips[p] : NULL;
67333ba16761SJacob Faibussowitsch           PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, -1, NULL, add, clperm, values, &offset, array));
67349371c9d4SSatish Balay         }
67359371c9d4SSatish Balay         break;
6736d71ae5a4SJacob Faibussowitsch       default:
6737d71ae5a4SJacob Faibussowitsch         SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
6738552f7358SJed Brown       }
67399566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips));
67401a271a75SMatthew G. Knepley     }
6741552f7358SJed Brown   } else {
67421a271a75SMatthew G. Knepley     PetscInt            dof, off;
674397e99dd9SToby Isaac     const PetscInt    **perms = NULL;
674497e99dd9SToby Isaac     const PetscScalar **flips = NULL;
67451a271a75SMatthew G. Knepley 
67469566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(section, numPoints, points, &perms, &flips));
6747552f7358SJed Brown     switch (mode) {
6748552f7358SJed Brown     case INSERT_VALUES:
674997e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
675097e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
675197e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
675297e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
67539566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
67543ba16761SJacob Faibussowitsch         PetscCall(updatePoint_private(section, point, dof, insert, PETSC_FALSE, perm, flip, clperm, values, off, array));
67559371c9d4SSatish Balay       }
67569371c9d4SSatish Balay       break;
6757552f7358SJed Brown     case INSERT_ALL_VALUES:
675897e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
675997e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
676097e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
676197e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
67629566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
67633ba16761SJacob Faibussowitsch         PetscCall(updatePoint_private(section, point, dof, insert, PETSC_TRUE, perm, flip, clperm, values, off, array));
67649371c9d4SSatish Balay       }
67659371c9d4SSatish Balay       break;
6766a5e93ea8SMatthew G. Knepley     case INSERT_BC_VALUES:
676797e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
676897e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
676997e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
677097e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
67719566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
67723ba16761SJacob Faibussowitsch         PetscCall(updatePointBC_private(section, point, dof, insert, perm, flip, clperm, values, off, array));
67739371c9d4SSatish Balay       }
67749371c9d4SSatish Balay       break;
6775552f7358SJed Brown     case ADD_VALUES:
677697e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
677797e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
677897e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
677997e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
67809566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
67813ba16761SJacob Faibussowitsch         PetscCall(updatePoint_private(section, point, dof, add, PETSC_FALSE, perm, flip, clperm, values, off, array));
67829371c9d4SSatish Balay       }
67839371c9d4SSatish Balay       break;
6784552f7358SJed Brown     case ADD_ALL_VALUES:
678597e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
678697e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
678797e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
678897e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
67899566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
67903ba16761SJacob Faibussowitsch         PetscCall(updatePoint_private(section, point, dof, add, PETSC_TRUE, perm, flip, clperm, values, off, array));
67919371c9d4SSatish Balay       }
67929371c9d4SSatish Balay       break;
6793304ab55fSMatthew G. Knepley     case ADD_BC_VALUES:
679497e99dd9SToby Isaac       for (p = 0, off = 0; p < numPoints; p++, off += dof) {
679597e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
679697e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
679797e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
67989566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, point, &dof));
67993ba16761SJacob Faibussowitsch         PetscCall(updatePointBC_private(section, point, dof, add, perm, flip, clperm, values, off, array));
68009371c9d4SSatish Balay       }
68019371c9d4SSatish Balay       break;
6802d71ae5a4SJacob Faibussowitsch     default:
6803d71ae5a4SJacob Faibussowitsch       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
6804552f7358SJed Brown     }
68059566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(section, numPoints, points, &perms, &flips));
6806552f7358SJed Brown   }
68071a271a75SMatthew G. Knepley   /* Cleanup points */
68089566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
68091a271a75SMatthew G. Knepley   /* Cleanup array */
68109566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
68113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6812552f7358SJed Brown }
6813552f7358SJed Brown 
68145f790a90SMatthew G. Knepley /* Check whether the given point is in the label. If not, update the offset to skip this point */
6815d71ae5a4SJacob Faibussowitsch static inline PetscErrorCode CheckPoint_Private(DMLabel label, PetscInt labelId, PetscSection section, PetscInt point, PetscInt f, PetscInt *offset, PetscBool *contains)
6816d71ae5a4SJacob Faibussowitsch {
68175f790a90SMatthew G. Knepley   PetscFunctionBegin;
681811cc89d2SBarry Smith   *contains = PETSC_TRUE;
68195f790a90SMatthew G. Knepley   if (label) {
6820d6177c40SToby Isaac     PetscInt fdof;
68215f790a90SMatthew G. Knepley 
682211cc89d2SBarry Smith     PetscCall(DMLabelStratumHasPoint(label, labelId, point, contains));
682311cc89d2SBarry Smith     if (!*contains) {
68249566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
68255f790a90SMatthew G. Knepley       *offset += fdof;
68263ba16761SJacob Faibussowitsch       PetscFunctionReturn(PETSC_SUCCESS);
68275f790a90SMatthew G. Knepley     }
68285f790a90SMatthew G. Knepley   }
68293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
68305f790a90SMatthew G. Knepley }
68315f790a90SMatthew G. Knepley 
683297529cf3SJed Brown /* Unlike DMPlexVecSetClosure(), this uses plex-native closure permutation, not a user-specified permutation such as DMPlexSetClosurePermutationTensor(). */
6833d71ae5a4SJacob Faibussowitsch 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)
6834d71ae5a4SJacob Faibussowitsch {
6835e07394fbSMatthew G. Knepley   PetscSection    clSection;
6836e07394fbSMatthew G. Knepley   IS              clPoints;
6837e07394fbSMatthew G. Knepley   PetscScalar    *array;
6838e07394fbSMatthew G. Knepley   PetscInt       *points = NULL;
683997529cf3SJed Brown   const PetscInt *clp;
6840e07394fbSMatthew G. Knepley   PetscInt        numFields, numPoints, p;
684197e99dd9SToby Isaac   PetscInt        offset = 0, f;
6842e07394fbSMatthew G. Knepley 
6843e07394fbSMatthew G. Knepley   PetscFunctionBeginHot;
6844e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
68459566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
6846e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
6847e07394fbSMatthew G. Knepley   PetscValidHeaderSpecific(v, VEC_CLASSID, 3);
68489566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
6849e07394fbSMatthew G. Knepley   /* Get points */
685007218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &numPoints, &points, &clSection, &clPoints, &clp));
6851e07394fbSMatthew G. Knepley   /* Get array */
68529566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v, &array));
6853e07394fbSMatthew G. Knepley   /* Get values */
6854e07394fbSMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
685597e99dd9SToby Isaac     const PetscInt    **perms = NULL;
685697e99dd9SToby Isaac     const PetscScalar **flips = NULL;
685711cc89d2SBarry Smith     PetscBool           contains;
685897e99dd9SToby Isaac 
6859e07394fbSMatthew G. Knepley     if (!fieldActive[f]) {
6860e07394fbSMatthew G. Knepley       for (p = 0; p < numPoints * 2; p += 2) {
6861e07394fbSMatthew G. Knepley         PetscInt fdof;
68629566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof));
6863e07394fbSMatthew G. Knepley         offset += fdof;
6864e07394fbSMatthew G. Knepley       }
6865e07394fbSMatthew G. Knepley       continue;
6866e07394fbSMatthew G. Knepley     }
68679566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldPointSyms(section, f, numPoints, points, &perms, &flips));
6868e07394fbSMatthew G. Knepley     switch (mode) {
6869e07394fbSMatthew G. Knepley     case INSERT_VALUES:
687097e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
687197e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
687297e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
687397e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
687411cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
687511cc89d2SBarry Smith         if (!contains) continue;
68769566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_FALSE, NULL, values, &offset, array));
68779371c9d4SSatish Balay       }
68789371c9d4SSatish Balay       break;
6879e07394fbSMatthew G. Knepley     case INSERT_ALL_VALUES:
688097e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
688197e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
688297e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
688397e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
688411cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
688511cc89d2SBarry Smith         if (!contains) continue;
68869566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, insert, PETSC_TRUE, NULL, values, &offset, array));
68879371c9d4SSatish Balay       }
68889371c9d4SSatish Balay       break;
6889e07394fbSMatthew G. Knepley     case INSERT_BC_VALUES:
689097e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
689197e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
689297e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
689397e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
689411cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
689511cc89d2SBarry Smith         if (!contains) continue;
68969566063dSJacob Faibussowitsch         PetscCall(updatePointFieldsBC_private(section, point, perm, flip, f, Ncc, comps, insert, NULL, values, &offset, array));
68979371c9d4SSatish Balay       }
68989371c9d4SSatish Balay       break;
6899e07394fbSMatthew G. Knepley     case ADD_VALUES:
690097e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
690197e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
690297e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
690397e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
690411cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
690511cc89d2SBarry Smith         if (!contains) continue;
69069566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_FALSE, NULL, values, &offset, array));
69079371c9d4SSatish Balay       }
69089371c9d4SSatish Balay       break;
6909e07394fbSMatthew G. Knepley     case ADD_ALL_VALUES:
691097e99dd9SToby Isaac       for (p = 0; p < numPoints; p++) {
691197e99dd9SToby Isaac         const PetscInt     point = points[2 * p];
691297e99dd9SToby Isaac         const PetscInt    *perm  = perms ? perms[p] : NULL;
691397e99dd9SToby Isaac         const PetscScalar *flip  = flips ? flips[p] : NULL;
691411cc89d2SBarry Smith         PetscCall(CheckPoint_Private(label, labelId, section, point, f, &offset, &contains));
691511cc89d2SBarry Smith         if (!contains) continue;
69169566063dSJacob Faibussowitsch         PetscCall(updatePointFields_private(section, point, perm, flip, f, add, PETSC_TRUE, NULL, values, &offset, array));
69179371c9d4SSatish Balay       }
69189371c9d4SSatish Balay       break;
6919d71ae5a4SJacob Faibussowitsch     default:
6920d71ae5a4SJacob Faibussowitsch       SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode);
6921e07394fbSMatthew G. Knepley     }
69229566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestoreFieldPointSyms(section, f, numPoints, points, &perms, &flips));
6923e07394fbSMatthew G. Knepley   }
6924e07394fbSMatthew G. Knepley   /* Cleanup points */
69259566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &numPoints, &points, &clSection, &clPoints, &clp));
6926e07394fbSMatthew G. Knepley   /* Cleanup array */
69279566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v, &array));
69283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6929e07394fbSMatthew G. Knepley }
6930e07394fbSMatthew G. Knepley 
6931d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[])
6932d71ae5a4SJacob Faibussowitsch {
6933552f7358SJed Brown   PetscMPIInt rank;
6934552f7358SJed Brown   PetscInt    i, j;
6935552f7358SJed Brown 
6936552f7358SJed Brown   PetscFunctionBegin;
69379566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
693863a3b9bcSJacob Faibussowitsch   PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat for point %" PetscInt_FMT "\n", rank, point));
693963a3b9bcSJacob Faibussowitsch   for (i = 0; i < numRIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, rindices[i]));
694063a3b9bcSJacob Faibussowitsch   for (i = 0; i < numCIndices; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%" PetscInt_FMT "] = %" PetscInt_FMT "\n", rank, i, cindices[i]));
6941b0ecff45SMatthew G. Knepley   numCIndices = numCIndices ? numCIndices : numRIndices;
69423ba16761SJacob Faibussowitsch   if (!values) PetscFunctionReturn(PETSC_SUCCESS);
6943b0ecff45SMatthew G. Knepley   for (i = 0; i < numRIndices; i++) {
69449566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "[%d]", rank));
6945b0ecff45SMatthew G. Knepley     for (j = 0; j < numCIndices; j++) {
6946519f805aSKarl Rupp #if defined(PETSC_USE_COMPLEX)
69479566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i * numCIndices + j]), (double)PetscImaginaryPart(values[i * numCIndices + j])));
6948552f7358SJed Brown #else
69499566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, " %g", (double)values[i * numCIndices + j]));
6950552f7358SJed Brown #endif
6951552f7358SJed Brown     }
69529566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "\n"));
6953552f7358SJed Brown   }
69543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6955552f7358SJed Brown }
6956552f7358SJed Brown 
695705586334SMatthew G. Knepley /*
695805586334SMatthew G. Knepley   DMPlexGetIndicesPoint_Internal - Add the indices for dofs on a point to an index array
695905586334SMatthew G. Knepley 
696005586334SMatthew G. Knepley   Input Parameters:
696105586334SMatthew G. Knepley + section - The section for this data layout
696236fa2b79SJed Brown . islocal - Is the section (and thus indices being requested) local or global?
696305586334SMatthew G. Knepley . point   - The point contributing dofs with these indices
696405586334SMatthew G. Knepley . off     - The global offset of this point
696505586334SMatthew G. Knepley . loff    - The local offset of each field
6966a5b23f4aSJose E. Roman . setBC   - The flag determining whether to include indices of boundary values
696705586334SMatthew G. Knepley . perm    - A permutation of the dofs on this point, or NULL
696805586334SMatthew G. Knepley - indperm - A permutation of the entire indices array, or NULL
696905586334SMatthew G. Knepley 
697005586334SMatthew G. Knepley   Output Parameter:
697105586334SMatthew G. Knepley . indices - Indices for dofs on this point
697205586334SMatthew G. Knepley 
697305586334SMatthew G. Knepley   Level: developer
697405586334SMatthew G. Knepley 
697505586334SMatthew G. Knepley   Note: The indices could be local or global, depending on the value of 'off'.
697605586334SMatthew G. Knepley */
6977d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetIndicesPoint_Internal(PetscSection section, PetscBool islocal, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, const PetscInt perm[], const PetscInt indperm[], PetscInt indices[])
6978d71ae5a4SJacob Faibussowitsch {
6979e6ccafaeSMatthew G Knepley   PetscInt        dof;   /* The number of unknowns on this point */
6980552f7358SJed Brown   PetscInt        cdof;  /* The number of constraints on this point */
6981552f7358SJed Brown   const PetscInt *cdofs; /* The indices of the constrained dofs on this point */
6982552f7358SJed Brown   PetscInt        cind = 0, k;
6983552f7358SJed Brown 
6984552f7358SJed Brown   PetscFunctionBegin;
698508401ef6SPierre Jolivet   PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC");
69869566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetDof(section, point, &dof));
69879566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstraintDof(section, point, &cdof));
6988552f7358SJed Brown   if (!cdof || setBC) {
698905586334SMatthew G. Knepley     for (k = 0; k < dof; ++k) {
699005586334SMatthew G. Knepley       const PetscInt preind = perm ? *loff + perm[k] : *loff + k;
699105586334SMatthew G. Knepley       const PetscInt ind    = indperm ? indperm[preind] : preind;
699205586334SMatthew G. Knepley 
699305586334SMatthew G. Knepley       indices[ind] = off + k;
6994552f7358SJed Brown     }
6995552f7358SJed Brown   } else {
69969566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstraintIndices(section, point, &cdofs));
69974acb8e1eSToby Isaac     for (k = 0; k < dof; ++k) {
699805586334SMatthew G. Knepley       const PetscInt preind = perm ? *loff + perm[k] : *loff + k;
699905586334SMatthew G. Knepley       const PetscInt ind    = indperm ? indperm[preind] : preind;
700005586334SMatthew G. Knepley 
70014acb8e1eSToby Isaac       if ((cind < cdof) && (k == cdofs[cind])) {
70024acb8e1eSToby Isaac         /* Insert check for returning constrained indices */
700305586334SMatthew G. Knepley         indices[ind] = -(off + k + 1);
70044acb8e1eSToby Isaac         ++cind;
70054acb8e1eSToby Isaac       } else {
700636fa2b79SJed Brown         indices[ind] = off + k - (islocal ? 0 : cind);
7007552f7358SJed Brown       }
7008552f7358SJed Brown     }
7009552f7358SJed Brown   }
7010e6ccafaeSMatthew G Knepley   *loff += dof;
70113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7012552f7358SJed Brown }
7013552f7358SJed Brown 
70147e29afd2SMatthew G. Knepley /*
701536fa2b79SJed Brown  DMPlexGetIndicesPointFields_Internal - gets section indices for a point in its canonical ordering.
70167e29afd2SMatthew G. Knepley 
701736fa2b79SJed Brown  Input Parameters:
701836fa2b79SJed Brown + section - a section (global or local)
701920f4b53cSBarry Smith - islocal - `PETSC_TRUE` if requesting local indices (i.e., section is local); `PETSC_FALSE` for global
702036fa2b79SJed Brown . point - point within section
702136fa2b79SJed Brown . off - The offset of this point in the (local or global) indexed space - should match islocal and (usually) the section
702236fa2b79SJed Brown . foffs - array of length numFields containing the offset in canonical point ordering (the location in indices) of each field
702336fa2b79SJed Brown . setBC - identify constrained (boundary condition) points via involution.
702436fa2b79SJed Brown . perms - perms[f][permsoff][:] is a permutation of dofs within each field
702536fa2b79SJed Brown . permsoff - offset
702636fa2b79SJed Brown - indperm - index permutation
702736fa2b79SJed Brown 
702836fa2b79SJed Brown  Output Parameter:
702936fa2b79SJed Brown . foffs - each entry is incremented by the number of (unconstrained if setBC=FALSE) dofs in that field
703036fa2b79SJed Brown . indices - array to hold indices (as defined by section) of each dof associated with point
703136fa2b79SJed Brown 
703236fa2b79SJed Brown  Notes:
703336fa2b79SJed Brown  If section is local and setBC=true, there is no distinction between constrained and unconstrained dofs.
703436fa2b79SJed Brown  If section is local and setBC=false, the indices for constrained points are the involution -(i+1) of their position
703536fa2b79SJed Brown  in the local vector.
703636fa2b79SJed Brown 
703736fa2b79SJed Brown  If section is global and setBC=false, the indices for constrained points are negative (and their value is not
703836fa2b79SJed Brown  significant).  It is invalid to call with a global section and setBC=true.
703936fa2b79SJed Brown 
704036fa2b79SJed Brown  Developer Note:
704136fa2b79SJed Brown  The section is only used for field layout, so islocal is technically a statement about the offset (off).  At some point
704236fa2b79SJed Brown  in the future, global sections may have fields set, in which case we could pass the global section and obtain the
704336fa2b79SJed Brown  offset could be obtained from the section instead of passing it explicitly as we do now.
704436fa2b79SJed Brown 
704536fa2b79SJed Brown  Example:
704636fa2b79SJed Brown  Suppose a point contains one field with three components, and for which the unconstrained indices are {10, 11, 12}.
704736fa2b79SJed Brown  When the middle component is constrained, we get the array {10, -12, 12} for (islocal=TRUE, setBC=FALSE).
704836fa2b79SJed Brown  Note that -12 is the involution of 11, so the user can involute negative indices to recover local indices.
704936fa2b79SJed 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.
705036fa2b79SJed Brown 
705136fa2b79SJed Brown  Level: developer
70527e29afd2SMatthew G. Knepley */
7053d71ae5a4SJacob Faibussowitsch 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[])
7054d71ae5a4SJacob Faibussowitsch {
7055552f7358SJed Brown   PetscInt numFields, foff, f;
7056552f7358SJed Brown 
7057552f7358SJed Brown   PetscFunctionBegin;
705808401ef6SPierre Jolivet   PetscCheck(islocal || !setBC, PetscObjectComm((PetscObject)section), PETSC_ERR_ARG_INCOMP, "setBC incompatible with global indices; use a local section or disable setBC");
70599566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
7060552f7358SJed Brown   for (f = 0, foff = 0; f < numFields; ++f) {
70614acb8e1eSToby Isaac     PetscInt        fdof, cfdof;
7062552f7358SJed Brown     const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
70634acb8e1eSToby Isaac     PetscInt        cind = 0, b;
70644acb8e1eSToby Isaac     const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL;
7065552f7358SJed Brown 
70669566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
70679566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof));
7068552f7358SJed Brown     if (!cfdof || setBC) {
706905586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
707005586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
707105586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
707205586334SMatthew G. Knepley 
707305586334SMatthew G. Knepley         indices[ind] = off + foff + b;
707405586334SMatthew G. Knepley       }
7075552f7358SJed Brown     } else {
70769566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
707705586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
707805586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
707905586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
708005586334SMatthew G. Knepley 
70814acb8e1eSToby Isaac         if ((cind < cfdof) && (b == fcdofs[cind])) {
708205586334SMatthew G. Knepley           indices[ind] = -(off + foff + b + 1);
7083552f7358SJed Brown           ++cind;
7084552f7358SJed Brown         } else {
708536fa2b79SJed Brown           indices[ind] = off + foff + b - (islocal ? 0 : cind);
7086552f7358SJed Brown         }
7087552f7358SJed Brown       }
7088552f7358SJed Brown     }
708936fa2b79SJed Brown     foff += (setBC || islocal ? fdof : (fdof - cfdof));
7090552f7358SJed Brown     foffs[f] += fdof;
7091552f7358SJed Brown   }
70923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7093552f7358SJed Brown }
7094552f7358SJed Brown 
70957e29afd2SMatthew G. Knepley /*
70967e29afd2SMatthew G. Knepley   This version believes the globalSection offsets for each field, rather than just the point offset
70977e29afd2SMatthew G. Knepley 
70987e29afd2SMatthew G. Knepley  . foffs - The offset into 'indices' for each field, since it is segregated by field
7099645102dcSJed Brown 
7100645102dcSJed Brown  Notes:
7101645102dcSJed Brown  The semantics of this function relate to that of setBC=FALSE in DMPlexGetIndicesPointFields_Internal.
7102645102dcSJed Brown  Since this function uses global indices, setBC=TRUE would be invalid, so no such argument exists.
71037e29afd2SMatthew G. Knepley */
7104d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexGetIndicesPointFieldsSplit_Internal(PetscSection section, PetscSection globalSection, PetscInt point, PetscInt foffs[], const PetscInt ***perms, PetscInt permsoff, const PetscInt indperm[], PetscInt indices[])
7105d71ae5a4SJacob Faibussowitsch {
71067e29afd2SMatthew G. Knepley   PetscInt numFields, foff, f;
71077e29afd2SMatthew G. Knepley 
71087e29afd2SMatthew G. Knepley   PetscFunctionBegin;
71099566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
71107e29afd2SMatthew G. Knepley   for (f = 0; f < numFields; ++f) {
71117e29afd2SMatthew G. Knepley     PetscInt        fdof, cfdof;
71127e29afd2SMatthew G. Knepley     const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */
71137e29afd2SMatthew G. Knepley     PetscInt        cind = 0, b;
71147e29afd2SMatthew G. Knepley     const PetscInt *perm = (perms && perms[f]) ? perms[f][permsoff] : NULL;
71157e29afd2SMatthew G. Knepley 
71169566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldDof(section, point, f, &fdof));
71179566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldConstraintDof(section, point, f, &cfdof));
71189566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetFieldOffset(globalSection, point, f, &foff));
7119645102dcSJed Brown     if (!cfdof) {
712005586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
712105586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
712205586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
712305586334SMatthew G. Knepley 
712405586334SMatthew G. Knepley         indices[ind] = foff + b;
712505586334SMatthew G. Knepley       }
71267e29afd2SMatthew G. Knepley     } else {
71279566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs));
712805586334SMatthew G. Knepley       for (b = 0; b < fdof; ++b) {
712905586334SMatthew G. Knepley         const PetscInt preind = perm ? foffs[f] + perm[b] : foffs[f] + b;
713005586334SMatthew G. Knepley         const PetscInt ind    = indperm ? indperm[preind] : preind;
713105586334SMatthew G. Knepley 
71327e29afd2SMatthew G. Knepley         if ((cind < cfdof) && (b == fcdofs[cind])) {
713305586334SMatthew G. Knepley           indices[ind] = -(foff + b + 1);
71347e29afd2SMatthew G. Knepley           ++cind;
71357e29afd2SMatthew G. Knepley         } else {
713605586334SMatthew G. Knepley           indices[ind] = foff + b - cind;
71377e29afd2SMatthew G. Knepley         }
71387e29afd2SMatthew G. Knepley       }
71397e29afd2SMatthew G. Knepley     }
71407e29afd2SMatthew G. Knepley     foffs[f] += fdof;
71417e29afd2SMatthew G. Knepley   }
71423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
71437e29afd2SMatthew G. Knepley }
71447e29afd2SMatthew G. Knepley 
7145d71ae5a4SJacob Faibussowitsch 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)
7146d71ae5a4SJacob Faibussowitsch {
7147d3d1a6afSToby Isaac   Mat             cMat;
7148d3d1a6afSToby Isaac   PetscSection    aSec, cSec;
7149d3d1a6afSToby Isaac   IS              aIS;
7150d3d1a6afSToby Isaac   PetscInt        aStart = -1, aEnd = -1;
7151d3d1a6afSToby Isaac   const PetscInt *anchors;
7152e17c06e0SMatthew G. Knepley   PetscInt        numFields, f, p, q, newP = 0;
7153d3d1a6afSToby Isaac   PetscInt        newNumPoints = 0, newNumIndices = 0;
7154d3d1a6afSToby Isaac   PetscInt       *newPoints, *indices, *newIndices;
7155d3d1a6afSToby Isaac   PetscInt        maxAnchor, maxDof;
7156d3d1a6afSToby Isaac   PetscInt        newOffsets[32];
7157d3d1a6afSToby Isaac   PetscInt       *pointMatOffsets[32];
7158d3d1a6afSToby Isaac   PetscInt       *newPointOffsets[32];
7159d3d1a6afSToby Isaac   PetscScalar    *pointMat[32];
71606ecaa68aSToby Isaac   PetscScalar    *newValues      = NULL, *tmpValues;
7161d3d1a6afSToby Isaac   PetscBool       anyConstrained = PETSC_FALSE;
7162d3d1a6afSToby Isaac 
7163d3d1a6afSToby Isaac   PetscFunctionBegin;
7164d3d1a6afSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
7165d3d1a6afSToby Isaac   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
71669566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
7167d3d1a6afSToby Isaac 
71689566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS));
7169d3d1a6afSToby Isaac   /* if there are point-to-point constraints */
7170d3d1a6afSToby Isaac   if (aSec) {
71719566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(newOffsets, 32));
71729566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(aIS, &anchors));
71739566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(aSec, &aStart, &aEnd));
7174d3d1a6afSToby Isaac     /* figure out how many points are going to be in the new element matrix
7175d3d1a6afSToby Isaac      * (we allow double counting, because it's all just going to be summed
7176d3d1a6afSToby Isaac      * into the global matrix anyway) */
7177d3d1a6afSToby Isaac     for (p = 0; p < 2 * numPoints; p += 2) {
7178d3d1a6afSToby Isaac       PetscInt b    = points[p];
71794b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7180d3d1a6afSToby Isaac 
71819566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
7182ad540459SPierre Jolivet       if (!bSecDof) continue;
718348a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7184d3d1a6afSToby Isaac       if (bDof) {
7185d3d1a6afSToby Isaac         /* this point is constrained */
7186d3d1a6afSToby Isaac         /* it is going to be replaced by its anchors */
7187d3d1a6afSToby Isaac         PetscInt bOff, q;
7188d3d1a6afSToby Isaac 
7189d3d1a6afSToby Isaac         anyConstrained = PETSC_TRUE;
7190d3d1a6afSToby Isaac         newNumPoints += bDof;
71919566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7192d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7193d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q];
7194d3d1a6afSToby Isaac           PetscInt aDof;
7195d3d1a6afSToby Isaac 
71969566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section, a, &aDof));
7197d3d1a6afSToby Isaac           newNumIndices += aDof;
7198d3d1a6afSToby Isaac           for (f = 0; f < numFields; ++f) {
7199d3d1a6afSToby Isaac             PetscInt fDof;
7200d3d1a6afSToby Isaac 
72019566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, a, f, &fDof));
7202d3d1a6afSToby Isaac             newOffsets[f + 1] += fDof;
7203d3d1a6afSToby Isaac           }
7204d3d1a6afSToby Isaac         }
72059371c9d4SSatish Balay       } else {
7206d3d1a6afSToby Isaac         /* this point is not constrained */
7207d3d1a6afSToby Isaac         newNumPoints++;
72084b2f2278SToby Isaac         newNumIndices += bSecDof;
7209d3d1a6afSToby Isaac         for (f = 0; f < numFields; ++f) {
7210d3d1a6afSToby Isaac           PetscInt fDof;
7211d3d1a6afSToby Isaac 
72129566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
7213d3d1a6afSToby Isaac           newOffsets[f + 1] += fDof;
7214d3d1a6afSToby Isaac         }
7215d3d1a6afSToby Isaac       }
7216d3d1a6afSToby Isaac     }
7217d3d1a6afSToby Isaac   }
7218d3d1a6afSToby Isaac   if (!anyConstrained) {
721972b80496SMatthew G. Knepley     if (outNumPoints) *outNumPoints = 0;
722072b80496SMatthew G. Knepley     if (outNumIndices) *outNumIndices = 0;
722172b80496SMatthew G. Knepley     if (outPoints) *outPoints = NULL;
722272b80496SMatthew G. Knepley     if (outValues) *outValues = NULL;
72239566063dSJacob Faibussowitsch     if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors));
72243ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
7225d3d1a6afSToby Isaac   }
7226d3d1a6afSToby Isaac 
72276ecaa68aSToby Isaac   if (outNumPoints) *outNumPoints = newNumPoints;
72286ecaa68aSToby Isaac   if (outNumIndices) *outNumIndices = newNumIndices;
72296ecaa68aSToby Isaac 
7230f13f9184SToby Isaac   for (f = 0; f < numFields; ++f) newOffsets[f + 1] += newOffsets[f];
7231d3d1a6afSToby Isaac 
72326ecaa68aSToby Isaac   if (!outPoints && !outValues) {
72336ecaa68aSToby Isaac     if (offsets) {
7234ad540459SPierre Jolivet       for (f = 0; f <= numFields; f++) offsets[f] = newOffsets[f];
72356ecaa68aSToby Isaac     }
72369566063dSJacob Faibussowitsch     if (aSec) PetscCall(ISRestoreIndices(aIS, &anchors));
72373ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
72386ecaa68aSToby Isaac   }
72396ecaa68aSToby Isaac 
72401dca8a05SBarry 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);
7241d3d1a6afSToby Isaac 
72429566063dSJacob Faibussowitsch   PetscCall(DMGetDefaultConstraints(dm, &cSec, &cMat, NULL));
7243d3d1a6afSToby Isaac 
7244d3d1a6afSToby Isaac   /* workspaces */
7245d3d1a6afSToby Isaac   if (numFields) {
7246d3d1a6afSToby Isaac     for (f = 0; f < numFields; f++) {
72479566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[f]));
72489566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[f]));
7249d3d1a6afSToby Isaac     }
72509371c9d4SSatish Balay   } else {
72519566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[0]));
72529566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, numPoints, MPIU_INT, &newPointOffsets[0]));
7253d3d1a6afSToby Isaac   }
7254d3d1a6afSToby Isaac 
7255d3d1a6afSToby Isaac   /* get workspaces for the point-to-point matrices */
7256d3d1a6afSToby Isaac   if (numFields) {
72574b2f2278SToby Isaac     PetscInt totalOffset, totalMatOffset;
72584b2f2278SToby Isaac 
7259d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
7260d3d1a6afSToby Isaac       PetscInt b    = points[2 * p];
72614b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7262d3d1a6afSToby Isaac 
72639566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
72644b2f2278SToby Isaac       if (!bSecDof) {
72654b2f2278SToby Isaac         for (f = 0; f < numFields; f++) {
72664b2f2278SToby Isaac           newPointOffsets[f][p + 1] = 0;
72674b2f2278SToby Isaac           pointMatOffsets[f][p + 1] = 0;
72684b2f2278SToby Isaac         }
72694b2f2278SToby Isaac         continue;
72704b2f2278SToby Isaac       }
727148a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7272d3d1a6afSToby Isaac       if (bDof) {
7273d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7274d3d1a6afSToby Isaac           PetscInt fDof, q, bOff, allFDof = 0;
7275d3d1a6afSToby Isaac 
72769566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
72779566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7278d3d1a6afSToby Isaac           for (q = 0; q < bDof; q++) {
7279d3d1a6afSToby Isaac             PetscInt a = anchors[bOff + q];
7280d3d1a6afSToby Isaac             PetscInt aFDof;
7281d3d1a6afSToby Isaac 
72829566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, a, f, &aFDof));
7283d3d1a6afSToby Isaac             allFDof += aFDof;
7284d3d1a6afSToby Isaac           }
7285d3d1a6afSToby Isaac           newPointOffsets[f][p + 1] = allFDof;
7286d3d1a6afSToby Isaac           pointMatOffsets[f][p + 1] = fDof * allFDof;
7287d3d1a6afSToby Isaac         }
72889371c9d4SSatish Balay       } else {
7289d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7290d3d1a6afSToby Isaac           PetscInt fDof;
7291d3d1a6afSToby Isaac 
72929566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &fDof));
7293d3d1a6afSToby Isaac           newPointOffsets[f][p + 1] = fDof;
7294d3d1a6afSToby Isaac           pointMatOffsets[f][p + 1] = 0;
7295d3d1a6afSToby Isaac         }
7296d3d1a6afSToby Isaac       }
7297d3d1a6afSToby Isaac     }
72984b2f2278SToby Isaac     for (f = 0, totalOffset = 0, totalMatOffset = 0; f < numFields; f++) {
72994b2f2278SToby Isaac       newPointOffsets[f][0] = totalOffset;
73004b2f2278SToby Isaac       pointMatOffsets[f][0] = totalMatOffset;
7301d3d1a6afSToby Isaac       for (p = 0; p < numPoints; p++) {
7302d3d1a6afSToby Isaac         newPointOffsets[f][p + 1] += newPointOffsets[f][p];
7303d3d1a6afSToby Isaac         pointMatOffsets[f][p + 1] += pointMatOffsets[f][p];
7304d3d1a6afSToby Isaac       }
730519f70fd5SToby Isaac       totalOffset    = newPointOffsets[f][numPoints];
730619f70fd5SToby Isaac       totalMatOffset = pointMatOffsets[f][numPoints];
73079566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm, pointMatOffsets[f][numPoints], MPIU_SCALAR, &pointMat[f]));
7308d3d1a6afSToby Isaac     }
73099371c9d4SSatish Balay   } else {
7310d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
7311d3d1a6afSToby Isaac       PetscInt b    = points[2 * p];
73124b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7313d3d1a6afSToby Isaac 
73149566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
73154b2f2278SToby Isaac       if (!bSecDof) {
73164b2f2278SToby Isaac         newPointOffsets[0][p + 1] = 0;
73174b2f2278SToby Isaac         pointMatOffsets[0][p + 1] = 0;
73184b2f2278SToby Isaac         continue;
73194b2f2278SToby Isaac       }
732048a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7321d3d1a6afSToby Isaac       if (bDof) {
73224b2f2278SToby Isaac         PetscInt bOff, q, allDof = 0;
7323d3d1a6afSToby Isaac 
73249566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7325d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7326d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aDof;
7327d3d1a6afSToby Isaac 
73289566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section, a, &aDof));
7329d3d1a6afSToby Isaac           allDof += aDof;
7330d3d1a6afSToby Isaac         }
7331d3d1a6afSToby Isaac         newPointOffsets[0][p + 1] = allDof;
73324b2f2278SToby Isaac         pointMatOffsets[0][p + 1] = bSecDof * allDof;
73339371c9d4SSatish Balay       } else {
73344b2f2278SToby Isaac         newPointOffsets[0][p + 1] = bSecDof;
7335d3d1a6afSToby Isaac         pointMatOffsets[0][p + 1] = 0;
7336d3d1a6afSToby Isaac       }
7337d3d1a6afSToby Isaac     }
7338d3d1a6afSToby Isaac     newPointOffsets[0][0] = 0;
7339d3d1a6afSToby Isaac     pointMatOffsets[0][0] = 0;
7340d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
7341d3d1a6afSToby Isaac       newPointOffsets[0][p + 1] += newPointOffsets[0][p];
7342d3d1a6afSToby Isaac       pointMatOffsets[0][p + 1] += pointMatOffsets[0][p];
7343d3d1a6afSToby Isaac     }
73449566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, pointMatOffsets[0][numPoints], MPIU_SCALAR, &pointMat[0]));
7345d3d1a6afSToby Isaac   }
7346d3d1a6afSToby Isaac 
73476ecaa68aSToby Isaac   /* output arrays */
73489566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints));
73496ecaa68aSToby Isaac 
7350d3d1a6afSToby Isaac   /* get the point-to-point matrices; construct newPoints */
73519566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetMaxDof(aSec, &maxAnchor));
73529566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetMaxDof(section, &maxDof));
73539566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxDof, MPIU_INT, &indices));
73549566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, maxAnchor * maxDof, MPIU_INT, &newIndices));
7355d3d1a6afSToby Isaac   if (numFields) {
7356d3d1a6afSToby Isaac     for (p = 0, newP = 0; p < numPoints; p++) {
7357d3d1a6afSToby Isaac       PetscInt b    = points[2 * p];
7358d3d1a6afSToby Isaac       PetscInt o    = points[2 * p + 1];
73594b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7360d3d1a6afSToby Isaac 
73619566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
7362ad540459SPierre Jolivet       if (!bSecDof) continue;
736348a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7364d3d1a6afSToby Isaac       if (bDof) {
7365d3d1a6afSToby Isaac         PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q;
7366d3d1a6afSToby Isaac 
7367d3d1a6afSToby Isaac         fStart[0] = 0;
7368d3d1a6afSToby Isaac         fEnd[0]   = 0;
7369d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7370d3d1a6afSToby Isaac           PetscInt fDof;
7371d3d1a6afSToby Isaac 
73729566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(cSec, b, f, &fDof));
7373d3d1a6afSToby Isaac           fStart[f + 1] = fStart[f] + fDof;
7374d3d1a6afSToby Isaac           fEnd[f + 1]   = fStart[f + 1];
7375d3d1a6afSToby Isaac         }
73769566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(cSec, b, &bOff));
73779566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFields_Internal(cSec, PETSC_TRUE, b, bOff, fEnd, PETSC_TRUE, perms, p, NULL, indices));
7378d3d1a6afSToby Isaac 
7379d3d1a6afSToby Isaac         fAnchorStart[0] = 0;
7380d3d1a6afSToby Isaac         fAnchorEnd[0]   = 0;
7381d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7382d3d1a6afSToby Isaac           PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p];
7383d3d1a6afSToby Isaac 
7384d3d1a6afSToby Isaac           fAnchorStart[f + 1] = fAnchorStart[f] + fDof;
7385d3d1a6afSToby Isaac           fAnchorEnd[f + 1]   = fAnchorStart[f + 1];
7386d3d1a6afSToby Isaac         }
73879566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7388d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7389d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aOff;
7390d3d1a6afSToby Isaac 
7391d3d1a6afSToby 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 */
7392d3d1a6afSToby Isaac           newPoints[2 * (newP + q)]     = a;
7393d3d1a6afSToby Isaac           newPoints[2 * (newP + q) + 1] = 0;
73949566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(section, a, &aOff));
73959566063dSJacob Faibussowitsch           PetscCall(DMPlexGetIndicesPointFields_Internal(section, PETSC_TRUE, a, aOff, fAnchorEnd, PETSC_TRUE, NULL, -1, NULL, newIndices));
7396d3d1a6afSToby Isaac         }
7397d3d1a6afSToby Isaac         newP += bDof;
7398d3d1a6afSToby Isaac 
73996ecaa68aSToby Isaac         if (outValues) {
7400d3d1a6afSToby Isaac           /* get the point-to-point submatrix */
740148a46eb9SPierre Jolivet           for (f = 0; f < numFields; f++) PetscCall(MatGetValues(cMat, fEnd[f] - fStart[f], indices + fStart[f], fAnchorEnd[f] - fAnchorStart[f], newIndices + fAnchorStart[f], pointMat[f] + pointMatOffsets[f][p]));
7402d3d1a6afSToby Isaac         }
74039371c9d4SSatish Balay       } else {
7404d3d1a6afSToby Isaac         newPoints[2 * newP]     = b;
7405d3d1a6afSToby Isaac         newPoints[2 * newP + 1] = o;
7406d3d1a6afSToby Isaac         newP++;
7407d3d1a6afSToby Isaac       }
7408d3d1a6afSToby Isaac     }
7409d3d1a6afSToby Isaac   } else {
7410d3d1a6afSToby Isaac     for (p = 0; p < numPoints; p++) {
7411d3d1a6afSToby Isaac       PetscInt b    = points[2 * p];
7412d3d1a6afSToby Isaac       PetscInt o    = points[2 * p + 1];
74134b2f2278SToby Isaac       PetscInt bDof = 0, bSecDof;
7414d3d1a6afSToby Isaac 
74159566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, b, &bSecDof));
7416ad540459SPierre Jolivet       if (!bSecDof) continue;
741748a46eb9SPierre Jolivet       if (b >= aStart && b < aEnd) PetscCall(PetscSectionGetDof(aSec, b, &bDof));
7418d3d1a6afSToby Isaac       if (bDof) {
7419d3d1a6afSToby Isaac         PetscInt bEnd = 0, bAnchorEnd = 0, bOff;
7420d3d1a6afSToby Isaac 
74219566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(cSec, b, &bOff));
74229566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPoint_Internal(cSec, PETSC_TRUE, b, bOff, &bEnd, PETSC_TRUE, (perms && perms[0]) ? perms[0][p] : NULL, NULL, indices));
7423d3d1a6afSToby Isaac 
74249566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, b, &bOff));
7425d3d1a6afSToby Isaac         for (q = 0; q < bDof; q++) {
7426d3d1a6afSToby Isaac           PetscInt a = anchors[bOff + q], aOff;
7427d3d1a6afSToby Isaac 
7428d3d1a6afSToby 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 */
7429d3d1a6afSToby Isaac 
7430d3d1a6afSToby Isaac           newPoints[2 * (newP + q)]     = a;
7431d3d1a6afSToby Isaac           newPoints[2 * (newP + q) + 1] = 0;
74329566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(section, a, &aOff));
74339566063dSJacob Faibussowitsch           PetscCall(DMPlexGetIndicesPoint_Internal(section, PETSC_TRUE, a, aOff, &bAnchorEnd, PETSC_TRUE, NULL, NULL, newIndices));
7434d3d1a6afSToby Isaac         }
7435d3d1a6afSToby Isaac         newP += bDof;
7436d3d1a6afSToby Isaac 
7437d3d1a6afSToby Isaac         /* get the point-to-point submatrix */
743848a46eb9SPierre Jolivet         if (outValues) PetscCall(MatGetValues(cMat, bEnd, indices, bAnchorEnd, newIndices, pointMat[0] + pointMatOffsets[0][p]));
74399371c9d4SSatish Balay       } else {
7440d3d1a6afSToby Isaac         newPoints[2 * newP]     = b;
7441d3d1a6afSToby Isaac         newPoints[2 * newP + 1] = o;
7442d3d1a6afSToby Isaac         newP++;
7443d3d1a6afSToby Isaac       }
7444d3d1a6afSToby Isaac     }
7445d3d1a6afSToby Isaac   }
7446d3d1a6afSToby Isaac 
74476ecaa68aSToby Isaac   if (outValues) {
74489566063dSJacob Faibussowitsch     PetscCall(DMGetWorkArray(dm, newNumIndices * numIndices, MPIU_SCALAR, &tmpValues));
74499566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(tmpValues, newNumIndices * numIndices));
7450d3d1a6afSToby Isaac     /* multiply constraints on the right */
7451d3d1a6afSToby Isaac     if (numFields) {
7452d3d1a6afSToby Isaac       for (f = 0; f < numFields; f++) {
7453d3d1a6afSToby Isaac         PetscInt oldOff = offsets[f];
7454d3d1a6afSToby Isaac 
7455d3d1a6afSToby Isaac         for (p = 0; p < numPoints; p++) {
7456d3d1a6afSToby Isaac           PetscInt cStart = newPointOffsets[f][p];
7457d3d1a6afSToby Isaac           PetscInt b      = points[2 * p];
7458d3d1a6afSToby Isaac           PetscInt c, r, k;
7459d3d1a6afSToby Isaac           PetscInt dof;
7460d3d1a6afSToby Isaac 
74619566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, b, f, &dof));
7462ad540459SPierre Jolivet           if (!dof) continue;
7463d3d1a6afSToby Isaac           if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) {
7464d3d1a6afSToby Isaac             PetscInt           nCols = newPointOffsets[f][p + 1] - cStart;
7465d3d1a6afSToby Isaac             const PetscScalar *mat   = pointMat[f] + pointMatOffsets[f][p];
7466d3d1a6afSToby Isaac 
7467d3d1a6afSToby Isaac             for (r = 0; r < numIndices; r++) {
7468d3d1a6afSToby Isaac               for (c = 0; c < nCols; c++) {
7469ad540459SPierre Jolivet                 for (k = 0; k < dof; k++) tmpValues[r * newNumIndices + cStart + c] += values[r * numIndices + oldOff + k] * mat[k * nCols + c];
7470d3d1a6afSToby Isaac               }
7471d3d1a6afSToby Isaac             }
74729371c9d4SSatish Balay           } else {
7473d3d1a6afSToby Isaac             /* copy this column as is */
7474d3d1a6afSToby Isaac             for (r = 0; r < numIndices; r++) {
7475ad540459SPierre Jolivet               for (c = 0; c < dof; c++) tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c];
7476d3d1a6afSToby Isaac             }
7477d3d1a6afSToby Isaac           }
7478d3d1a6afSToby Isaac           oldOff += dof;
7479d3d1a6afSToby Isaac         }
7480d3d1a6afSToby Isaac       }
74819371c9d4SSatish Balay     } else {
7482d3d1a6afSToby Isaac       PetscInt oldOff = 0;
7483d3d1a6afSToby Isaac       for (p = 0; p < numPoints; p++) {
7484d3d1a6afSToby Isaac         PetscInt cStart = newPointOffsets[0][p];
7485d3d1a6afSToby Isaac         PetscInt b      = points[2 * p];
7486d3d1a6afSToby Isaac         PetscInt c, r, k;
7487d3d1a6afSToby Isaac         PetscInt dof;
7488d3d1a6afSToby Isaac 
74899566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, b, &dof));
7490ad540459SPierre Jolivet         if (!dof) continue;
7491d3d1a6afSToby Isaac         if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) {
7492d3d1a6afSToby Isaac           PetscInt           nCols = newPointOffsets[0][p + 1] - cStart;
7493d3d1a6afSToby Isaac           const PetscScalar *mat   = pointMat[0] + pointMatOffsets[0][p];
7494d3d1a6afSToby Isaac 
7495d3d1a6afSToby Isaac           for (r = 0; r < numIndices; r++) {
7496d3d1a6afSToby Isaac             for (c = 0; c < nCols; c++) {
7497ad540459SPierre Jolivet               for (k = 0; k < dof; k++) tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k];
7498d3d1a6afSToby Isaac             }
7499d3d1a6afSToby Isaac           }
75009371c9d4SSatish Balay         } else {
7501d3d1a6afSToby Isaac           /* copy this column as is */
7502d3d1a6afSToby Isaac           for (r = 0; r < numIndices; r++) {
7503ad540459SPierre Jolivet             for (c = 0; c < dof; c++) tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c];
7504d3d1a6afSToby Isaac           }
7505d3d1a6afSToby Isaac         }
7506d3d1a6afSToby Isaac         oldOff += dof;
7507d3d1a6afSToby Isaac       }
7508d3d1a6afSToby Isaac     }
7509d3d1a6afSToby Isaac 
75106ecaa68aSToby Isaac     if (multiplyLeft) {
75119566063dSJacob Faibussowitsch       PetscCall(DMGetWorkArray(dm, newNumIndices * newNumIndices, MPIU_SCALAR, &newValues));
75129566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(newValues, newNumIndices * newNumIndices));
7513d3d1a6afSToby Isaac       /* multiply constraints transpose on the left */
7514d3d1a6afSToby Isaac       if (numFields) {
7515d3d1a6afSToby Isaac         for (f = 0; f < numFields; f++) {
7516d3d1a6afSToby Isaac           PetscInt oldOff = offsets[f];
7517d3d1a6afSToby Isaac 
7518d3d1a6afSToby Isaac           for (p = 0; p < numPoints; p++) {
7519d3d1a6afSToby Isaac             PetscInt rStart = newPointOffsets[f][p];
7520d3d1a6afSToby Isaac             PetscInt b      = points[2 * p];
7521d3d1a6afSToby Isaac             PetscInt c, r, k;
7522d3d1a6afSToby Isaac             PetscInt dof;
7523d3d1a6afSToby Isaac 
75249566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, b, f, &dof));
7525d3d1a6afSToby Isaac             if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) {
7526d3d1a6afSToby Isaac               PetscInt                          nRows = newPointOffsets[f][p + 1] - rStart;
7527d3d1a6afSToby Isaac               const PetscScalar *PETSC_RESTRICT mat   = pointMat[f] + pointMatOffsets[f][p];
7528d3d1a6afSToby Isaac 
7529d3d1a6afSToby Isaac               for (r = 0; r < nRows; r++) {
7530d3d1a6afSToby Isaac                 for (c = 0; c < newNumIndices; c++) {
7531ad540459SPierre Jolivet                   for (k = 0; k < dof; k++) newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c];
7532d3d1a6afSToby Isaac                 }
7533d3d1a6afSToby Isaac               }
75349371c9d4SSatish Balay             } else {
7535d3d1a6afSToby Isaac               /* copy this row as is */
7536d3d1a6afSToby Isaac               for (r = 0; r < dof; r++) {
7537ad540459SPierre Jolivet                 for (c = 0; c < newNumIndices; c++) newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c];
7538d3d1a6afSToby Isaac               }
7539d3d1a6afSToby Isaac             }
7540d3d1a6afSToby Isaac             oldOff += dof;
7541d3d1a6afSToby Isaac           }
7542d3d1a6afSToby Isaac         }
75439371c9d4SSatish Balay       } else {
7544d3d1a6afSToby Isaac         PetscInt oldOff = 0;
7545d3d1a6afSToby Isaac 
7546d3d1a6afSToby Isaac         for (p = 0; p < numPoints; p++) {
7547d3d1a6afSToby Isaac           PetscInt rStart = newPointOffsets[0][p];
7548d3d1a6afSToby Isaac           PetscInt b      = points[2 * p];
7549d3d1a6afSToby Isaac           PetscInt c, r, k;
7550d3d1a6afSToby Isaac           PetscInt dof;
7551d3d1a6afSToby Isaac 
75529566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section, b, &dof));
7553d3d1a6afSToby Isaac           if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) {
7554d3d1a6afSToby Isaac             PetscInt                          nRows = newPointOffsets[0][p + 1] - rStart;
7555d3d1a6afSToby Isaac             const PetscScalar *PETSC_RESTRICT mat   = pointMat[0] + pointMatOffsets[0][p];
7556d3d1a6afSToby Isaac 
7557d3d1a6afSToby Isaac             for (r = 0; r < nRows; r++) {
7558d3d1a6afSToby Isaac               for (c = 0; c < newNumIndices; c++) {
7559ad540459SPierre Jolivet                 for (k = 0; k < dof; k++) newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c];
7560d3d1a6afSToby Isaac               }
7561d3d1a6afSToby Isaac             }
75629371c9d4SSatish Balay           } else {
7563d3d1a6afSToby Isaac             /* copy this row as is */
75649fc93327SToby Isaac             for (r = 0; r < dof; r++) {
7565ad540459SPierre Jolivet               for (c = 0; c < newNumIndices; c++) newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c];
7566d3d1a6afSToby Isaac             }
7567d3d1a6afSToby Isaac           }
7568d3d1a6afSToby Isaac           oldOff += dof;
7569d3d1a6afSToby Isaac         }
7570d3d1a6afSToby Isaac       }
7571d3d1a6afSToby Isaac 
75729566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm, newNumIndices * numIndices, MPIU_SCALAR, &tmpValues));
75739371c9d4SSatish Balay     } else {
75746ecaa68aSToby Isaac       newValues = tmpValues;
75756ecaa68aSToby Isaac     }
75766ecaa68aSToby Isaac   }
75776ecaa68aSToby Isaac 
7578d3d1a6afSToby Isaac   /* clean up */
75799566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, maxDof, MPIU_INT, &indices));
75809566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, maxAnchor * maxDof, MPIU_INT, &newIndices));
75816ecaa68aSToby Isaac 
7582d3d1a6afSToby Isaac   if (numFields) {
7583d3d1a6afSToby Isaac     for (f = 0; f < numFields; f++) {
75849566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm, pointMatOffsets[f][numPoints], MPIU_SCALAR, &pointMat[f]));
75859566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[f]));
75869566063dSJacob Faibussowitsch       PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[f]));
7587d3d1a6afSToby Isaac     }
75889371c9d4SSatish Balay   } else {
75899566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, pointMatOffsets[0][numPoints], MPIU_SCALAR, &pointMat[0]));
75909566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &pointMatOffsets[0]));
75919566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, numPoints + 1, MPIU_INT, &newPointOffsets[0]));
7592d3d1a6afSToby Isaac   }
75939566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(aIS, &anchors));
7594d3d1a6afSToby Isaac 
7595d3d1a6afSToby Isaac   /* output */
75966ecaa68aSToby Isaac   if (outPoints) {
7597d3d1a6afSToby Isaac     *outPoints = newPoints;
75989371c9d4SSatish Balay   } else {
75999566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, 2 * newNumPoints, MPIU_INT, &newPoints));
76006ecaa68aSToby Isaac   }
7601ad540459SPierre Jolivet   if (outValues) *outValues = newValues;
7602ad540459SPierre Jolivet   for (f = 0; f <= numFields; f++) offsets[f] = newOffsets[f];
76033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7604d3d1a6afSToby Isaac }
7605d3d1a6afSToby Isaac 
76064a1e0b3eSMatthew G. Knepley /*@C
760771f0bbf9SMatthew G. Knepley   DMPlexGetClosureIndices - Gets the global dof indices associated with the closure of the given point within the provided sections.
76087cd05799SMatthew G. Knepley 
76097cd05799SMatthew G. Knepley   Not collective
76107cd05799SMatthew G. Knepley 
76117cd05799SMatthew G. Knepley   Input Parameters:
7612a1cb98faSBarry Smith + dm         - The `DM`
7613a1cb98faSBarry Smith . section    - The `PetscSection` describing the points (a local section)
7614a1cb98faSBarry Smith . idxSection - The `PetscSection` from which to obtain indices (may be local or global)
761571f0bbf9SMatthew G. Knepley . point      - The point defining the closure
761671f0bbf9SMatthew G. Knepley - useClPerm  - Use the closure point permutation if available
76177cd05799SMatthew G. Knepley 
761871f0bbf9SMatthew G. Knepley   Output Parameters:
761971f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections
762071f0bbf9SMatthew G. Knepley . indices    - The dof indices
762120f4b53cSBarry Smith . outOffsets - Array to write the field offsets into, or `NULL`
762220f4b53cSBarry Smith - values     - The input values, which may be modified if sign flips are induced by the point symmetries, or `NULL`
76237cd05799SMatthew G. Knepley 
7624a1cb98faSBarry Smith   Level: advanced
762536fa2b79SJed Brown 
7626a1cb98faSBarry Smith   Notes:
7627a1cb98faSBarry Smith   Must call `DMPlexRestoreClosureIndices()` to free allocated memory
7628a1cb98faSBarry Smith 
762920f4b53cSBarry Smith   If `idxSection` is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices.  The value
763020f4b53cSBarry Smith   of those indices is not significant.  If `idxSection` is local, the constrained dofs will yield the involution -(idx+1)
763136fa2b79SJed Brown   of their index in a local vector.  A caller who does not wish to distinguish those points may recover the nonnegative
763220f4b53cSBarry Smith   indices via involution, -(-(idx+1)+1)==idx.  Local indices are provided when `idxSection` == section, otherwise global
763336fa2b79SJed Brown   indices (with the above semantics) are implied.
76347cd05799SMatthew G. Knepley 
76351cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexRestoreClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`,
7636a1cb98faSBarry Smith           `PetscSection`, `DMGetGlobalSection()`
76374a1e0b3eSMatthew G. Knepley @*/
7638d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[])
7639d71ae5a4SJacob Faibussowitsch {
764071f0bbf9SMatthew G. Knepley   /* Closure ordering */
76417773e69fSMatthew G. Knepley   PetscSection    clSection;
76427773e69fSMatthew G. Knepley   IS              clPoints;
764371f0bbf9SMatthew G. Knepley   const PetscInt *clp;
764471f0bbf9SMatthew G. Knepley   PetscInt       *points;
764571f0bbf9SMatthew G. Knepley   const PetscInt *clperm = NULL;
764671f0bbf9SMatthew G. Knepley   /* Dof permutation and sign flips */
76474acb8e1eSToby Isaac   const PetscInt    **perms[32] = {NULL};
764871f0bbf9SMatthew G. Knepley   const PetscScalar **flips[32] = {NULL};
764971f0bbf9SMatthew G. Knepley   PetscScalar        *valCopy   = NULL;
765071f0bbf9SMatthew G. Knepley   /* Hanging node constraints */
765171f0bbf9SMatthew G. Knepley   PetscInt    *pointsC = NULL;
765271f0bbf9SMatthew G. Knepley   PetscScalar *valuesC = NULL;
765371f0bbf9SMatthew G. Knepley   PetscInt     NclC, NiC;
765471f0bbf9SMatthew G. Knepley 
765571f0bbf9SMatthew G. Knepley   PetscInt *idx;
765671f0bbf9SMatthew G. Knepley   PetscInt  Nf, Ncl, Ni = 0, offsets[32], p, f;
765771f0bbf9SMatthew G. Knepley   PetscBool isLocal = (section == idxSection) ? PETSC_TRUE : PETSC_FALSE;
76587773e69fSMatthew G. Knepley 
765971f0bbf9SMatthew G. Knepley   PetscFunctionBeginHot;
76607773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
76617773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
766236fa2b79SJed Brown   PetscValidHeaderSpecific(idxSection, PETSC_SECTION_CLASSID, 3);
76634f572ea9SToby Isaac   if (numIndices) PetscAssertPointer(numIndices, 6);
76644f572ea9SToby Isaac   if (indices) PetscAssertPointer(indices, 7);
76654f572ea9SToby Isaac   if (outOffsets) PetscAssertPointer(outOffsets, 8);
76664f572ea9SToby Isaac   if (values) PetscAssertPointer(values, 9);
76679566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &Nf));
766863a3b9bcSJacob Faibussowitsch   PetscCheck(Nf <= 31, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", Nf);
76699566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(offsets, 32));
767071f0bbf9SMatthew G. Knepley   /* 1) Get points in closure */
767107218a29SMatthew G. Knepley   PetscCall(DMPlexGetCompressedClosure(dm, section, point, 0, &Ncl, &points, &clSection, &clPoints, &clp));
7672c459fbc1SJed Brown   if (useClPerm) {
7673c459fbc1SJed Brown     PetscInt depth, clsize;
76749566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPointDepth(dm, point, &depth));
7675c459fbc1SJed Brown     for (clsize = 0, p = 0; p < Ncl; p++) {
7676c459fbc1SJed Brown       PetscInt dof;
76779566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, points[2 * p], &dof));
7678c459fbc1SJed Brown       clsize += dof;
7679c459fbc1SJed Brown     }
76809566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetClosureInversePermutation_Internal(section, (PetscObject)dm, depth, clsize, &clperm));
7681c459fbc1SJed Brown   }
768271f0bbf9SMatthew G. Knepley   /* 2) Get number of indices on these points and field offsets from section */
768371f0bbf9SMatthew G. Knepley   for (p = 0; p < Ncl * 2; p += 2) {
76847773e69fSMatthew G. Knepley     PetscInt dof, fdof;
76857773e69fSMatthew G. Knepley 
76869566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(section, points[p], &dof));
76877773e69fSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
76889566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(section, points[p], f, &fdof));
76897773e69fSMatthew G. Knepley       offsets[f + 1] += fdof;
76907773e69fSMatthew G. Knepley     }
769171f0bbf9SMatthew G. Knepley     Ni += dof;
76927773e69fSMatthew G. Knepley   }
76937773e69fSMatthew G. Knepley   for (f = 1; f < Nf; ++f) offsets[f + 1] += offsets[f];
76941dca8a05SBarry 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);
769571f0bbf9SMatthew G. Knepley   /* 3) Get symmetries and sign flips. Apply sign flips to values if passed in (only works for square values matrix) */
769671f0bbf9SMatthew G. Knepley   for (f = 0; f < PetscMax(1, Nf); ++f) {
76979566063dSJacob Faibussowitsch     if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
76989566063dSJacob Faibussowitsch     else PetscCall(PetscSectionGetPointSyms(section, Ncl, points, &perms[f], &flips[f]));
769971f0bbf9SMatthew G. Knepley     /* may need to apply sign changes to the element matrix */
770071f0bbf9SMatthew G. Knepley     if (values && flips[f]) {
770171f0bbf9SMatthew G. Knepley       PetscInt foffset = offsets[f];
77026ecaa68aSToby Isaac 
770371f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
770471f0bbf9SMatthew G. Knepley         PetscInt           pnt  = points[2 * p], fdof;
770571f0bbf9SMatthew G. Knepley         const PetscScalar *flip = flips[f] ? flips[f][p] : NULL;
770671f0bbf9SMatthew G. Knepley 
77079566063dSJacob Faibussowitsch         if (!Nf) PetscCall(PetscSectionGetDof(section, pnt, &fdof));
77089566063dSJacob Faibussowitsch         else PetscCall(PetscSectionGetFieldDof(section, pnt, f, &fdof));
770971f0bbf9SMatthew G. Knepley         if (flip) {
771071f0bbf9SMatthew G. Knepley           PetscInt i, j, k;
771171f0bbf9SMatthew G. Knepley 
771271f0bbf9SMatthew G. Knepley           if (!valCopy) {
77139566063dSJacob Faibussowitsch             PetscCall(DMGetWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy));
771471f0bbf9SMatthew G. Knepley             for (j = 0; j < Ni * Ni; ++j) valCopy[j] = (*values)[j];
771571f0bbf9SMatthew G. Knepley             *values = valCopy;
771671f0bbf9SMatthew G. Knepley           }
771771f0bbf9SMatthew G. Knepley           for (i = 0; i < fdof; ++i) {
771871f0bbf9SMatthew G. Knepley             PetscScalar fval = flip[i];
771971f0bbf9SMatthew G. Knepley 
772071f0bbf9SMatthew G. Knepley             for (k = 0; k < Ni; ++k) {
772171f0bbf9SMatthew G. Knepley               valCopy[Ni * (foffset + i) + k] *= fval;
772271f0bbf9SMatthew G. Knepley               valCopy[Ni * k + (foffset + i)] *= fval;
77236ecaa68aSToby Isaac             }
77246ecaa68aSToby Isaac           }
772571f0bbf9SMatthew G. Knepley         }
772671f0bbf9SMatthew G. Knepley         foffset += fdof;
772771f0bbf9SMatthew G. Knepley       }
772871f0bbf9SMatthew G. Knepley     }
772971f0bbf9SMatthew G. Knepley   }
773071f0bbf9SMatthew G. Knepley   /* 4) Apply hanging node constraints. Get new symmetries and replace all storage with constrained storage */
77319566063dSJacob Faibussowitsch   PetscCall(DMPlexAnchorsModifyMat(dm, section, Ncl, Ni, points, perms, values ? *values : NULL, &NclC, &NiC, &pointsC, values ? &valuesC : NULL, offsets, PETSC_TRUE));
773271f0bbf9SMatthew G. Knepley   if (NclC) {
77339566063dSJacob Faibussowitsch     if (valCopy) PetscCall(DMRestoreWorkArray(dm, Ni * Ni, MPIU_SCALAR, &valCopy));
773471f0bbf9SMatthew G. Knepley     for (f = 0; f < PetscMax(1, Nf); ++f) {
77359566063dSJacob Faibussowitsch       if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
77369566063dSJacob Faibussowitsch       else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]));
773771f0bbf9SMatthew G. Knepley     }
773871f0bbf9SMatthew G. Knepley     for (f = 0; f < PetscMax(1, Nf); ++f) {
77399566063dSJacob Faibussowitsch       if (Nf) PetscCall(PetscSectionGetFieldPointSyms(section, f, NclC, pointsC, &perms[f], &flips[f]));
77409566063dSJacob Faibussowitsch       else PetscCall(PetscSectionGetPointSyms(section, NclC, pointsC, &perms[f], &flips[f]));
774171f0bbf9SMatthew G. Knepley     }
77429566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
774371f0bbf9SMatthew G. Knepley     Ncl    = NclC;
774471f0bbf9SMatthew G. Knepley     Ni     = NiC;
774571f0bbf9SMatthew G. Knepley     points = pointsC;
774671f0bbf9SMatthew G. Knepley     if (values) *values = valuesC;
774771f0bbf9SMatthew G. Knepley   }
774871f0bbf9SMatthew G. Knepley   /* 5) Calculate indices */
77499566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dm, Ni, MPIU_INT, &idx));
775071f0bbf9SMatthew G. Knepley   if (Nf) {
775171f0bbf9SMatthew G. Knepley     PetscInt  idxOff;
775271f0bbf9SMatthew G. Knepley     PetscBool useFieldOffsets;
775371f0bbf9SMatthew G. Knepley 
77549371c9d4SSatish Balay     if (outOffsets) {
77559371c9d4SSatish Balay       for (f = 0; f <= Nf; f++) outOffsets[f] = offsets[f];
77569371c9d4SSatish Balay     }
77579566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetUseFieldOffsets(idxSection, &useFieldOffsets));
775871f0bbf9SMatthew G. Knepley     if (useFieldOffsets) {
775971f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
776071f0bbf9SMatthew G. Knepley         const PetscInt pnt = points[p * 2];
776171f0bbf9SMatthew G. Knepley 
77629566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFieldsSplit_Internal(section, idxSection, pnt, offsets, perms, p, clperm, idx));
77637773e69fSMatthew G. Knepley       }
77647773e69fSMatthew G. Knepley     } else {
776571f0bbf9SMatthew G. Knepley       for (p = 0; p < Ncl; ++p) {
776671f0bbf9SMatthew G. Knepley         const PetscInt pnt = points[p * 2];
776771f0bbf9SMatthew G. Knepley 
77689566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff));
776971f0bbf9SMatthew G. Knepley         /* Note that we pass a local section even though we're using global offsets.  This is because global sections do
777071f0bbf9SMatthew G. Knepley          * not (at the time of this writing) have fields set. They probably should, in which case we would pass the
777171f0bbf9SMatthew G. Knepley          * global section. */
77729566063dSJacob Faibussowitsch         PetscCall(DMPlexGetIndicesPointFields_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, offsets, PETSC_FALSE, perms, p, clperm, idx));
777371f0bbf9SMatthew G. Knepley       }
777471f0bbf9SMatthew G. Knepley     }
777571f0bbf9SMatthew G. Knepley   } else {
777671f0bbf9SMatthew G. Knepley     PetscInt off = 0, idxOff;
777771f0bbf9SMatthew G. Knepley 
777871f0bbf9SMatthew G. Knepley     for (p = 0; p < Ncl; ++p) {
777971f0bbf9SMatthew G. Knepley       const PetscInt  pnt  = points[p * 2];
77804acb8e1eSToby Isaac       const PetscInt *perm = perms[0] ? perms[0][p] : NULL;
77814acb8e1eSToby Isaac 
77829566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(idxSection, pnt, &idxOff));
778371f0bbf9SMatthew G. Knepley       /* Note that we pass a local section even though we're using global offsets.  This is because global sections do
778471f0bbf9SMatthew G. Knepley        * not (at the time of this writing) have fields set. They probably should, in which case we would pass the global section. */
77859566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(section, isLocal, pnt, idxOff < 0 ? -(idxOff + 1) : idxOff, &off, PETSC_FALSE, perm, clperm, idx));
77867773e69fSMatthew G. Knepley     }
77877773e69fSMatthew G. Knepley   }
778871f0bbf9SMatthew G. Knepley   /* 6) Cleanup */
778971f0bbf9SMatthew G. Knepley   for (f = 0; f < PetscMax(1, Nf); ++f) {
77909566063dSJacob Faibussowitsch     if (Nf) PetscCall(PetscSectionRestoreFieldPointSyms(section, f, Ncl, points, &perms[f], &flips[f]));
77919566063dSJacob Faibussowitsch     else PetscCall(PetscSectionRestorePointSyms(section, Ncl, points, &perms[f], &flips[f]));
77924acb8e1eSToby Isaac   }
779371f0bbf9SMatthew G. Knepley   if (NclC) {
77949566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dm, NclC * 2, MPIU_INT, &pointsC));
77957773e69fSMatthew G. Knepley   } else {
77969566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreCompressedClosure(dm, section, point, &Ncl, &points, &clSection, &clPoints, &clp));
77977773e69fSMatthew G. Knepley   }
779871f0bbf9SMatthew G. Knepley 
779971f0bbf9SMatthew G. Knepley   if (numIndices) *numIndices = Ni;
780071f0bbf9SMatthew G. Knepley   if (indices) *indices = idx;
78013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
78027773e69fSMatthew G. Knepley }
78037773e69fSMatthew G. Knepley 
78047cd05799SMatthew G. Knepley /*@C
780571f0bbf9SMatthew G. Knepley   DMPlexRestoreClosureIndices - Restores the global dof indices associated with the closure of the given point within the provided sections.
78067cd05799SMatthew G. Knepley 
78077cd05799SMatthew G. Knepley   Not collective
78087cd05799SMatthew G. Knepley 
78097cd05799SMatthew G. Knepley   Input Parameters:
7810a1cb98faSBarry Smith + dm         - The `DM`
7811a1cb98faSBarry Smith . section    - The `PetscSection` describing the points (a local section)
7812a1cb98faSBarry Smith . idxSection - The `PetscSection` from which to obtain indices (may be local or global)
781371f0bbf9SMatthew G. Knepley . point      - The point defining the closure
781471f0bbf9SMatthew G. Knepley - useClPerm  - Use the closure point permutation if available
781571f0bbf9SMatthew G. Knepley 
781671f0bbf9SMatthew G. Knepley   Output Parameters:
781771f0bbf9SMatthew G. Knepley + numIndices - The number of dof indices in the closure of point with the input sections
781871f0bbf9SMatthew G. Knepley . indices    - The dof indices
781920f4b53cSBarry Smith . outOffsets - Array to write the field offsets into, or `NULL`
782020f4b53cSBarry Smith - values     - The input values, which may be modified if sign flips are induced by the point symmetries, or `NULL`
782171f0bbf9SMatthew G. Knepley 
7822a1cb98faSBarry Smith   Level: advanced
782371f0bbf9SMatthew G. Knepley 
7824a1cb98faSBarry Smith   Notes:
7825a1cb98faSBarry Smith   If values were modified, the user is responsible for calling `DMRestoreWorkArray`(dm, 0, `MPIU_SCALAR`, &values).
7826a1cb98faSBarry Smith 
7827a1cb98faSBarry Smith   If idxSection is global, any constrained dofs (see `DMAddBoundary()`, for example) will get negative indices.  The value
782871f0bbf9SMatthew G. Knepley   of those indices is not significant.  If idxSection is local, the constrained dofs will yield the involution -(idx+1)
782971f0bbf9SMatthew G. Knepley   of their index in a local vector.  A caller who does not wish to distinguish those points may recover the nonnegative
783071f0bbf9SMatthew G. Knepley   indices via involution, -(-(idx+1)+1)==idx.  Local indices are provided when idxSection == section, otherwise global
783171f0bbf9SMatthew G. Knepley   indices (with the above semantics) are implied.
78327cd05799SMatthew G. Knepley 
78331cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetClosureIndices()`, `DMPlexVecGetClosure()`, `DMPlexMatSetClosure()`, `DMGetLocalSection()`, `DMGetGlobalSection()`
78347cd05799SMatthew G. Knepley @*/
7835d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection idxSection, PetscInt point, PetscBool useClPerm, PetscInt *numIndices, PetscInt *indices[], PetscInt outOffsets[], PetscScalar *values[])
7836d71ae5a4SJacob Faibussowitsch {
78377773e69fSMatthew G. Knepley   PetscFunctionBegin;
78387773e69fSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
78394f572ea9SToby Isaac   PetscAssertPointer(indices, 7);
78409566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, indices));
78413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
78427773e69fSMatthew G. Knepley }
78437773e69fSMatthew G. Knepley 
78447f5d1fdeSMatthew G. Knepley /*@C
78457f5d1fdeSMatthew G. Knepley   DMPlexMatSetClosure - Set an array of the values on the closure of 'point'
78467f5d1fdeSMatthew G. Knepley 
78477f5d1fdeSMatthew G. Knepley   Not collective
78487f5d1fdeSMatthew G. Knepley 
78497f5d1fdeSMatthew G. Knepley   Input Parameters:
7850a1cb98faSBarry Smith + dm            - The `DM`
785120f4b53cSBarry Smith . section       - The section describing the layout in `v`, or `NULL` to use the default section
785220f4b53cSBarry Smith . globalSection - The section describing the layout in `v`, or `NULL` to use the default global section
78537f5d1fdeSMatthew G. Knepley . A             - The matrix
7854a1cb98faSBarry Smith . point         - The point in the `DM`
78557f5d1fdeSMatthew G. Knepley . values        - The array of values
7856a1cb98faSBarry Smith - mode          - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions
78577f5d1fdeSMatthew G. Knepley 
78587f5d1fdeSMatthew G. Knepley   Level: intermediate
78597f5d1fdeSMatthew G. Knepley 
78601cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosureGeneral()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`
78617f5d1fdeSMatthew G. Knepley @*/
7862d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
7863d71ae5a4SJacob Faibussowitsch {
7864552f7358SJed Brown   DM_Plex           *mesh = (DM_Plex *)dm->data;
7865552f7358SJed Brown   PetscInt          *indices;
786671f0bbf9SMatthew G. Knepley   PetscInt           numIndices;
786771f0bbf9SMatthew G. Knepley   const PetscScalar *valuesOrig = values;
7868552f7358SJed Brown   PetscErrorCode     ierr;
7869552f7358SJed Brown 
7870552f7358SJed Brown   PetscFunctionBegin;
7871552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
78729566063dSJacob Faibussowitsch   if (!section) PetscCall(DMGetLocalSection(dm, &section));
78733dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2);
78749566063dSJacob Faibussowitsch   if (!globalSection) PetscCall(DMGetGlobalSection(dm, &globalSection));
78753dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3);
78763dc93601SMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 4);
7877552f7358SJed Brown 
78789566063dSJacob Faibussowitsch   PetscCall(DMPlexGetClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values));
78790d644c17SKarl Rupp 
78809566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values));
7881d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
78824a1e0b3eSMatthew G. Knepley   ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode);
7883552f7358SJed Brown   if (ierr) {
7884552f7358SJed Brown     PetscMPIInt rank;
7885552f7358SJed Brown 
78869566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
78879566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
78889566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values));
78899566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values));
78909566063dSJacob Faibussowitsch     if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values));
7891c3e24edfSBarry Smith     SETERRQ(PetscObjectComm((PetscObject)dm), ierr, "Not possible to set matrix values");
7892552f7358SJed Brown   }
78934a1e0b3eSMatthew G. Knepley   if (mesh->printFEM > 1) {
78944a1e0b3eSMatthew G. Knepley     PetscInt i;
78959566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "  Indices:"));
789663a3b9bcSJacob Faibussowitsch     for (i = 0; i < numIndices; ++i) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, indices[i]));
78979566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
78984a1e0b3eSMatthew G. Knepley   }
789971f0bbf9SMatthew G. Knepley 
79009566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreClosureIndices(dm, section, globalSection, point, PETSC_TRUE, &numIndices, &indices, NULL, (PetscScalar **)&values));
79019566063dSJacob Faibussowitsch   if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dm, 0, MPIU_SCALAR, &values));
79023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
79034acb8e1eSToby Isaac }
790471f0bbf9SMatthew G. Knepley 
79054a1e0b3eSMatthew G. Knepley /*@C
790660225df5SJacob Faibussowitsch   DMPlexMatSetClosureGeneral - Set an array of the values on the closure of 'point' using a different row and column section
79074a1e0b3eSMatthew G. Knepley 
79084a1e0b3eSMatthew G. Knepley   Not collective
79094a1e0b3eSMatthew G. Knepley 
79104a1e0b3eSMatthew G. Knepley   Input Parameters:
7911a1cb98faSBarry Smith + dmRow            - The `DM` for the row fields
791220f4b53cSBarry Smith . sectionRow       - The section describing the layout, or `NULL` to use the default section in `dmRow`
791320f4b53cSBarry Smith . globalSectionRow - The section describing the layout, or `NULL` to use the default global section in `dmRow`
7914a1cb98faSBarry Smith . dmCol            - The `DM` for the column fields
791520f4b53cSBarry Smith . sectionCol       - The section describing the layout, or `NULL` to use the default section in `dmCol`
791620f4b53cSBarry Smith . globalSectionCol - The section describing the layout, or `NULL` to use the default global section in `dmCol`
79174a1e0b3eSMatthew G. Knepley . A                - The matrix
7918a1cb98faSBarry Smith . point            - The point in the `DM`
79194a1e0b3eSMatthew G. Knepley . values           - The array of values
7920a1cb98faSBarry Smith - mode             - The insert mode, where `INSERT_ALL_VALUES` and `ADD_ALL_VALUES` also overwrite boundary conditions
79214a1e0b3eSMatthew G. Knepley 
79224a1e0b3eSMatthew G. Knepley   Level: intermediate
79234a1e0b3eSMatthew G. Knepley 
79241cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexMatSetClosure()`, `DMPlexVecGetClosure()`, `DMPlexVecSetClosure()`
79254a1e0b3eSMatthew G. Knepley @*/
7926d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatSetClosureGeneral(DM dmRow, PetscSection sectionRow, PetscSection globalSectionRow, DM dmCol, PetscSection sectionCol, PetscSection globalSectionCol, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
7927d71ae5a4SJacob Faibussowitsch {
792871f0bbf9SMatthew G. Knepley   DM_Plex           *mesh = (DM_Plex *)dmRow->data;
792971f0bbf9SMatthew G. Knepley   PetscInt          *indicesRow, *indicesCol;
793071f0bbf9SMatthew G. Knepley   PetscInt           numIndicesRow, numIndicesCol;
793171f0bbf9SMatthew G. Knepley   const PetscScalar *valuesOrig = values;
793271f0bbf9SMatthew G. Knepley   PetscErrorCode     ierr;
793371f0bbf9SMatthew G. Knepley 
793471f0bbf9SMatthew G. Knepley   PetscFunctionBegin;
793571f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(dmRow, DM_CLASSID, 1);
79369566063dSJacob Faibussowitsch   if (!sectionRow) PetscCall(DMGetLocalSection(dmRow, &sectionRow));
793771f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(sectionRow, PETSC_SECTION_CLASSID, 2);
79389566063dSJacob Faibussowitsch   if (!globalSectionRow) PetscCall(DMGetGlobalSection(dmRow, &globalSectionRow));
793971f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(globalSectionRow, PETSC_SECTION_CLASSID, 3);
794071f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(dmCol, DM_CLASSID, 4);
79419566063dSJacob Faibussowitsch   if (!sectionCol) PetscCall(DMGetLocalSection(dmCol, &sectionCol));
794271f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(sectionCol, PETSC_SECTION_CLASSID, 5);
79439566063dSJacob Faibussowitsch   if (!globalSectionCol) PetscCall(DMGetGlobalSection(dmCol, &globalSectionCol));
794471f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(globalSectionCol, PETSC_SECTION_CLASSID, 6);
794571f0bbf9SMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 7);
794671f0bbf9SMatthew G. Knepley 
79479566063dSJacob Faibussowitsch   PetscCall(DMPlexGetClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values));
79489566063dSJacob Faibussowitsch   PetscCall(DMPlexGetClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&values));
794971f0bbf9SMatthew G. Knepley 
79509566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values));
7951d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
79524a1e0b3eSMatthew G. Knepley   ierr = MatSetValues(A, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values, mode);
795371f0bbf9SMatthew G. Knepley   if (ierr) {
795471f0bbf9SMatthew G. Knepley     PetscMPIInt rank;
795571f0bbf9SMatthew G. Knepley 
79569566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
79579566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
79589566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndicesRow, indicesRow, numIndicesCol, indicesCol, values));
79599566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values));
79609566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesRow, NULL, (PetscScalar **)&values));
79619566063dSJacob Faibussowitsch     if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values));
7962d3d1a6afSToby Isaac   }
796371f0bbf9SMatthew G. Knepley 
79649566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreClosureIndices(dmRow, sectionRow, globalSectionRow, point, PETSC_TRUE, &numIndicesRow, &indicesRow, NULL, (PetscScalar **)&values));
79659566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreClosureIndices(dmCol, sectionCol, globalSectionCol, point, PETSC_TRUE, &numIndicesCol, &indicesCol, NULL, (PetscScalar **)&values));
79669566063dSJacob Faibussowitsch   if (values != valuesOrig) PetscCall(DMRestoreWorkArray(dmRow, 0, MPIU_SCALAR, &values));
79673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7968552f7358SJed Brown }
7969552f7358SJed Brown 
7970d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode)
7971d71ae5a4SJacob Faibussowitsch {
7972de41b84cSMatthew G. Knepley   DM_Plex        *mesh    = (DM_Plex *)dmf->data;
7973de41b84cSMatthew G. Knepley   PetscInt       *fpoints = NULL, *ftotpoints = NULL;
7974de41b84cSMatthew G. Knepley   PetscInt       *cpoints = NULL;
7975de41b84cSMatthew G. Knepley   PetscInt       *findices, *cindices;
797617c0192bSMatthew G. Knepley   const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */
7977de41b84cSMatthew G. Knepley   PetscInt        foffsets[32], coffsets[32];
7978412e9a14SMatthew G. Knepley   DMPolytopeType  ct;
79794ca5e9f5SMatthew G. Knepley   PetscInt        numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f;
7980de41b84cSMatthew G. Knepley   PetscErrorCode  ierr;
7981de41b84cSMatthew G. Knepley 
7982de41b84cSMatthew G. Knepley   PetscFunctionBegin;
7983de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 1);
7984de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 4);
79859566063dSJacob Faibussowitsch   if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection));
7986de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2);
79879566063dSJacob Faibussowitsch   if (!csection) PetscCall(DMGetLocalSection(dmc, &csection));
7988de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5);
79899566063dSJacob Faibussowitsch   if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection));
7990de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3);
79919566063dSJacob Faibussowitsch   if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection));
7992de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6);
7993de41b84cSMatthew G. Knepley   PetscValidHeaderSpecific(A, MAT_CLASSID, 7);
79949566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(fsection, &numFields));
799563a3b9bcSJacob Faibussowitsch   PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields);
79969566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(foffsets, 32));
79979566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(coffsets, 32));
7998de41b84cSMatthew G. Knepley   /* Column indices */
79999566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
80004ca5e9f5SMatthew G. Knepley   maxFPoints = numCPoints;
8001de41b84cSMatthew G. Knepley   /* Compress out points not in the section */
8002de41b84cSMatthew G. Knepley   /*   TODO: Squeeze out points with 0 dof as well */
80039566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd));
8004de41b84cSMatthew G. Knepley   for (p = 0, q = 0; p < numCPoints * 2; p += 2) {
8005de41b84cSMatthew G. Knepley     if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) {
8006de41b84cSMatthew G. Knepley       cpoints[q * 2]     = cpoints[p];
8007de41b84cSMatthew G. Knepley       cpoints[q * 2 + 1] = cpoints[p + 1];
8008de41b84cSMatthew G. Knepley       ++q;
8009de41b84cSMatthew G. Knepley     }
8010de41b84cSMatthew G. Knepley   }
8011de41b84cSMatthew G. Knepley   numCPoints = q;
8012de41b84cSMatthew G. Knepley   for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) {
8013de41b84cSMatthew G. Knepley     PetscInt fdof;
8014de41b84cSMatthew G. Knepley 
80159566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof));
80164ca5e9f5SMatthew G. Knepley     if (!dof) continue;
8017de41b84cSMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
80189566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof));
8019de41b84cSMatthew G. Knepley       coffsets[f + 1] += fdof;
8020de41b84cSMatthew G. Knepley     }
8021de41b84cSMatthew G. Knepley     numCIndices += dof;
8022de41b84cSMatthew G. Knepley   }
8023de41b84cSMatthew G. Knepley   for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f];
8024de41b84cSMatthew G. Knepley   /* Row indices */
80259566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dmc, point, &ct));
8026412e9a14SMatthew G. Knepley   {
8027012bc364SMatthew G. Knepley     DMPlexTransform tr;
8028012bc364SMatthew G. Knepley     DMPolytopeType *rct;
8029012bc364SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt, Nt;
8030012bc364SMatthew G. Knepley 
80319566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr));
80329566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR));
80339566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt));
8034012bc364SMatthew G. Knepley     numSubcells = rsize[Nt - 1];
80359566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformDestroy(&tr));
8036412e9a14SMatthew G. Knepley   }
80379566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints));
8038de41b84cSMatthew G. Knepley   for (r = 0, q = 0; r < numSubcells; ++r) {
8039de41b84cSMatthew G. Knepley     /* TODO Map from coarse to fine cells */
80409566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints));
8041de41b84cSMatthew G. Knepley     /* Compress out points not in the section */
80429566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd));
8043de41b84cSMatthew G. Knepley     for (p = 0; p < numFPoints * 2; p += 2) {
8044de41b84cSMatthew G. Knepley       if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) {
80459566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof));
80464ca5e9f5SMatthew G. Knepley         if (!dof) continue;
80479371c9d4SSatish Balay         for (s = 0; s < q; ++s)
80489371c9d4SSatish Balay           if (fpoints[p] == ftotpoints[s * 2]) break;
80494ca5e9f5SMatthew G. Knepley         if (s < q) continue;
8050de41b84cSMatthew G. Knepley         ftotpoints[q * 2]     = fpoints[p];
8051de41b84cSMatthew G. Knepley         ftotpoints[q * 2 + 1] = fpoints[p + 1];
8052de41b84cSMatthew G. Knepley         ++q;
8053de41b84cSMatthew G. Knepley       }
8054de41b84cSMatthew G. Knepley     }
80559566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints));
8056de41b84cSMatthew G. Knepley   }
8057de41b84cSMatthew G. Knepley   numFPoints = q;
8058de41b84cSMatthew G. Knepley   for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) {
8059de41b84cSMatthew G. Knepley     PetscInt fdof;
8060de41b84cSMatthew G. Knepley 
80619566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof));
80624ca5e9f5SMatthew G. Knepley     if (!dof) continue;
8063de41b84cSMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
80649566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof));
8065de41b84cSMatthew G. Knepley       foffsets[f + 1] += fdof;
8066de41b84cSMatthew G. Knepley     }
8067de41b84cSMatthew G. Knepley     numFIndices += dof;
8068de41b84cSMatthew G. Knepley   }
8069de41b84cSMatthew G. Knepley   for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f];
8070de41b84cSMatthew G. Knepley 
80711dca8a05SBarry 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);
80721dca8a05SBarry 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);
80739566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, numFIndices, MPIU_INT, &findices));
80749566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
8075de41b84cSMatthew G. Knepley   if (numFields) {
80764acb8e1eSToby Isaac     const PetscInt **permsF[32] = {NULL};
80774acb8e1eSToby Isaac     const PetscInt **permsC[32] = {NULL};
80784acb8e1eSToby Isaac 
80794acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
80809566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
80819566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
8082de41b84cSMatthew G. Knepley     }
80834acb8e1eSToby Isaac     for (p = 0; p < numFPoints; p++) {
80849566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
80859566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices));
80864acb8e1eSToby Isaac     }
80874acb8e1eSToby Isaac     for (p = 0; p < numCPoints; p++) {
80889566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
80899566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices));
80904acb8e1eSToby Isaac     }
80914acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
80929566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
80939566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
8094de41b84cSMatthew G. Knepley     }
8095de41b84cSMatthew G. Knepley   } else {
80964acb8e1eSToby Isaac     const PetscInt **permsF = NULL;
80974acb8e1eSToby Isaac     const PetscInt **permsC = NULL;
80984acb8e1eSToby Isaac 
80999566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
81009566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL));
81014acb8e1eSToby Isaac     for (p = 0, off = 0; p < numFPoints; p++) {
81024acb8e1eSToby Isaac       const PetscInt *perm = permsF ? permsF[p] : NULL;
81034acb8e1eSToby Isaac 
81049566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
81059566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices));
8106de41b84cSMatthew G. Knepley     }
81074acb8e1eSToby Isaac     for (p = 0, off = 0; p < numCPoints; p++) {
81084acb8e1eSToby Isaac       const PetscInt *perm = permsC ? permsC[p] : NULL;
81094acb8e1eSToby Isaac 
81109566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
81119566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices));
8112de41b84cSMatthew G. Knepley     }
81139566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
81149566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL));
8115de41b84cSMatthew G. Knepley   }
81169566063dSJacob Faibussowitsch   if (mesh->printSetValues) PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values));
81174acb8e1eSToby Isaac   /* TODO: flips */
8118d0609cedSBarry Smith   /* TODO: fix this code to not use error codes as handle-able exceptions! */
8119de41b84cSMatthew G. Knepley   ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode);
8120de41b84cSMatthew G. Knepley   if (ierr) {
8121de41b84cSMatthew G. Knepley     PetscMPIInt rank;
8122de41b84cSMatthew G. Knepley 
81239566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank));
81249566063dSJacob Faibussowitsch     PetscCall((*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank));
81259566063dSJacob Faibussowitsch     PetscCall(DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values));
81269566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices));
81279566063dSJacob Faibussowitsch     PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
8128de41b84cSMatthew G. Knepley   }
81299566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints));
81309566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
81319566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numFIndices, MPIU_INT, &findices));
81329566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmc, numCIndices, MPIU_INT, &cindices));
81333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8134de41b84cSMatthew G. Knepley }
8135de41b84cSMatthew G. Knepley 
8136d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[])
8137d71ae5a4SJacob Faibussowitsch {
81387c927364SMatthew G. Knepley   PetscInt       *fpoints = NULL, *ftotpoints = NULL;
81397c927364SMatthew G. Knepley   PetscInt       *cpoints = NULL;
81407c927364SMatthew G. Knepley   PetscInt        foffsets[32], coffsets[32];
814117c0192bSMatthew G. Knepley   const PetscInt *fclperm = NULL, *cclperm = NULL; /* Closure permutations cannot work here */
8142412e9a14SMatthew G. Knepley   DMPolytopeType  ct;
81437c927364SMatthew G. Knepley   PetscInt        numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f;
81447c927364SMatthew G. Knepley 
81457c927364SMatthew G. Knepley   PetscFunctionBegin;
81467c927364SMatthew G. Knepley   PetscValidHeaderSpecific(dmf, DM_CLASSID, 1);
81477c927364SMatthew G. Knepley   PetscValidHeaderSpecific(dmc, DM_CLASSID, 4);
81489566063dSJacob Faibussowitsch   if (!fsection) PetscCall(DMGetLocalSection(dmf, &fsection));
81497c927364SMatthew G. Knepley   PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2);
81509566063dSJacob Faibussowitsch   if (!csection) PetscCall(DMGetLocalSection(dmc, &csection));
81517c927364SMatthew G. Knepley   PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5);
81529566063dSJacob Faibussowitsch   if (!globalFSection) PetscCall(DMGetGlobalSection(dmf, &globalFSection));
81537c927364SMatthew G. Knepley   PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3);
81549566063dSJacob Faibussowitsch   if (!globalCSection) PetscCall(DMGetGlobalSection(dmc, &globalCSection));
81557c927364SMatthew G. Knepley   PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6);
81569566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(fsection, &numFields));
815763a3b9bcSJacob Faibussowitsch   PetscCheck(numFields <= 31, PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %" PetscInt_FMT " limited to 31", numFields);
81589566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(foffsets, 32));
81599566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(coffsets, 32));
81607c927364SMatthew G. Knepley   /* Column indices */
81619566063dSJacob Faibussowitsch   PetscCall(DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
81627c927364SMatthew G. Knepley   maxFPoints = numCPoints;
81637c927364SMatthew G. Knepley   /* Compress out points not in the section */
81647c927364SMatthew G. Knepley   /*   TODO: Squeeze out points with 0 dof as well */
81659566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(csection, &pStart, &pEnd));
81667c927364SMatthew G. Knepley   for (p = 0, q = 0; p < numCPoints * 2; p += 2) {
81677c927364SMatthew G. Knepley     if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) {
81687c927364SMatthew G. Knepley       cpoints[q * 2]     = cpoints[p];
81697c927364SMatthew G. Knepley       cpoints[q * 2 + 1] = cpoints[p + 1];
81707c927364SMatthew G. Knepley       ++q;
81717c927364SMatthew G. Knepley     }
81727c927364SMatthew G. Knepley   }
81737c927364SMatthew G. Knepley   numCPoints = q;
81747c927364SMatthew G. Knepley   for (p = 0, numCIndices = 0; p < numCPoints * 2; p += 2) {
81757c927364SMatthew G. Knepley     PetscInt fdof;
81767c927364SMatthew G. Knepley 
81779566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(csection, cpoints[p], &dof));
81787c927364SMatthew G. Knepley     if (!dof) continue;
81797c927364SMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
81809566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof));
81817c927364SMatthew G. Knepley       coffsets[f + 1] += fdof;
81827c927364SMatthew G. Knepley     }
81837c927364SMatthew G. Knepley     numCIndices += dof;
81847c927364SMatthew G. Knepley   }
81857c927364SMatthew G. Knepley   for (f = 1; f < numFields; ++f) coffsets[f + 1] += coffsets[f];
81867c927364SMatthew G. Knepley   /* Row indices */
81879566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dmc, point, &ct));
8188412e9a14SMatthew G. Knepley   {
8189012bc364SMatthew G. Knepley     DMPlexTransform tr;
8190012bc364SMatthew G. Knepley     DMPolytopeType *rct;
8191012bc364SMatthew G. Knepley     PetscInt       *rsize, *rcone, *rornt, Nt;
8192012bc364SMatthew G. Knepley 
81939566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr));
81949566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR));
81959566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nt, &rct, &rsize, &rcone, &rornt));
8196012bc364SMatthew G. Knepley     numSubcells = rsize[Nt - 1];
81979566063dSJacob Faibussowitsch     PetscCall(DMPlexTransformDestroy(&tr));
8198412e9a14SMatthew G. Knepley   }
81999566063dSJacob Faibussowitsch   PetscCall(DMGetWorkArray(dmf, maxFPoints * 2 * numSubcells, MPIU_INT, &ftotpoints));
82007c927364SMatthew G. Knepley   for (r = 0, q = 0; r < numSubcells; ++r) {
82017c927364SMatthew G. Knepley     /* TODO Map from coarse to fine cells */
82029566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dmf, point * numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints));
82037c927364SMatthew G. Knepley     /* Compress out points not in the section */
82049566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(fsection, &pStart, &pEnd));
82057c927364SMatthew G. Knepley     for (p = 0; p < numFPoints * 2; p += 2) {
82067c927364SMatthew G. Knepley       if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) {
82079566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(fsection, fpoints[p], &dof));
82087c927364SMatthew G. Knepley         if (!dof) continue;
82099371c9d4SSatish Balay         for (s = 0; s < q; ++s)
82109371c9d4SSatish Balay           if (fpoints[p] == ftotpoints[s * 2]) break;
82117c927364SMatthew G. Knepley         if (s < q) continue;
82127c927364SMatthew G. Knepley         ftotpoints[q * 2]     = fpoints[p];
82137c927364SMatthew G. Knepley         ftotpoints[q * 2 + 1] = fpoints[p + 1];
82147c927364SMatthew G. Knepley         ++q;
82157c927364SMatthew G. Knepley       }
82167c927364SMatthew G. Knepley     }
82179566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints));
82187c927364SMatthew G. Knepley   }
82197c927364SMatthew G. Knepley   numFPoints = q;
82207c927364SMatthew G. Knepley   for (p = 0, numFIndices = 0; p < numFPoints * 2; p += 2) {
82217c927364SMatthew G. Knepley     PetscInt fdof;
82227c927364SMatthew G. Knepley 
82239566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(fsection, ftotpoints[p], &dof));
82247c927364SMatthew G. Knepley     if (!dof) continue;
82257c927364SMatthew G. Knepley     for (f = 0; f < numFields; ++f) {
82269566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof));
82277c927364SMatthew G. Knepley       foffsets[f + 1] += fdof;
82287c927364SMatthew G. Knepley     }
82297c927364SMatthew G. Knepley     numFIndices += dof;
82307c927364SMatthew G. Knepley   }
82317c927364SMatthew G. Knepley   for (f = 1; f < numFields; ++f) foffsets[f + 1] += foffsets[f];
82327c927364SMatthew G. Knepley 
82331dca8a05SBarry 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);
82341dca8a05SBarry 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);
82357c927364SMatthew G. Knepley   if (numFields) {
82364acb8e1eSToby Isaac     const PetscInt **permsF[32] = {NULL};
82374acb8e1eSToby Isaac     const PetscInt **permsC[32] = {NULL};
82384acb8e1eSToby Isaac 
82394acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
82409566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
82419566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
82427c927364SMatthew G. Knepley     }
82434acb8e1eSToby Isaac     for (p = 0; p < numFPoints; p++) {
82449566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
82459566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, foffsets, PETSC_FALSE, permsF, p, fclperm, findices));
82464acb8e1eSToby Isaac     }
82474acb8e1eSToby Isaac     for (p = 0; p < numCPoints; p++) {
82489566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
82499566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPointFields_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, coffsets, PETSC_FALSE, permsC, p, cclperm, cindices));
82504acb8e1eSToby Isaac     }
82514acb8e1eSToby Isaac     for (f = 0; f < numFields; f++) {
82529566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(fsection, f, numFPoints, ftotpoints, &permsF[f], NULL));
82539566063dSJacob Faibussowitsch       PetscCall(PetscSectionRestoreFieldPointSyms(csection, f, numCPoints, cpoints, &permsC[f], NULL));
82547c927364SMatthew G. Knepley     }
82557c927364SMatthew G. Knepley   } else {
82564acb8e1eSToby Isaac     const PetscInt **permsF = NULL;
82574acb8e1eSToby Isaac     const PetscInt **permsC = NULL;
82584acb8e1eSToby Isaac 
82599566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
82609566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointSyms(csection, numCPoints, cpoints, &permsC, NULL));
82614acb8e1eSToby Isaac     for (p = 0, off = 0; p < numFPoints; p++) {
82624acb8e1eSToby Isaac       const PetscInt *perm = permsF ? permsF[p] : NULL;
82634acb8e1eSToby Isaac 
82649566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalFSection, ftotpoints[2 * p], &globalOff));
82659566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(fsection, PETSC_FALSE, ftotpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, fclperm, findices));
82667c927364SMatthew G. Knepley     }
82674acb8e1eSToby Isaac     for (p = 0, off = 0; p < numCPoints; p++) {
82684acb8e1eSToby Isaac       const PetscInt *perm = permsC ? permsC[p] : NULL;
82694acb8e1eSToby Isaac 
82709566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(globalCSection, cpoints[2 * p], &globalOff));
82719566063dSJacob Faibussowitsch       PetscCall(DMPlexGetIndicesPoint_Internal(csection, PETSC_FALSE, cpoints[2 * p], globalOff < 0 ? -(globalOff + 1) : globalOff, &off, PETSC_FALSE, perm, cclperm, cindices));
82727c927364SMatthew G. Knepley     }
82739566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(fsection, numFPoints, ftotpoints, &permsF, NULL));
82749566063dSJacob Faibussowitsch     PetscCall(PetscSectionRestorePointSyms(csection, numCPoints, cpoints, &permsC, NULL));
82757c927364SMatthew G. Knepley   }
82769566063dSJacob Faibussowitsch   PetscCall(DMRestoreWorkArray(dmf, numCPoints * 2 * 4, MPIU_INT, &ftotpoints));
82779566063dSJacob Faibussowitsch   PetscCall(DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints));
82783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
82797c927364SMatthew G. Knepley }
82807c927364SMatthew G. Knepley 
82817cd05799SMatthew G. Knepley /*@C
82827cd05799SMatthew G. Knepley   DMPlexGetVTKCellHeight - Returns the height in the DAG used to determine which points are cells (normally 0)
82837cd05799SMatthew G. Knepley 
82847cd05799SMatthew G. Knepley   Input Parameter:
8285a1cb98faSBarry Smith . dm - The `DMPLEX` object
82867cd05799SMatthew G. Knepley 
82877cd05799SMatthew G. Knepley   Output Parameter:
82887cd05799SMatthew G. Knepley . cellHeight - The height of a cell
82897cd05799SMatthew G. Knepley 
82907cd05799SMatthew G. Knepley   Level: developer
82917cd05799SMatthew G. Knepley 
82921cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetVTKCellHeight()`
82937cd05799SMatthew G. Knepley @*/
8294d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight)
8295d71ae5a4SJacob Faibussowitsch {
8296552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
8297552f7358SJed Brown 
8298552f7358SJed Brown   PetscFunctionBegin;
8299552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
83004f572ea9SToby Isaac   PetscAssertPointer(cellHeight, 2);
8301552f7358SJed Brown   *cellHeight = mesh->vtkCellHeight;
83023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8303552f7358SJed Brown }
8304552f7358SJed Brown 
83057cd05799SMatthew G. Knepley /*@C
83067cd05799SMatthew G. Knepley   DMPlexSetVTKCellHeight - Sets the height in the DAG used to determine which points are cells (normally 0)
83077cd05799SMatthew G. Knepley 
83087cd05799SMatthew G. Knepley   Input Parameters:
8309a1cb98faSBarry Smith + dm         - The `DMPLEX` object
83107cd05799SMatthew G. Knepley - cellHeight - The height of a cell
83117cd05799SMatthew G. Knepley 
83127cd05799SMatthew G. Knepley   Level: developer
83137cd05799SMatthew G. Knepley 
83141cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetVTKCellHeight()`
83157cd05799SMatthew G. Knepley @*/
8316d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight)
8317d71ae5a4SJacob Faibussowitsch {
8318552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
8319552f7358SJed Brown 
8320552f7358SJed Brown   PetscFunctionBegin;
8321552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
8322552f7358SJed Brown   mesh->vtkCellHeight = cellHeight;
83233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8324552f7358SJed Brown }
8325552f7358SJed Brown 
8326e6139122SMatthew G. Knepley /*@
83272827ebadSStefano Zampini   DMPlexGetCellTypeStratum - Get the range of cells of a given celltype
8328e6139122SMatthew G. Knepley 
83292827ebadSStefano Zampini   Input Parameters:
83302827ebadSStefano Zampini + dm - The `DMPLEX` object
83312827ebadSStefano Zampini - ct - The `DMPolytopeType` of the cell
8332e6139122SMatthew G. Knepley 
8333e6139122SMatthew G. Knepley   Output Parameters:
83342827ebadSStefano Zampini + start - The first cell of this type, or `NULL`
83352827ebadSStefano Zampini - end   - The upper bound on this celltype, or `NULL`
8336e6139122SMatthew G. Knepley 
83372a9f31c0SMatthew G. Knepley   Level: advanced
8338e6139122SMatthew G. Knepley 
83392827ebadSStefano Zampini .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexConstructGhostCells()`, `DMPlexGetDepthStratum()`, `DMPlexGetHeightStratum()`
8340e6139122SMatthew G. Knepley @*/
83412827ebadSStefano Zampini PetscErrorCode DMPlexGetCellTypeStratum(DM dm, DMPolytopeType ct, PetscInt *start, PetscInt *end)
8342d71ae5a4SJacob Faibussowitsch {
83432827ebadSStefano Zampini   DM_Plex *mesh = (DM_Plex *)dm->data;
83442827ebadSStefano Zampini   DMLabel  label;
83452827ebadSStefano Zampini   PetscInt pStart, pEnd;
8346e6139122SMatthew G. Knepley 
8347e6139122SMatthew G. Knepley   PetscFunctionBegin;
8348e6139122SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
83492827ebadSStefano Zampini   if (start) {
83504f572ea9SToby Isaac     PetscAssertPointer(start, 3);
83512827ebadSStefano Zampini     *start = 0;
83522827ebadSStefano Zampini   }
83532827ebadSStefano Zampini   if (end) {
83544f572ea9SToby Isaac     PetscAssertPointer(end, 4);
83552827ebadSStefano Zampini     *end = 0;
83562827ebadSStefano Zampini   }
83572827ebadSStefano Zampini   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
83582827ebadSStefano Zampini   if (pStart == pEnd) PetscFunctionReturn(PETSC_SUCCESS);
83592827ebadSStefano Zampini   if (mesh->tr) {
83602827ebadSStefano Zampini     PetscCall(DMPlexTransformGetCellTypeStratum(mesh->tr, ct, start, end));
83612827ebadSStefano Zampini   } else {
83622827ebadSStefano Zampini     PetscCall(DMPlexGetCellTypeLabel(dm, &label));
83632827ebadSStefano Zampini     PetscCheck(label, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "No label named celltype was found");
83642827ebadSStefano Zampini     PetscCall(DMLabelGetStratumBounds(label, ct, start, end));
83652827ebadSStefano Zampini   }
83663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8367e6139122SMatthew G. Knepley }
8368e6139122SMatthew G. Knepley 
8369d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateNumbering_Plex(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering)
8370d71ae5a4SJacob Faibussowitsch {
8371552f7358SJed Brown   PetscSection section, globalSection;
8372552f7358SJed Brown   PetscInt    *numbers, p;
8373552f7358SJed Brown 
8374552f7358SJed Brown   PetscFunctionBegin;
8375d7d32a9aSMatthew G. Knepley   if (PetscDefined(USE_DEBUG)) PetscCall(DMPlexCheckPointSF(dm, sf, PETSC_TRUE));
83769566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &section));
83779566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(section, pStart, pEnd));
837848a46eb9SPierre Jolivet   for (p = pStart; p < pEnd; ++p) PetscCall(PetscSectionSetDof(section, p, 1));
83799566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(section));
83809566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection));
83819566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(pEnd - pStart, &numbers));
8382552f7358SJed Brown   for (p = pStart; p < pEnd; ++p) {
83839566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(globalSection, p, &numbers[p - pStart]));
8384ef48cebcSMatthew G. Knepley     if (numbers[p - pStart] < 0) numbers[p - pStart] -= shift;
8385ef48cebcSMatthew G. Knepley     else numbers[p - pStart] += shift;
8386552f7358SJed Brown   }
83879566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering));
8388ef48cebcSMatthew G. Knepley   if (globalSize) {
8389ef48cebcSMatthew G. Knepley     PetscLayout layout;
83909566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetPointLayout(PetscObjectComm((PetscObject)dm), globalSection, &layout));
83919566063dSJacob Faibussowitsch     PetscCall(PetscLayoutGetSize(layout, globalSize));
83929566063dSJacob Faibussowitsch     PetscCall(PetscLayoutDestroy(&layout));
8393ef48cebcSMatthew G. Knepley   }
83949566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&section));
83959566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&globalSection));
83963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8397552f7358SJed Brown }
8398552f7358SJed Brown 
8399d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCellNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalCellNumbers)
8400d71ae5a4SJacob Faibussowitsch {
8401412e9a14SMatthew G. Knepley   PetscInt cellHeight, cStart, cEnd;
8402552f7358SJed Brown 
8403552f7358SJed Brown   PetscFunctionBegin;
84049566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
84059566063dSJacob Faibussowitsch   if (includeHybrid) PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
84069566063dSJacob Faibussowitsch   else PetscCall(DMPlexGetSimplexOrBoxCells(dm, cellHeight, &cStart, &cEnd));
84079566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateNumbering_Plex(dm, cStart, cEnd, 0, NULL, dm->sf, globalCellNumbers));
84083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8409552f7358SJed Brown }
841081ed3555SMatthew G. Knepley 
84118dab3259SMatthew G. Knepley /*@
84127cd05799SMatthew G. Knepley   DMPlexGetCellNumbering - Get a global cell numbering for all cells on this process
84137cd05799SMatthew G. Knepley 
84147cd05799SMatthew G. Knepley   Input Parameter:
8415a1cb98faSBarry Smith . dm - The `DMPLEX` object
84167cd05799SMatthew G. Knepley 
84177cd05799SMatthew G. Knepley   Output Parameter:
84187cd05799SMatthew G. Knepley . globalCellNumbers - Global cell numbers for all cells on this process
84197cd05799SMatthew G. Knepley 
84207cd05799SMatthew G. Knepley   Level: developer
84217cd05799SMatthew G. Knepley 
84221cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetVertexNumbering()`
84237cd05799SMatthew G. Knepley @*/
8424d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers)
8425d71ae5a4SJacob Faibussowitsch {
842681ed3555SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
842781ed3555SMatthew G. Knepley 
842881ed3555SMatthew G. Knepley   PetscFunctionBegin;
842981ed3555SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
84309566063dSJacob Faibussowitsch   if (!mesh->globalCellNumbers) PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_FALSE, &mesh->globalCellNumbers));
8431552f7358SJed Brown   *globalCellNumbers = mesh->globalCellNumbers;
84323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8433552f7358SJed Brown }
8434552f7358SJed Brown 
8435d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateVertexNumbering_Internal(DM dm, PetscBool includeHybrid, IS *globalVertexNumbers)
8436d71ae5a4SJacob Faibussowitsch {
8437412e9a14SMatthew G. Knepley   PetscInt vStart, vEnd;
843881ed3555SMatthew G. Knepley 
843981ed3555SMatthew G. Knepley   PetscFunctionBegin;
844081ed3555SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
84419566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
84429566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateNumbering_Plex(dm, vStart, vEnd, 0, NULL, dm->sf, globalVertexNumbers));
84433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
844481ed3555SMatthew G. Knepley }
844581ed3555SMatthew G. Knepley 
84468dab3259SMatthew G. Knepley /*@
84476aa51ba9SJacob Faibussowitsch   DMPlexGetVertexNumbering - Get a global vertex numbering for all vertices on this process
84487cd05799SMatthew G. Knepley 
84497cd05799SMatthew G. Knepley   Input Parameter:
8450a1cb98faSBarry Smith . dm - The `DMPLEX` object
84517cd05799SMatthew G. Knepley 
84527cd05799SMatthew G. Knepley   Output Parameter:
84537cd05799SMatthew G. Knepley . globalVertexNumbers - Global vertex numbers for all vertices on this process
84547cd05799SMatthew G. Knepley 
84557cd05799SMatthew G. Knepley   Level: developer
84567cd05799SMatthew G. Knepley 
84571cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()`
84587cd05799SMatthew G. Knepley @*/
8459d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers)
8460d71ae5a4SJacob Faibussowitsch {
8461552f7358SJed Brown   DM_Plex *mesh = (DM_Plex *)dm->data;
8462552f7358SJed Brown 
8463552f7358SJed Brown   PetscFunctionBegin;
8464552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
84659566063dSJacob Faibussowitsch   if (!mesh->globalVertexNumbers) PetscCall(DMPlexCreateVertexNumbering_Internal(dm, PETSC_FALSE, &mesh->globalVertexNumbers));
8466552f7358SJed Brown   *globalVertexNumbers = mesh->globalVertexNumbers;
84673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8468552f7358SJed Brown }
8469552f7358SJed Brown 
84708dab3259SMatthew G. Knepley /*@
8471966484cfSJed Brown   DMPlexCreatePointNumbering - Create a global numbering for all points.
8472966484cfSJed Brown 
847320f4b53cSBarry Smith   Collective
84747cd05799SMatthew G. Knepley 
84757cd05799SMatthew G. Knepley   Input Parameter:
8476a1cb98faSBarry Smith . dm - The `DMPLEX` object
84777cd05799SMatthew G. Knepley 
84787cd05799SMatthew G. Knepley   Output Parameter:
84797cd05799SMatthew G. Knepley . globalPointNumbers - Global numbers for all points on this process
84807cd05799SMatthew G. Knepley 
8481a1cb98faSBarry Smith   Level: developer
8482966484cfSJed Brown 
8483a1cb98faSBarry Smith   Notes:
8484a1cb98faSBarry Smith   The point numbering `IS` is parallel, with local portion indexed by local points (see `DMGetLocalSection()`). The global
8485966484cfSJed Brown   points are taken as stratified, with each MPI rank owning a contiguous subset of each stratum. In the IS, owned points
8486966484cfSJed Brown   will have their non-negative value while points owned by different ranks will be involuted -(idx+1). As an example,
8487966484cfSJed Brown   consider a parallel mesh in which the first two elements and first two vertices are owned by rank 0.
8488966484cfSJed Brown 
8489966484cfSJed Brown   The partitioned mesh is
8490966484cfSJed Brown   ```
8491966484cfSJed Brown   (2)--0--(3)--1--(4)    (1)--0--(2)
8492966484cfSJed Brown   ```
8493966484cfSJed Brown   and its global numbering is
8494966484cfSJed Brown   ```
8495966484cfSJed Brown   (3)--0--(4)--1--(5)--2--(6)
8496966484cfSJed Brown   ```
8497966484cfSJed Brown   Then the global numbering is provided as
8498966484cfSJed Brown   ```
8499966484cfSJed Brown   [0] Number of indices in set 5
8500966484cfSJed Brown   [0] 0 0
8501966484cfSJed Brown   [0] 1 1
8502966484cfSJed Brown   [0] 2 3
8503966484cfSJed Brown   [0] 3 4
8504966484cfSJed Brown   [0] 4 -6
8505966484cfSJed Brown   [1] Number of indices in set 3
8506966484cfSJed Brown   [1] 0 2
8507966484cfSJed Brown   [1] 1 5
8508966484cfSJed Brown   [1] 2 6
8509966484cfSJed Brown   ```
8510966484cfSJed Brown 
85111cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetCellNumbering()`
85127cd05799SMatthew G. Knepley @*/
8513d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers)
8514d71ae5a4SJacob Faibussowitsch {
8515ef48cebcSMatthew G. Knepley   IS        nums[4];
8516862913ffSStefano Zampini   PetscInt  depths[4], gdepths[4], starts[4];
8517ef48cebcSMatthew G. Knepley   PetscInt  depth, d, shift = 0;
85180c15888dSMatthew G. Knepley   PetscBool empty = PETSC_FALSE;
8519ef48cebcSMatthew G. Knepley 
8520ef48cebcSMatthew G. Knepley   PetscFunctionBegin;
8521ef48cebcSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
85229566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
85230c15888dSMatthew G. Knepley   // For unstratified meshes use dim instead of depth
85249566063dSJacob Faibussowitsch   if (depth < 0) PetscCall(DMGetDimension(dm, &depth));
85250c15888dSMatthew G. Knepley   // If any stratum is empty, we must mark all empty
8526862913ffSStefano Zampini   for (d = 0; d <= depth; ++d) {
8527862913ffSStefano Zampini     PetscInt end;
8528862913ffSStefano Zampini 
8529862913ffSStefano Zampini     depths[d] = depth - d;
85309566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, depths[d], &starts[d], &end));
85310c15888dSMatthew G. Knepley     if (!(starts[d] - end)) empty = PETSC_TRUE;
8532862913ffSStefano Zampini   }
85330c15888dSMatthew G. Knepley   if (empty)
85340c15888dSMatthew G. Knepley     for (d = 0; d <= depth; ++d) {
85350c15888dSMatthew G. Knepley       depths[d] = -1;
85360c15888dSMatthew G. Knepley       starts[d] = -1;
85370c15888dSMatthew G. Knepley     }
85380c15888dSMatthew G. Knepley   else PetscCall(PetscSortIntWithArray(depth + 1, starts, depths));
85391c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(depths, gdepths, depth + 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
8540ad540459SPierre Jolivet   for (d = 0; d <= depth; ++d) PetscCheck(starts[d] < 0 || depths[d] == gdepths[d], PETSC_COMM_SELF, PETSC_ERR_PLIB, "Expected depth %" PetscInt_FMT ", found %" PetscInt_FMT, depths[d], gdepths[d]);
85410c15888dSMatthew G. Knepley   // Note here that 'shift' is collective, so that the numbering is stratified by depth
8542ef48cebcSMatthew G. Knepley   for (d = 0; d <= depth; ++d) {
8543ef48cebcSMatthew G. Knepley     PetscInt pStart, pEnd, gsize;
8544ef48cebcSMatthew G. Knepley 
85459566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, gdepths[d], &pStart, &pEnd));
85469566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateNumbering_Plex(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]));
8547ef48cebcSMatthew G. Knepley     shift += gsize;
8548ef48cebcSMatthew G. Knepley   }
8549d1c35871SJed Brown   PetscCall(ISConcatenate(PETSC_COMM_SELF, depth + 1, nums, globalPointNumbers));
85509566063dSJacob Faibussowitsch   for (d = 0; d <= depth; ++d) PetscCall(ISDestroy(&nums[d]));
85513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8552ef48cebcSMatthew G. Knepley }
8553ef48cebcSMatthew G. Knepley 
855408a22f4bSMatthew G. Knepley /*@
855508a22f4bSMatthew G. Knepley   DMPlexCreateRankField - Create a cell field whose value is the rank of the owner
855608a22f4bSMatthew G. Knepley 
855708a22f4bSMatthew G. Knepley   Input Parameter:
8558a1cb98faSBarry Smith . dm - The `DMPLEX` object
855908a22f4bSMatthew G. Knepley 
856008a22f4bSMatthew G. Knepley   Output Parameter:
856108a22f4bSMatthew G. Knepley . ranks - The rank field
856208a22f4bSMatthew G. Knepley 
8563a1cb98faSBarry Smith   Options Database Key:
856420f4b53cSBarry Smith . -dm_partition_view - Adds the rank field into the `DM` output from `-dm_view` using the same viewer
856508a22f4bSMatthew G. Knepley 
856608a22f4bSMatthew G. Knepley   Level: intermediate
856708a22f4bSMatthew G. Knepley 
85681cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`
856908a22f4bSMatthew G. Knepley @*/
8570d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateRankField(DM dm, Vec *ranks)
8571d71ae5a4SJacob Faibussowitsch {
857208a22f4bSMatthew G. Knepley   DM             rdm;
857308a22f4bSMatthew G. Knepley   PetscFE        fe;
857408a22f4bSMatthew G. Knepley   PetscScalar   *r;
857508a22f4bSMatthew G. Knepley   PetscMPIInt    rank;
8576a55f9a55SMatthew G. Knepley   DMPolytopeType ct;
857708a22f4bSMatthew G. Knepley   PetscInt       dim, cStart, cEnd, c;
8578a55f9a55SMatthew G. Knepley   PetscBool      simplex;
857908a22f4bSMatthew G. Knepley 
858008a22f4bSMatthew G. Knepley   PetscFunctionBeginUser;
8581f95ace6aSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
85824f572ea9SToby Isaac   PetscAssertPointer(ranks, 2);
85839566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
85849566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &rdm));
85859566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(rdm, &dim));
85869566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd));
85879566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCellType(dm, cStart, &ct));
8588a55f9a55SMatthew G. Knepley   simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct) + 1 ? PETSC_TRUE : PETSC_FALSE;
85899566063dSJacob Faibussowitsch   PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, "PETSc___rank_", -1, &fe));
85909566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)fe, "rank"));
85919566063dSJacob Faibussowitsch   PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe));
85929566063dSJacob Faibussowitsch   PetscCall(PetscFEDestroy(&fe));
85939566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(rdm));
85949566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(rdm, ranks));
85959566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*ranks, "partition"));
85969566063dSJacob Faibussowitsch   PetscCall(VecGetArray(*ranks, &r));
859708a22f4bSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
859808a22f4bSMatthew G. Knepley     PetscScalar *lr;
859908a22f4bSMatthew G. Knepley 
86009566063dSJacob Faibussowitsch     PetscCall(DMPlexPointGlobalRef(rdm, c, r, &lr));
860171f09efeSPierre Jolivet     if (lr) *lr = rank;
860208a22f4bSMatthew G. Knepley   }
86039566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(*ranks, &r));
86049566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&rdm));
86053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
860608a22f4bSMatthew G. Knepley }
860708a22f4bSMatthew G. Knepley 
8608ca8062c8SMatthew G. Knepley /*@
860918e14f0cSMatthew G. Knepley   DMPlexCreateLabelField - Create a cell field whose value is the label value for that cell
861018e14f0cSMatthew G. Knepley 
861118e14f0cSMatthew G. Knepley   Input Parameters:
861220f4b53cSBarry Smith + dm    - The `DMPLEX`
861320f4b53cSBarry Smith - label - The `DMLabel`
861418e14f0cSMatthew G. Knepley 
861518e14f0cSMatthew G. Knepley   Output Parameter:
861618e14f0cSMatthew G. Knepley . val - The label value field
861718e14f0cSMatthew G. Knepley 
861820f4b53cSBarry Smith   Options Database Key:
861920f4b53cSBarry Smith . -dm_label_view - Adds the label value field into the `DM` output from `-dm_view` using the same viewer
862018e14f0cSMatthew G. Knepley 
862118e14f0cSMatthew G. Knepley   Level: intermediate
862218e14f0cSMatthew G. Knepley 
86231cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMView()`
862418e14f0cSMatthew G. Knepley @*/
8625d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateLabelField(DM dm, DMLabel label, Vec *val)
8626d71ae5a4SJacob Faibussowitsch {
862718e14f0cSMatthew G. Knepley   DM           rdm;
862818e14f0cSMatthew G. Knepley   PetscFE      fe;
862918e14f0cSMatthew G. Knepley   PetscScalar *v;
863018e14f0cSMatthew G. Knepley   PetscInt     dim, cStart, cEnd, c;
863118e14f0cSMatthew G. Knepley 
863218e14f0cSMatthew G. Knepley   PetscFunctionBeginUser;
863318e14f0cSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
86344f572ea9SToby Isaac   PetscAssertPointer(label, 2);
86354f572ea9SToby Isaac   PetscAssertPointer(val, 3);
86369566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &rdm));
86379566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(rdm, &dim));
86389566063dSJacob Faibussowitsch   PetscCall(PetscFECreateDefault(PetscObjectComm((PetscObject)rdm), dim, 1, PETSC_TRUE, "PETSc___label_value_", -1, &fe));
86399566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)fe, "label_value"));
86409566063dSJacob Faibussowitsch   PetscCall(DMSetField(rdm, 0, NULL, (PetscObject)fe));
86419566063dSJacob Faibussowitsch   PetscCall(PetscFEDestroy(&fe));
86429566063dSJacob Faibussowitsch   PetscCall(DMCreateDS(rdm));
86439566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(rdm, 0, &cStart, &cEnd));
86449566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(rdm, val));
86459566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*val, "label_value"));
86469566063dSJacob Faibussowitsch   PetscCall(VecGetArray(*val, &v));
864718e14f0cSMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
864818e14f0cSMatthew G. Knepley     PetscScalar *lv;
864918e14f0cSMatthew G. Knepley     PetscInt     cval;
865018e14f0cSMatthew G. Knepley 
86519566063dSJacob Faibussowitsch     PetscCall(DMPlexPointGlobalRef(rdm, c, v, &lv));
86529566063dSJacob Faibussowitsch     PetscCall(DMLabelGetValue(label, c, &cval));
865318e14f0cSMatthew G. Knepley     *lv = cval;
865418e14f0cSMatthew G. Knepley   }
86559566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(*val, &v));
86569566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&rdm));
86573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
865818e14f0cSMatthew G. Knepley }
865918e14f0cSMatthew G. Knepley 
866018e14f0cSMatthew G. Knepley /*@
8661ca8062c8SMatthew G. Knepley   DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric.
8662ca8062c8SMatthew G. Knepley 
866369916449SMatthew G. Knepley   Input Parameter:
8664a1cb98faSBarry Smith . dm - The `DMPLEX` object
8665a1cb98faSBarry Smith 
8666a1cb98faSBarry Smith   Level: developer
8667ca8062c8SMatthew G. Knepley 
866895eb5ee5SVaclav Hapla   Notes:
866995eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
867095eb5ee5SVaclav Hapla 
867120f4b53cSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
8672ca8062c8SMatthew G. Knepley 
86731cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()`
8674ca8062c8SMatthew G. Knepley @*/
8675d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSymmetry(DM dm)
8676d71ae5a4SJacob Faibussowitsch {
8677ca8062c8SMatthew G. Knepley   PetscSection    coneSection, supportSection;
8678ca8062c8SMatthew G. Knepley   const PetscInt *cone, *support;
8679ca8062c8SMatthew G. Knepley   PetscInt        coneSize, c, supportSize, s;
868057beb4faSStefano Zampini   PetscInt        pStart, pEnd, p, pp, csize, ssize;
868157beb4faSStefano Zampini   PetscBool       storagecheck = PETSC_TRUE;
8682ca8062c8SMatthew G. Knepley 
8683ca8062c8SMatthew G. Knepley   PetscFunctionBegin;
8684ca8062c8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
86859566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(dm, NULL, "-sym_dm_view"));
86869566063dSJacob Faibussowitsch   PetscCall(DMPlexGetConeSection(dm, &coneSection));
86879566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSupportSection(dm, &supportSection));
8688ca8062c8SMatthew G. Knepley   /* Check that point p is found in the support of its cone points, and vice versa */
86899566063dSJacob Faibussowitsch   PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
8690ca8062c8SMatthew G. Knepley   for (p = pStart; p < pEnd; ++p) {
86919566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, p, &coneSize));
86929566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, p, &cone));
8693ca8062c8SMatthew G. Knepley     for (c = 0; c < coneSize; ++c) {
869442e66dfaSMatthew G. Knepley       PetscBool dup = PETSC_FALSE;
869542e66dfaSMatthew G. Knepley       PetscInt  d;
869642e66dfaSMatthew G. Knepley       for (d = c - 1; d >= 0; --d) {
86979371c9d4SSatish Balay         if (cone[c] == cone[d]) {
86989371c9d4SSatish Balay           dup = PETSC_TRUE;
86999371c9d4SSatish Balay           break;
87009371c9d4SSatish Balay         }
870142e66dfaSMatthew G. Knepley       }
87029566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupportSize(dm, cone[c], &supportSize));
87039566063dSJacob Faibussowitsch       PetscCall(DMPlexGetSupport(dm, cone[c], &support));
8704ca8062c8SMatthew G. Knepley       for (s = 0; s < supportSize; ++s) {
8705ca8062c8SMatthew G. Knepley         if (support[s] == p) break;
8706ca8062c8SMatthew G. Knepley       }
870742e66dfaSMatthew G. Knepley       if ((s >= supportSize) || (dup && (support[s + 1] != p))) {
870863a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", p));
870948a46eb9SPierre Jolivet         for (s = 0; s < coneSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[s]));
87109566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
871163a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", cone[c]));
871248a46eb9SPierre Jolivet         for (s = 0; s < supportSize; ++s) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[s]));
87139566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
871463a3b9bcSJacob 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]);
8715f7d195e4SLawrence Mitchell         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in support of cone point %" PetscInt_FMT, p, cone[c]);
8716ca8062c8SMatthew G. Knepley       }
871742e66dfaSMatthew G. Knepley     }
87189566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTreeParent(dm, p, &pp, NULL));
87199371c9d4SSatish Balay     if (p != pp) {
87209371c9d4SSatish Balay       storagecheck = PETSC_FALSE;
87219371c9d4SSatish Balay       continue;
87229371c9d4SSatish Balay     }
87239566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupportSize(dm, p, &supportSize));
87249566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSupport(dm, p, &support));
8725ca8062c8SMatthew G. Knepley     for (s = 0; s < supportSize; ++s) {
87269566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, support[s], &coneSize));
87279566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, support[s], &cone));
8728ca8062c8SMatthew G. Knepley       for (c = 0; c < coneSize; ++c) {
87299566063dSJacob Faibussowitsch         PetscCall(DMPlexGetTreeParent(dm, cone[c], &pp, NULL));
87309371c9d4SSatish Balay         if (cone[c] != pp) {
87319371c9d4SSatish Balay           c = 0;
87329371c9d4SSatish Balay           break;
87339371c9d4SSatish Balay         }
8734ca8062c8SMatthew G. Knepley         if (cone[c] == p) break;
8735ca8062c8SMatthew G. Knepley       }
8736ca8062c8SMatthew G. Knepley       if (c >= coneSize) {
873763a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " support: ", p));
873848a46eb9SPierre Jolivet         for (c = 0; c < supportSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", support[c]));
87399566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
874063a3b9bcSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "p: %" PetscInt_FMT " cone: ", support[s]));
874148a46eb9SPierre Jolivet         for (c = 0; c < coneSize; ++c) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT ", ", cone[c]));
87429566063dSJacob Faibussowitsch         PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
874363a3b9bcSJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " not found in cone of support point %" PetscInt_FMT, p, support[s]);
8744ca8062c8SMatthew G. Knepley       }
8745ca8062c8SMatthew G. Knepley     }
8746ca8062c8SMatthew G. Knepley   }
874757beb4faSStefano Zampini   if (storagecheck) {
87489566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coneSection, &csize));
87499566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(supportSection, &ssize));
875063a3b9bcSJacob Faibussowitsch     PetscCheck(csize == ssize, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %" PetscInt_FMT " != Total support size %" PetscInt_FMT, csize, ssize);
875157beb4faSStefano Zampini   }
87523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8753ca8062c8SMatthew G. Knepley }
8754ca8062c8SMatthew G. Knepley 
8755412e9a14SMatthew G. Knepley /*
8756412e9a14SMatthew 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.
8757412e9a14SMatthew G. Knepley */
8758d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCellUnsplitVertices_Private(DM dm, PetscInt c, DMPolytopeType ct, PetscInt *unsplit)
8759d71ae5a4SJacob Faibussowitsch {
8760412e9a14SMatthew G. Knepley   DMPolytopeType  cct;
8761412e9a14SMatthew G. Knepley   PetscInt        ptpoints[4];
8762412e9a14SMatthew G. Knepley   const PetscInt *cone, *ccone, *ptcone;
8763412e9a14SMatthew G. Knepley   PetscInt        coneSize, cp, cconeSize, ccp, npt = 0, pt;
8764412e9a14SMatthew G. Knepley 
8765412e9a14SMatthew G. Knepley   PetscFunctionBegin;
8766412e9a14SMatthew G. Knepley   *unsplit = 0;
8767412e9a14SMatthew G. Knepley   switch (ct) {
8768d71ae5a4SJacob Faibussowitsch   case DM_POLYTOPE_POINT_PRISM_TENSOR:
8769d71ae5a4SJacob Faibussowitsch     ptpoints[npt++] = c;
8770d71ae5a4SJacob Faibussowitsch     break;
8771412e9a14SMatthew G. Knepley   case DM_POLYTOPE_SEG_PRISM_TENSOR:
87729566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
87739566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
8774412e9a14SMatthew G. Knepley     for (cp = 0; cp < coneSize; ++cp) {
87759566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, cone[cp], &cct));
8776412e9a14SMatthew G. Knepley       if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) ptpoints[npt++] = cone[cp];
8777412e9a14SMatthew G. Knepley     }
8778412e9a14SMatthew G. Knepley     break;
8779412e9a14SMatthew G. Knepley   case DM_POLYTOPE_TRI_PRISM_TENSOR:
8780412e9a14SMatthew G. Knepley   case DM_POLYTOPE_QUAD_PRISM_TENSOR:
87819566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, c, &cone));
87829566063dSJacob Faibussowitsch     PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
8783412e9a14SMatthew G. Knepley     for (cp = 0; cp < coneSize; ++cp) {
87849566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, cone[cp], &ccone));
87859566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, cone[cp], &cconeSize));
8786412e9a14SMatthew G. Knepley       for (ccp = 0; ccp < cconeSize; ++ccp) {
87879566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, ccone[ccp], &cct));
8788412e9a14SMatthew G. Knepley         if (cct == DM_POLYTOPE_POINT_PRISM_TENSOR) {
8789412e9a14SMatthew G. Knepley           PetscInt p;
87909371c9d4SSatish Balay           for (p = 0; p < npt; ++p)
87919371c9d4SSatish Balay             if (ptpoints[p] == ccone[ccp]) break;
8792412e9a14SMatthew G. Knepley           if (p == npt) ptpoints[npt++] = ccone[ccp];
8793412e9a14SMatthew G. Knepley         }
8794412e9a14SMatthew G. Knepley       }
8795412e9a14SMatthew G. Knepley     }
8796412e9a14SMatthew G. Knepley     break;
8797d71ae5a4SJacob Faibussowitsch   default:
8798d71ae5a4SJacob Faibussowitsch     break;
8799412e9a14SMatthew G. Knepley   }
8800412e9a14SMatthew G. Knepley   for (pt = 0; pt < npt; ++pt) {
88019566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCone(dm, ptpoints[pt], &ptcone));
8802412e9a14SMatthew G. Knepley     if (ptcone[0] == ptcone[1]) ++(*unsplit);
8803412e9a14SMatthew G. Knepley   }
88043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8805412e9a14SMatthew G. Knepley }
8806412e9a14SMatthew G. Knepley 
8807ca8062c8SMatthew G. Knepley /*@
8808ca8062c8SMatthew G. Knepley   DMPlexCheckSkeleton - Check that each cell has the correct number of vertices
8809ca8062c8SMatthew G. Knepley 
8810ca8062c8SMatthew G. Knepley   Input Parameters:
8811a1cb98faSBarry Smith + dm         - The `DMPLEX` object
881258723a97SMatthew G. Knepley - cellHeight - Normally 0
8813ca8062c8SMatthew G. Knepley 
8814a1cb98faSBarry Smith   Level: developer
8815a1cb98faSBarry Smith 
881695eb5ee5SVaclav Hapla   Notes:
881795eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
881825c50c26SVaclav Hapla   Currently applicable only to homogeneous simplex or tensor meshes.
8819ca8062c8SMatthew G. Knepley 
882020f4b53cSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
882195eb5ee5SVaclav Hapla 
88221cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()`
8823ca8062c8SMatthew G. Knepley @*/
8824d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscInt cellHeight)
8825d71ae5a4SJacob Faibussowitsch {
8826412e9a14SMatthew G. Knepley   DMPlexInterpolatedFlag interp;
8827412e9a14SMatthew G. Knepley   DMPolytopeType         ct;
8828412e9a14SMatthew G. Knepley   PetscInt               vStart, vEnd, cStart, cEnd, c;
8829ca8062c8SMatthew G. Knepley 
8830ca8062c8SMatthew G. Knepley   PetscFunctionBegin;
8831ca8062c8SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
88329566063dSJacob Faibussowitsch   PetscCall(DMPlexIsInterpolated(dm, &interp));
88339566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
88349566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
8835412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
8836412e9a14SMatthew G. Knepley     PetscInt *closure = NULL;
8837412e9a14SMatthew G. Knepley     PetscInt  coneSize, closureSize, cl, Nv = 0;
883858723a97SMatthew G. Knepley 
88399566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
884063a3b9bcSJacob Faibussowitsch     PetscCheck((PetscInt)ct >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %" PetscInt_FMT " has no cell type", c);
8841412e9a14SMatthew G. Knepley     if (ct == DM_POLYTOPE_UNKNOWN) continue;
8842412e9a14SMatthew G. Knepley     if (interp == DMPLEX_INTERPOLATED_FULL) {
88439566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
884463a3b9bcSJacob 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));
8845412e9a14SMatthew G. Knepley     }
88469566063dSJacob Faibussowitsch     PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
884758723a97SMatthew G. Knepley     for (cl = 0; cl < closureSize * 2; cl += 2) {
884858723a97SMatthew G. Knepley       const PetscInt p = closure[cl];
8849412e9a14SMatthew G. Knepley       if ((p >= vStart) && (p < vEnd)) ++Nv;
885058723a97SMatthew G. Knepley     }
88519566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
8852412e9a14SMatthew G. Knepley     /* Special Case: Tensor faces with identified vertices */
8853412e9a14SMatthew G. Knepley     if (Nv < DMPolytopeTypeGetNumVertices(ct)) {
8854412e9a14SMatthew G. Knepley       PetscInt unsplit;
885542363296SMatthew G. Knepley 
88569566063dSJacob Faibussowitsch       PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
8857412e9a14SMatthew G. Knepley       if (Nv + unsplit == DMPolytopeTypeGetNumVertices(ct)) continue;
885842363296SMatthew G. Knepley     }
885963a3b9bcSJacob 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));
886042363296SMatthew G. Knepley   }
88613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8862ca8062c8SMatthew G. Knepley }
88639bf0dad6SMatthew G. Knepley 
88649bf0dad6SMatthew G. Knepley /*@
88659bf0dad6SMatthew 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
88669bf0dad6SMatthew G. Knepley 
886720f4b53cSBarry Smith   Collective
8868899ea2b8SJacob Faibussowitsch 
88699bf0dad6SMatthew G. Knepley   Input Parameters:
8870a1cb98faSBarry Smith + dm         - The `DMPLEX` object
88719bf0dad6SMatthew G. Knepley - cellHeight - Normally 0
88729bf0dad6SMatthew G. Knepley 
8873a1cb98faSBarry Smith   Level: developer
8874a1cb98faSBarry Smith 
887545da879fSVaclav Hapla   Notes:
887645da879fSVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
887745da879fSVaclav Hapla   This routine is only relevant for meshes that are fully interpolated across all ranks.
887845da879fSVaclav Hapla   It will error out if a partially interpolated mesh is given on some rank.
887945da879fSVaclav Hapla   It will do nothing for locally uninterpolated mesh (as there is nothing to check).
88809bf0dad6SMatthew G. Knepley 
8881a1cb98faSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
888295eb5ee5SVaclav Hapla 
88831cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMPlexGetVTKCellHeight()`, `DMSetFromOptions()`
88849bf0dad6SMatthew G. Knepley @*/
8885d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckFaces(DM dm, PetscInt cellHeight)
8886d71ae5a4SJacob Faibussowitsch {
8887ab91121cSMatthew G. Knepley   PetscInt               dim, depth, vStart, vEnd, cStart, cEnd, c, h;
8888899ea2b8SJacob Faibussowitsch   DMPlexInterpolatedFlag interpEnum;
88899bf0dad6SMatthew G. Knepley 
88909bf0dad6SMatthew G. Knepley   PetscFunctionBegin;
88919bf0dad6SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
88928f6815adSVaclav Hapla   PetscCall(DMPlexIsInterpolatedCollective(dm, &interpEnum));
88933ba16761SJacob Faibussowitsch   if (interpEnum == DMPLEX_INTERPOLATED_NONE) PetscFunctionReturn(PETSC_SUCCESS);
88948f6815adSVaclav Hapla   if (interpEnum != DMPLEX_INTERPOLATED_FULL) {
88953ba16761SJacob Faibussowitsch     PetscCall(PetscPrintf(PetscObjectComm((PetscObject)dm), "DMPlexCheckFaces() warning: Mesh is only partially interpolated, this is currently not supported"));
88963ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
8897899ea2b8SJacob Faibussowitsch   }
8898899ea2b8SJacob Faibussowitsch 
88999566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
89009566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
89019566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
8902ab91121cSMatthew G. Knepley   for (h = cellHeight; h < PetscMin(depth, dim); ++h) {
89039566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, h, &cStart, &cEnd));
89043554e41dSMatthew G. Knepley     for (c = cStart; c < cEnd; ++c) {
8905412e9a14SMatthew G. Knepley       const PetscInt       *cone, *ornt, *faceSizes, *faces;
8906412e9a14SMatthew G. Knepley       const DMPolytopeType *faceTypes;
8907ba2698f1SMatthew G. Knepley       DMPolytopeType        ct;
8908412e9a14SMatthew G. Knepley       PetscInt              numFaces, coneSize, f;
8909412e9a14SMatthew G. Knepley       PetscInt             *closure = NULL, closureSize, cl, numCorners = 0, fOff = 0, unsplit;
89109bf0dad6SMatthew G. Knepley 
89119566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCellType(dm, c, &ct));
89129566063dSJacob Faibussowitsch       PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
8913412e9a14SMatthew G. Knepley       if (unsplit) continue;
89149566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, c, &coneSize));
89159566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, c, &cone));
89169566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeOrientation(dm, c, &ornt));
89179566063dSJacob Faibussowitsch       PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
89189bf0dad6SMatthew G. Knepley       for (cl = 0; cl < closureSize * 2; cl += 2) {
89199bf0dad6SMatthew G. Knepley         const PetscInt p = closure[cl];
89209bf0dad6SMatthew G. Knepley         if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p;
89219bf0dad6SMatthew G. Knepley       }
89229566063dSJacob Faibussowitsch       PetscCall(DMPlexGetRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces));
892363a3b9bcSJacob 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);
89249bf0dad6SMatthew G. Knepley       for (f = 0; f < numFaces; ++f) {
8925d4961f80SStefano Zampini         DMPolytopeType fct;
89269bf0dad6SMatthew G. Knepley         PetscInt      *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v;
89279bf0dad6SMatthew G. Knepley 
89289566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(dm, cone[f], &fct));
89299566063dSJacob Faibussowitsch         PetscCall(DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure));
89309bf0dad6SMatthew G. Knepley         for (cl = 0; cl < fclosureSize * 2; cl += 2) {
89319bf0dad6SMatthew G. Knepley           const PetscInt p = fclosure[cl];
89329bf0dad6SMatthew G. Knepley           if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p;
89339bf0dad6SMatthew G. Knepley         }
893463a3b9bcSJacob 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]);
89359bf0dad6SMatthew G. Knepley         for (v = 0; v < fnumCorners; ++v) {
8936b5a892a1SMatthew G. Knepley           if (fclosure[v] != faces[fOff + v]) {
8937b5a892a1SMatthew G. Knepley             PetscInt v1;
8938b5a892a1SMatthew G. Knepley 
89399566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "face closure:"));
894063a3b9bcSJacob Faibussowitsch             for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, fclosure[v1]));
89419566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "\ncell face:"));
894263a3b9bcSJacob Faibussowitsch             for (v1 = 0; v1 < fnumCorners; ++v1) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, faces[fOff + v1]));
89439566063dSJacob Faibussowitsch             PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
894463a3b9bcSJacob 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]);
8945b5a892a1SMatthew G. Knepley           }
89469bf0dad6SMatthew G. Knepley         }
89479566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure));
8948412e9a14SMatthew G. Knepley         fOff += faceSizes[f];
89499bf0dad6SMatthew G. Knepley       }
89509566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreRawFaces_Internal(dm, ct, closure, &numFaces, &faceTypes, &faceSizes, &faces));
89519566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure));
89529bf0dad6SMatthew G. Knepley     }
89533554e41dSMatthew G. Knepley   }
89543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8955552f7358SJed Brown }
89563913d7c8SMatthew G. Knepley 
8957bb6a34a8SMatthew G. Knepley /*@
8958bb6a34a8SMatthew G. Knepley   DMPlexCheckGeometry - Check the geometry of mesh cells
8959bb6a34a8SMatthew G. Knepley 
8960bb6a34a8SMatthew G. Knepley   Input Parameter:
8961a1cb98faSBarry Smith . dm - The `DMPLEX` object
8962a1cb98faSBarry Smith 
8963a1cb98faSBarry Smith   Level: developer
8964bb6a34a8SMatthew G. Knepley 
896595eb5ee5SVaclav Hapla   Notes:
896695eb5ee5SVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
896795eb5ee5SVaclav Hapla 
896820f4b53cSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
8969bb6a34a8SMatthew G. Knepley 
89701cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()`
8971bb6a34a8SMatthew G. Knepley @*/
8972d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckGeometry(DM dm)
8973d71ae5a4SJacob Faibussowitsch {
8974a2a9e04cSMatthew G. Knepley   Vec       coordinates;
8975bb6a34a8SMatthew G. Knepley   PetscReal detJ, J[9], refVol = 1.0;
8976bb6a34a8SMatthew G. Knepley   PetscReal vol;
897751a74b61SMatthew G. Knepley   PetscInt  dim, depth, dE, d, cStart, cEnd, c;
8978bb6a34a8SMatthew G. Knepley 
8979bb6a34a8SMatthew G. Knepley   PetscFunctionBegin;
89809566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
89819566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dE));
89823ba16761SJacob Faibussowitsch   if (dim != dE) PetscFunctionReturn(PETSC_SUCCESS);
89839566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
8984bb6a34a8SMatthew G. Knepley   for (d = 0; d < dim; ++d) refVol *= 2.0;
89859566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
8986a2a9e04cSMatthew G. Knepley   /* Make sure local coordinates are created, because that step is collective */
89879566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
89883ba16761SJacob Faibussowitsch   if (!coordinates) PetscFunctionReturn(PETSC_SUCCESS);
8989412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
8990412e9a14SMatthew G. Knepley     DMPolytopeType ct;
8991412e9a14SMatthew G. Knepley     PetscInt       unsplit;
8992412e9a14SMatthew G. Knepley     PetscBool      ignoreZeroVol = PETSC_FALSE;
8993412e9a14SMatthew G. Knepley 
89949566063dSJacob Faibussowitsch     PetscCall(DMPlexGetCellType(dm, c, &ct));
8995412e9a14SMatthew G. Knepley     switch (ct) {
8996412e9a14SMatthew G. Knepley     case DM_POLYTOPE_SEG_PRISM_TENSOR:
8997412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:
8998d71ae5a4SJacob Faibussowitsch     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
8999d71ae5a4SJacob Faibussowitsch       ignoreZeroVol = PETSC_TRUE;
9000d71ae5a4SJacob Faibussowitsch       break;
9001d71ae5a4SJacob Faibussowitsch     default:
9002d71ae5a4SJacob Faibussowitsch       break;
9003412e9a14SMatthew G. Knepley     }
9004412e9a14SMatthew G. Knepley     switch (ct) {
9005412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM:
9006412e9a14SMatthew G. Knepley     case DM_POLYTOPE_TRI_PRISM_TENSOR:
9007412e9a14SMatthew G. Knepley     case DM_POLYTOPE_QUAD_PRISM_TENSOR:
9008d71ae5a4SJacob Faibussowitsch     case DM_POLYTOPE_PYRAMID:
9009d71ae5a4SJacob Faibussowitsch       continue;
9010d71ae5a4SJacob Faibussowitsch     default:
9011d71ae5a4SJacob Faibussowitsch       break;
9012412e9a14SMatthew G. Knepley     }
90139566063dSJacob Faibussowitsch     PetscCall(DMPlexCellUnsplitVertices_Private(dm, c, ct, &unsplit));
9014412e9a14SMatthew G. Knepley     if (unsplit) continue;
90159566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellGeometryFEM(dm, c, NULL, NULL, J, NULL, &detJ));
90161dca8a05SBarry 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);
901763a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FEM Volume %g\n", c, (double)(detJ * refVol)));
90186858538eSMatthew G. Knepley     /* This should work with periodicity since DG coordinates should be used */
90196858538eSMatthew G. Knepley     if (depth > 1) {
90209566063dSJacob Faibussowitsch       PetscCall(DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL));
90211dca8a05SBarry 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);
902263a3b9bcSJacob Faibussowitsch       PetscCall(PetscInfo(dm, "Cell %" PetscInt_FMT " FVM Volume %g\n", c, (double)vol));
9023bb6a34a8SMatthew G. Knepley     }
9024bb6a34a8SMatthew G. Knepley   }
90253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9026bb6a34a8SMatthew G. Knepley }
9027bb6a34a8SMatthew G. Knepley 
902803da9461SVaclav Hapla /*@
902920f4b53cSBarry Smith   DMPlexCheckPointSF - Check that several necessary conditions are met for the point `PetscSF` of this plex.
90307726db96SVaclav Hapla 
903120f4b53cSBarry Smith   Collective
903203da9461SVaclav Hapla 
903303da9461SVaclav Hapla   Input Parameters:
9034a1cb98faSBarry Smith + dm              - The `DMPLEX` object
903520f4b53cSBarry Smith . pointSF         - The `PetscSF`, or `NULL` for `PointSF` attached to `DM`
9036a1cb98faSBarry Smith - allowExtraRoots - Flag to allow extra points not present in the `DM`
9037a1cb98faSBarry Smith 
9038a1cb98faSBarry Smith   Level: developer
903903da9461SVaclav Hapla 
9040e83a0d2dSVaclav Hapla   Notes:
9041e83a0d2dSVaclav Hapla   This is mainly intended for debugging/testing purposes.
904203da9461SVaclav Hapla 
9043a1cb98faSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
904495eb5ee5SVaclav Hapla 
9045d7d32a9aSMatthew G. Knepley   Extra roots can come from priodic cuts, where additional points appear on the boundary
9046d7d32a9aSMatthew G. Knepley 
90471cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMGetPointSF()`, `DMSetFromOptions()`
904803da9461SVaclav Hapla @*/
9049d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckPointSF(DM dm, PetscSF pointSF, PetscBool allowExtraRoots)
9050d71ae5a4SJacob Faibussowitsch {
90517726db96SVaclav Hapla   PetscInt           l, nleaves, nroots, overlap;
90527726db96SVaclav Hapla   const PetscInt    *locals;
90537726db96SVaclav Hapla   const PetscSFNode *remotes;
9054f0cfc026SVaclav Hapla   PetscBool          distributed;
90557726db96SVaclav Hapla   MPI_Comm           comm;
90567726db96SVaclav Hapla   PetscMPIInt        rank;
905703da9461SVaclav Hapla 
905803da9461SVaclav Hapla   PetscFunctionBegin;
905903da9461SVaclav Hapla   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
90607726db96SVaclav Hapla   if (pointSF) PetscValidHeaderSpecific(pointSF, PETSCSF_CLASSID, 2);
90617726db96SVaclav Hapla   else pointSF = dm->sf;
90627726db96SVaclav Hapla   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
90637726db96SVaclav Hapla   PetscCheck(pointSF, comm, PETSC_ERR_ARG_WRONGSTATE, "DMPlex must have Point SF attached");
90647726db96SVaclav Hapla   PetscCallMPI(MPI_Comm_rank(comm, &rank));
90657726db96SVaclav Hapla   {
90667726db96SVaclav Hapla     PetscMPIInt mpiFlag;
90677726db96SVaclav Hapla 
90687726db96SVaclav Hapla     PetscCallMPI(MPI_Comm_compare(comm, PetscObjectComm((PetscObject)pointSF), &mpiFlag));
90697726db96SVaclav 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);
90707726db96SVaclav Hapla   }
90717726db96SVaclav Hapla   PetscCall(PetscSFGetGraph(pointSF, &nroots, &nleaves, &locals, &remotes));
90729566063dSJacob Faibussowitsch   PetscCall(DMPlexIsDistributed(dm, &distributed));
90737726db96SVaclav Hapla   if (!distributed) {
90747726db96SVaclav 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);
90753ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
90768918e3e2SVaclav Hapla   }
90777726db96SVaclav 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);
90787726db96SVaclav Hapla   PetscCall(DMPlexGetOverlap(dm, &overlap));
907903da9461SVaclav Hapla 
90807726db96SVaclav Hapla   /* Check SF graph is compatible with DMPlex chart */
90817726db96SVaclav Hapla   {
90827726db96SVaclav Hapla     PetscInt pStart, pEnd, maxLeaf;
90837726db96SVaclav Hapla 
90847726db96SVaclav Hapla     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
90857726db96SVaclav Hapla     PetscCall(PetscSFGetLeafRange(pointSF, NULL, &maxLeaf));
9086d7d32a9aSMatthew G. Knepley     PetscCheck(allowExtraRoots || pEnd - pStart == nroots, PETSC_COMM_SELF, PETSC_ERR_PLIB, "pEnd - pStart = %" PetscInt_FMT " != nroots = %" PetscInt_FMT, pEnd - pStart, nroots);
90877726db96SVaclav Hapla     PetscCheck(maxLeaf < pEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "maxLeaf = %" PetscInt_FMT " >= pEnd = %" PetscInt_FMT, maxLeaf, pEnd);
90887726db96SVaclav Hapla   }
90897726db96SVaclav Hapla 
90907726db96SVaclav Hapla   /* Check Point SF has no local points referenced */
90917726db96SVaclav Hapla   for (l = 0; l < nleaves; l++) {
90927726db96SVaclav 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);
90937726db96SVaclav Hapla   }
90947726db96SVaclav Hapla 
90957726db96SVaclav Hapla   /* Check there are no cells in interface */
90967726db96SVaclav Hapla   if (!overlap) {
90977726db96SVaclav Hapla     PetscInt cellHeight, cStart, cEnd;
90987726db96SVaclav Hapla 
90999566063dSJacob Faibussowitsch     PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
91009566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
9101f5869d18SMatthew G. Knepley     for (l = 0; l < nleaves; ++l) {
91027726db96SVaclav Hapla       const PetscInt point = locals ? locals[l] : l;
9103f5869d18SMatthew G. Knepley 
91047726db96SVaclav Hapla       PetscCheck(point < cStart || point >= cEnd, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point SF contains %" PetscInt_FMT " which is a cell", point);
91057726db96SVaclav Hapla     }
910603da9461SVaclav Hapla   }
9107ece87651SVaclav Hapla 
91087726db96SVaclav Hapla   /* If some point is in interface, then all its cone points must be also in interface (either as leaves or roots) */
91097726db96SVaclav Hapla   {
91107726db96SVaclav Hapla     const PetscInt *rootdegree;
91117726db96SVaclav Hapla 
91127726db96SVaclav Hapla     PetscCall(PetscSFComputeDegreeBegin(pointSF, &rootdegree));
91137726db96SVaclav Hapla     PetscCall(PetscSFComputeDegreeEnd(pointSF, &rootdegree));
9114f5869d18SMatthew G. Knepley     for (l = 0; l < nleaves; ++l) {
91157726db96SVaclav Hapla       const PetscInt  point = locals ? locals[l] : l;
9116f5869d18SMatthew G. Knepley       const PetscInt *cone;
9117f5869d18SMatthew G. Knepley       PetscInt        coneSize, c, idx;
9118f5869d18SMatthew G. Knepley 
91199566063dSJacob Faibussowitsch       PetscCall(DMPlexGetConeSize(dm, point, &coneSize));
91209566063dSJacob Faibussowitsch       PetscCall(DMPlexGetCone(dm, point, &cone));
9121f5869d18SMatthew G. Knepley       for (c = 0; c < coneSize; ++c) {
9122f5869d18SMatthew G. Knepley         if (!rootdegree[cone[c]]) {
91237726db96SVaclav Hapla           if (locals) {
91249566063dSJacob Faibussowitsch             PetscCall(PetscFindInt(cone[c], nleaves, locals, &idx));
91257726db96SVaclav Hapla           } else {
91267726db96SVaclav Hapla             idx = (cone[c] < nleaves) ? cone[c] : -1;
91277726db96SVaclav Hapla           }
912863a3b9bcSJacob 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]);
9129f5869d18SMatthew G. Knepley         }
9130f5869d18SMatthew G. Knepley       }
9131ece87651SVaclav Hapla     }
91327726db96SVaclav Hapla   }
91333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
913403da9461SVaclav Hapla }
913503da9461SVaclav Hapla 
91367f9d8d6cSVaclav Hapla /*@
913720f4b53cSBarry Smith   DMPlexCheck - Perform various checks of `DMPLEX` sanity
91387f9d8d6cSVaclav Hapla 
91397f9d8d6cSVaclav Hapla   Input Parameter:
9140a1cb98faSBarry Smith . dm - The `DMPLEX` object
9141a1cb98faSBarry Smith 
9142a1cb98faSBarry Smith   Level: developer
91437f9d8d6cSVaclav Hapla 
91447f9d8d6cSVaclav Hapla   Notes:
91457f9d8d6cSVaclav Hapla   This is a useful diagnostic when creating meshes programmatically.
91467f9d8d6cSVaclav Hapla 
914720f4b53cSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
91487f9d8d6cSVaclav Hapla 
914920f4b53cSBarry Smith   Currently does not include `DMPlexCheckCellShape()`.
91507f9d8d6cSVaclav Hapla 
91511cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMCreate()`, `DMSetFromOptions()`
91527f9d8d6cSVaclav Hapla @*/
9153d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheck(DM dm)
9154d71ae5a4SJacob Faibussowitsch {
91557f9d8d6cSVaclav Hapla   PetscInt cellHeight;
91567f9d8d6cSVaclav Hapla 
9157b5a892a1SMatthew G. Knepley   PetscFunctionBegin;
91587f9d8d6cSVaclav Hapla   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
91599566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckSymmetry(dm));
91609566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckSkeleton(dm, cellHeight));
91619566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckFaces(dm, cellHeight));
91629566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckGeometry(dm));
9163d7d32a9aSMatthew G. Knepley   PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE));
91649566063dSJacob Faibussowitsch   PetscCall(DMPlexCheckInterfaceCones(dm));
91653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9166b5a892a1SMatthew G. Knepley }
9167b5a892a1SMatthew G. Knepley 
91689371c9d4SSatish Balay typedef struct cell_stats {
9169068a5610SStefano Zampini   PetscReal min, max, sum, squaresum;
9170068a5610SStefano Zampini   PetscInt  count;
9171068a5610SStefano Zampini } cell_stats_t;
9172068a5610SStefano Zampini 
9173d71ae5a4SJacob Faibussowitsch static void MPIAPI cell_stats_reduce(void *a, void *b, int *len, MPI_Datatype *datatype)
9174d71ae5a4SJacob Faibussowitsch {
9175068a5610SStefano Zampini   PetscInt i, N = *len;
9176068a5610SStefano Zampini 
9177068a5610SStefano Zampini   for (i = 0; i < N; i++) {
9178068a5610SStefano Zampini     cell_stats_t *A = (cell_stats_t *)a;
9179068a5610SStefano Zampini     cell_stats_t *B = (cell_stats_t *)b;
9180068a5610SStefano Zampini 
9181068a5610SStefano Zampini     B->min = PetscMin(A->min, B->min);
9182068a5610SStefano Zampini     B->max = PetscMax(A->max, B->max);
9183068a5610SStefano Zampini     B->sum += A->sum;
9184068a5610SStefano Zampini     B->squaresum += A->squaresum;
9185068a5610SStefano Zampini     B->count += A->count;
9186068a5610SStefano Zampini   }
9187068a5610SStefano Zampini }
9188068a5610SStefano Zampini 
9189068a5610SStefano Zampini /*@
919043fa8764SMatthew G. Knepley   DMPlexCheckCellShape - Checks the Jacobian of the mapping from reference to real cells and computes some minimal statistics.
9191068a5610SStefano Zampini 
919220f4b53cSBarry Smith   Collective
91938261a58bSMatthew G. Knepley 
9194068a5610SStefano Zampini   Input Parameters:
9195a1cb98faSBarry Smith + dm        - The `DMPLEX` object
919620f4b53cSBarry Smith . output    - If true, statistics will be displayed on `stdout`
9197a1cb98faSBarry Smith - condLimit - Display all cells above this condition number, or `PETSC_DETERMINE` for no cell output
9198a1cb98faSBarry Smith 
9199a1cb98faSBarry Smith   Level: developer
9200068a5610SStefano Zampini 
920195eb5ee5SVaclav Hapla   Notes:
920295eb5ee5SVaclav Hapla   This is mainly intended for debugging/testing purposes.
920395eb5ee5SVaclav Hapla 
9204a1cb98faSBarry Smith   For the complete list of DMPlexCheck* functions, see `DMSetFromOptions()`.
9205068a5610SStefano Zampini 
92061cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexComputeOrthogonalQuality()`
9207068a5610SStefano Zampini @*/
9208d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCheckCellShape(DM dm, PetscBool output, PetscReal condLimit)
9209d71ae5a4SJacob Faibussowitsch {
9210068a5610SStefano Zampini   DM           dmCoarse;
921143fa8764SMatthew G. Knepley   cell_stats_t stats, globalStats;
921243fa8764SMatthew G. Knepley   MPI_Comm     comm = PetscObjectComm((PetscObject)dm);
921343fa8764SMatthew G. Knepley   PetscReal   *J, *invJ, min = 0, max = 0, mean = 0, stdev = 0;
921443fa8764SMatthew G. Knepley   PetscReal    limit = condLimit > 0 ? condLimit : PETSC_MAX_REAL;
9215412e9a14SMatthew G. Knepley   PetscInt     cdim, cStart, cEnd, c, eStart, eEnd, count = 0;
921643fa8764SMatthew G. Knepley   PetscMPIInt  rank, size;
9217068a5610SStefano Zampini 
9218068a5610SStefano Zampini   PetscFunctionBegin;
9219068a5610SStefano Zampini   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9220068a5610SStefano Zampini   stats.min = PETSC_MAX_REAL;
9221068a5610SStefano Zampini   stats.max = PETSC_MIN_REAL;
9222068a5610SStefano Zampini   stats.sum = stats.squaresum = 0.;
9223068a5610SStefano Zampini   stats.count                 = 0;
9224068a5610SStefano Zampini 
92259566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
92269566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
92279566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &cdim));
92289566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(PetscSqr(cdim), &J, PetscSqr(cdim), &invJ));
92299566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSimplexOrBoxCells(dm, 0, &cStart, &cEnd));
92309566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd));
9231412e9a14SMatthew G. Knepley   for (c = cStart; c < cEnd; c++) {
9232068a5610SStefano Zampini     PetscInt  i;
9233068a5610SStefano Zampini     PetscReal frobJ = 0., frobInvJ = 0., cond2, cond, detJ;
9234068a5610SStefano Zampini 
92359566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeCellGeometryAffineFEM(dm, c, NULL, J, invJ, &detJ));
923663a3b9bcSJacob Faibussowitsch     PetscCheck(detJ >= 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Mesh cell %" PetscInt_FMT " is inverted", c);
923743fa8764SMatthew G. Knepley     for (i = 0; i < PetscSqr(cdim); ++i) {
9238068a5610SStefano Zampini       frobJ += J[i] * J[i];
9239068a5610SStefano Zampini       frobInvJ += invJ[i] * invJ[i];
9240068a5610SStefano Zampini     }
9241068a5610SStefano Zampini     cond2 = frobJ * frobInvJ;
9242068a5610SStefano Zampini     cond  = PetscSqrtReal(cond2);
9243068a5610SStefano Zampini 
9244068a5610SStefano Zampini     stats.min = PetscMin(stats.min, cond);
9245068a5610SStefano Zampini     stats.max = PetscMax(stats.max, cond);
9246068a5610SStefano Zampini     stats.sum += cond;
9247068a5610SStefano Zampini     stats.squaresum += cond2;
9248068a5610SStefano Zampini     stats.count++;
92498261a58bSMatthew G. Knepley     if (output && cond > limit) {
925043fa8764SMatthew G. Knepley       PetscSection coordSection;
925143fa8764SMatthew G. Knepley       Vec          coordsLocal;
925243fa8764SMatthew G. Knepley       PetscScalar *coords = NULL;
925343fa8764SMatthew G. Knepley       PetscInt     Nv, d, clSize, cl, *closure = NULL;
925443fa8764SMatthew G. Knepley 
92559566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal));
92569566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinateSection(dm, &coordSection));
92579566063dSJacob Faibussowitsch       PetscCall(DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, &Nv, &coords));
925863a3b9bcSJacob Faibussowitsch       PetscCall(PetscSynchronizedPrintf(comm, "[%d] Cell %" PetscInt_FMT " cond %g\n", rank, c, (double)cond));
925943fa8764SMatthew G. Knepley       for (i = 0; i < Nv / cdim; ++i) {
926063a3b9bcSJacob Faibussowitsch         PetscCall(PetscSynchronizedPrintf(comm, "  Vertex %" PetscInt_FMT ": (", i));
926143fa8764SMatthew G. Knepley         for (d = 0; d < cdim; ++d) {
92629566063dSJacob Faibussowitsch           if (d > 0) PetscCall(PetscSynchronizedPrintf(comm, ", "));
92639566063dSJacob Faibussowitsch           PetscCall(PetscSynchronizedPrintf(comm, "%g", (double)PetscRealPart(coords[i * cdim + d])));
926443fa8764SMatthew G. Knepley         }
92659566063dSJacob Faibussowitsch         PetscCall(PetscSynchronizedPrintf(comm, ")\n"));
926643fa8764SMatthew G. Knepley       }
92679566063dSJacob Faibussowitsch       PetscCall(DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure));
926843fa8764SMatthew G. Knepley       for (cl = 0; cl < clSize * 2; cl += 2) {
926943fa8764SMatthew G. Knepley         const PetscInt edge = closure[cl];
927043fa8764SMatthew G. Knepley 
927143fa8764SMatthew G. Knepley         if ((edge >= eStart) && (edge < eEnd)) {
927243fa8764SMatthew G. Knepley           PetscReal len;
927343fa8764SMatthew G. Knepley 
92749566063dSJacob Faibussowitsch           PetscCall(DMPlexComputeCellGeometryFVM(dm, edge, &len, NULL, NULL));
927563a3b9bcSJacob Faibussowitsch           PetscCall(PetscSynchronizedPrintf(comm, "  Edge %" PetscInt_FMT ": length %g\n", edge, (double)len));
927643fa8764SMatthew G. Knepley         }
927743fa8764SMatthew G. Knepley       }
92789566063dSJacob Faibussowitsch       PetscCall(DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &clSize, &closure));
92799566063dSJacob Faibussowitsch       PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, &Nv, &coords));
928043fa8764SMatthew G. Knepley     }
9281068a5610SStefano Zampini   }
92829566063dSJacob Faibussowitsch   if (output) PetscCall(PetscSynchronizedFlush(comm, NULL));
9283068a5610SStefano Zampini 
9284068a5610SStefano Zampini   if (size > 1) {
9285068a5610SStefano Zampini     PetscMPIInt  blockLengths[2] = {4, 1};
9286068a5610SStefano Zampini     MPI_Aint     blockOffsets[2] = {offsetof(cell_stats_t, min), offsetof(cell_stats_t, count)};
9287068a5610SStefano Zampini     MPI_Datatype blockTypes[2]   = {MPIU_REAL, MPIU_INT}, statType;
9288068a5610SStefano Zampini     MPI_Op       statReduce;
9289068a5610SStefano Zampini 
92909566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_create_struct(2, blockLengths, blockOffsets, blockTypes, &statType));
92919566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_commit(&statType));
92929566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Op_create(cell_stats_reduce, PETSC_TRUE, &statReduce));
92939566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Reduce(&stats, &globalStats, 1, statType, statReduce, 0, comm));
92949566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Op_free(&statReduce));
92959566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_free(&statType));
9296068a5610SStefano Zampini   } else {
92979566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(&globalStats, &stats, 1));
9298068a5610SStefano Zampini   }
9299dd400576SPatrick Sanan   if (rank == 0) {
9300068a5610SStefano Zampini     count = globalStats.count;
9301068a5610SStefano Zampini     min   = globalStats.min;
9302068a5610SStefano Zampini     max   = globalStats.max;
9303068a5610SStefano Zampini     mean  = globalStats.sum / globalStats.count;
9304068a5610SStefano Zampini     stdev = globalStats.count > 1 ? PetscSqrtReal(PetscMax((globalStats.squaresum - globalStats.count * mean * mean) / (globalStats.count - 1), 0)) : 0.0;
9305068a5610SStefano Zampini   }
9306068a5610SStefano Zampini 
930748a46eb9SPierre Jolivet   if (output) PetscCall(PetscPrintf(comm, "Mesh with %" PetscInt_FMT " cells, shape condition numbers: min = %g, max = %g, mean = %g, stddev = %g\n", count, (double)min, (double)max, (double)mean, (double)stdev));
93089566063dSJacob Faibussowitsch   PetscCall(PetscFree2(J, invJ));
9309068a5610SStefano Zampini 
93109566063dSJacob Faibussowitsch   PetscCall(DMGetCoarseDM(dm, &dmCoarse));
9311068a5610SStefano Zampini   if (dmCoarse) {
9312068a5610SStefano Zampini     PetscBool isplex;
9313068a5610SStefano Zampini 
93149566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)dmCoarse, DMPLEX, &isplex));
93151baa6e33SBarry Smith     if (isplex) PetscCall(DMPlexCheckCellShape(dmCoarse, output, condLimit));
9316068a5610SStefano Zampini   }
93173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9318068a5610SStefano Zampini }
9319068a5610SStefano Zampini 
9320f108dbd7SJacob Faibussowitsch /*@
9321f108dbd7SJacob Faibussowitsch   DMPlexComputeOrthogonalQuality - Compute cell-wise orthogonal quality mesh statistic. Optionally tags all cells with
9322f108dbd7SJacob Faibussowitsch   orthogonal quality below given tolerance.
9323f108dbd7SJacob Faibussowitsch 
932420f4b53cSBarry Smith   Collective
9325f108dbd7SJacob Faibussowitsch 
9326f108dbd7SJacob Faibussowitsch   Input Parameters:
9327a1cb98faSBarry Smith + dm   - The `DMPLEX` object
9328a1cb98faSBarry Smith . fv   - Optional `PetscFV` object for pre-computed cell/face centroid information
9329f108dbd7SJacob Faibussowitsch - atol - [0, 1] Absolute tolerance for tagging cells.
9330f108dbd7SJacob Faibussowitsch 
9331f108dbd7SJacob Faibussowitsch   Output Parameters:
933220f4b53cSBarry Smith + OrthQual      - `Vec` containing orthogonal quality per cell
9333a1cb98faSBarry Smith - OrthQualLabel - `DMLabel` tagging cells below atol with `DM_ADAPT_REFINE`
9334f108dbd7SJacob Faibussowitsch 
9335f108dbd7SJacob Faibussowitsch   Options Database Keys:
9336a1cb98faSBarry Smith + -dm_plex_orthogonal_quality_label_view - view OrthQualLabel if label is requested. Currently only `PETSCVIEWERASCII` is supported.
9337f108dbd7SJacob Faibussowitsch - -dm_plex_orthogonal_quality_vec_view   - view OrthQual vector.
9338f108dbd7SJacob Faibussowitsch 
9339a1cb98faSBarry Smith   Level: intermediate
9340a1cb98faSBarry Smith 
9341f108dbd7SJacob Faibussowitsch   Notes:
9342a4e35b19SJacob Faibussowitsch   Orthogonal quality is given by the following formula\:
9343f108dbd7SJacob Faibussowitsch 
9344a1cb98faSBarry Smith   $ \min \left[ \frac{A_i \cdot f_i}{\|A_i\| \|f_i\|} , \frac{A_i \cdot c_i}{\|A_i\| \|c_i\|} \right]$
9345f108dbd7SJacob Faibussowitsch 
9346f108dbd7SJacob 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
9347f108dbd7SJacob Faibussowitsch   is the vector from the current cells centroid to the centroid of its i'th neighbor (which shares a face with the
9348f108dbd7SJacob Faibussowitsch   current cell). This computes the vector similarity between each cell face and its corresponding neighbor centroid by
9349f108dbd7SJacob Faibussowitsch   calculating the cosine of the angle between these vectors.
9350f108dbd7SJacob Faibussowitsch 
9351f108dbd7SJacob Faibussowitsch   Orthogonal quality ranges from 1 (best) to 0 (worst).
9352f108dbd7SJacob Faibussowitsch 
9353a1cb98faSBarry Smith   This routine is mainly useful for FVM, however is not restricted to only FVM. The `PetscFV` object is optionally used to check for
9354f108dbd7SJacob Faibussowitsch   pre-computed FVM cell data, but if it is not passed in then this data will be computed.
9355f108dbd7SJacob Faibussowitsch 
9356f108dbd7SJacob Faibussowitsch   Cells are tagged if they have an orthogonal quality less than or equal to the absolute tolerance.
9357f108dbd7SJacob Faibussowitsch 
93581cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCheckCellShape()`, `DMCreateLabel()`, `PetscFV`, `DMLabel`, `Vec`
9359f108dbd7SJacob Faibussowitsch @*/
9360d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexComputeOrthogonalQuality(DM dm, PetscFV fv, PetscReal atol, Vec *OrthQual, DMLabel *OrthQualLabel)
9361d71ae5a4SJacob Faibussowitsch {
93626ed19f2fSJacob Faibussowitsch   PetscInt               nc, cellHeight, cStart, cEnd, cell, cellIter = 0;
93636ed19f2fSJacob Faibussowitsch   PetscInt              *idx;
93646ed19f2fSJacob Faibussowitsch   PetscScalar           *oqVals;
9365f108dbd7SJacob Faibussowitsch   const PetscScalar     *cellGeomArr, *faceGeomArr;
93666ed19f2fSJacob Faibussowitsch   PetscReal             *ci, *fi, *Ai;
9367f108dbd7SJacob Faibussowitsch   MPI_Comm               comm;
9368f108dbd7SJacob Faibussowitsch   Vec                    cellgeom, facegeom;
9369f108dbd7SJacob Faibussowitsch   DM                     dmFace, dmCell;
9370f108dbd7SJacob Faibussowitsch   IS                     glob;
9371f108dbd7SJacob Faibussowitsch   ISLocalToGlobalMapping ltog;
9372f108dbd7SJacob Faibussowitsch   PetscViewer            vwr;
9373f108dbd7SJacob Faibussowitsch 
9374f108dbd7SJacob Faibussowitsch   PetscFunctionBegin;
9375f108dbd7SJacob Faibussowitsch   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9376ad540459SPierre Jolivet   if (fv) PetscValidHeaderSpecific(fv, PETSCFV_CLASSID, 2);
93774f572ea9SToby Isaac   PetscAssertPointer(OrthQual, 4);
93786bdcaf15SBarry Smith   PetscCheck(atol >= 0.0 && atol <= 1.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Absolute tolerance %g not in [0,1]", (double)atol);
93799566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
93809566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &nc));
938163a3b9bcSJacob Faibussowitsch   PetscCheck(nc >= 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must have dimension >= 2 (current %" PetscInt_FMT ")", nc);
93826ed19f2fSJacob Faibussowitsch   {
93836ed19f2fSJacob Faibussowitsch     DMPlexInterpolatedFlag interpFlag;
93846ed19f2fSJacob Faibussowitsch 
93859566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated(dm, &interpFlag));
9386f108dbd7SJacob Faibussowitsch     if (interpFlag != DMPLEX_INTERPOLATED_FULL) {
9387f108dbd7SJacob Faibussowitsch       PetscMPIInt rank;
9388f108dbd7SJacob Faibussowitsch 
93899566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Comm_rank(comm, &rank));
939098921bdaSJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM must be fully interpolated, DM on rank %d is not fully interpolated", rank);
9391f108dbd7SJacob Faibussowitsch     }
93926ed19f2fSJacob Faibussowitsch   }
9393f108dbd7SJacob Faibussowitsch   if (OrthQualLabel) {
93944f572ea9SToby Isaac     PetscAssertPointer(OrthQualLabel, 5);
93959566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(dm, "Orthogonal_Quality"));
93969566063dSJacob Faibussowitsch     PetscCall(DMGetLabel(dm, "Orthogonal_Quality", OrthQualLabel));
93979371c9d4SSatish Balay   } else {
93989371c9d4SSatish Balay     *OrthQualLabel = NULL;
93999371c9d4SSatish Balay   }
94009566063dSJacob Faibussowitsch   PetscCall(DMPlexGetVTKCellHeight(dm, &cellHeight));
94019566063dSJacob Faibussowitsch   PetscCall(DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd));
94029566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateCellNumbering_Internal(dm, PETSC_TRUE, &glob));
94039566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingCreateIS(glob, &ltog));
94049566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingSetType(ltog, ISLOCALTOGLOBALMAPPINGHASH));
94059566063dSJacob Faibussowitsch   PetscCall(VecCreate(comm, OrthQual));
94069566063dSJacob Faibussowitsch   PetscCall(VecSetType(*OrthQual, VECSTANDARD));
94079566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(*OrthQual, cEnd - cStart, PETSC_DETERMINE));
94089566063dSJacob Faibussowitsch   PetscCall(VecSetLocalToGlobalMapping(*OrthQual, ltog));
94099566063dSJacob Faibussowitsch   PetscCall(VecSetUp(*OrthQual));
94109566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&glob));
94119566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&ltog));
94129566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDataFVM(dm, fv, &cellgeom, &facegeom, NULL));
94139566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(cellgeom, &cellGeomArr));
94149566063dSJacob Faibussowitsch   PetscCall(VecGetArrayRead(facegeom, &faceGeomArr));
94159566063dSJacob Faibussowitsch   PetscCall(VecGetDM(cellgeom, &dmCell));
94169566063dSJacob Faibussowitsch   PetscCall(VecGetDM(facegeom, &dmFace));
94179566063dSJacob Faibussowitsch   PetscCall(PetscMalloc5(cEnd - cStart, &idx, cEnd - cStart, &oqVals, nc, &ci, nc, &fi, nc, &Ai));
94186ed19f2fSJacob Faibussowitsch   for (cell = cStart; cell < cEnd; cellIter++, cell++) {
94196ed19f2fSJacob Faibussowitsch     PetscInt         cellneigh, cellneighiter = 0, adjSize = PETSC_DETERMINE;
9420f108dbd7SJacob Faibussowitsch     PetscInt         cellarr[2], *adj = NULL;
9421f108dbd7SJacob Faibussowitsch     PetscScalar     *cArr, *fArr;
9422898cd552SSatish Balay     PetscReal        minvalc = 1.0, minvalf = 1.0;
9423f108dbd7SJacob Faibussowitsch     PetscFVCellGeom *cg;
9424f108dbd7SJacob Faibussowitsch 
94256ed19f2fSJacob Faibussowitsch     idx[cellIter] = cell - cStart;
9426f108dbd7SJacob Faibussowitsch     cellarr[0]    = cell;
9427f108dbd7SJacob Faibussowitsch     /* Make indexing into cellGeom easier */
94289566063dSJacob Faibussowitsch     PetscCall(DMPlexPointLocalRead(dmCell, cell, cellGeomArr, &cg));
94299566063dSJacob Faibussowitsch     PetscCall(DMPlexGetAdjacency_Internal(dm, cell, PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, &adjSize, &adj));
9430f108dbd7SJacob Faibussowitsch     /* Technically 1 too big, but easier than fiddling with empty adjacency array */
94319566063dSJacob Faibussowitsch     PetscCall(PetscCalloc2(adjSize, &cArr, adjSize, &fArr));
94326ed19f2fSJacob Faibussowitsch     for (cellneigh = 0; cellneigh < adjSize; cellneighiter++, cellneigh++) {
94336ed19f2fSJacob Faibussowitsch       PetscInt         i;
94346ed19f2fSJacob Faibussowitsch       const PetscInt   neigh  = adj[cellneigh];
9435f108dbd7SJacob Faibussowitsch       PetscReal        normci = 0, normfi = 0, normai = 0;
9436f108dbd7SJacob Faibussowitsch       PetscFVCellGeom *cgneigh;
9437f108dbd7SJacob Faibussowitsch       PetscFVFaceGeom *fg;
9438f108dbd7SJacob Faibussowitsch 
9439f108dbd7SJacob Faibussowitsch       /* Don't count ourselves in the neighbor list */
9440f108dbd7SJacob Faibussowitsch       if (neigh == cell) continue;
94419566063dSJacob Faibussowitsch       PetscCall(DMPlexPointLocalRead(dmCell, neigh, cellGeomArr, &cgneigh));
9442f108dbd7SJacob Faibussowitsch       cellarr[1] = neigh;
94436ed19f2fSJacob Faibussowitsch       {
94446ed19f2fSJacob Faibussowitsch         PetscInt        numcovpts;
94456ed19f2fSJacob Faibussowitsch         const PetscInt *covpts;
94466ed19f2fSJacob Faibussowitsch 
94479566063dSJacob Faibussowitsch         PetscCall(DMPlexGetMeet(dm, 2, cellarr, &numcovpts, &covpts));
94489566063dSJacob Faibussowitsch         PetscCall(DMPlexPointLocalRead(dmFace, covpts[0], faceGeomArr, &fg));
94499566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreMeet(dm, 2, cellarr, &numcovpts, &covpts));
94506ed19f2fSJacob Faibussowitsch       }
9451f108dbd7SJacob Faibussowitsch 
9452f108dbd7SJacob Faibussowitsch       /* Compute c_i, f_i and their norms */
9453f108dbd7SJacob Faibussowitsch       for (i = 0; i < nc; i++) {
9454f108dbd7SJacob Faibussowitsch         ci[i] = cgneigh->centroid[i] - cg->centroid[i];
9455f108dbd7SJacob Faibussowitsch         fi[i] = fg->centroid[i] - cg->centroid[i];
9456f108dbd7SJacob Faibussowitsch         Ai[i] = fg->normal[i];
9457addd1e01SJunchao Zhang         normci += PetscPowReal(ci[i], 2);
9458addd1e01SJunchao Zhang         normfi += PetscPowReal(fi[i], 2);
9459addd1e01SJunchao Zhang         normai += PetscPowReal(Ai[i], 2);
9460f108dbd7SJacob Faibussowitsch       }
9461addd1e01SJunchao Zhang       normci = PetscSqrtReal(normci);
9462addd1e01SJunchao Zhang       normfi = PetscSqrtReal(normfi);
9463addd1e01SJunchao Zhang       normai = PetscSqrtReal(normai);
9464f108dbd7SJacob Faibussowitsch 
9465f108dbd7SJacob Faibussowitsch       /* Normalize and compute for each face-cell-normal pair */
9466f108dbd7SJacob Faibussowitsch       for (i = 0; i < nc; i++) {
9467f108dbd7SJacob Faibussowitsch         ci[i] = ci[i] / normci;
9468f108dbd7SJacob Faibussowitsch         fi[i] = fi[i] / normfi;
9469f108dbd7SJacob Faibussowitsch         Ai[i] = Ai[i] / normai;
9470f108dbd7SJacob Faibussowitsch         /* PetscAbs because I don't know if normals are guaranteed to point out */
9471f108dbd7SJacob Faibussowitsch         cArr[cellneighiter] += PetscAbs(Ai[i] * ci[i]);
9472f108dbd7SJacob Faibussowitsch         fArr[cellneighiter] += PetscAbs(Ai[i] * fi[i]);
9473f108dbd7SJacob Faibussowitsch       }
9474ad540459SPierre Jolivet       if (PetscRealPart(cArr[cellneighiter]) < minvalc) minvalc = PetscRealPart(cArr[cellneighiter]);
9475ad540459SPierre Jolivet       if (PetscRealPart(fArr[cellneighiter]) < minvalf) minvalf = PetscRealPart(fArr[cellneighiter]);
9476f108dbd7SJacob Faibussowitsch     }
94779566063dSJacob Faibussowitsch     PetscCall(PetscFree(adj));
94789566063dSJacob Faibussowitsch     PetscCall(PetscFree2(cArr, fArr));
9479f108dbd7SJacob Faibussowitsch     /* Defer to cell if they're equal */
94806ed19f2fSJacob Faibussowitsch     oqVals[cellIter] = PetscMin(minvalf, minvalc);
9481f108dbd7SJacob Faibussowitsch     if (OrthQualLabel) {
94829566063dSJacob Faibussowitsch       if (PetscRealPart(oqVals[cellIter]) <= atol) PetscCall(DMLabelSetValue(*OrthQualLabel, cell, DM_ADAPT_REFINE));
9483f108dbd7SJacob Faibussowitsch     }
9484f108dbd7SJacob Faibussowitsch   }
94859566063dSJacob Faibussowitsch   PetscCall(VecSetValuesLocal(*OrthQual, cEnd - cStart, idx, oqVals, INSERT_VALUES));
94869566063dSJacob Faibussowitsch   PetscCall(VecAssemblyBegin(*OrthQual));
94879566063dSJacob Faibussowitsch   PetscCall(VecAssemblyEnd(*OrthQual));
94889566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(cellgeom, &cellGeomArr));
94899566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(facegeom, &faceGeomArr));
94909566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetViewer(comm, NULL, NULL, "-dm_plex_orthogonal_quality_label_view", &vwr, NULL, NULL));
9491f108dbd7SJacob Faibussowitsch   if (OrthQualLabel) {
94929566063dSJacob Faibussowitsch     if (vwr) PetscCall(DMLabelView(*OrthQualLabel, vwr));
9493f108dbd7SJacob Faibussowitsch   }
94949566063dSJacob Faibussowitsch   PetscCall(PetscFree5(idx, oqVals, ci, fi, Ai));
94959566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(&vwr));
94969566063dSJacob Faibussowitsch   PetscCall(VecViewFromOptions(*OrthQual, NULL, "-dm_plex_orthogonal_quality_vec_view"));
94973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9498f108dbd7SJacob Faibussowitsch }
9499f108dbd7SJacob Faibussowitsch 
9500d5b43468SJose E. Roman /* this is here instead of DMGetOutputDM because output DM still has constraints in the local indices that affect
95011eb70e55SToby Isaac  * interpolator construction */
9502d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetFullDM(DM dm, DM *odm)
9503d71ae5a4SJacob Faibussowitsch {
95041eb70e55SToby Isaac   PetscSection section, newSection, gsection;
95051eb70e55SToby Isaac   PetscSF      sf;
95061eb70e55SToby Isaac   PetscBool    hasConstraints, ghasConstraints;
95071eb70e55SToby Isaac 
95081eb70e55SToby Isaac   PetscFunctionBegin;
95091eb70e55SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
95104f572ea9SToby Isaac   PetscAssertPointer(odm, 2);
95119566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
95129566063dSJacob Faibussowitsch   PetscCall(PetscSectionHasConstraints(section, &hasConstraints));
9513712fec58SPierre Jolivet   PetscCall(MPIU_Allreduce(&hasConstraints, &ghasConstraints, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)dm)));
95141eb70e55SToby Isaac   if (!ghasConstraints) {
95159566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)dm));
95161eb70e55SToby Isaac     *odm = dm;
95173ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
95181eb70e55SToby Isaac   }
95199566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, odm));
95209566063dSJacob Faibussowitsch   PetscCall(DMCopyFields(dm, *odm));
95219566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(*odm, &newSection));
95229566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(*odm, &sf));
95239566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreateGlobalSection(newSection, sf, PETSC_TRUE, PETSC_FALSE, &gsection));
95249566063dSJacob Faibussowitsch   PetscCall(DMSetGlobalSection(*odm, gsection));
95259566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&gsection));
95263ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
95271eb70e55SToby Isaac }
95281eb70e55SToby Isaac 
9529d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateAffineInterpolationCorrection_Plex(DM dmc, DM dmf, Vec *shift)
9530d71ae5a4SJacob Faibussowitsch {
95311eb70e55SToby Isaac   DM        dmco, dmfo;
95321eb70e55SToby Isaac   Mat       interpo;
95331eb70e55SToby Isaac   Vec       rscale;
95341eb70e55SToby Isaac   Vec       cglobalo, clocal;
95351eb70e55SToby Isaac   Vec       fglobal, fglobalo, flocal;
95361eb70e55SToby Isaac   PetscBool regular;
95371eb70e55SToby Isaac 
95381eb70e55SToby Isaac   PetscFunctionBegin;
95399566063dSJacob Faibussowitsch   PetscCall(DMGetFullDM(dmc, &dmco));
95409566063dSJacob Faibussowitsch   PetscCall(DMGetFullDM(dmf, &dmfo));
95419566063dSJacob Faibussowitsch   PetscCall(DMSetCoarseDM(dmfo, dmco));
95429566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRegularRefinement(dmf, &regular));
95439566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRegularRefinement(dmfo, regular));
95449566063dSJacob Faibussowitsch   PetscCall(DMCreateInterpolation(dmco, dmfo, &interpo, &rscale));
95459566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmco, &cglobalo));
95469566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dmc, &clocal));
95479566063dSJacob Faibussowitsch   PetscCall(VecSet(cglobalo, 0.));
95489566063dSJacob Faibussowitsch   PetscCall(VecSet(clocal, 0.));
95499566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmf, &fglobal));
95509566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmfo, &fglobalo));
95519566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(dmf, &flocal));
95529566063dSJacob Faibussowitsch   PetscCall(VecSet(fglobal, 0.));
95539566063dSJacob Faibussowitsch   PetscCall(VecSet(fglobalo, 0.));
95549566063dSJacob Faibussowitsch   PetscCall(VecSet(flocal, 0.));
95559566063dSJacob Faibussowitsch   PetscCall(DMPlexInsertBoundaryValues(dmc, PETSC_TRUE, clocal, 0., NULL, NULL, NULL));
95569566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmco, clocal, INSERT_VALUES, cglobalo));
95579566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmco, clocal, INSERT_VALUES, cglobalo));
95589566063dSJacob Faibussowitsch   PetscCall(MatMult(interpo, cglobalo, fglobalo));
95599566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalBegin(dmfo, fglobalo, INSERT_VALUES, flocal));
95609566063dSJacob Faibussowitsch   PetscCall(DMGlobalToLocalEnd(dmfo, fglobalo, INSERT_VALUES, flocal));
95619566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmf, flocal, INSERT_VALUES, fglobal));
95629566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmf, flocal, INSERT_VALUES, fglobal));
95631eb70e55SToby Isaac   *shift = fglobal;
95649566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&flocal));
95659566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&fglobalo));
95669566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&clocal));
95679566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&cglobalo));
95689566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&rscale));
95699566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&interpo));
95709566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmfo));
95719566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmco));
95723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
95731eb70e55SToby Isaac }
95741eb70e55SToby Isaac 
9575d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM coarse, DM fine, Mat interp, Vec coarseSol, Vec fineSol)
9576d71ae5a4SJacob Faibussowitsch {
95771eb70e55SToby Isaac   PetscObject shifto;
95781eb70e55SToby Isaac   Vec         shift;
95791eb70e55SToby Isaac 
95801eb70e55SToby Isaac   PetscFunctionBegin;
95811eb70e55SToby Isaac   if (!interp) {
95821eb70e55SToby Isaac     Vec rscale;
95831eb70e55SToby Isaac 
95849566063dSJacob Faibussowitsch     PetscCall(DMCreateInterpolation(coarse, fine, &interp, &rscale));
95859566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&rscale));
95861eb70e55SToby Isaac   } else {
95879566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)interp));
95881eb70e55SToby Isaac   }
95899566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", &shifto));
95901eb70e55SToby Isaac   if (!shifto) {
95919566063dSJacob Faibussowitsch     PetscCall(DMCreateAffineInterpolationCorrection_Plex(coarse, fine, &shift));
95929566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)interp, "_DMInterpolateSolution_Plex_Vec", (PetscObject)shift));
95931eb70e55SToby Isaac     shifto = (PetscObject)shift;
95949566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&shift));
95951eb70e55SToby Isaac   }
95961eb70e55SToby Isaac   shift = (Vec)shifto;
95979566063dSJacob Faibussowitsch   PetscCall(MatInterpolate(interp, coarseSol, fineSol));
95989566063dSJacob Faibussowitsch   PetscCall(VecAXPY(fineSol, 1.0, shift));
95999566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&interp));
96003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
96011eb70e55SToby Isaac }
96021eb70e55SToby Isaac 
9603bceba477SMatthew G. Knepley /* Pointwise interpolation
9604bceba477SMatthew G. Knepley      Just code FEM for now
9605bceba477SMatthew G. Knepley      u^f = I u^c
96064ca5e9f5SMatthew G. Knepley      sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j
96074ca5e9f5SMatthew G. Knepley      u^f_i = sum_j psi^f_i I phi^c_j u^c_j
96084ca5e9f5SMatthew G. Knepley      I_{ij} = psi^f_i phi^c_j
9609bceba477SMatthew G. Knepley */
9610d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling)
9611d71ae5a4SJacob Faibussowitsch {
9612bceba477SMatthew G. Knepley   PetscSection gsc, gsf;
9613bceba477SMatthew G. Knepley   PetscInt     m, n;
9614a063dac3SMatthew G. Knepley   void        *ctx;
961568132eb9SMatthew G. Knepley   DM           cdm;
9616cf51de39SMatthew G. Knepley   PetscBool    regular, ismatis, isRefined = dmCoarse->data == dmFine->data ? PETSC_FALSE : PETSC_TRUE;
9617bceba477SMatthew G. Knepley 
9618bceba477SMatthew G. Knepley   PetscFunctionBegin;
96199566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmFine, &gsf));
96209566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m));
96219566063dSJacob Faibussowitsch   PetscCall(DMGetGlobalSection(dmCoarse, &gsc));
96229566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n));
962368132eb9SMatthew G. Knepley 
96249566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dmCoarse->mattype, MATIS, &ismatis));
96259566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), interpolation));
96269566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE));
96279566063dSJacob Faibussowitsch   PetscCall(MatSetType(*interpolation, ismatis ? MATAIJ : dmCoarse->mattype));
96289566063dSJacob Faibussowitsch   PetscCall(DMGetApplicationContext(dmFine, &ctx));
962968132eb9SMatthew G. Knepley 
96309566063dSJacob Faibussowitsch   PetscCall(DMGetCoarseDM(dmFine, &cdm));
96319566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRegularRefinement(dmFine, &regular));
96329566063dSJacob Faibussowitsch   if (!isRefined || (regular && cdm == dmCoarse)) PetscCall(DMPlexComputeInterpolatorNested(dmCoarse, dmFine, isRefined, *interpolation, ctx));
96339566063dSJacob Faibussowitsch   else PetscCall(DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx));
96349566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(*interpolation, NULL, "-interp_mat_view"));
96354db47ee9SStefano Zampini   if (scaling) {
96365d1c2e58SMatthew G. Knepley     /* Use naive scaling */
96379566063dSJacob Faibussowitsch     PetscCall(DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling));
96384db47ee9SStefano Zampini   }
96393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9640a063dac3SMatthew G. Knepley }
9641bceba477SMatthew G. Knepley 
9642d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat)
9643d71ae5a4SJacob Faibussowitsch {
96446dbf9973SLawrence Mitchell   VecScatter ctx;
964590748bafSMatthew G. Knepley 
9646a063dac3SMatthew G. Knepley   PetscFunctionBegin;
96479566063dSJacob Faibussowitsch   PetscCall(DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL));
96489566063dSJacob Faibussowitsch   PetscCall(MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat));
96499566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&ctx));
96503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9651bceba477SMatthew G. Knepley }
9652bceba477SMatthew G. Knepley 
9653d71ae5a4SJacob Faibussowitsch static void g0_identity_private(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[])
9654d71ae5a4SJacob Faibussowitsch {
965500635df3SMatthew G. Knepley   const PetscInt Nc = uOff[1] - uOff[0];
965600635df3SMatthew G. Knepley   PetscInt       c;
965700635df3SMatthew G. Knepley   for (c = 0; c < Nc; ++c) g0[c * Nc + c] = 1.0;
96583e9753d6SMatthew G. Knepley }
96593e9753d6SMatthew G. Knepley 
9660d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrixLumped_Plex(DM dm, Vec *mass)
9661d71ae5a4SJacob Faibussowitsch {
9662b4937a87SMatthew G. Knepley   DM           dmc;
9663b4937a87SMatthew G. Knepley   PetscDS      ds;
9664b4937a87SMatthew G. Knepley   Vec          ones, locmass;
9665b4937a87SMatthew G. Knepley   IS           cellIS;
9666b4937a87SMatthew G. Knepley   PetscFormKey key;
9667b4937a87SMatthew G. Knepley   PetscInt     depth;
9668b4937a87SMatthew G. Knepley 
9669b4937a87SMatthew G. Knepley   PetscFunctionBegin;
96709566063dSJacob Faibussowitsch   PetscCall(DMClone(dm, &dmc));
96719566063dSJacob Faibussowitsch   PetscCall(DMCopyDisc(dm, dmc));
96729566063dSJacob Faibussowitsch   PetscCall(DMGetDS(dmc, &ds));
96739566063dSJacob Faibussowitsch   PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL));
96749566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector(dmc, mass));
96759566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dmc, &ones));
96769566063dSJacob Faibussowitsch   PetscCall(DMGetLocalVector(dmc, &locmass));
96779566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dmc, &depth));
96789566063dSJacob Faibussowitsch   PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS));
96799566063dSJacob Faibussowitsch   PetscCall(VecSet(locmass, 0.0));
96809566063dSJacob Faibussowitsch   PetscCall(VecSet(ones, 1.0));
9681b4937a87SMatthew G. Knepley   key.label = NULL;
9682b4937a87SMatthew G. Knepley   key.value = 0;
9683b4937a87SMatthew G. Knepley   key.field = 0;
9684b4937a87SMatthew G. Knepley   key.part  = 0;
96859566063dSJacob Faibussowitsch   PetscCall(DMPlexComputeJacobian_Action_Internal(dmc, key, cellIS, 0.0, 0.0, ones, NULL, ones, locmass, NULL));
96869566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&cellIS));
96879566063dSJacob Faibussowitsch   PetscCall(VecSet(*mass, 0.0));
96889566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalBegin(dmc, locmass, ADD_VALUES, *mass));
96899566063dSJacob Faibussowitsch   PetscCall(DMLocalToGlobalEnd(dmc, locmass, ADD_VALUES, *mass));
96909566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dmc, &ones));
96919566063dSJacob Faibussowitsch   PetscCall(DMRestoreLocalVector(dmc, &locmass));
96929566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&dmc));
96933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9694b4937a87SMatthew G. Knepley }
9695b4937a87SMatthew G. Knepley 
9696d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMassMatrix_Plex(DM dmCoarse, DM dmFine, Mat *mass)
9697d71ae5a4SJacob Faibussowitsch {
9698bd041c0cSMatthew G. Knepley   PetscSection gsc, gsf;
9699bd041c0cSMatthew G. Knepley   PetscInt     m, n;
9700bd041c0cSMatthew G. Knepley   void        *ctx;
9701bd041c0cSMatthew G. Knepley   DM           cdm;
9702bd041c0cSMatthew G. Knepley   PetscBool    regular;
9703bd041c0cSMatthew G. Knepley 
9704bd041c0cSMatthew G. Knepley   PetscFunctionBegin;
97053e9753d6SMatthew G. Knepley   if (dmFine == dmCoarse) {
97063e9753d6SMatthew G. Knepley     DM            dmc;
97073e9753d6SMatthew G. Knepley     PetscDS       ds;
9708b4937a87SMatthew G. Knepley     PetscWeakForm wf;
97093e9753d6SMatthew G. Knepley     Vec           u;
97103e9753d6SMatthew G. Knepley     IS            cellIS;
971106ad1575SMatthew G. Knepley     PetscFormKey  key;
97123e9753d6SMatthew G. Knepley     PetscInt      depth;
97133e9753d6SMatthew G. Knepley 
97149566063dSJacob Faibussowitsch     PetscCall(DMClone(dmFine, &dmc));
97159566063dSJacob Faibussowitsch     PetscCall(DMCopyDisc(dmFine, dmc));
97169566063dSJacob Faibussowitsch     PetscCall(DMGetDS(dmc, &ds));
97179566063dSJacob Faibussowitsch     PetscCall(PetscDSGetWeakForm(ds, &wf));
97189566063dSJacob Faibussowitsch     PetscCall(PetscWeakFormClear(wf));
97199566063dSJacob Faibussowitsch     PetscCall(PetscDSSetJacobian(ds, 0, 0, g0_identity_private, NULL, NULL, NULL));
97209566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(dmc, mass));
97218d94ca23SJed Brown     PetscCall(DMGetLocalVector(dmc, &u));
97229566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dmc, &depth));
97239566063dSJacob Faibussowitsch     PetscCall(DMGetStratumIS(dmc, "depth", depth, &cellIS));
97249566063dSJacob Faibussowitsch     PetscCall(MatZeroEntries(*mass));
97256528b96dSMatthew G. Knepley     key.label = NULL;
97266528b96dSMatthew G. Knepley     key.value = 0;
97276528b96dSMatthew G. Knepley     key.field = 0;
972806ad1575SMatthew G. Knepley     key.part  = 0;
97299566063dSJacob Faibussowitsch     PetscCall(DMPlexComputeJacobian_Internal(dmc, key, cellIS, 0.0, 0.0, u, NULL, *mass, *mass, NULL));
97309566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&cellIS));
97318d94ca23SJed Brown     PetscCall(DMRestoreLocalVector(dmc, &u));
97329566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&dmc));
97333e9753d6SMatthew G. Knepley   } else {
97349566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dmFine, &gsf));
97359566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstrainedStorageSize(gsf, &m));
97369566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dmCoarse, &gsc));
97379566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetConstrainedStorageSize(gsc, &n));
9738bd041c0cSMatthew G. Knepley 
97399566063dSJacob Faibussowitsch     PetscCall(MatCreate(PetscObjectComm((PetscObject)dmCoarse), mass));
97409566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE));
97419566063dSJacob Faibussowitsch     PetscCall(MatSetType(*mass, dmCoarse->mattype));
97429566063dSJacob Faibussowitsch     PetscCall(DMGetApplicationContext(dmFine, &ctx));
9743bd041c0cSMatthew G. Knepley 
97449566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dmFine, &cdm));
97459566063dSJacob Faibussowitsch     PetscCall(DMPlexGetRegularRefinement(dmFine, &regular));
97469566063dSJacob Faibussowitsch     if (regular && cdm == dmCoarse) PetscCall(DMPlexComputeMassMatrixNested(dmCoarse, dmFine, *mass, ctx));
97479566063dSJacob Faibussowitsch     else PetscCall(DMPlexComputeMassMatrixGeneral(dmCoarse, dmFine, *mass, ctx));
97483e9753d6SMatthew G. Knepley   }
97499566063dSJacob Faibussowitsch   PetscCall(MatViewFromOptions(*mass, NULL, "-mass_mat_view"));
97503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9751bd041c0cSMatthew G. Knepley }
9752bd041c0cSMatthew G. Knepley 
97530aef6b92SMatthew G. Knepley /*@
97540aef6b92SMatthew G. Knepley   DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh
97550aef6b92SMatthew G. Knepley 
97560aef6b92SMatthew G. Knepley   Input Parameter:
9757a1cb98faSBarry Smith . dm - The `DMPLEX` object
97580aef6b92SMatthew G. Knepley 
97590aef6b92SMatthew G. Knepley   Output Parameter:
97600aef6b92SMatthew G. Knepley . regular - The flag
97610aef6b92SMatthew G. Knepley 
97620aef6b92SMatthew G. Knepley   Level: intermediate
97630aef6b92SMatthew G. Knepley 
97641cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetRegularRefinement()`
97650aef6b92SMatthew G. Knepley @*/
9766d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular)
9767d71ae5a4SJacob Faibussowitsch {
97680aef6b92SMatthew G. Knepley   PetscFunctionBegin;
97690aef6b92SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
97704f572ea9SToby Isaac   PetscAssertPointer(regular, 2);
97710aef6b92SMatthew G. Knepley   *regular = ((DM_Plex *)dm->data)->regularRefinement;
97723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
97730aef6b92SMatthew G. Knepley }
97740aef6b92SMatthew G. Knepley 
97750aef6b92SMatthew G. Knepley /*@
97760aef6b92SMatthew G. Knepley   DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh
97770aef6b92SMatthew G. Knepley 
97780aef6b92SMatthew G. Knepley   Input Parameters:
9779a1cb98faSBarry Smith + dm      - The `DMPLEX` object
97800aef6b92SMatthew G. Knepley - regular - The flag
97810aef6b92SMatthew G. Knepley 
97820aef6b92SMatthew G. Knepley   Level: intermediate
97830aef6b92SMatthew G. Knepley 
97841cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetRegularRefinement()`
97850aef6b92SMatthew G. Knepley @*/
9786d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular)
9787d71ae5a4SJacob Faibussowitsch {
97880aef6b92SMatthew G. Knepley   PetscFunctionBegin;
97890aef6b92SMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
97900aef6b92SMatthew G. Knepley   ((DM_Plex *)dm->data)->regularRefinement = regular;
97913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
97920aef6b92SMatthew G. Knepley }
97930aef6b92SMatthew G. Knepley 
9794a68b90caSToby Isaac /*@
9795f7c74593SToby Isaac   DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints.  Typically, the user will not have to
9796a1cb98faSBarry Smith   call DMPlexGetAnchors() directly: if there are anchors, then `DMPlexGetAnchors()` is called during `DMGetDefaultConstraints()`.
9797a68b90caSToby Isaac 
9798a1cb98faSBarry Smith   Not Collective
9799a68b90caSToby Isaac 
9800f899ff85SJose E. Roman   Input Parameter:
9801a1cb98faSBarry Smith . dm - The `DMPLEX` object
9802a68b90caSToby Isaac 
9803a68b90caSToby Isaac   Output Parameters:
980420f4b53cSBarry Smith + anchorSection - If not `NULL`, set to the section describing which points anchor the constrained points.
980520f4b53cSBarry Smith - anchorIS      - If not `NULL`, set to the list of anchors indexed by `anchorSection`
9806a68b90caSToby Isaac 
9807a68b90caSToby Isaac   Level: intermediate
9808a68b90caSToby Isaac 
98091cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexSetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()`, `IS`, `PetscSection`
9810a68b90caSToby Isaac @*/
9811d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS)
9812d71ae5a4SJacob Faibussowitsch {
9813a68b90caSToby Isaac   DM_Plex *plex = (DM_Plex *)dm->data;
9814a68b90caSToby Isaac 
9815a68b90caSToby Isaac   PetscFunctionBegin;
9816a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
98179566063dSJacob Faibussowitsch   if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) PetscCall((*plex->createanchors)(dm));
9818a68b90caSToby Isaac   if (anchorSection) *anchorSection = plex->anchorSection;
9819a68b90caSToby Isaac   if (anchorIS) *anchorIS = plex->anchorIS;
98203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9821a68b90caSToby Isaac }
9822a68b90caSToby Isaac 
9823a68b90caSToby Isaac /*@
9824a4e35b19SJacob Faibussowitsch   DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints.
9825a68b90caSToby Isaac 
982620f4b53cSBarry Smith   Collective
9827a68b90caSToby Isaac 
9828a68b90caSToby Isaac   Input Parameters:
9829a1cb98faSBarry Smith + dm            - The `DMPLEX` object
9830a1cb98faSBarry Smith . anchorSection - The section that describes the mapping from constrained points to the anchor points listed in anchorIS.
9831a1cb98faSBarry Smith                   Must have a local communicator (`PETSC_COMM_SELF` or derivative).
9832a1cb98faSBarry Smith - anchorIS      - The list of all anchor points.  Must have a local communicator (`PETSC_COMM_SELF` or derivative).
9833a68b90caSToby Isaac 
9834a68b90caSToby Isaac   Level: intermediate
9835a68b90caSToby Isaac 
9836a1cb98faSBarry Smith   Notes:
9837a4e35b19SJacob Faibussowitsch   Unlike boundary conditions, when a point's degrees of freedom in a section are constrained to
9838a4e35b19SJacob Faibussowitsch   an outside value, the anchor constraints set a point's degrees of freedom to be a linear
9839a4e35b19SJacob Faibussowitsch   combination of other points' degrees of freedom.
9840a4e35b19SJacob Faibussowitsch 
9841a1cb98faSBarry Smith   After specifying the layout of constraints with `DMPlexSetAnchors()`, one specifies the constraints by calling
9842a1cb98faSBarry Smith   `DMGetDefaultConstraints()` and filling in the entries in the constraint matrix.
9843a1cb98faSBarry Smith 
984420f4b53cSBarry Smith   The reference counts of `anchorSection` and `anchorIS` are incremented.
9845a1cb98faSBarry Smith 
98461cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexGetAnchors()`, `DMGetDefaultConstraints()`, `DMSetDefaultConstraints()`
9847a68b90caSToby Isaac @*/
9848d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS)
9849d71ae5a4SJacob Faibussowitsch {
9850a68b90caSToby Isaac   DM_Plex    *plex = (DM_Plex *)dm->data;
9851e228b242SToby Isaac   PetscMPIInt result;
9852a68b90caSToby Isaac 
9853a68b90caSToby Isaac   PetscFunctionBegin;
9854a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
9855e228b242SToby Isaac   if (anchorSection) {
9856e228b242SToby Isaac     PetscValidHeaderSpecific(anchorSection, PETSC_SECTION_CLASSID, 2);
98579566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorSection), &result));
98581dca8a05SBarry Smith     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor section must have local communicator");
9859e228b242SToby Isaac   }
9860e228b242SToby Isaac   if (anchorIS) {
9861e228b242SToby Isaac     PetscValidHeaderSpecific(anchorIS, IS_CLASSID, 3);
98629566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_compare(PETSC_COMM_SELF, PetscObjectComm((PetscObject)anchorIS), &result));
98631dca8a05SBarry Smith     PetscCheck(result == MPI_CONGRUENT || result == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "anchor IS must have local communicator");
9864e228b242SToby Isaac   }
9865a68b90caSToby Isaac 
98669566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)anchorSection));
98679566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&plex->anchorSection));
9868a68b90caSToby Isaac   plex->anchorSection = anchorSection;
9869a68b90caSToby Isaac 
98709566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)anchorIS));
98719566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&plex->anchorIS));
9872a68b90caSToby Isaac   plex->anchorIS = anchorIS;
9873a68b90caSToby Isaac 
9874cf9c20a2SJed Brown   if (PetscUnlikelyDebug(anchorIS && anchorSection)) {
9875a68b90caSToby Isaac     PetscInt        size, a, pStart, pEnd;
9876a68b90caSToby Isaac     const PetscInt *anchors;
9877a68b90caSToby Isaac 
98789566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd));
98799566063dSJacob Faibussowitsch     PetscCall(ISGetLocalSize(anchorIS, &size));
98809566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(anchorIS, &anchors));
9881a68b90caSToby Isaac     for (a = 0; a < size; a++) {
9882a68b90caSToby Isaac       PetscInt p;
9883a68b90caSToby Isaac 
9884a68b90caSToby Isaac       p = anchors[a];
9885a68b90caSToby Isaac       if (p >= pStart && p < pEnd) {
9886a68b90caSToby Isaac         PetscInt dof;
9887a68b90caSToby Isaac 
98889566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(anchorSection, p, &dof));
9889a68b90caSToby Isaac         if (dof) {
98909566063dSJacob Faibussowitsch           PetscCall(ISRestoreIndices(anchorIS, &anchors));
989163a3b9bcSJacob Faibussowitsch           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Point %" PetscInt_FMT " cannot be constrained and an anchor", p);
9892a68b90caSToby Isaac         }
9893a68b90caSToby Isaac       }
9894a68b90caSToby Isaac     }
98959566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(anchorIS, &anchors));
9896a68b90caSToby Isaac   }
9897f7c74593SToby Isaac   /* reset the generic constraints */
98989566063dSJacob Faibussowitsch   PetscCall(DMSetDefaultConstraints(dm, NULL, NULL, NULL));
98993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9900a68b90caSToby Isaac }
9901a68b90caSToby Isaac 
9902d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec)
9903d71ae5a4SJacob Faibussowitsch {
9904f7c74593SToby Isaac   PetscSection anchorSection;
99056995de1eSToby Isaac   PetscInt     pStart, pEnd, sStart, sEnd, p, dof, numFields, f;
9906a68b90caSToby Isaac 
9907a68b90caSToby Isaac   PetscFunctionBegin;
9908a68b90caSToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
99099566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL));
99109566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PETSC_COMM_SELF, cSec));
99119566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
99126995de1eSToby Isaac   if (numFields) {
9913719ab38cSToby Isaac     PetscInt f;
99149566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(*cSec, numFields));
9915719ab38cSToby Isaac 
9916719ab38cSToby Isaac     for (f = 0; f < numFields; f++) {
9917719ab38cSToby Isaac       PetscInt numComp;
9918719ab38cSToby Isaac 
99199566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetFieldComponents(section, f, &numComp));
99209566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldComponents(*cSec, f, numComp));
9921719ab38cSToby Isaac     }
99226995de1eSToby Isaac   }
99239566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(anchorSection, &pStart, &pEnd));
99249566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &sStart, &sEnd));
99256995de1eSToby Isaac   pStart = PetscMax(pStart, sStart);
99266995de1eSToby Isaac   pEnd   = PetscMin(pEnd, sEnd);
99276995de1eSToby Isaac   pEnd   = PetscMax(pStart, pEnd);
99289566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(*cSec, pStart, pEnd));
9929a68b90caSToby Isaac   for (p = pStart; p < pEnd; p++) {
99309566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(anchorSection, p, &dof));
9931a68b90caSToby Isaac     if (dof) {
99329566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(section, p, &dof));
99339566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(*cSec, p, dof));
9934a68b90caSToby Isaac       for (f = 0; f < numFields; f++) {
99359566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(section, p, f, &dof));
99369566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetFieldDof(*cSec, p, f, dof));
9937a68b90caSToby Isaac       }
9938a68b90caSToby Isaac     }
9939a68b90caSToby Isaac   }
99409566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(*cSec));
99419566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)*cSec, "Constraint Section"));
99423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9943a68b90caSToby Isaac }
9944a68b90caSToby Isaac 
9945d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat)
9946d71ae5a4SJacob Faibussowitsch {
9947f7c74593SToby Isaac   PetscSection    aSec;
9948ae65431dSMatthew G. Knepley   PetscInt        pStart, pEnd, p, sStart, sEnd, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j;
99490ac89760SToby Isaac   const PetscInt *anchors;
99500ac89760SToby Isaac   PetscInt        numFields, f;
995166ad2231SToby Isaac   IS              aIS;
9952e19f7ee6SMark Adams   MatType         mtype;
9953e19f7ee6SMark Adams   PetscBool       iscuda, iskokkos;
99540ac89760SToby Isaac 
99550ac89760SToby Isaac   PetscFunctionBegin;
99560ac89760SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
99579566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(cSec, &m));
99589566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(section, &n));
99599566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_SELF, cMat));
99609566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*cMat, m, n, m, n));
99619566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJCUSPARSE, &iscuda));
99629566063dSJacob Faibussowitsch   if (!iscuda) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJCUSPARSE, &iscuda));
99639566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dm->mattype, MATSEQAIJKOKKOS, &iskokkos));
99649566063dSJacob Faibussowitsch   if (!iskokkos) PetscCall(PetscStrcmp(dm->mattype, MATMPIAIJKOKKOS, &iskokkos));
9965e19f7ee6SMark Adams   if (iscuda) mtype = MATSEQAIJCUSPARSE;
9966e19f7ee6SMark Adams   else if (iskokkos) mtype = MATSEQAIJKOKKOS;
9967e19f7ee6SMark Adams   else mtype = MATSEQAIJ;
99689566063dSJacob Faibussowitsch   PetscCall(MatSetType(*cMat, mtype));
99699566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &aSec, &aIS));
99709566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(aIS, &anchors));
99716995de1eSToby Isaac   /* cSec will be a subset of aSec and section */
99729566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(cSec, &pStart, &pEnd));
99739566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetChart(section, &sStart, &sEnd));
99749566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(m + 1, &i));
99750ac89760SToby Isaac   i[0] = 0;
99769566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetNumFields(section, &numFields));
99770ac89760SToby Isaac   for (p = pStart; p < pEnd; p++) {
9978f19733c5SToby Isaac     PetscInt rDof, rOff, r;
9979f19733c5SToby Isaac 
99809566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetDof(aSec, p, &rDof));
9981f19733c5SToby Isaac     if (!rDof) continue;
99829566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetOffset(aSec, p, &rOff));
99830ac89760SToby Isaac     if (numFields) {
99840ac89760SToby Isaac       for (f = 0; f < numFields; f++) {
99850ac89760SToby Isaac         annz = 0;
9986f19733c5SToby Isaac         for (r = 0; r < rDof; r++) {
9987f19733c5SToby Isaac           a = anchors[rOff + r];
9988ae65431dSMatthew G. Knepley           if (a < sStart || a >= sEnd) continue;
99899566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof));
99900ac89760SToby Isaac           annz += aDof;
99910ac89760SToby Isaac         }
99929566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof));
99939566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldOffset(cSec, p, f, &off));
9994ad540459SPierre Jolivet         for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz;
99950ac89760SToby Isaac       }
99962f7452b8SBarry Smith     } else {
99970ac89760SToby Isaac       annz = 0;
99989566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
99990ac89760SToby Isaac       for (q = 0; q < dof; q++) {
10000ae65431dSMatthew G. Knepley         a = anchors[rOff + q];
10001ae65431dSMatthew G. Knepley         if (a < sStart || a >= sEnd) continue;
100029566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(section, a, &aDof));
100030ac89760SToby Isaac         annz += aDof;
100040ac89760SToby Isaac       }
100059566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
100069566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(cSec, p, &off));
10007ad540459SPierre Jolivet       for (q = 0; q < dof; q++) i[off + q + 1] = i[off + q] + annz;
100080ac89760SToby Isaac     }
100090ac89760SToby Isaac   }
100100ac89760SToby Isaac   nnz = i[m];
100119566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nnz, &j));
100120ac89760SToby Isaac   offset = 0;
100130ac89760SToby Isaac   for (p = pStart; p < pEnd; p++) {
100140ac89760SToby Isaac     if (numFields) {
100150ac89760SToby Isaac       for (f = 0; f < numFields; f++) {
100169566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetFieldDof(cSec, p, f, &dof));
100170ac89760SToby Isaac         for (q = 0; q < dof; q++) {
100180ac89760SToby Isaac           PetscInt rDof, rOff, r;
100199566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(aSec, p, &rDof));
100209566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(aSec, p, &rOff));
100210ac89760SToby Isaac           for (r = 0; r < rDof; r++) {
100220ac89760SToby Isaac             PetscInt s;
100230ac89760SToby Isaac 
100240ac89760SToby Isaac             a = anchors[rOff + r];
10025ae65431dSMatthew G. Knepley             if (a < sStart || a >= sEnd) continue;
100269566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, a, f, &aDof));
100279566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldOffset(section, a, f, &aOff));
10028ad540459SPierre Jolivet             for (s = 0; s < aDof; s++) j[offset++] = aOff + s;
100290ac89760SToby Isaac           }
100300ac89760SToby Isaac         }
100310ac89760SToby Isaac       }
100322f7452b8SBarry Smith     } else {
100339566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(cSec, p, &dof));
100340ac89760SToby Isaac       for (q = 0; q < dof; q++) {
100350ac89760SToby Isaac         PetscInt rDof, rOff, r;
100369566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(aSec, p, &rDof));
100379566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(aSec, p, &rOff));
100380ac89760SToby Isaac         for (r = 0; r < rDof; r++) {
100390ac89760SToby Isaac           PetscInt s;
100400ac89760SToby Isaac 
100410ac89760SToby Isaac           a = anchors[rOff + r];
10042ae65431dSMatthew G. Knepley           if (a < sStart || a >= sEnd) continue;
100439566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetDof(section, a, &aDof));
100449566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetOffset(section, a, &aOff));
10045ad540459SPierre Jolivet           for (s = 0; s < aDof; s++) j[offset++] = aOff + s;
100460ac89760SToby Isaac         }
100470ac89760SToby Isaac       }
100480ac89760SToby Isaac     }
100490ac89760SToby Isaac   }
100509566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocationCSR(*cMat, i, j, NULL));
100519566063dSJacob Faibussowitsch   PetscCall(PetscFree(i));
100529566063dSJacob Faibussowitsch   PetscCall(PetscFree(j));
100539566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(aIS, &anchors));
100543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
100550ac89760SToby Isaac }
100560ac89760SToby Isaac 
10057d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm)
10058d71ae5a4SJacob Faibussowitsch {
10059f7c74593SToby Isaac   DM_Plex     *plex = (DM_Plex *)dm->data;
10060f7c74593SToby Isaac   PetscSection anchorSection, section, cSec;
1006166ad2231SToby Isaac   Mat          cMat;
1006266ad2231SToby Isaac 
1006366ad2231SToby Isaac   PetscFunctionBegin;
1006466ad2231SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
100659566063dSJacob Faibussowitsch   PetscCall(DMPlexGetAnchors(dm, &anchorSection, NULL));
1006666ad2231SToby Isaac   if (anchorSection) {
1006744a7f3ddSMatthew G. Knepley     PetscInt Nf;
10068e228b242SToby Isaac 
100699566063dSJacob Faibussowitsch     PetscCall(DMGetLocalSection(dm, &section));
100709566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateConstraintSection_Anchors(dm, section, &cSec));
100719566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateConstraintMatrix_Anchors(dm, section, cSec, &cMat));
100729566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
100739566063dSJacob Faibussowitsch     if (Nf && plex->computeanchormatrix) PetscCall((*plex->computeanchormatrix)(dm, section, cSec, cMat));
100749566063dSJacob Faibussowitsch     PetscCall(DMSetDefaultConstraints(dm, cSec, cMat, NULL));
100759566063dSJacob Faibussowitsch     PetscCall(PetscSectionDestroy(&cSec));
100769566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&cMat));
1007766ad2231SToby Isaac   }
100783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1007966ad2231SToby Isaac }
10080a93c429eSMatthew G. Knepley 
10081d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateSubDomainDM_Plex(DM dm, DMLabel label, PetscInt value, IS *is, DM *subdm)
10082d71ae5a4SJacob Faibussowitsch {
10083a93c429eSMatthew G. Knepley   IS           subis;
10084a93c429eSMatthew G. Knepley   PetscSection section, subsection;
10085a93c429eSMatthew G. Knepley 
10086a93c429eSMatthew G. Knepley   PetscFunctionBegin;
100879566063dSJacob Faibussowitsch   PetscCall(DMGetLocalSection(dm, &section));
1008828b400f6SJacob Faibussowitsch   PetscCheck(section, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting subdomain");
1008928b400f6SJacob Faibussowitsch   PetscCheck(subdm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set output subDM for splitting subdomain");
10090a93c429eSMatthew G. Knepley   /* Create subdomain */
100919566063dSJacob Faibussowitsch   PetscCall(DMPlexFilter(dm, label, value, subdm));
10092a93c429eSMatthew G. Knepley   /* Create submodel */
100939566063dSJacob Faibussowitsch   PetscCall(DMPlexGetSubpointIS(*subdm, &subis));
100949566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreateSubmeshSection(section, subis, &subsection));
100959566063dSJacob Faibussowitsch   PetscCall(DMSetLocalSection(*subdm, subsection));
100969566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&subsection));
100979566063dSJacob Faibussowitsch   PetscCall(DMCopyDisc(dm, *subdm));
10098a93c429eSMatthew G. Knepley   /* Create map from submodel to global model */
10099a93c429eSMatthew G. Knepley   if (is) {
10100a93c429eSMatthew G. Knepley     PetscSection    sectionGlobal, subsectionGlobal;
10101a93c429eSMatthew G. Knepley     IS              spIS;
10102a93c429eSMatthew G. Knepley     const PetscInt *spmap;
10103a93c429eSMatthew G. Knepley     PetscInt       *subIndices;
10104a93c429eSMatthew G. Knepley     PetscInt        subSize = 0, subOff = 0, pStart, pEnd, p;
10105a93c429eSMatthew G. Knepley     PetscInt        Nf, f, bs = -1, bsLocal[2], bsMinMax[2];
10106a93c429eSMatthew G. Knepley 
101079566063dSJacob Faibussowitsch     PetscCall(DMPlexGetSubpointIS(*subdm, &spIS));
101089566063dSJacob Faibussowitsch     PetscCall(ISGetIndices(spIS, &spmap));
101099566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetNumFields(section, &Nf));
101109566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(dm, &sectionGlobal));
101119566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalSection(*subdm, &subsectionGlobal));
101129566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetChart(subsection, &pStart, &pEnd));
10113a93c429eSMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
10114a93c429eSMatthew G. Knepley       PetscInt gdof, pSubSize = 0;
10115a93c429eSMatthew G. Knepley 
101169566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof));
10117a93c429eSMatthew G. Knepley       if (gdof > 0) {
10118a93c429eSMatthew G. Knepley         for (f = 0; f < Nf; ++f) {
10119a93c429eSMatthew G. Knepley           PetscInt fdof, fcdof;
10120a93c429eSMatthew G. Knepley 
101219566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(subsection, p, f, &fdof));
101229566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(subsection, p, f, &fcdof));
10123a93c429eSMatthew G. Knepley           pSubSize += fdof - fcdof;
10124a93c429eSMatthew G. Knepley         }
10125a93c429eSMatthew G. Knepley         subSize += pSubSize;
10126a93c429eSMatthew G. Knepley         if (pSubSize) {
10127a93c429eSMatthew G. Knepley           if (bs < 0) {
10128a93c429eSMatthew G. Knepley             bs = pSubSize;
10129a93c429eSMatthew G. Knepley           } else if (bs != pSubSize) {
10130a93c429eSMatthew G. Knepley             /* Layout does not admit a pointwise block size */
10131a93c429eSMatthew G. Knepley             bs = 1;
10132a93c429eSMatthew G. Knepley           }
10133a93c429eSMatthew G. Knepley         }
10134a93c429eSMatthew G. Knepley       }
10135a93c429eSMatthew G. Knepley     }
10136a93c429eSMatthew G. Knepley     /* Must have same blocksize on all procs (some might have no points) */
101379371c9d4SSatish Balay     bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs;
101389371c9d4SSatish Balay     bsLocal[1] = bs;
101399566063dSJacob Faibussowitsch     PetscCall(PetscGlobalMinMaxInt(PetscObjectComm((PetscObject)dm), bsLocal, bsMinMax));
101409371c9d4SSatish Balay     if (bsMinMax[0] != bsMinMax[1]) {
101419371c9d4SSatish Balay       bs = 1;
101429371c9d4SSatish Balay     } else {
101439371c9d4SSatish Balay       bs = bsMinMax[0];
101449371c9d4SSatish Balay     }
101459566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(subSize, &subIndices));
10146a93c429eSMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
10147a93c429eSMatthew G. Knepley       PetscInt gdof, goff;
10148a93c429eSMatthew G. Knepley 
101499566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetDof(subsectionGlobal, p, &gdof));
10150a93c429eSMatthew G. Knepley       if (gdof > 0) {
10151a93c429eSMatthew G. Knepley         const PetscInt point = spmap[p];
10152a93c429eSMatthew G. Knepley 
101539566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetOffset(sectionGlobal, point, &goff));
10154a93c429eSMatthew G. Knepley         for (f = 0; f < Nf; ++f) {
10155a93c429eSMatthew G. Knepley           PetscInt fdof, fcdof, fc, f2, poff = 0;
10156a93c429eSMatthew G. Knepley 
10157a93c429eSMatthew G. Knepley           /* Can get rid of this loop by storing field information in the global section */
10158a93c429eSMatthew G. Knepley           for (f2 = 0; f2 < f; ++f2) {
101599566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldDof(section, p, f2, &fdof));
101609566063dSJacob Faibussowitsch             PetscCall(PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof));
10161a93c429eSMatthew G. Knepley             poff += fdof - fcdof;
10162a93c429eSMatthew G. Knepley           }
101639566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldDof(section, p, f, &fdof));
101649566063dSJacob Faibussowitsch           PetscCall(PetscSectionGetFieldConstraintDof(section, p, f, &fcdof));
10165ad540459SPierre Jolivet           for (fc = 0; fc < fdof - fcdof; ++fc, ++subOff) subIndices[subOff] = goff + poff + fc;
10166a93c429eSMatthew G. Knepley         }
10167a93c429eSMatthew G. Knepley       }
10168a93c429eSMatthew G. Knepley     }
101699566063dSJacob Faibussowitsch     PetscCall(ISRestoreIndices(spIS, &spmap));
101709566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is));
10171a93c429eSMatthew G. Knepley     if (bs > 1) {
10172a93c429eSMatthew G. Knepley       /* We need to check that the block size does not come from non-contiguous fields */
10173a93c429eSMatthew G. Knepley       PetscInt i, j, set = 1;
10174a93c429eSMatthew G. Knepley       for (i = 0; i < subSize; i += bs) {
10175a93c429eSMatthew G. Knepley         for (j = 0; j < bs; ++j) {
101769371c9d4SSatish Balay           if (subIndices[i + j] != subIndices[i] + j) {
101779371c9d4SSatish Balay             set = 0;
101789371c9d4SSatish Balay             break;
101799371c9d4SSatish Balay           }
10180a93c429eSMatthew G. Knepley         }
10181a93c429eSMatthew G. Knepley       }
101829566063dSJacob Faibussowitsch       if (set) PetscCall(ISSetBlockSize(*is, bs));
10183a93c429eSMatthew G. Knepley     }
10184a93c429eSMatthew G. Knepley     /* Attach nullspace */
10185a93c429eSMatthew G. Knepley     for (f = 0; f < Nf; ++f) {
10186a93c429eSMatthew G. Knepley       (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[f];
10187a93c429eSMatthew G. Knepley       if ((*subdm)->nullspaceConstructors[f]) break;
10188a93c429eSMatthew G. Knepley     }
10189a93c429eSMatthew G. Knepley     if (f < Nf) {
10190a93c429eSMatthew G. Knepley       MatNullSpace nullSpace;
101919566063dSJacob Faibussowitsch       PetscCall((*(*subdm)->nullspaceConstructors[f])(*subdm, f, f, &nullSpace));
101926823f3c5SBlaise Bourdin 
101939566063dSJacob Faibussowitsch       PetscCall(PetscObjectCompose((PetscObject)*is, "nullspace", (PetscObject)nullSpace));
101949566063dSJacob Faibussowitsch       PetscCall(MatNullSpaceDestroy(&nullSpace));
10195a93c429eSMatthew G. Knepley     }
10196a93c429eSMatthew G. Knepley   }
101973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10198a93c429eSMatthew G. Knepley }
10199c0f0dcc3SMatthew G. Knepley 
10200c0f0dcc3SMatthew G. Knepley /*@
10201c0f0dcc3SMatthew G. Knepley   DMPlexMonitorThroughput - Report the cell throughput of FE integration
10202c0f0dcc3SMatthew G. Knepley 
10203a1cb98faSBarry Smith   Input Parameters:
10204a1cb98faSBarry Smith + dm    - The `DM`
10205a1cb98faSBarry Smith - dummy - unused argument
10206a1cb98faSBarry Smith 
10207a1cb98faSBarry Smith   Options Database Key:
10208a1cb98faSBarry Smith . -dm_plex_monitor_throughput - Activate the monitor
10209c0f0dcc3SMatthew G. Knepley 
10210c0f0dcc3SMatthew G. Knepley   Level: developer
10211c0f0dcc3SMatthew G. Knepley 
102121cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreate()`
10213c0f0dcc3SMatthew G. Knepley @*/
10214d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexMonitorThroughput(DM dm, void *dummy)
10215d71ae5a4SJacob Faibussowitsch {
10216b665b14eSToby Isaac   PetscLogHandler default_handler;
10217b665b14eSToby Isaac 
102182611ad71SToby Isaac   PetscFunctionBegin;
102192611ad71SToby Isaac   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
10220b665b14eSToby Isaac   PetscCall(PetscLogGetDefaultHandler(&default_handler));
10221b665b14eSToby Isaac   if (default_handler) {
10222c0f0dcc3SMatthew G. Knepley     PetscLogEvent      event;
10223c0f0dcc3SMatthew G. Knepley     PetscEventPerfInfo eventInfo;
10224c0f0dcc3SMatthew G. Knepley     PetscReal          cellRate, flopRate;
10225c0f0dcc3SMatthew G. Knepley     PetscInt           cStart, cEnd, Nf, N;
10226c0f0dcc3SMatthew G. Knepley     const char        *name;
10227c0f0dcc3SMatthew G. Knepley 
102289566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
102299566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
102309566063dSJacob Faibussowitsch     PetscCall(DMGetNumFields(dm, &Nf));
102319566063dSJacob Faibussowitsch     PetscCall(PetscLogEventGetId("DMPlexResidualFE", &event));
10232b665b14eSToby Isaac     PetscCall(PetscLogEventGetPerfInfo(PETSC_DEFAULT, event, &eventInfo));
10233c0f0dcc3SMatthew G. Knepley     N        = (cEnd - cStart) * Nf * eventInfo.count;
10234c0f0dcc3SMatthew G. Knepley     flopRate = eventInfo.flops / eventInfo.time;
10235c0f0dcc3SMatthew G. Knepley     cellRate = N / eventInfo.time;
1023663a3b9bcSJacob 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)));
102372611ad71SToby Isaac   } else {
10238b665b14eSToby Isaac     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Plex Throughput Monitor is not supported if logging is turned off or the default log handler is not running. Reconfigure using --with-log and run with -log_view.");
102392611ad71SToby Isaac   }
102403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
10241c0f0dcc3SMatthew G. Knepley }
10242